home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / mapi / checkers.frm / wcheck.cpp < prev    next >
C/C++ Source or Header  |  1996-04-11  |  98KB  |  2,848 lines

  1. /* --------------------------------------------------------------------------
  2.  
  3. Basic Forms example of a custom sendable form.  It is an EXE server
  4. rather than a DLL.  It implements the minimum form interface required
  5. to launch and send a form.
  6.  
  7. Copyright (C) 1995 Microsoft Corporation
  8.  
  9. -------------------------------------------------------------------------- */
  10.  
  11. #define WINDOWS
  12.  
  13. #include <windows.h>
  14. #include <windowsx.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <process.h>
  19. #include <malloc.h>
  20. #include <memory.h>
  21. #include <conio.h>
  22. #include <time.h>
  23. #include <ctype.h>
  24. #include <search.h>
  25.  
  26. #ifdef _WIN32
  27. #include <winver.h>
  28. #else
  29. #include <ver.h>
  30. #endif
  31.  
  32. //$FORM
  33.  
  34. //---[ Form specific includes ]--------------------------------------------
  35.  
  36. #include <ole2.h>
  37. #include <mapiform.h>
  38. #include <mapix.h>
  39. #include <mapiutil.h>
  40.  
  41. //$FORM
  42.  
  43. //---[ Various platform defines ]------------------------------------------
  44.  
  45. #ifndef APIENTRY                // Windows NT defines APIENTRY,
  46. #define APIENTRY far pascal             // but 3.x doesn't.
  47. #endif
  48.  
  49. #ifndef _WIN32                   // Windows 3.x uses a FARPROC
  50. #define DLGPROC FARPROC                 // for dialogs
  51. #endif
  52.  
  53. unsigned int _charmax;
  54.  
  55. #ifdef _WIN32
  56. #define MoveTo(_1, _2, _3) MoveToEx(_1,_2,_3,NULL)
  57. #endif
  58.  
  59. //---[ Define Debug Trace Tags ]-------------------------------------------
  60.  
  61. #include "dbugit.h"
  62.  
  63. #ifdef DEBUG
  64. ASSERTDATA
  65. #endif
  66.  
  67. //---[ Local header dependencies ]-----------------------------------------
  68.  
  69. #include "check.h"
  70. #include "dlg.h"
  71. #include "wcheck.h"
  72. #include "checkdta.h"
  73. #include "movelist.h"
  74. #include "form.h" //$FORM
  75.  
  76. //---[ Globally Accessible Config Info ]-----------------------------------
  77.  
  78. struct  rCheckConfigRec rConfig;                // Config struct
  79. struct  rGameStateRec rGameState;               // Game state
  80. class   CMoveList CMoves;                               // Move list
  81. SQUARE  b[SQRS_MAX];                                    // Board structure
  82.  
  83. static  POINT       pntStart;                   // For buttonup/down processing.
  84.  
  85. char szAppName[] = APP_NAME;                    // The name of this application
  86.  
  87. #ifdef DEBUG
  88. char szTitle[]   = "Checkers (debug)";
  89. #else
  90. #ifdef TEST
  91. char szTitle[]   = "Checkers (test)";
  92. #else
  93. char szTitle[]   = "Checkers";
  94. #endif
  95. #endif
  96.  
  97. //---[ Globally Accessible Handles ]---------------------------------------
  98.  
  99. HINSTANCE       hInst;          // current instance handle
  100.  
  101. HWND    hMainWnd        = NULL;         // Main window handle
  102. HWND    hClientWnd      = NULL;         // Client window handle
  103. HBRUSH  hbrBlack;                       
  104. HBRUSH  hbrWhite;                       
  105. HBRUSH  hbrRed;                         
  106. HBRUSH  hbrBckgrnd;                     
  107. HBRUSH  hbrBlue;                        
  108. HBRUSH  hbrHuman;                       
  109. HBRUSH  hbrComputer;            
  110. HBRUSH  hbrDkgrey;                      
  111. HPEN    hpenDkgrey;                     
  112. HBITMAP hBtmaps;                        // Piece bitmaps
  113.  
  114. HCURSOR curNormal;                      // Standard cursor
  115. HCURSOR curThink;                       // Computer is thinking cursor
  116. HCURSOR curPiece;                       // Piece cursor (move in progress)
  117. HCURSOR curResize;                      // Resize cursor
  118.  
  119. #define SQR_XSIZE       rConfig.iSquareSize
  120. #define SQR_YSIZE       rConfig.iSquareSize
  121.  
  122. #define OFST_INCREMENT      rConfig.iSquareSize         // OFFSET into bitmap
  123. #define OFST_BLANK          (0*OFST_INCREMENT)          // OFFSET into bitmap
  124. #define OFST_BLANK_RED      (1*OFST_INCREMENT)          // OFFSET into bitmap
  125. #define OFST_COMPUTER       (2*OFST_INCREMENT)          // OFFSET into bitmap
  126. #define OFST_COMPUTER_KING  (3*OFST_INCREMENT)          // OFFSET into bitmap
  127. #define OFST_HUMAN_KING     (4*OFST_INCREMENT)          // OFFSET into bitmap
  128. #define OFST_HUMAN          (5*OFST_INCREMENT)          // OFFSET into bitmap
  129.  
  130. FRM *pfrm; //$FORM
  131.  
  132. //---[ Inline code includes ]----------------------------------------------
  133.  
  134. /****************************************************************************
  135. *****************************************************************************
  136. *****************************************************************************
  137. ****************************************************************************/
  138. CMoveList::CMoveList()
  139. {
  140.     m_iNumBoards = 0;
  141.     m_fClassInitialized = FALSE;
  142.     m_prFirstBoard = NULL;
  143.     m_prCurrentBoard = m_prFirstBoard;
  144.     m_prCurrentSearchBoard = m_prFirstBoard;
  145. }
  146.  
  147. CMoveList::~CMoveList()
  148. {
  149.     m_prCurrentBoard = m_prFirstBoard;
  150.     PurgeBoards();
  151. }
  152.  
  153. BOARD CMoveList::GetFirstBoard(BOARD b, int *piPlayerTurn)
  154. {
  155.     AssertSz(m_fClassInitialized, "MoveList class not initialized in GetFirstBoard()");
  156.  
  157.     m_prCurrentSearchBoard = m_prFirstBoard;
  158.     if (NULL == m_prCurrentSearchBoard)
  159.     return NULL;
  160.     else
  161.     {
  162.     AssertSz((BLACK == m_prCurrentSearchBoard->iPlayerTurn) ||
  163.              (RED == m_prCurrentSearchBoard->iPlayerTurn), 
  164.              "EBr rocks!");
  165.     
  166.         *piPlayerTurn = m_prCurrentSearchBoard->iPlayerTurn;
  167.     CopyBoard(m_prCurrentSearchBoard->b, b);
  168.         
  169.     m_prCurrentSearchBoard = m_prCurrentSearchBoard->prNextBoard;
  170.     return b;
  171.     }
  172. }
  173.  
  174. BOARD CMoveList::GetNextBoard(BOARD b, int *piPlayerTurn)
  175. {
  176.     AssertSz(m_fClassInitialized, "MoveList class not initialized in GetNextBoard()");
  177.  
  178.     if (NULL == m_prCurrentSearchBoard)
  179.     {
  180.     return NULL;
  181.     }
  182.     else
  183.     {
  184.     AssertSz((BLACK == m_prCurrentSearchBoard->iPlayerTurn) ||
  185.              (RED == m_prCurrentSearchBoard->iPlayerTurn), 
  186.              "Kt C abayn  04/07/94");
  187.     
  188.         *piPlayerTurn = m_prCurrentSearchBoard->iPlayerTurn;        
  189.     CopyBoard(m_prCurrentSearchBoard->b, b);
  190.     m_prCurrentSearchBoard = m_prCurrentSearchBoard->prNextBoard;
  191.     return b;
  192.     }
  193. }
  194.  
  195. BOOL CMoveList::Init()
  196. {
  197.     AssertSz(!m_fClassInitialized, "Class already initialized");
  198.  
  199.     m_fClassInitialized = TRUE;
  200.     return TRUE;
  201. }
  202.  
  203. BOOL CMoveList::BackMove(BOARD b, int *piPlayerTurn)
  204. {
  205.     AssertSz(m_fClassInitialized, "MoveList class not initialized in BackMove()");
  206.  
  207.     if (NULL == m_prFirstBoard)
  208.     return FALSE;
  209.  
  210.     AssertSz(m_prCurrentBoard, "Current Board hosed");
  211.  
  212.     if (m_prCurrentBoard == m_prFirstBoard)
  213.     {
  214.     return FALSE;
  215.     }
  216.     else
  217.     {
  218.     m_prCurrentBoard = m_prCurrentBoard->prPrevBoard;
  219.     
  220.     AssertSz((BLACK == m_prCurrentBoard->iPlayerTurn) ||
  221.              (RED == m_prCurrentBoard->iPlayerTurn), 
  222.              "Meatloaf");
  223.  
  224.         *piPlayerTurn = m_prCurrentBoard->iPlayerTurn;
  225.     CopyBoard(m_prCurrentBoard->b, b);
  226.     return TRUE;
  227.     }
  228. }
  229.  
  230. BOOL CMoveList::ForwardMove(BOARD b, int *piPlayerTurn)
  231. {
  232.     AssertSz(m_fClassInitialized, "MoveList class not initialized in ForwardMove()");
  233.  
  234.     if (NULL == m_prCurrentBoard)
  235.     return FALSE;
  236.  
  237.     if (NULL == m_prCurrentBoard->prNextBoard)
  238.     return FALSE;
  239.     else
  240.     {
  241.     m_prCurrentBoard = m_prCurrentBoard->prNextBoard;
  242.  
  243.     AssertSz((BLACK == m_prCurrentBoard->iPlayerTurn) ||
  244.              (RED == m_prCurrentBoard->iPlayerTurn), 
  245.              "Just say no to yes.");
  246.  
  247.         *piPlayerTurn = m_prCurrentBoard->iPlayerTurn;
  248.     CopyBoard(m_prCurrentBoard->b, b);
  249.     return TRUE;
  250.     }
  251. }
  252.  
  253. BOOL CMoveList::NewMove(BOARD b, int iPlayerTurn)
  254. {
  255.     struct rBoardNode *prNewBoard = NULL;
  256.  
  257.     AssertSz(m_fClassInitialized, "MoveList class not initialized in NewMove()");
  258.  
  259.     // Remove any old boards that would get overwritten.
  260.  
  261.     if (NULL != m_prCurrentBoard)
  262.     {
  263.     PurgeBoards();
  264.     }
  265.     
  266.     prNewBoard = (struct rBoardNode *)malloc(sizeof(struct rBoardNode));
  267.     if (!prNewBoard)
  268.     {
  269.     MessageBox(NULL, "Out of memory.", "Checkers", MB_ICONEXCLAMATION | MB_OK);
  270.     return FALSE;
  271.     }
  272.     else
  273.     {
  274.     m_iNumBoards++;
  275.  
  276.     prNewBoard->prNextBoard = NULL;
  277.     prNewBoard->prPrevBoard = NULL;
  278.     CopyBoard(b, prNewBoard->b);
  279.  
  280.     if (NULL == m_prFirstBoard)
  281.     {
  282.         m_prFirstBoard = prNewBoard;
  283.     }
  284.     else
  285.     {
  286.         m_prCurrentBoard->prNextBoard = prNewBoard;
  287.     }
  288.  
  289.     prNewBoard->prPrevBoard = m_prCurrentBoard;
  290.     prNewBoard->iPlayerTurn = iPlayerTurn;
  291.     m_prCurrentBoard = prNewBoard;
  292.     return TRUE;
  293.     }
  294. }
  295.  
  296. BOOL CMoveList::ClearBoards()
  297. {
  298.     m_prCurrentBoard = m_prFirstBoard;
  299.     return (PurgeBoards());
  300. }
  301.  
  302. BOOL CMoveList::PurgeBoards()
  303. {
  304.     struct rBoardNode *prDeleteBoard;
  305.     
  306.     if (NULL == m_prCurrentBoard || 0 == m_fClassInitialized)
  307.     return TRUE;
  308.     else
  309.     {
  310.     prDeleteBoard = m_prCurrentBoard->prNextBoard;
  311.     while (prDeleteBoard != NULL)
  312.     {
  313.         m_prCurrentBoard->prNextBoard = prDeleteBoard->prNextBoard;
  314.         free (prDeleteBoard);
  315.         m_iNumBoards--;
  316.         prDeleteBoard = m_prCurrentBoard->prNextBoard;
  317.     }
  318.     return TRUE;
  319.     }
  320. }
  321.  
  322. /****************************************************************************
  323. *****************************************************************************
  324. *****************************************************************************
  325. ****************************************************************************/
  326.  
  327. BOOL WritePrivateProfileLong(LPCSTR lpszSection, LPCSTR lpszEntry, long lTheLong, LPCSTR lpszFilename);
  328. BOOL WritePrivateProfileInt(LPCSTR lpszSection, LPCSTR lpszEntry, int iTheInt, LPCSTR lpszFilename);
  329. long GetDlgItemLong(HWND hDlg, WORD id);
  330. int  GetDlgItemInt(HWND hDlg, WORD id);
  331. void SetDlgItemInt(HWND hDlg, WORD id, int iValue);
  332. void SetDlgItemLong(HWND hDlg, WORD id, long lValue);
  333. BOOL ValidateNumeric(char *pszText);
  334. LONG GetPrivateProfileLong(LPCSTR lpszSection, LPCSTR lpszEntry, long lDefault, LPCSTR lpszFileName);
  335.  
  336. BOOL WritePrivateProfileInt(LPCSTR lpszSection, LPCSTR lpszEntry, int iTheInt, LPCSTR lpszFilename)
  337. {
  338.     char szINIString[32];
  339.  
  340.     AssertSz(lpszSection, "lpszSection == NULL");
  341.     AssertSz(lpszEntry, "lpszEntry == NULL");
  342.     AssertSz(lpszFilename, "lpszFilename == NULL");
  343.  
  344.     _itoa(iTheInt, szINIString, 10);   // Convert the int to a string. Base10
  345.      return WritePrivateProfileString(lpszSection, lpszEntry, (LPSTR)szINIString, lpszFilename);
  346. }
  347.  
  348. long GetDlgItemLong(HWND hDlg, WORD id)
  349. {
  350.     char szTemp[20];    // Can't imagine a number longer than this.
  351.     long lTemp;
  352.  
  353.     GetDlgItemText (hDlg, id, (LPSTR) szTemp, sizeof(szTemp));
  354.     lTemp = atol(szTemp);
  355.  
  356.     return lTemp;
  357. }
  358.  
  359. int GetDlgItemInt(HWND hDlg, WORD id)
  360. {
  361.     char szTemp[20];    // Can't imagine a number longer than this.
  362.     int iTemp;
  363.  
  364.     GetDlgItemText (hDlg, id, (LPSTR) szTemp, sizeof(szTemp));
  365.     iTemp = atoi(szTemp);
  366.  
  367.     return iTemp;
  368. }
  369.  
  370. void SetDlgItemInt(HWND hDlg, WORD id, int iValue)
  371. {
  372.     char szTemp[20];     // Can't imagine a number longer than this.
  373.     
  374.     _itoa(iValue, szTemp, 10);
  375.     SetDlgItemText (hDlg, id, szTemp);
  376. }
  377.  
  378. void SetDlgItemLong(HWND hDlg, WORD id, long lValue)
  379. {
  380.     char szTemp[20];     // Can't imagine a number longer than this.
  381.     
  382.     _ltoa(lValue, szTemp, 10);
  383.     SetDlgItemText (hDlg, id, szTemp);
  384. }
  385.  
  386. LONG GetPrivateProfileLong(LPCSTR lpszSection, LPCSTR lpszEntry, long lDefault, LPCSTR lpszFileName)
  387. {
  388.     LONG l;
  389.     char szTemp[20];
  390.  
  391.     GetPrivateProfileString(lpszSection, lpszEntry, "~~", szTemp, 20, lpszFileName);
  392.     if (lstrcmp(szTemp, "~~") == 0)
  393.     l = lDefault;
  394.     else
  395.     l = atol(szTemp);
  396.     return l;
  397. }
  398.  
  399. BOOL WritePrivateProfileLong(LPCSTR lpszSection, LPCSTR lpszEntry, long lTheLong, LPCSTR lpszFilename)
  400. {
  401.     char szINIString[32];
  402.  
  403.     AssertSz(lpszSection, "lpszSection == NULL");
  404.     AssertSz(lpszEntry, "lpszEntry == NULL");
  405.     AssertSz(lpszFilename, "lpszFilename == NULL");
  406.  
  407.     _ltoa(lTheLong, szINIString, 10);   // Convert the int to a string. Base10
  408.      return WritePrivateProfileString(lpszSection, lpszEntry, (LPSTR)szINIString, lpszFilename);
  409. }
  410.  
  411. /****************************************************************************
  412. *****************************************************************************
  413. *****************************************************************************
  414. ****************************************************************************/
  415. int OpenCheckers(HINSTANCE hInstance, int nCmdShow)
  416. {
  417.     MSG msg;
  418.     HACCEL hAccelTable = NULL;          // Accelerator table handle.
  419.  
  420.     // Perform initializations that apply to a specific instance
  421.  
  422.     if (!InitInstance(hInstance, nCmdShow)) 
  423.     {
  424.     AssertSz(0,"InitInst failed");
  425.         return (FALSE);
  426.     }
  427.  
  428.     hAccelTable = LoadAccelerators (hInstance, (LPSTR)"WCheck");
  429.     AssertSz(hAccelTable,"no accelerators");
  430.  
  431.     // Acquire and dispatch messages until a WM_QUIT message is received.
  432.  
  433.     while (GetMessage(&msg,         // message structure
  434.         NULL,                                   // handle of window receiving the message
  435.         0,                                      // lowest message to examine
  436.         0))                                     // highest message to examine
  437.     {
  438.         if (!TranslateAccelerator (msg.hwnd, hAccelTable, &msg)) 
  439.         {
  440.             TranslateMessage(&msg); // Translates virtual key codes
  441.             DispatchMessage(&msg);  // Dispatches message to window
  442.         }
  443.     }
  444.  
  445.     return 0;
  446.  
  447. } /* end open checkers */
  448.  
  449. /****************************************************************************
  450.  
  451.     FUNCTION: WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
  452.  
  453.     PURPOSE: calls initialization function, processes message loop
  454.  
  455.     COMMENTS:
  456.  
  457.         Windows recognizes this function by name as the initial entry point
  458.         for the program.  This function calls the application initialization
  459.         routine, if no other instance of the program is running, and always
  460.         calls the instance initialization routine.  It then executes a message
  461.         retrieval and dispatch loop that is the top-level control structure
  462.         for the remainder of execution.  The loop is terminated when a WM_QUIT
  463.         message is received, at which time this function exits the application
  464.         instance by returning the value passed by PostQuitMessage().
  465.  
  466.         If this function must abort before entering the message loop, it
  467.         returns the conventional value NULL.
  468.  
  469. ****************************************************************************/
  470. int APIENTRY WinMain(
  471.     HINSTANCE hInstance,
  472.     HINSTANCE hPrevInstance,
  473.     LPSTR lpCmdLine,
  474.     int nCmdShow)
  475. {
  476.  
  477.     AssertSz(((RED == PLAYER1) && (BLACK == PLAYER2)) || 
  478.          ((BLACK == PLAYER1) && (RED == PLAYER2)), "Players are schizoid");
  479.  
  480.     hInst = hInstance;                              // Set global Instance handle
  481.  
  482.     if (!hPrevInstance)                                             
  483.     {
  484.         if (!InitApplication(hInstance))        
  485.         {
  486.             return (FALSE);     
  487.         }
  488.     }
  489.  
  490.     // Check for the -Embedding switch
  491.  
  492.     if (lpCmdLine && (lpCmdLine[0] == '/' || lpCmdLine[0] == '-'))
  493.     {
  494.  
  495.         // Attempt to be a form
  496.  
  497.     if (NOERROR == HrStartOleAndRegisterClassFactory())
  498.         {
  499.         rGameState.fPlayAsForm = TRUE; // we are acting as a form
  500.  
  501.         #ifdef DEBUG
  502.         nCmdShow = SW_SHOWMINIMIZED;
  503.         #else
  504.         nCmdShow = SW_HIDE;
  505.         #endif
  506.  
  507.         // Open the checkers form window .. but do not show until we're DoVerb'd
  508.  
  509.         OpenCheckers(hInstance, nCmdShow);
  510.  
  511.         // Call this function if ..StartForms succeeded
  512.  
  513.         HrStopForms();
  514.  
  515.         return 0;
  516.         }
  517.  
  518.         if (IDYES == MessageBox(GetFocus(), "Unable to initialize messaging subsystem.\nWould you like to play against the computer?", "Checkers", MB_YESNO ))
  519.         {
  520.         OpenCheckers(hInstance, nCmdShow);
  521.         return 0;
  522.         }
  523.  
  524.     }
  525.  
  526.     OpenCheckers(hInstance, nCmdShow);
  527.     return 0;
  528. }
  529.  
  530. VOID ReadPlayerInfo(int iPlayerNum, char *pszPlayerName)
  531. {
  532.     AssertSz((iPlayerNum == BLACK) || (iPlayerNum == RED), "Invalid Player Num");
  533.     AssertSz(pszPlayerName, "Playername can't be NULL");
  534.  
  535.     if (rGameState.fPlayAsForm)
  536.     {
  537.     rConfig.rPlayer[iPlayerNum].iPlayerType = HUMAN_PLAYER;
  538.     if (22871 == GetPrivateProfileInt ("Computer", "Config", HUMAN_PLAYER, INI_NAME))
  539.         {
  540.         rConfig.rPlayer[iPlayerNum].iPlayerType = COMPUTER_PLAYER;
  541.         }
  542.     }
  543.     else
  544.     {
  545.     if (PLAYER1 == iPlayerNum)
  546.         rConfig.rPlayer[iPlayerNum].iPlayerType = HUMAN_PLAYER;
  547.     else
  548.         rConfig.rPlayer[iPlayerNum].iPlayerType = COMPUTER_PLAYER;
  549.     }
  550.        
  551.     // Get computer config options.
  552.  
  553.     rConfig.rPlayer[iPlayerNum].iMemPositions = GetPrivateProfileInt (pszPlayerName, "MemPositions", 0, INI_NAME);
  554.     rConfig.rPlayer[iPlayerNum].iUseMoveTheory = GetPrivateProfileInt (pszPlayerName, "UseMoveTheory", 1, INI_NAME);
  555.     rConfig.rPlayer[iPlayerNum].iUseMoveShuffling = GetPrivateProfileInt (pszPlayerName, "UseMoveShuffling", 1, INI_NAME);
  556.     rConfig.rPlayer[iPlayerNum].iUseEqualMoveSkipping = GetPrivateProfileInt (pszPlayerName, "UseEqualMoveSkipping", 1, INI_NAME);
  557.     rConfig.rPlayer[iPlayerNum].iUseOpeningBook = GetPrivateProfileInt (pszPlayerName, "UseOpeningBook", 1, INI_NAME);
  558.     rConfig.rPlayer[iPlayerNum].lUseGoodMoveSkipping = GetPrivateProfileLong (pszPlayerName, "UseGoodMoveSkipping", 0, INI_NAME);
  559.     rConfig.rPlayer[iPlayerNum].iMaxRecursionDepth = GetPrivateProfileInt (pszPlayerName, "MaxRecursionDepth", 5, INI_NAME);
  560.     rConfig.rPlayer[iPlayerNum].iUseAlphaBetaPruning = GetPrivateProfileInt (pszPlayerName, "UseAlphaBetaPruning", 1, INI_NAME);
  561.     rConfig.rPlayer[iPlayerNum].lAlphaPruningOriginalDepth = GetPrivateProfileLong (pszPlayerName, "AlphaPruningOriginalDepth", 2, INI_NAME);
  562.     rConfig.rPlayer[iPlayerNum].lAlphaPruningWidth = GetPrivateProfileLong (pszPlayerName, "AlphaPruningWidth", 35, INI_NAME);
  563.  
  564. }
  565.  
  566. VOID    ReadINI ()
  567. {
  568.     TraceTag(tagUI,"ReadINI()");
  569.  
  570.     // Read general config info
  571.  
  572.     rConfig.iGameType = GetPrivateProfileInt ("Config", "GameType", GAME_CHECKERS, INI_NAME);
  573.     rConfig.iMustJump = GetPrivateProfileInt ("Config", "MustJump", 1, INI_NAME);
  574.     rConfig.iBoardFlipped = 1;
  575.     rConfig.iSquareSize = GetPrivateProfileInt ("Config", "SquareSize", 30, INI_NAME);
  576.     rConfig.iMaxMoves = GetPrivateProfileInt ("Config", "MaxMoves", 200, INI_NAME);
  577.  
  578.     // Read specific player config for both (potential) computer players.
  579.  
  580.     ReadPlayerInfo(PLAYER1, "Player1");
  581.     ReadPlayerInfo(PLAYER2, "Player2");
  582. }
  583.  
  584. VOID WritePlayerInfo(int iPlayerNum, char *pszPlayerName)
  585. {
  586.     AssertSz((iPlayerNum == RED) || (iPlayerNum == BLACK), "Invalid Player Num");
  587.     AssertSz(pszPlayerName, "Playername can't be NULL");
  588.  
  589.     // Player specific config items
  590.  
  591.     WritePrivateProfileInt (pszPlayerName, "PlayerType", rConfig.rPlayer[iPlayerNum].iPlayerType, INI_NAME);
  592.     WritePrivateProfileInt (pszPlayerName, "MemPositions", rConfig.rPlayer[iPlayerNum].iMemPositions, INI_NAME);
  593.     WritePrivateProfileInt (pszPlayerName, "UseMoveTheory", rConfig.rPlayer[iPlayerNum].iUseMoveTheory, INI_NAME);
  594.     WritePrivateProfileInt (pszPlayerName, "UseMoveShuffling", rConfig.rPlayer[iPlayerNum].iUseMoveShuffling, INI_NAME);
  595.     WritePrivateProfileInt (pszPlayerName, "UseEqualMoveSkipping", rConfig.rPlayer[iPlayerNum].iUseEqualMoveSkipping, INI_NAME);
  596.     WritePrivateProfileInt (pszPlayerName, "UseOpeningBook", rConfig.rPlayer[iPlayerNum].iUseOpeningBook, INI_NAME);
  597.     WritePrivateProfileLong(pszPlayerName, "UseGoodMoveSkipping", rConfig.rPlayer[iPlayerNum].lUseGoodMoveSkipping, INI_NAME);
  598.     WritePrivateProfileInt (pszPlayerName, "MaxRecursionDepth", rConfig.rPlayer[iPlayerNum].iMaxRecursionDepth, INI_NAME);
  599.     WritePrivateProfileInt (pszPlayerName, "UseAlphaBetaPruning", rConfig.rPlayer[iPlayerNum].iUseAlphaBetaPruning, INI_NAME);
  600.     WritePrivateProfileLong(pszPlayerName, "AlphaPruningOriginalDepth", rConfig.rPlayer[iPlayerNum].lAlphaPruningOriginalDepth, INI_NAME);
  601.     WritePrivateProfileLong(pszPlayerName, "AlphaPruningWidth", rConfig.rPlayer[iPlayerNum].lAlphaPruningWidth, INI_NAME);
  602.  
  603. }
  604.  
  605. VOID    WriteINI ()
  606. {
  607.     RECT    rect;
  608.     char    szTempStr[10];                       // For rect.value translation
  609.  
  610.     TraceTag(tagUI,"WriteINI()");
  611.  
  612.     // Store state of config radio buttons
  613.  
  614.     WritePrivateProfileInt ("Config", "GameType", rConfig.iGameType, INI_NAME);
  615.     WritePrivateProfileInt ("Config", "MustJump", rConfig.iMustJump, INI_NAME);
  616.     WritePrivateProfileInt ("Config", "SquareSize", rConfig.iSquareSize, INI_NAME);
  617.     WritePrivateProfileInt ("Config", "MaxMoves", rConfig.iMaxMoves, INI_NAME);
  618.  
  619.     // Write player info
  620.  
  621.     WritePlayerInfo(PLAYER1, "Player1");
  622.     WritePlayerInfo(PLAYER2, "Player2");
  623.  
  624.     // Store state of Window
  625.  
  626.     GetWindowRect (hMainWnd, &rect);
  627.     if (!IsIconic(hMainWnd))
  628.     {
  629.     wsprintf (szTempStr, "%d", rect.left);
  630.     WritePrivateProfileString ("Window", "Left", szTempStr, INI_NAME);
  631.     wsprintf (szTempStr, "%d", rect.top);
  632.     WritePrivateProfileString ("Window", "Top", szTempStr, INI_NAME);
  633.     wsprintf (szTempStr, "%d", rect.right - rect.left);
  634.     WritePrivateProfileString ("Window", "Width", szTempStr, INI_NAME);
  635.     wsprintf (szTempStr, "%d", rect.bottom - rect.top);
  636.     WritePrivateProfileString ("Window", "Height", szTempStr, INI_NAME);
  637.     }
  638.  
  639. }
  640.  
  641. BOOL InitApplication(HINSTANCE hInstance)
  642. {
  643.     WNDCLASS        wc;
  644.  
  645.     // Fill in window class structure with parameters that describe the
  646.     // main window.
  647.  
  648.     wc.style         = CS_HREDRAW | CS_VREDRAW;             // Class style(s).
  649.     wc.lpfnWndProc   = (WNDPROC)CheckersWndProc;    // Window Procedure
  650.     wc.cbClsExtra    = 0;                                   // No per-class extra data.
  651.     wc.cbWndExtra    = 0;                                   // No per-window extra data.
  652.     wc.hInstance     = hInstance;                           // Owner of this class
  653.     wc.hIcon         = LoadIcon (hInstance, "WCheckIcon");  // Icon name from .RC
  654.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);                 // Cursor
  655.     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);                    // Default color
  656.     wc.lpszMenuName  = (LPSTR)"WCheck_NORMAL";              // Menu name from .RC
  657.     wc.lpszClassName = szAppName;                                           // Name to register as
  658.  
  659.     // Register the window class and return success/failure code.
  660.     return (RegisterClass(&wc));
  661. }
  662.  
  663.  
  664. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  665. {
  666.     HWND    hWnd; // Main window handle.
  667.     HDC hdc = NULL;
  668.  
  669.     // Save the instance handle in static variable, which will be used in
  670.     // many subsequence calls from this application to Windows.
  671.  
  672.     // need to set this here because we may get call from somewhere besides winmain
  673.     hInst = hInstance; // Store instance handle in our global variable
  674.  
  675.     hbrWhite = (HBRUSH)GetStockObject(WHITE_BRUSH);
  676.     hbrBlack = (HBRUSH)GetStockObject(BLACK_BRUSH);
  677.  
  678.     hbrRed        = CreateSolidBrush(RGB(0xFF,0,0));
  679.     hbrBckgrnd    = CreateSolidBrush(GetNearestColor(hdc, RGB(0xAA,0xAA,0xAA)));
  680.     hbrBlue       = CreateSolidBrush(RGB(0,0,0xFF));
  681.     hpenDkgrey    = CreatePen( PS_SOLID, 1, RGB( 0x55, 0x55, 0x55 ) );
  682.  
  683.     #ifdef _WIN32
  684.         hbrDkgrey     = CreateSolidBrush(RGB(0x55,0x55,0x55));
  685.     #else
  686.         hbrDkgrey     = CreateSolidBrush(GetNearestColor(hdc, RGB(0x55,0x55,0x55)));
  687.     #endif
  688.  
  689.     // Fail initialization if we can't create brushs/pens/etc..
  690.  
  691.     if (!hbrRed || 
  692.         !hbrBckgrnd || 
  693.         !hbrBlue ||
  694.         !hbrWhite || 
  695.         !hbrBlack || 
  696.         !hpenDkgrey || 
  697.         !hbrDkgrey)
  698.     return(FALSE);
  699.  
  700.     curNormal   = LoadCursor(NULL, IDC_ARROW);
  701.     curThink    = LoadCursor(NULL, IDC_WAIT);
  702.     curResize       = LoadCursor(NULL, IDC_SIZENWSE);
  703.  
  704.     if (!curNormal || !curThink || !curResize)
  705.     return(FALSE);
  706.  
  707.     // Create a main window for this application instance.
  708.     hWnd = CreateWindow(
  709.         szAppName,           // See RegisterClass() call.
  710.         szTitle,             // Text for window title bar.
  711.         WS_OVERLAPPEDWINDOW, // Window style.
  712.     GetPrivateProfileInt ("Window", "Left",  13  /* CW_USEDEFAULT */, INI_NAME),
  713.     GetPrivateProfileInt ("Window", "Top",   8   /* CW_USEDEFAULT */, INI_NAME),
  714.     GetPrivateProfileInt ("Window", "Width", 356 /* CW_USEDEFAULT */, INI_NAME),
  715.     GetPrivateProfileInt ("Window", "Height",306 /* CW_USEDEFAULT */, INI_NAME),
  716.         NULL,                // Overlapped windows have no parent.
  717.         NULL,                // Use the window class menu.
  718.         hInstance,           // This instance owns this window.
  719.         NULL                 // We don't use any data in our WM_CREATE
  720.     );
  721.  
  722.     // If window could not be created, return "failure"
  723.     if (!hWnd) {
  724.         return (FALSE);
  725.     }
  726.  
  727.     while (!SetTimer (hWnd, ID_TIMER, TIMER_GRANULARITY, NULL))
  728.     {
  729.     if (IDCANCEL == MessageBox (hWnd, "Too many clocks or timers!", szAppName,
  730.         MB_ICONEXCLAMATION | MB_RETRYCANCEL))
  731.         {
  732.         return FALSE;
  733.         }
  734.     }
  735.  
  736.     // Make the window visible; update its client area; and return "success"
  737.  
  738.     ShowWindow(hWnd, nCmdShow); // Show the window // SW_SHOWNORMAL // SW_HIDE
  739.     UpdateWindow(hWnd);         // Sends WM_PAINT message
  740.  
  741.     SendMessage(hWnd, WM_OTHERINIT, 0, 0L);
  742.  
  743.     return (TRUE);              // We succeeded...
  744.  
  745. }
  746.  
  747. /****************************************************************************
  748. *****************************************************************************
  749. *****************************************************************************
  750. ****************************************************************************/
  751.  
  752. // FillBoard() puts the pieces on the board (draws them).
  753.  
  754. void NEAR PASCAL FillBoard(BOARD b, HDC hDC)
  755.  
  756. {
  757.     int         i                       = 0;            // Loop (for pieces) variable
  758.     HDC         hTmpDC          = NULL;         // Temp work DC
  759.     HBITMAP hOldbm              = NULL;         // Store old Bitmap handle
  760.     int         yBm             = 0;            // Bitmap to use (depending on piece)
  761.     int         iOffset         = 0;            // Squares alternate starting postion..
  762.     int         iX                      = 0;            // Location (x) to place square
  763.     int             iY                      = 0;            // Location (y) to place square
  764.     int     iLocation       = 0;            // For figuring real location after swap..
  765.  
  766.     hTmpDC = CreateCompatibleDC( hDC );
  767.     hOldbm = (HBITMAP)SelectObject( hTmpDC, hBtmaps );
  768.  
  769.     for (i=1; i <= 32; i++)
  770.     {
  771.         if (rConfig.iBoardFlipped)
  772.             iLocation = 33-i;
  773.         else
  774.             iLocation = i;
  775.             
  776.     AssertSz(iLocation > 0, "Bee-Gees r a bit");
  777.     AssertSz(iLocation <= SQRS_MAX, "Jello: The environmentally safe defoliant");
  778.  
  779.     switch(b[iLocation])
  780.     {
  781.         case 0:
  782.         yBm = 0;
  783.         break;
  784.         case (RED | KING):
  785.         yBm = OFST_COMPUTER_KING;
  786.         break;
  787.         case RED:
  788.         yBm = OFST_COMPUTER;
  789.         break;
  790.         case (BLACK | KING):
  791.         yBm = OFST_HUMAN_KING;
  792.         break;
  793.         case BLACK:
  794.         yBm = OFST_HUMAN;
  795.         break;
  796.         default:
  797.         {
  798.         AssertSz(FALSE, "Piece value invalid");
  799.         TraceTag(tagUI, "Invalid piece value of piece %d is: %d", i, b[i]);
  800.         }
  801.         break;
  802.     }
  803.  
  804.         // Calculate location of square on board. (offset?)
  805.  
  806.         iY = (i-1) / 4;
  807.         iX = (i-1) % 4;
  808.     if ((iY % 2) == 1)
  809.             iOffset = 0;
  810.         else
  811.             iOffset = 1;
  812.  
  813.         // Place the square on the board
  814.  
  815.         BitBlt( hDC, BOARD_LEFT + (rConfig.iSquareSize*(2*iX+iOffset)), BOARD_TOP + (rConfig.iSquareSize*iY),
  816.         rConfig.iSquareSize, rConfig.iSquareSize, hTmpDC, 0, yBm, SRCCOPY );
  817.  
  818.         // All squares have an accompanying blank square. Depending on the 
  819.         // offset, it can be on either side of the filled square.
  820.  
  821.         if (iOffset == 1)
  822.             BitBlt( hDC, BOARD_LEFT + (rConfig.iSquareSize*(2*iX)), BOARD_TOP + (rConfig.iSquareSize*iY),
  823.                 rConfig.iSquareSize, rConfig.iSquareSize, hTmpDC, 0, OFST_BLANK_RED, SRCCOPY);
  824.         else
  825.             BitBlt( hDC, BOARD_LEFT + (rConfig.iSquareSize*(2*iX+1)), BOARD_TOP + (rConfig.iSquareSize*iY),
  826.                 rConfig.iSquareSize, rConfig.iSquareSize, hTmpDC, 0, OFST_BLANK_RED, SRCCOPY);
  827.  
  828.     }
  829.  
  830.     // Draw setup rack if the user is in setup mode.
  831.  
  832.     if (rGameState.fSetupMode)
  833.     {
  834.  
  835.         BitBlt( hDC, BOARD_LEFT + (rConfig.iSquareSize * RACK_LEFT), 
  836.             BOARD_TOP + (rConfig.iSquareSize * (RACK_TOP)), 
  837.             rConfig.iSquareSize, rConfig.iSquareSize, 
  838.             hTmpDC, 0, OFST_COMPUTER, SRCCOPY);
  839.  
  840.         BitBlt( hDC, BOARD_LEFT + (rConfig.iSquareSize * RACK_LEFT), 
  841.             BOARD_TOP + (rConfig.iSquareSize * (RACK_TOP + 1)), 
  842.             rConfig.iSquareSize, rConfig.iSquareSize, 
  843.             hTmpDC, 0, OFST_HUMAN, SRCCOPY);
  844.  
  845.         BitBlt( hDC, BOARD_LEFT + (rConfig.iSquareSize * RACK_LEFT), 
  846.             BOARD_TOP + (rConfig.iSquareSize * (RACK_TOP + 2)), 
  847.             rConfig.iSquareSize, rConfig.iSquareSize, 
  848.             hTmpDC, 0, OFST_COMPUTER_KING, SRCCOPY);
  849.  
  850.         BitBlt( hDC, BOARD_LEFT + (rConfig.iSquareSize * RACK_LEFT), 
  851.             BOARD_TOP + (rConfig.iSquareSize * (RACK_TOP + 3)), 
  852.             rConfig.iSquareSize, rConfig.iSquareSize, 
  853.             hTmpDC, 0, OFST_HUMAN_KING, SRCCOPY);
  854.  
  855.         BitBlt( hDC, BOARD_LEFT + (rConfig.iSquareSize * RACK_LEFT), 
  856.             BOARD_TOP + (rConfig.iSquareSize * (RACK_TOP + 4)), 
  857.             rConfig.iSquareSize, rConfig.iSquareSize, 
  858.             hTmpDC, 0, OFST_BLANK, SRCCOPY);
  859.     }
  860.  
  861.     SelectObject( hTmpDC, hOldbm );
  862.     DeleteDC( hTmpDC );
  863. }
  864.  
  865. // Removes the piece that's moving, and replaces with a blank square.
  866.  
  867. void vClearMovingPiece(HDC hDC, int iX, int iY)
  868. {
  869.     HDC   hTmpDC;
  870.     HBITMAP hOldbm;
  871.     int   yBm;
  872.  
  873.     hTmpDC = CreateCompatibleDC( hDC );
  874.     hOldbm = (HBITMAP)SelectObject( hTmpDC, hBtmaps );
  875.  
  876.     yBm = 0;
  877.  
  878.     BitBlt( hDC, BOARD_LEFT + (rConfig.iSquareSize*iX), BOARD_TOP + (rConfig.iSquareSize*iY),
  879.     rConfig.iSquareSize, rConfig.iSquareSize, hTmpDC, 0, yBm, SRCCOPY );
  880.  
  881.     SelectObject( hTmpDC, hOldbm );
  882.     DeleteDC( hTmpDC );
  883. }
  884.  
  885. // Reset the board to starting positions.
  886. void ClearBoard(BOARD b)
  887. {
  888.     Assert(b);
  889.  
  890.     b[0]  = 0;          b[1]  = BLACK;  b[2]  = BLACK;  b[3] = BLACK;
  891.     b[4]  = BLACK;  b[5]  = BLACK;  b[6]  = BLACK;      b[7] = BLACK;
  892.     b[8]  = BLACK;  b[9]  = BLACK;  b[10] = BLACK;      b[11] = BLACK;
  893.     b[12] = BLACK;  b[13] = EMPTY;      b[14] = EMPTY;  b[15] = EMPTY;
  894.     b[16] = EMPTY;  b[17] = EMPTY;      b[18] = EMPTY;  b[19] = EMPTY;
  895.     b[20] = EMPTY;  b[21] = RED;        b[22] = RED;    b[23] = RED;
  896.     b[24] = RED;        b[25] = RED;    b[26] = RED;    b[27] = RED;
  897.     b[28] = RED;        b[29] = RED;    b[30] = RED;    b[31] = RED;
  898.     b[32] = RED;
  899. }
  900.  
  901. void DrawBoard(BOARD b)
  902. {
  903.     HDC hDC = GetDC(hMainWnd);
  904.     
  905.     Assert(b);
  906.  
  907.     FillBoard(b, hDC);
  908.     ReleaseDC(hMainWnd, hDC);
  909.  
  910. }
  911.  
  912. /****************************************************************************
  913. *****************************************************************************
  914. *****************************************************************************
  915. ****************************************************************************/
  916.  
  917. void DisplayGameOver(HWND hWnd, int iPlayerTurn)
  918. {
  919.     int iWinner = BLACK;
  920.  
  921.     AssertSz(hWnd, "hWnd hosed, homey.");
  922.     AssertSz((rGameState.iPlayerTurn == BLACK) || 
  923.              (rGameState.iPlayerTurn == RED), "Very low sodium");
  924.  
  925.     // NOTE: Caller is passing in the losing player. The turn has already
  926.     // switched before this gets called. This makes iPlayerTurn 
  927.     // equivalent to the winner in a give-away game. If the game type is 
  928.     // standard checkers, I want to invert winner.
  929.  
  930.     iWinner = iPlayerTurn;
  931.     if (rConfig.iGameType == GAME_CHECKERS)
  932.     iWinner = next(iWinner);
  933.     
  934.     if (RED == iWinner)
  935.         MessageBox(hWnd, "Game over. Red wins!", "Checkers", MB_OK );
  936.     else
  937.         MessageBox(hWnd, "Game over. Black wins!", "Checkers", MB_OK );
  938.  
  939. }
  940.  
  941. void DisplayGameDrawn(HWND hWnd, int iPlayerTurn)
  942. {
  943.     AssertSz(hWnd, "hWnd hosed (in DisplayGameDrawn), homey.");
  944.     AssertSz((rGameState.iPlayerTurn == BLACK) || 
  945.              (rGameState.iPlayerTurn == RED), "Vl bites");
  946.  
  947.     MessageBox(hWnd, "Game drawn. (Game over)", "Checkers", MB_OK );
  948. }
  949.  
  950.  
  951. /****************************************************************************
  952. *****************************************************************************
  953. *****************************************************************************
  954. ****************************************************************************/
  955.  
  956. void NEAR PASCAL CheckGenPieces(HDC hDC)
  957. {
  958.     HDC     hTmpDC  = NULL;
  959.     HBITMAP hOldbm  = NULL;
  960.     HBRUSH  hOldbr  = NULL;
  961.     int     i               = 0;
  962.  
  963.     AssertSz(hDC, "Null hDC in CheckGenPieces");
  964.  
  965.     if( hBtmaps != NULL )
  966.         DeleteObject( hBtmaps );
  967.  
  968.     // We have 6 different pieces (including the blank). So we just fill
  969.     // a region big enough for 6 squares.
  970.     hBtmaps = CreateCompatibleBitmap( hDC, SQR_XSIZE, 6*SQR_YSIZE );
  971.  
  972.     /* allocate an off-screen DC, so we can paint the ellipses now */
  973.     hTmpDC = CreateCompatibleDC( hDC );
  974.     hOldbm = (HBITMAP)SelectObject( hTmpDC, hBtmaps );
  975.  
  976.     /* blank out the off-screen bitmap, ie: paint the background into it */
  977.     hOldbr = (HBRUSH)SelectObject( hTmpDC, GetStockObject( LTGRAY_BRUSH ));
  978.     PatBlt( hTmpDC, 0, 0, SQR_XSIZE, SQR_YSIZE, PATCOPY );
  979.     SetBkMode( hTmpDC, TRANSPARENT );
  980.  
  981.     /* draw the square's "grooved" borders */
  982.     SelectObject( hTmpDC, hpenDkgrey );
  983.     MoveTo( hTmpDC, 2, SQR_YSIZE-2 );
  984.     LineTo( hTmpDC, SQR_XSIZE-2, SQR_YSIZE-2 );
  985.     LineTo( hTmpDC, SQR_XSIZE-2, 1 );
  986.     SelectObject( hTmpDC, GetStockObject( WHITE_PEN ) );
  987.     LineTo( hTmpDC, 1, 1 );
  988.     LineTo( hTmpDC, 1, SQR_YSIZE );
  989.     SelectObject( hTmpDC, GetStockObject( BLACK_PEN ) );
  990.     MoveTo( hTmpDC, 2, SQR_YSIZE-1 );
  991.     LineTo( hTmpDC, SQR_XSIZE-1, SQR_YSIZE-1 );
  992.     LineTo( hTmpDC, SQR_XSIZE-1, 0 );
  993.  
  994.     /* copy the borders to the other bitmaps */
  995.     for( i=OFST_INCREMENT; i <= OFST_HUMAN; i+=OFST_INCREMENT )
  996.     BitBlt(hTmpDC, 0, i, SQR_XSIZE, SQR_YSIZE, hTmpDC, 0, 0, SRCCOPY);
  997.  
  998.     /* Attempt at RED SQUARE*/
  999.     SelectObject( hTmpDC, hbrDkgrey );
  1000.     hOldbr = (HBRUSH)SelectObject( hTmpDC, GetStockObject( LTGRAY_BRUSH ));
  1001.     SelectObject( hTmpDC, hbrRed);
  1002.     PatBlt( hTmpDC, 0+2, OFST_BLANK_RED+2, SQR_XSIZE-4, SQR_YSIZE-4, PATCOPY );
  1003.  
  1004.     /* first piece: computer */
  1005.     SelectObject(hTmpDC, GetStockObject( WHITE_PEN ) );
  1006.     SelectObject(hTmpDC, GetStockObject( WHITE_BRUSH ) );
  1007.     Ellipse( hTmpDC, 3, OFST_COMPUTER+3, SQR_XSIZE-6, OFST_COMPUTER+SQR_YSIZE-6 );
  1008.     SelectObject(hTmpDC, hpenDkgrey );
  1009.     SelectObject(hTmpDC, hbrDkgrey );
  1010.     Ellipse( hTmpDC, 6, OFST_COMPUTER+6, SQR_XSIZE-3, OFST_COMPUTER+SQR_YSIZE-3 );
  1011.     SelectObject(hTmpDC, GetStockObject( BLACK_PEN ) );
  1012.     SelectObject(hTmpDC, hbrRed);
  1013.     Ellipse( hTmpDC, 4, OFST_COMPUTER+4, SQR_XSIZE-5, OFST_COMPUTER+SQR_YSIZE-5 );
  1014.  
  1015.     /* computer king */
  1016.     BitBlt( hTmpDC, 0, OFST_COMPUTER_KING, SQR_XSIZE, OFST_COMPUTER_KING+SQR_YSIZE, hTmpDC,
  1017.         0, OFST_COMPUTER, SRCCOPY );
  1018.     SelectObject( hTmpDC, GetStockObject( WHITE_PEN ) );
  1019.     MoveTo(hTmpDC, (SQR_XSIZE / 2 - 4), OFST_COMPUTER_KING + (SQR_YSIZE / 2));
  1020.     LineTo(hTmpDC, (SQR_XSIZE / 2 + 4), OFST_COMPUTER_KING + (SQR_YSIZE / 2));
  1021.     MoveTo(hTmpDC, (SQR_XSIZE / 2 - 4), OFST_COMPUTER_KING + (SQR_YSIZE / 2) + 1);
  1022.     LineTo(hTmpDC, (SQR_XSIZE / 2 + 4), OFST_COMPUTER_KING + (SQR_YSIZE / 2) + 1);
  1023.     MoveTo(hTmpDC, (SQR_XSIZE / 2 - 2), OFST_COMPUTER_KING + (SQR_YSIZE / 2) - 1);
  1024.     LineTo(hTmpDC, (SQR_XSIZE / 2 + 2), OFST_COMPUTER_KING + (SQR_YSIZE / 2) - 1);
  1025.  
  1026.     MoveTo(hTmpDC, (SQR_XSIZE / 2 - 4), OFST_COMPUTER_KING + (SQR_YSIZE / 2) - 1);
  1027.     LineTo(hTmpDC, (SQR_XSIZE / 2 - 6), OFST_COMPUTER_KING + (SQR_YSIZE / 2) - 3);
  1028.     MoveTo(hTmpDC, (SQR_XSIZE / 2 + 3), OFST_COMPUTER_KING + (SQR_YSIZE / 2) - 1);
  1029.     LineTo(hTmpDC, (SQR_XSIZE / 2 + 5), OFST_COMPUTER_KING + (SQR_YSIZE / 2) - 3);
  1030.     MoveTo(hTmpDC, (SQR_XSIZE / 2 - 2), OFST_COMPUTER_KING + (SQR_YSIZE / 2) - 2);
  1031.     LineTo(hTmpDC, (SQR_XSIZE / 2 - 3), OFST_COMPUTER_KING + (SQR_YSIZE / 2) - 4);
  1032.     MoveTo(hTmpDC, (SQR_XSIZE / 2 + 1), OFST_COMPUTER_KING + (SQR_YSIZE / 2) - 2);
  1033.     LineTo(hTmpDC, (SQR_XSIZE / 2 + 3), OFST_COMPUTER_KING + (SQR_YSIZE / 2) - 4);
  1034.  
  1035.     /* human king */
  1036.     BitBlt( hTmpDC, 0, OFST_HUMAN_KING, SQR_XSIZE, OFST_HUMAN_KING+SQR_YSIZE, hTmpDC,
  1037.     0, OFST_COMPUTER, SRCCOPY );
  1038.     SelectObject(hTmpDC, hbrBlack);
  1039.     SelectObject(hTmpDC, GetStockObject( BLACK_PEN ) );
  1040.     Ellipse( hTmpDC, 4, OFST_HUMAN_KING+4, SQR_XSIZE-5, OFST_HUMAN_KING+SQR_YSIZE-5 );
  1041.     SelectObject( hTmpDC, GetStockObject( WHITE_PEN ) );
  1042.     SelectObject( hTmpDC, GetStockObject( WHITE_PEN ) );
  1043.     MoveTo(hTmpDC, (SQR_XSIZE / 2 - 4), OFST_HUMAN_KING + (SQR_YSIZE / 2));
  1044.     LineTo(hTmpDC, (SQR_XSIZE / 2 + 4), OFST_HUMAN_KING + (SQR_YSIZE / 2));
  1045.     MoveTo(hTmpDC, (SQR_XSIZE / 2 - 4), OFST_HUMAN_KING + (SQR_YSIZE / 2) + 1);
  1046.     LineTo(hTmpDC, (SQR_XSIZE / 2 + 4), OFST_HUMAN_KING + (SQR_YSIZE / 2) + 1);
  1047.     MoveTo(hTmpDC, (SQR_XSIZE / 2 - 2), OFST_HUMAN_KING + (SQR_YSIZE / 2) - 1);
  1048.     LineTo(hTmpDC, (SQR_XSIZE / 2 + 2), OFST_HUMAN_KING + (SQR_YSIZE / 2) - 1);
  1049.  
  1050.     MoveTo(hTmpDC, (SQR_XSIZE / 2 - 4), OFST_HUMAN_KING + (SQR_YSIZE / 2) - 1);
  1051.     LineTo(hTmpDC, (SQR_XSIZE / 2 - 6), OFST_HUMAN_KING + (SQR_YSIZE / 2) - 3);
  1052.     MoveTo(hTmpDC, (SQR_XSIZE / 2 + 3), OFST_HUMAN_KING + (SQR_YSIZE / 2) - 1);
  1053.     LineTo(hTmpDC, (SQR_XSIZE / 2 + 5), OFST_HUMAN_KING + (SQR_YSIZE / 2) - 3);
  1054.     MoveTo(hTmpDC, (SQR_XSIZE / 2 - 2), OFST_HUMAN_KING + (SQR_YSIZE / 2) - 2);
  1055.     LineTo(hTmpDC, (SQR_XSIZE / 2 - 3), OFST_HUMAN_KING + (SQR_YSIZE / 2) - 4);
  1056.     MoveTo(hTmpDC, (SQR_XSIZE / 2 + 1), OFST_HUMAN_KING + (SQR_YSIZE / 2) - 2);
  1057.     LineTo(hTmpDC, (SQR_XSIZE / 2 + 3), OFST_HUMAN_KING + (SQR_YSIZE / 2) - 4);
  1058.     
  1059.     /* human */
  1060.     BitBlt( hTmpDC, 0, OFST_HUMAN, SQR_XSIZE, SQR_YSIZE, hTmpDC,
  1061.     0, OFST_COMPUTER, SRCCOPY );
  1062.     SelectObject(hTmpDC, GetStockObject( BLACK_PEN ) );
  1063.     SelectObject(hTmpDC, hbrBlack);
  1064.     Ellipse( hTmpDC, 4, OFST_HUMAN+4, SQR_XSIZE-5, OFST_HUMAN+SQR_YSIZE-5 );
  1065.  
  1066.     SelectObject( hTmpDC, hOldbr );
  1067.     SelectObject( hTmpDC, hOldbm );
  1068.     DeleteDC( hTmpDC );
  1069. }
  1070.  
  1071. /****************************************************************************
  1072. *****************************************************************************
  1073. *****************************************************************************
  1074. ****************************************************************************/
  1075.  
  1076. void NEAR PASCAL CheckCreate()
  1077.  
  1078. {
  1079.     HDC  hDC;
  1080.     TEXTMETRIC    charsize;           /* characteristics of the characters */
  1081.     int COLOR = 1;
  1082.  
  1083.     hDC = GetDC(hMainWnd);
  1084.     GetTextMetrics(hDC, (LPTEXTMETRIC)&charsize);
  1085.  
  1086.     ReleaseDC(hMainWnd, hDC);
  1087.  
  1088.     COLOR = GetDeviceCaps(hDC, NUMCOLORS) > 2;
  1089.  
  1090.     if (COLOR == TRUE)
  1091.     {
  1092.     hbrComputer = hbrBlue;
  1093.     hbrHuman = hbrRed;
  1094.     }
  1095.     else
  1096.     {
  1097.     hbrComputer = hbrBlack;
  1098.     hbrHuman = hbrWhite;
  1099.     }
  1100. }
  1101.  
  1102. /****************************************************************************
  1103. *****************************************************************************
  1104. *****************************************************************************
  1105. ****************************************************************************/
  1106.  
  1107. /* Called on WM_PAINT messages. */
  1108.  
  1109. void NEAR PASCAL CheckPaint(BOARD b, HDC hDC)
  1110.  
  1111. {
  1112.     CheckGenPieces(hDC);
  1113.     SetBkMode(hDC, OPAQUE);
  1114.  
  1115.     DrawBoard(b);
  1116. }
  1117.  
  1118. /****************************************************************************
  1119. *****************************************************************************
  1120. *****************************************************************************
  1121. ****************************************************************************/
  1122.  
  1123. void inline vTranslateCurPosToSquare(POINT pntCur, int *pix, int *piy)
  1124. {
  1125.     Assert(pix);
  1126.     Assert(piy);
  1127.     Assert(rConfig.iSquareSize != 0);
  1128.  
  1129.     *pix = (pntCur.x - BOARD_LEFT) / rConfig.iSquareSize;
  1130.     *piy = (pntCur.y - BOARD_TOP) / rConfig.iSquareSize;
  1131.  
  1132.     if ((*pix < 0) || (*pix > 7) || (*piy < 0) || (*piy > 7))
  1133.     {
  1134.         if ((!rGameState.fSetupMode) || (*pix != 10) || (*piy < 2) || (*piy > 6))
  1135.         {
  1136.             *pix = -1;              // Return invalid x/y locations
  1137.             *piy = -1;              // Return invalid x/y locations
  1138.         }
  1139.     }
  1140. }
  1141.  
  1142. void inline vTranslateUIToEngineSquare(int *piEngine, int iX, int iY)
  1143. {
  1144.     AssertSz(piEngine, "piEngine == NULL");
  1145.  
  1146.     if (((iY + iX) % 2 == 0) ||
  1147.     (iY < 0) || (iY > 7) || (iX < 0) || (iX > 7))
  1148.     {
  1149.     *piEngine = -1;         // Return invalid engine ID
  1150.         return;
  1151.     }
  1152.     else
  1153.     {
  1154.     *piEngine = iY * 4 + (iX / 2) + 1;
  1155.     }
  1156.  
  1157.     if (rConfig.iBoardFlipped)
  1158.         *piEngine = (33 - *piEngine);
  1159. }
  1160.  
  1161. void inline vTranslateEngineToUISquare(int iEngine, int *piX, int *piY)
  1162. {
  1163.     Assert(iEngine > 0);
  1164.     Assert(piX);
  1165.     Assert(piY);
  1166.  
  1167.     if (rConfig.iBoardFlipped)
  1168.         iEngine = (33 - iEngine);
  1169.     
  1170.     *piY = (iEngine - 1) / 4;
  1171.     *piX = ((iEngine - 1) % 4) * 2 + ((*piY + 1) % 2);
  1172. }                           
  1173.  
  1174. /****************************************************************************
  1175. *****************************************************************************
  1176. *****************************************************************************
  1177. ****************************************************************************/
  1178.  
  1179. BOOL fValidSetupPiece(BOARD b, int ix, int iy)
  1180. {
  1181.     int iEngine = -1;
  1182.     int iPiece  = -1;
  1183.     BOOL fRackPiece = FALSE;
  1184.  
  1185.     AssertSz(b, "Where's the board");
  1186.  
  1187.     if ((ix < 0) || (ix > 7) || (iy < 0) || (iy > 7))
  1188.     {
  1189.         // Check for Setup Rack pieces
  1190.  
  1191.         if ((ix != 10) || (iy < 2) || (iy > 6))
  1192.             return FALSE;
  1193.         else
  1194.             fRackPiece = TRUE;
  1195.     }
  1196.     
  1197.     vTranslateUIToEngineSquare(&iEngine, ix, iy);
  1198.  
  1199.     AssertSz((iEngine == -1) || 
  1200.          ((iEngine > 0) && (iEngine <= SQRS_MAX)), 
  1201.              "iEngine needs counseling");
  1202.     
  1203.     if (iEngine != -1)
  1204.     {
  1205.         iPiece = (int) b[iEngine];
  1206.  
  1207.         if ((iPiece & RED) || (iPiece & BLACK) || (iPiece == EMPTY))
  1208.             return TRUE;
  1209.         else
  1210.             return FALSE;
  1211.     }
  1212.     else
  1213.     {
  1214.         if (!fRackPiece)
  1215.             return FALSE;
  1216.         else
  1217.             return TRUE;
  1218.     }
  1219.  
  1220. }
  1221.  
  1222. BOOL fValidPlayerPiece(BOARD b, int ix, int iy)
  1223. {
  1224.     int iEngine = 0;
  1225.     int iPiece = 0;
  1226.  
  1227.     AssertSz(b, "Where's the board?");
  1228.     AssertSz(((rGameState.iPlayerTurn == RED) || 
  1229.           (rGameState.iPlayerTurn == BLACK)), "Harrison");
  1230.     
  1231.     if ((ix < 0) || (ix > 7) || (iy < 0) || (iy > 7))
  1232.     return FALSE;
  1233.  
  1234.     vTranslateUIToEngineSquare(&iEngine, ix, iy);
  1235.  
  1236.     // Assert that the engine return is either a "normal" invalid, or
  1237.     // a normal engine square. Should NOT be 0.
  1238.  
  1239.     AssertSz((iEngine == -1) || 
  1240.          ((iEngine > 0) && (iEngine <= SQRS_MAX)), 
  1241.              "Abort, Retry, Fail?");
  1242.     
  1243.     if (iEngine != -1)
  1244.     iPiece = (int) b[iEngine];
  1245.     else
  1246.         return FALSE;
  1247.  
  1248.     if (RED == rGameState.iPlayerTurn)
  1249.     {
  1250.     if (iPiece & RED)
  1251.         return TRUE;
  1252.     else
  1253.         return FALSE;
  1254.     }
  1255.     else 
  1256.     {
  1257.         if (BLACK == rGameState.iPlayerTurn)
  1258.     {
  1259.         if (iPiece & BLACK)
  1260.         return TRUE;
  1261.         else
  1262.         return FALSE;
  1263.         }
  1264.     else
  1265.         {
  1266.         AssertSz(FALSE, "rGameState.iPlayerTurn invalid!");
  1267.         return FALSE;
  1268.     }
  1269.     }
  1270. }
  1271.  
  1272.  
  1273. /****************************************************************************
  1274. *****************************************************************************
  1275. *****************************************************************************
  1276. ****************************************************************************/
  1277.  
  1278. void OnGamePlayableAfterMove(void)
  1279. {
  1280.     if (pfrm)
  1281.     {
  1282.     AssertSz(pfrm->pMessage,"no message to send");
  1283.  
  1284.     // ----- Update our forms information based on user interaction
  1285.     pfrm->SetCheckersData(b,rGameState.iPlayerTurn,0,QualityOfBoard(b,rGameState.iPlayerTurn));
  1286.  
  1287.     // ----- Send this baby, and shut her down
  1288.     SetWindowText(hMainWnd,"Sending ...");
  1289.     pfrm->SendForm();
  1290.     pfrm->ShutdownForm(OLECLOSE_NOSAVE);
  1291.     }
  1292. }
  1293.  
  1294. /****************************************************************************
  1295. *****************************************************************************
  1296. *****************************************************************************
  1297. ****************************************************************************/
  1298. // Handle WM_INITMENU message.
  1299.  
  1300. VOID vHandle_WM_INITMENU(HWND hWnd, HMENU hMenu)
  1301. {
  1302.     hMenu = GetMenu(hWnd);
  1303.     if (rGameState.fThinking)
  1304.     {
  1305.     EnableMenuItem(hMenu, 0, MF_DISABLED | MF_BYPOSITION);
  1306.     EnableMenuItem(hMenu, 1, MF_DISABLED | MF_BYPOSITION);
  1307.     }
  1308.     else
  1309.     {
  1310.     EnableMenuItem(hMenu, 0, MF_ENABLED | MF_BYPOSITION);
  1311.     EnableMenuItem(hMenu, 1, MF_ENABLED | MF_BYPOSITION);
  1312.     }
  1313. }
  1314.  
  1315. BOOL fHandle_WM_CREATE(HWND hWnd, CREATESTRUCT FAR* lpCreateStruct)
  1316. {
  1317.     HDC         hDC     = NULL;
  1318.     HMENU       hm              = NULL;
  1319.  
  1320.     hMainWnd = hWnd;
  1321.     ReadINI();
  1322.  
  1323.     // Set game state variables.
  1324.  
  1325.     rGameState.fSetupMode = FALSE;          // Game in setup mode? Need for button processing
  1326.     rGameState.fThinking = FALSE;           // Is the computer thinking?
  1327.     rGameState.fPaused = FALSE;             // Is the game paused?
  1328.     rGameState.fGameInProgress = FALSE;     // Did the game start? How to react to "File:New"
  1329.     rGameState.fLMouseButtonDown = FALSE;   // Is the left mouse-button currently down?
  1330.     rGameState.fRMouseButtonDown = FALSE;   // Is the left mouse-button currently down?
  1331.     rGameState.fMoveInProgress = FALSE;     // Is the user in the middle of a move?
  1332.     rGameState.fComputerBusy = FALSE;               // Is the computer thinking?
  1333.     rGameState.fGameOver = FALSE;                   // Is the game over?
  1334.     rGameState.fInitDone = FALSE;                   // Is initialization done?
  1335.     rGameState.iPlayerTurn = BLACK;
  1336.     rGameState.iCursorState = NORMAL_CURSOR;        // What state is the cursor in?
  1337.     rGameState.fMouseResizeInProgress = FALSE;      // Is the user resizing right now?
  1338.     rConfig.iSetupPurgeBoards = TRUE;               // Purge boards when exit setup?
  1339.     
  1340.     CMoves.Init();
  1341.     CheckCreate();
  1342.     hDC = GetDC(hWnd);
  1343.     ClearBoard(b);
  1344.     CMoves.NewMove(b, rGameState.iPlayerTurn);
  1345.     FillBoard(b, hDC);
  1346.  
  1347.     hm = GetMenu(hWnd);
  1348.     if (!rConfig.iBoardFlipped)
  1349.     {
  1350.         CheckMenuItem(hm, IDM_FLIP, MF_CHECKED);
  1351.     }
  1352.  
  1353.     CheckMenuItem(hm, IDM_BASE_LEVEL + rConfig.rPlayer[RED].iMaxRecursionDepth, MF_CHECKED);
  1354.  
  1355.     switch(rConfig.iGameType)
  1356.     {
  1357.     case GAME_CHECKERS:
  1358.         CheckMenuItem(hm, IDM_GAME_CHECKERS, MF_CHECKED);
  1359.         CheckMenuItem(hm, IDM_GAME_GIVEAWAY, MF_UNCHECKED);
  1360.         break;
  1361.     case GAME_GIVEAWAY:
  1362.         CheckMenuItem(hm, IDM_GAME_GIVEAWAY, MF_CHECKED);
  1363.         CheckMenuItem(hm, IDM_GAME_CHECKERS, MF_UNCHECKED);
  1364.         break;
  1365.     default:
  1366.         // Set to checkers, assert if debug
  1367.         CheckMenuItem(hm, IDM_GAME_CHECKERS, MF_CHECKED);
  1368.         CheckMenuItem(hm, IDM_GAME_GIVEAWAY, MF_UNCHECKED);
  1369.         MessageBox(hWnd, "Game type invalid. Setting to checkers", "Checkers", MB_OK);
  1370.         rConfig.iGameType = GAME_CHECKERS;
  1371.         break;
  1372.     }
  1373.  
  1374.     // Load "Piece" cursor.
  1375.  
  1376.     curPiece   = LoadCursor(hInst, "PieceCur");
  1377.     if (curPiece)
  1378.     TraceTag(tagUI, "Cur Piece is valid");
  1379.     else
  1380.     TraceTag(tagUI, "Cur Piece is invalid");
  1381.  
  1382.     return TRUE;
  1383.  
  1384. }
  1385.  
  1386. VOID vHandle_WM_DESTROY(HWND hWnd)
  1387. {
  1388.     WriteINI();
  1389.  
  1390.     if (pfrm)
  1391.     {
  1392.         FRM *pfrml; //$FORM
  1393.         pfrml = pfrm;
  1394.         pfrm = NULL;
  1395.         pfrml->ShutdownForm(OLECLOSE_NOSAVE);
  1396.         pfrml->Release();
  1397.     }
  1398.  
  1399.     DeleteObject(hbrBckgrnd);
  1400.     DeleteObject(hbrRed);
  1401.     DeleteObject(hbrBlue);
  1402.     DeleteObject(hbrDkgrey);
  1403.     DeleteObject(hpenDkgrey);
  1404.     DeleteObject(hBtmaps);
  1405.  
  1406.     // WinHelp(hWnd, (LPSTR)szHelpFile, HELP_QUIT, 0L);
  1407.  
  1408.     PostQuitMessage(0);
  1409. }
  1410.  
  1411. VOID vHandle_WM_TIMER(HWND hWnd, UINT id)
  1412. {
  1413.     #ifdef DEBUG
  1414.     static int x=0;
  1415.     if (0==x)
  1416.     {
  1417.     if (!((BLACK == rGameState.iPlayerTurn) ||
  1418.       (RED == rGameState.iPlayerTurn))) x++;
  1419.     AssertSz(((BLACK == rGameState.iPlayerTurn) || 
  1420.           (RED == rGameState.iPlayerTurn)), 
  1421.           "Caffeine-Free? What's the point?");
  1422.     }
  1423.     #endif
  1424.     
  1425.     if ((rConfig.rPlayer[rGameState.iPlayerTurn].iPlayerType == COMPUTER_PLAYER) &&
  1426.         (rGameState.fInitDone) && 
  1427.         (!rGameState.fPaused) && 
  1428.         (!rGameState.fComputerBusy) &&
  1429.         (!rGameState.fGameOver))
  1430.     {
  1431.     ComputerMove();
  1432.     }
  1433. }
  1434.  
  1435. VOID vHandle_WM_RBUTTONDOWN(HWND hWnd, BOOL fDoubleClick, int x, int y, UINT keyFlags)
  1436. {
  1437.     AssertSz(!rGameState.fRMouseButtonDown, "David Copperfield with a mouse");
  1438.     TraceTag(tagMouse, "in vHandle_WM_RBUTTONDOWN");
  1439.     TraceTag(tagMouse, "rGameState.fRMouseButtonDown: %d", rGameState.fRMouseButtonDown);
  1440.  
  1441.     if (!rGameState.fLMouseButtonDown)
  1442.     {
  1443.         SetCapture(hWnd);
  1444.  
  1445.         if (rGameState.fSetupMode)
  1446.             SetupRButtonDown(hWnd, keyFlags, x, y);
  1447.         else
  1448.         {
  1449.         // No-op.
  1450.         }    
  1451.     }
  1452.     else
  1453.     {
  1454.     // No-op.
  1455.     }
  1456.     
  1457.  
  1458. }
  1459.  
  1460. VOID vHandle_WM_LBUTTONDOWN(HWND hWnd, BOOL fDoubleClick, int x, int y, UINT keyFlags)
  1461. {
  1462.     AssertSz(!rGameState.fLMouseButtonDown, "How'd you do that?");
  1463.  
  1464.     TraceTag(tagMouse, "in vHandle_WM_LBUTTONDOWN");
  1465.     TraceTag(tagMouse, "rGameState.fLMouseButtonDown: %d", rGameState.fLMouseButtonDown);
  1466.     TraceTag(tagMouse, "rGameState.fRMouseButtonDown: %d", rGameState.fRMouseButtonDown);
  1467.  
  1468.     SetCapture(hWnd);
  1469.  
  1470.     switch (rGameState.iCursorState)
  1471.     {
  1472.         case NORMAL_CURSOR:
  1473.             TraceTag(tagMouse, "Move LButtonDown");
  1474.             if (!rGameState.fRMouseButtonDown)
  1475.             {
  1476.                 SetCapture(hWnd);
  1477.  
  1478.                 if (rGameState.fSetupMode)
  1479.                 SetupLButtonDown(hWnd, keyFlags, x, y);
  1480.                 else
  1481.                 {
  1482.                     AssertSz(((BLACK == rGameState.iPlayerTurn) || 
  1483.                         (RED == rGameState.iPlayerTurn)), 
  1484.                         "Just how often am I going to check this?");
  1485.  
  1486.                     if ((!rGameState.fGameOver) &&
  1487.                     (HUMAN_PLAYER == rConfig.rPlayer[rGameState.iPlayerTurn].iPlayerType))
  1488.                     NormalLButtonDown(hWnd, keyFlags, x, y);
  1489.                 }    
  1490.             }
  1491.             else
  1492.             {
  1493.                 // NO-OP if other button already down
  1494.             }
  1495.             break;
  1496.  
  1497.         case RESIZE_CURSOR:
  1498.         {
  1499.             TraceTag(tagMouse, "Resize LButtonDown");
  1500.             rGameState.fMouseResizeInProgress = TRUE;
  1501.         }
  1502.     }               // end switch
  1503.         
  1504. }
  1505.  
  1506.  
  1507. VOID vHandle_WM_LBUTTONUP(HWND hWnd, int x, int y, UINT keyFlags)
  1508. {
  1509.     TraceTag(tagMouse, "in vHandle_WM_LBUTTONUP");
  1510.  
  1511.     TraceTag(tagMouse, "rGameState.fLMouseButtonDown: %d", rGameState.fLMouseButtonDown);
  1512.     TraceTag(tagMouse, "rGameState.fRMouseButtonDown: %d", rGameState.fRMouseButtonDown);
  1513.  
  1514.     ReleaseCapture();
  1515.     
  1516.     if (rGameState.fMouseResizeInProgress)
  1517.     {
  1518.         rGameState.fMouseResizeInProgress = FALSE;
  1519.     }
  1520.     else
  1521.     {
  1522.         if (rGameState.fSetupMode)
  1523.             SetupLButtonUp(hWnd, keyFlags, x, y);
  1524.         else
  1525.             if (!rGameState.fGameOver)
  1526.             NormalLButtonUp(hWnd, keyFlags, x, y);
  1527.     }
  1528. }
  1529.  
  1530. VOID vHandle_WM_RBUTTONUP(HWND hWnd, int x, int y, UINT keyFlags)
  1531. {
  1532.  
  1533.     TraceTag(tagMouse, "in vHandle_WM_RBUTTONUP");
  1534.  
  1535.     TraceTag(tagMouse, "rGameState.fLMouseButtonDown: %d", rGameState.fLMouseButtonDown);
  1536.     TraceTag(tagMouse, "rGameState.fRMouseButtonDown: %d", rGameState.fRMouseButtonDown);
  1537.  
  1538.     ReleaseCapture();
  1539.     if (rGameState.fSetupMode)
  1540.     SetupRButtonUp(hWnd, keyFlags, x, y);
  1541.     else
  1542.     {
  1543.     // NO-OP
  1544.     }
  1545. }
  1546.  
  1547. VOID vHandle_WM_MOUSEMOVE(HWND hWnd, int x, int y, UINT keyFlags)
  1548. {
  1549.  
  1550.     TraceTag(tagMouse, "in vHandle_WM_MOUSEMOVE. Mouse position: x:%d  y:%d", x, y);
  1551.  
  1552.     if (rGameState.fRMouseButtonDown)
  1553.     {
  1554.         // NO-OP
  1555.     }
  1556.     else
  1557.     {
  1558.         if (rGameState.fLMouseButtonDown)
  1559.         {
  1560.             // NO-OP: Should be the actual mouse resize code.
  1561.         }
  1562.         else
  1563.         {
  1564.             if (rGameState.fMouseResizeInProgress)
  1565.             {
  1566.                 int iNewBoardSize = 0;
  1567.                 int iNewSquareSize = 0;
  1568.                 HDC hDC = 0;
  1569.                 RECT rectInvalidate;
  1570.  
  1571.                 TraceTag(tagMouse, "End of mouse resize");
  1572.         
  1573.                 iNewBoardSize = ((x - BOARD_LEFT) + (y - BOARD_TOP)) / 2;
  1574.                 TraceTag(tagMouse, "iNewBoardSize: %d", iNewBoardSize);
  1575.  
  1576.                 iNewSquareSize = iNewBoardSize / 8;
  1577.  
  1578.                 AssertSz(MAX_SQUARE_SIZE >= MIN_SQUARE_SIZE, "Max < Min. Duh.");
  1579.         
  1580.                 if (iNewSquareSize < MIN_SQUARE_SIZE)
  1581.                     iNewSquareSize = MIN_SQUARE_SIZE;
  1582.  
  1583.                 if (iNewSquareSize > MAX_SQUARE_SIZE)
  1584.                     iNewSquareSize = MAX_SQUARE_SIZE;
  1585.  
  1586.                 if (iNewSquareSize != rConfig.iSquareSize)
  1587.                 {
  1588.                     rectInvalidate.left             = BOARD_LEFT;
  1589.                     rectInvalidate.right    = BOARD_LEFT + rConfig.iSquareSize*13;
  1590.                     rectInvalidate.top              = BOARD_TOP;
  1591.                     rectInvalidate.bottom   = BOARD_TOP + rConfig.iSquareSize*8;
  1592.  
  1593.                     InvalidateRect(hWnd, &rectInvalidate, TRUE);
  1594.                     hDC = GetDC(hWnd);
  1595.                     rConfig.iSquareSize = iNewSquareSize;
  1596.                 CheckGenPieces(hDC);
  1597.                     UpdateWindow(hWnd);
  1598.                 DrawBoard(b);    
  1599.                 }
  1600.                 
  1601.                 SetCursor(curResize);
  1602.                 TraceTag(tagMouse, "Resize now: x: %d, y: %d", x, y);
  1603.             }
  1604.             else
  1605.             {
  1606.                 // User is in normal play/setup mode. No mouse down. We want to 
  1607.                 // change the cursor based on whether we're scanning over pieces
  1608.                 // or over the "resize" area.
  1609.  
  1610.                 switch(rGameState.iCursorState)
  1611.                 {
  1612.                     case NORMAL_CURSOR:
  1613.                         if ((x > BOARD_LEFT + rConfig.iSquareSize*8 - RESIZE_RANGE) && 
  1614.                         (x < BOARD_LEFT + rConfig.iSquareSize*8 + RESIZE_RANGE) &&
  1615.                             (y > BOARD_TOP + rConfig.iSquareSize*8 - RESIZE_RANGE) &&
  1616.                             (y < BOARD_TOP + rConfig.iSquareSize*8 + RESIZE_RANGE))
  1617.                         {
  1618.                             TraceTag(tagMouse, "Setting RESIZE_CURSOR");
  1619.                             SetCursor(curResize);
  1620.                             rGameState.iCursorState = RESIZE_CURSOR;
  1621.                         }
  1622.                         else
  1623.                         {
  1624.                             SetCursor(curNormal);
  1625.                         }
  1626.                         break;
  1627.     
  1628.                     case RESIZE_CURSOR:
  1629.                         if ((x < BOARD_LEFT + rConfig.iSquareSize*8 - RESIZE_RANGE) ||
  1630.                         (x > BOARD_LEFT + rConfig.iSquareSize*8 + RESIZE_RANGE) ||
  1631.                             (y < BOARD_TOP + rConfig.iSquareSize*8 - RESIZE_RANGE) ||
  1632.                             (y > BOARD_TOP + rConfig.iSquareSize*8 + RESIZE_RANGE))
  1633.                         {
  1634.                             TraceTag(tagMouse, "Setting NORMAL_CURSOR");
  1635.                             SetCursor(curNormal);
  1636.                             rGameState.iCursorState = NORMAL_CURSOR;
  1637.                         }
  1638.                         else
  1639.                         {
  1640.                             SetCursor(curResize);
  1641.                         }
  1642.                         break;
  1643.                     default:
  1644.                         AssertSz(FALSE, "Forest AND the trees");
  1645.                         break;
  1646.                 }                                                       // end switch
  1647.             }                                                               // end else fMouseResizeInProgress
  1648.         }                                                                       // end else fLMouseButtonDown
  1649.     }                                                                               // end else fRMouseButtonDown
  1650. }
  1651.  
  1652. VOID vHandle_WM_PAINT(HWND hWnd)
  1653. {
  1654.     PAINTSTRUCT ps;
  1655.  
  1656.     BeginPaint(hWnd, (LPPAINTSTRUCT)&ps);
  1657.     CheckPaint(b, ps.hdc);
  1658.     EndPaint(hWnd, (LPPAINTSTRUCT)&ps);
  1659. }
  1660.  
  1661. VOID vHandle_WM_VSCROLL(HWND hWnd, HWND hWndCtl, UINT code, int pos)
  1662. {
  1663.     AssertSz(FALSE, "When did I start getting VSCROLL messages?");
  1664. }
  1665.  
  1666. VOID vHandle_WM_HSCROLL(HWND hWnd, HWND hWndCtl, UINT code, int pos)
  1667. {
  1668.     AssertSz(FALSE, "When did I start getting HSCROLL messages?");
  1669. }
  1670.  
  1671. VOID vHandle_WM_GETMINMAXINFO(HWND hWnd, MINMAXINFO FAR * lpMinMaxInfo)
  1672. {
  1673.     // NO-OP
  1674. }
  1675.  
  1676. VOID vHandle_WM_COMMAND(HWND hWnd, int wmId, HWND hwndCtl, UINT wmEvent)
  1677. {
  1678.     // Used by various commands
  1679.  
  1680.     FARPROC lpProcDialog = NULL;
  1681.     int iDialogBoxResult = -1;
  1682.     RECT rectInvalidate;
  1683.     HDC hDC = NULL;
  1684.     HMENU hm = NULL;
  1685.  
  1686.     switch (wmId)
  1687.     {
  1688.     #ifdef NEVER
  1689.     case IDM_FILENEW:
  1690.     {
  1691.         int iResponse;
  1692.  
  1693.         iResponse = MessageBox(hWnd, "You have asked to start " \
  1694.         "a new game. Note, this will end your current game. " \
  1695.         "Would you like to save your game first?", "New Game?",
  1696.         MB_YESNOCANCEL | MB_DEFBUTTON2 | MB_ICONQUESTION);
  1697.  
  1698.         switch (iResponse)
  1699.         {
  1700.         case IDYES:
  1701.             SaveAsBoard(b);
  1702.             // We mean to fall through to the IDNO case below
  1703.  
  1704.         case IDNO:
  1705.             ClearBoard(b);
  1706.             CMoves.ClearBoards();
  1707.                     rGameState.fGameOver = FALSE;
  1708.                     rGameState.iPlayerTurn = BLACK;
  1709.                     CMoves.NewMove(b, rGameState.iPlayerTurn);
  1710.             DrawBoard(b);
  1711.             break;
  1712.  
  1713.         case IDCANCEL:
  1714.                     DrawBoard(b);
  1715.             break;
  1716.         }
  1717.         break;
  1718.     }
  1719.     #endif //never
  1720.  
  1721.     case IDM_SAVE:
  1722.         NYI("IDM_SAVE");
  1723.         break;
  1724.  
  1725.     case IDM_GAME_CHECKERS:
  1726.         if (rConfig.iGameType != GAME_CHECKERS)
  1727.         {
  1728.         hm = GetMenu(hWnd);
  1729.         CheckMenuItem(hm, IDM_GAME_CHECKERS, MF_CHECKED);
  1730.         CheckMenuItem(hm, IDM_GAME_GIVEAWAY, MF_UNCHECKED);
  1731.         rConfig.iGameType = GAME_CHECKERS;
  1732.         }
  1733.         break;
  1734.  
  1735.     case IDM_GAME_GIVEAWAY:
  1736.         if (rConfig.iGameType != GAME_GIVEAWAY)
  1737.         {
  1738.         hm = GetMenu(hWnd);
  1739.         CheckMenuItem(hm,IDM_GAME_CHECKERS,MF_UNCHECKED);
  1740.         CheckMenuItem(hm,IDM_GAME_GIVEAWAY,MF_CHECKED);
  1741.         rConfig.iGameType = GAME_GIVEAWAY;
  1742.         }
  1743.         break;
  1744.  
  1745.     case IDM_SETUP_BOARD:
  1746.  
  1747.         SetMenu(hWnd, LoadMenu(hInst, "WCheck_SETUP"));
  1748.         rGameState.fSetupMode = TRUE;
  1749.  
  1750.             rectInvalidate.left= BOARD_LEFT + rConfig.iSquareSize*10;
  1751.             rectInvalidate.right = rectInvalidate.left + rConfig.iSquareSize;
  1752.             rectInvalidate.top = BOARD_TOP + rConfig.iSquareSize*2;
  1753.             rectInvalidate.bottom = BOARD_TOP + rConfig.iSquareSize*7;
  1754.             InvalidateRect(hMainWnd, &rectInvalidate, TRUE);
  1755.         
  1756.             //$$ () game over state
  1757.             break;
  1758.  
  1759.     case IDM_SETUP_EXIT:
  1760.  
  1761.         lpProcDialog = MakeProcInstance ((FARPROC) PlayerTurnDialogProc, hInst);
  1762.         iDialogBoxResult = DialogBox(hInst, "PLAYER_TURN", 
  1763.         hWnd, (DLGPROC) lpProcDialog);
  1764.         if (iDialogBoxResult != -1)        
  1765.             {
  1766.  
  1767.             AssertSz((BLACK == iDialogBoxResult) ||
  1768.                      (RED == iDialogBoxResult), 
  1769.                      "Darn tootin!");
  1770.         
  1771.         SetMenu(hWnd, LoadMenu(hInst, "WCheck_NORMAL"));
  1772.                 rGameState.iPlayerTurn = iDialogBoxResult;
  1773.         rGameState.fSetupMode = FALSE;
  1774.                 rectInvalidate.left= BOARD_LEFT + rConfig.iSquareSize*10;
  1775.                 rectInvalidate.right = rectInvalidate.left + rConfig.iSquareSize;
  1776.                 rectInvalidate.top = BOARD_TOP + rConfig.iSquareSize*2;
  1777.                 rectInvalidate.bottom = BOARD_TOP + rConfig.iSquareSize*7;
  1778.                 InvalidateRect(hMainWnd, &rectInvalidate, TRUE);
  1779.                 if (rConfig.iSetupPurgeBoards)
  1780.                     CMoves.ClearBoards();
  1781.                 else
  1782.                     CMoves.PurgeBoards();
  1783.                 CMoves.NewMove(b, rGameState.iPlayerTurn);
  1784.         }
  1785.         break;
  1786.  
  1787.     case IDM_PLAYERS:
  1788.         lpProcDialog = MakeProcInstance ((FARPROC) PlayersDialogProc, hInst);
  1789.         DialogBox (hInst, "PLAYERS", hWnd, (DLGPROC) lpProcDialog);
  1790.         FreeProcInstance (lpProcDialog);
  1791.         break;
  1792.  
  1793.     case IDM_BACK:
  1794.         {
  1795.         // Change menu to say "Continue"
  1796.         rGameState.fPaused = TRUE;
  1797.                 rGameState.fGameOver = FALSE;
  1798.  
  1799.                 // $$ () game over state
  1800.  
  1801.         TraceTag(tagUI, "Calling CMoves.BackMove(b)");
  1802.         if (FALSE == CMoves.BackMove(b, &rGameState.iPlayerTurn))
  1803.                 {
  1804.                     TraceTag(tagUI, "BEEP: Can't back up.");
  1805.             MessageBeep(MB_OK);
  1806.                 }
  1807.         else
  1808.             DrawBoard(b);
  1809.         }
  1810.         break;
  1811.  
  1812.     case IDM_FORWARD:
  1813.     {
  1814.         // Change menu to say "Continue"
  1815.         rGameState.fPaused = TRUE;
  1816.  
  1817.             // $$ () game over state
  1818.         TraceTag(tagUI, "Calling CMoves.ForwardMove(b)");
  1819.         if (FALSE == CMoves.ForwardMove(b, &rGameState.iPlayerTurn))
  1820.             {
  1821.                 TraceTag(tagUI, "BEEP: Can't go forward.");
  1822.                 MessageBeep(MB_OK);
  1823.             }
  1824.         else
  1825.         DrawBoard(b);
  1826.     }
  1827.     break;
  1828.  
  1829.         case IDM_FLIP:
  1830.             hm = GetMenu(hWnd);
  1831.             if (FALSE == rConfig.iBoardFlipped)
  1832.             {
  1833.                 rConfig.iBoardFlipped = TRUE;
  1834.                 CheckMenuItem(hm, IDM_FLIP, MF_UNCHECKED);
  1835.             }
  1836.             else
  1837.             {
  1838.                 rConfig.iBoardFlipped = FALSE;
  1839.                 CheckMenuItem(hm, IDM_FLIP, MF_CHECKED);
  1840.             }
  1841.  
  1842.             DrawBoard(b);
  1843.             break;
  1844.  
  1845.         case IDM_CONTINUE:
  1846.  
  1847.         rGameState.fPaused = FALSE;
  1848.         CMoves.PurgeBoards();
  1849.  
  1850.             // $$ () game over state
  1851.  
  1852.         AssertSz(((BLACK == rGameState.iPlayerTurn) || 
  1853.                 (RED == rGameState.iPlayerTurn)), 
  1854.                 "Who flicked that?");
  1855.  
  1856.         if (COMPUTER_PLAYER == rConfig.rPlayer[rGameState.iPlayerTurn].iPlayerType)
  1857.         {
  1858.         ComputerMove();
  1859.         }
  1860.         break;
  1861.  
  1862.         case IDM_SETDRAWMOVES:
  1863.         lpProcDialog = MakeProcInstance ((FARPROC) DebugConfigDialogProc, hInst);
  1864.         DialogBox (hInst, "DEBUG_CONFIG", hWnd, (DLGPROC) lpProcDialog);
  1865.         FreeProcInstance (lpProcDialog);
  1866.             break;
  1867.  
  1868.  
  1869.     case IDM_BASE_LEVEL:
  1870.     case IDM_BASE_LEVEL + 1:
  1871.     case IDM_BASE_LEVEL + 2:
  1872.     case IDM_BASE_LEVEL + 3:
  1873.     case IDM_BASE_LEVEL + 4:
  1874.     case IDM_BASE_LEVEL + 5:
  1875.     case IDM_BASE_LEVEL + 6:
  1876.     case IDM_BASE_LEVEL + 7:
  1877.     case IDM_BASE_LEVEL + 8:
  1878.     case IDM_BASE_LEVEL + 9:
  1879.     case IDM_BASE_LEVEL + 10:
  1880.     case IDM_BASE_LEVEL + 11:
  1881.     case IDM_BASE_LEVEL + 12:
  1882.     case IDM_BASE_LEVEL + 13:
  1883.     case IDM_BASE_LEVEL + 14:
  1884.     case IDM_BASE_LEVEL + 15:
  1885.     case IDM_BASE_LEVEL + 16:
  1886.     case IDM_BASE_LEVEL + 17:
  1887.     case IDM_BASE_LEVEL + 18:
  1888.     case IDM_BASE_LEVEL + 19:
  1889.     case IDM_BASE_LEVEL + 20:
  1890.         HMENU hm;
  1891.         int i;
  1892.  
  1893.         hm = GetMenu(hWnd);
  1894.         i=20;
  1895.         for (;i;i--)
  1896.             CheckMenuItem(hm, IDM_BASE_LEVEL + i, MF_UNCHECKED);
  1897.         CheckMenuItem(hm, wmId, MF_CHECKED);
  1898.         rConfig.rPlayer[BLACK].iMaxRecursionDepth =
  1899.             rConfig.rPlayer[RED].iMaxRecursionDepth = wmId - IDM_BASE_LEVEL;
  1900.         break;
  1901.  
  1902.     case IDM_HINT:
  1903.         {
  1904.         SQUARE      db[SQRS_MAX];
  1905.         int i;
  1906.  
  1907.         SetCursor(curThink);
  1908.         CopyBoard(b,db);
  1909.         PlayBestMove(db, rGameState.iPlayerTurn, 0, 0,
  1910.             (int)rConfig.rPlayer[rGameState.iPlayerTurn].lAlphaPruningOriginalDepth,    /* prune depth */
  1911.             (int)rConfig.rPlayer[rGameState.iPlayerTurn].lAlphaPruningWidth,    /* prune size */
  1912.             (int)rConfig.rPlayer[rGameState.iPlayerTurn].iMaxRecursionDepth   /* max depth */
  1913.             );
  1914.         SetCursor(curNormal);
  1915.         for (i=0; i<3; ++i)
  1916.         {
  1917.         #define WAIT_TICKS 250
  1918.         #ifndef _WIN32
  1919.         DWORD startTick;
  1920.         #endif
  1921.         DrawBoard(db);
  1922.         #ifdef _WIN32
  1923.         Sleep(WAIT_TICKS);
  1924.         #else
  1925.         startTick = GetTickCount() + WAIT_TICKS;
  1926.         while (GetTickCount() < startTick) /* do nothing */;
  1927.         #endif
  1928.         DrawBoard(b);
  1929.         #ifdef _WIN32
  1930.         Sleep(WAIT_TICKS);
  1931.         #else
  1932.         startTick = GetTickCount() + WAIT_TICKS;
  1933.         while (GetTickCount() < startTick) /* do nothing */;
  1934.         #endif
  1935.         }
  1936.  
  1937.         
  1938.         }
  1939.         break;
  1940.  
  1941.     case IDM_ADDRESS:
  1942.         if (pfrm) // $ FORM
  1943.         pfrm->AddressForm(hWnd,(BOOL) wmEvent);
  1944.         else
  1945.         MessageBeep(MB_OK);
  1946.         break;
  1947.  
  1948.         case IDM_ABOUT:
  1949.             
  1950.             lpProcDialog = MakeProcInstance((FARPROC)About, hInst);
  1951.  
  1952.             DialogBox(hInst,           // current instance
  1953.                 "AboutBox",            // dlg resource to use
  1954.                 hWnd,                  // parent handle
  1955.                 (DLGPROC)lpProcDialog); // About() instance address
  1956.  
  1957.             FreeProcInstance(lpProcDialog);
  1958.             break;
  1959.  
  1960.         case IDM_EXIT:
  1961.             DestroyWindow (hWnd);
  1962.             break;
  1963.     }
  1964. }
  1965.  
  1966. /****************************************************************************
  1967. *****************************************************************************
  1968. *****************************************************************************
  1969. ****************************************************************************/
  1970.  
  1971. LRESULT CALLBACK CheckersWndProc(
  1972.         HWND hWnd,         // window handle
  1973.         UINT message,      // type of message
  1974.         WPARAM wParam,     // additional information
  1975.         LPARAM lParam)     // additional information
  1976.  
  1977. {
  1978.     switch (message)
  1979.     {
  1980.     HANDLE_MSG(hWnd, WM_CREATE, fHandle_WM_CREATE);
  1981.         HANDLE_MSG(hWnd, WM_INITMENU, vHandle_WM_INITMENU);
  1982.         HANDLE_MSG(hWnd, WM_DESTROY, vHandle_WM_DESTROY);
  1983.         HANDLE_MSG(hWnd, WM_TIMER, vHandle_WM_TIMER);
  1984.         HANDLE_MSG(hWnd, WM_LBUTTONDOWN, vHandle_WM_LBUTTONDOWN);
  1985.         HANDLE_MSG(hWnd, WM_LBUTTONUP, vHandle_WM_LBUTTONUP);
  1986.         HANDLE_MSG(hWnd, WM_RBUTTONDOWN, vHandle_WM_RBUTTONDOWN);
  1987.         HANDLE_MSG(hWnd, WM_RBUTTONUP, vHandle_WM_RBUTTONUP);
  1988.         HANDLE_MSG(hWnd, WM_MOUSEMOVE, vHandle_WM_MOUSEMOVE);
  1989.         HANDLE_MSG(hWnd, WM_PAINT, vHandle_WM_PAINT);
  1990.         HANDLE_MSG(hWnd, WM_VSCROLL, vHandle_WM_VSCROLL);
  1991.         HANDLE_MSG(hWnd, WM_HSCROLL, vHandle_WM_HSCROLL);
  1992.         HANDLE_MSG(hWnd, WM_GETMINMAXINFO, vHandle_WM_GETMINMAXINFO);
  1993.         HANDLE_MSG(hWnd, WM_COMMAND, vHandle_WM_COMMAND);
  1994.  
  1995.         case EM_GIVEFORMTOHWND:
  1996.  
  1997.         ShowWindow(hWnd, SW_SHOWNORMAL);
  1998.  
  1999.         // ----- params valid
  2000.         AssertSz(NULL == pfrm,"two forms?");
  2001.         AssertSz(lParam,"no forms?");
  2002.         pfrm = (FRM*) lParam;
  2003.         TraceTag(tagForm,"wcheck pfrm->AddRef");
  2004.         pfrm->AddRef();
  2005.         Assert(pfrm->pMessage);
  2006.  
  2007.         pfrm->GetCheckersData(b,&rGameState.iPlayerTurn,NULL,NULL);
  2008.         AssertSz(rGameState.iPlayerTurn == RED || rGameState.iPlayerTurn == BLACK,"cool: neither red or blacks turn according to mapi");
  2009.         rConfig.iBoardFlipped = 1;
  2010.         if (RED == rGameState.iPlayerTurn)
  2011.         rConfig.iBoardFlipped = 0;
  2012.         rGameState.fPaused = FALSE;
  2013.  
  2014.  
  2015.         DrawBoard(b);
  2016.  
  2017.         break;
  2018.  
  2019.         case WM_OTHERINIT:
  2020.  
  2021.         if (!rGameState.fPlayAsForm)
  2022.         {
  2023.         if (COMPUTER_PLAYER == rConfig.rPlayer[PLAYER1].iPlayerType)
  2024.             {
  2025.             MessageBox(hWnd, "Computer is configured to move first. The " \
  2026.             "game will start out paused. Select 'Continue' from the " \
  2027.             "main menu to start.", "Checkers", MB_OK);
  2028.             rGameState.fPaused = TRUE;
  2029.             }
  2030.         }
  2031.         else
  2032.         {
  2033.         rGameState.fPaused = TRUE;
  2034.         }
  2035.             rGameState.fInitDone = TRUE;
  2036.         break;
  2037.  
  2038.     case WM_CLOSE:
  2039.         if (pfrm)
  2040.         {
  2041.         FRM *pfrml; //$FORM
  2042.         pfrml = pfrm;
  2043.         pfrm = NULL;
  2044.         pfrml->ShutdownForm(OLECLOSE_NOSAVE);
  2045.         pfrml->Release();
  2046.         }
  2047.         return(DefWindowProc(hWnd, message, wParam, lParam));
  2048.  
  2049.         default:          // Passes it on if unproccessed
  2050.             return (DefWindowProc(hWnd, message, wParam, lParam));
  2051.     }
  2052.     return (0);
  2053. }
  2054.  
  2055. /****************************************************************************
  2056. *****************************************************************************
  2057. *****************************************************************************
  2058. ****************************************************************************/
  2059.  
  2060. long WINAPI ComputerMove()
  2061. {
  2062.     int iGameState = GAME_PLAYABLE;
  2063.     
  2064.     rGameState.fComputerBusy = TRUE;
  2065.     rGameState.fGameInProgress = TRUE;
  2066.  
  2067.     TraceTag(tagUI, "Calling PlayBestMove()");
  2068.     SetCursor(curThink);
  2069.  
  2070.     AssertSz(((BLACK == rGameState.iPlayerTurn) || 
  2071.               (RED == rGameState.iPlayerTurn)), 
  2072.               "This one says x!");
  2073.  
  2074.         PlayBestMove(b, rGameState.iPlayerTurn, 0, 0,
  2075.         (int)rConfig.rPlayer[rGameState.iPlayerTurn].lAlphaPruningOriginalDepth,    /* prune depth */
  2076.         (int)rConfig.rPlayer[rGameState.iPlayerTurn].lAlphaPruningWidth,    /* prune size */
  2077.         (int)rConfig.rPlayer[rGameState.iPlayerTurn].iMaxRecursionDepth   /* max depth */
  2078.         );
  2079.         
  2080.     SetCursor(curNormal);
  2081.     TraceTag(tagUI, "Done with PlayBestMove()");
  2082.     DrawBoard(b);
  2083.  
  2084.     if (rGameState.iPlayerTurn == BLACK)
  2085.     rGameState.iPlayerTurn = RED;
  2086.     else
  2087.     rGameState.iPlayerTurn = BLACK;
  2088.  
  2089.     CMoves.NewMove(b, rGameState.iPlayerTurn);
  2090.  
  2091.     iGameState = GameOver(b, rGameState.iPlayerTurn);
  2092.     switch (iGameState)
  2093.     {
  2094.     case GAME_WON:
  2095.             rGameState.fGameOver = TRUE;
  2096.             DisplayGameOver(hMainWnd, rGameState.iPlayerTurn);
  2097.         break;
  2098.         case GAME_DRAWN:
  2099.         rGameState.fGameOver = TRUE;
  2100.         DisplayGameDrawn(hMainWnd, rGameState.iPlayerTurn);
  2101.             break;            
  2102.         case GAME_PLAYABLE:
  2103.         OnGamePlayableAfterMove();
  2104.             break;         
  2105.         default:
  2106.             AssertSz(FALSE, "STILL dead");                     
  2107.     }
  2108.  
  2109.     rGameState.fComputerBusy = FALSE;
  2110.     
  2111.     return(0);
  2112.     
  2113. }
  2114.  
  2115. /****************************************************************************
  2116. *****************************************************************************
  2117. *****************************************************************************
  2118. ****************************************************************************/
  2119.  
  2120. void inline SetupLButtonDown(HWND hWnd, UINT keyFlags, int x, int y)
  2121. {
  2122.     int iSX = 0;
  2123.     int iSY = 0;
  2124.  
  2125.     (pntStart).x = x;
  2126.     (pntStart).y = y;
  2127.  
  2128.     vTranslateCurPosToSquare(pntStart, &iSX, &iSY);
  2129.  
  2130.     if (fValidSetupPiece(b, iSX, iSY))
  2131.     {
  2132.     HDC hDC;
  2133.  
  2134.     SetCursor(curPiece);
  2135.     hDC = GetDC(hWnd);
  2136.     AssertSz((iSX >= 0) && ((iSX <= 7) || (iSX == 10)), "iSX out of range on ButtonDown");
  2137.     AssertSz((iSY >= 0) && (iSY <= 7), "iSY out of range on ButtonDown");
  2138.         if ((iSX != 10) && (!(GetKeyState(VK_CONTROL) & 0x8000)))
  2139.             vClearMovingPiece(hDC, iSX, iSY);
  2140.     rGameState.fMoveInProgress = TRUE;
  2141.     }
  2142.     else
  2143.     {
  2144.         TraceTag(tagUI, "BEEP: Not a valid setup piece");
  2145.     MessageBeep(MB_OK);
  2146.     rGameState.fMoveInProgress = FALSE;
  2147.     }
  2148.     rGameState.fLMouseButtonDown = TRUE;
  2149.     TraceTag(tagMouse, "rGameState.fLMouseButtonDown: %d", rGameState.fLMouseButtonDown);
  2150.     
  2151. }
  2152.  
  2153. void inline SetupRButtonDown(HWND hWnd, UINT keyFlags, int x, int y)
  2154. {
  2155.     int iSX = 0;
  2156.     int iSY = 0;
  2157.  
  2158.     TraceTag(tagMouse, "in SetupRButtonDown()");
  2159.  
  2160.     (pntStart).x = x;
  2161.     (pntStart).y = y;
  2162.  
  2163.     vTranslateCurPosToSquare(pntStart, &iSX, &iSY);
  2164.  
  2165.     if (fValidSetupPiece(b, iSX, iSY))
  2166.     {
  2167.     HDC hDC;
  2168.  
  2169.     SetCursor(curPiece);
  2170.     hDC = GetDC(hWnd);
  2171.     AssertSz((iSX >= 0) && ((iSX <= 7) || (iSX == 10)), "iSX out of range on ButtonDown");
  2172.     AssertSz((iSY >= 0) && (iSY <= 7), "iSY out of range on ButtonDown");
  2173.         vClearMovingPiece(hDC, iSX, iSY);
  2174.     rGameState.fMoveInProgress = TRUE;
  2175.     }
  2176.     else
  2177.     {
  2178.         TraceTag(tagUI, "BEEP: Not a valid setup piece (in RButtonDown)");
  2179.     MessageBeep(MB_OK);
  2180.     rGameState.fMoveInProgress = FALSE;
  2181.     }
  2182.     rGameState.fRMouseButtonDown = TRUE;
  2183.     TraceTag(tagMouse, "rGameState.fRMouseButtonDown: %d", rGameState.fRMouseButtonDown);
  2184.     
  2185. }
  2186.  
  2187. void inline NormalLButtonDown(HWND hWnd, UINT keyFlags, int x, int y)
  2188. {
  2189.     int iSX = 0;
  2190.     int iSY = 0;
  2191.  
  2192.     AssertSz((rGameState.iPlayerTurn == RED) ||
  2193.        (rGameState.iPlayerTurn == BLACK), "Player turn is bogus.");
  2194.  
  2195.     TraceTag(tagMouse, "in NormalLButtonDown()");
  2196.  
  2197.     if ((HUMAN_PLAYER == rConfig.rPlayer[rGameState.iPlayerTurn].iPlayerType) && 
  2198.     (!rGameState.fPaused))
  2199.     {
  2200.     TraceTag(tagUI, "Button down at x:%d - y:%d", x, y);
  2201.     (pntStart).x = x;
  2202.     (pntStart).y = y;
  2203.  
  2204.     vTranslateCurPosToSquare(pntStart, &iSX, &iSY);
  2205.     if (fValidPlayerPiece(b, iSX, iSY))
  2206.     {
  2207.         HDC hDC;
  2208.  
  2209.         SetCursor(curPiece);
  2210.         hDC = GetDC(hWnd);
  2211.         AssertSz((iSX >= 0) && (iSX <= 7), "iSX out of range on ButtonDown");
  2212.         AssertSz((iSY >= 0) && (iSY <= 7), "iSY out of range on ButtonDown");
  2213.         vClearMovingPiece(hDC, iSX, iSY);
  2214.         rGameState.fMoveInProgress = TRUE;
  2215.     }
  2216.     else
  2217.     {
  2218.             TraceTag(tagUI, "BEEP: Not a valid piece in LButtonDown");
  2219.         MessageBeep(MB_OK);
  2220.         rGameState.fMoveInProgress = FALSE;
  2221.     }
  2222.     }
  2223.     else
  2224.     {
  2225.         TraceTag(tagUI, "BEEP: Wrong player in LButtonDown");
  2226.     MessageBeep(MB_OK);
  2227.     }
  2228.  
  2229.     rGameState.fLMouseButtonDown = TRUE;
  2230.     TraceTag(tagMouse, "rGameState.fLMouseButtonDown: %d", rGameState.fLMouseButtonDown);
  2231.     
  2232. }
  2233.  
  2234. void inline SetupLButtonUp(HWND hWnd, WPARAM uParam, int x, int y)
  2235. {
  2236.  
  2237.     TraceTag(tagMouse, "in SetupLButtonUp()");
  2238.  
  2239.     if (rGameState.fMoveInProgress)
  2240.     {
  2241.     int     iEngineStart=0;
  2242.     int     iEngineEnd=0;
  2243.     int     iSX = 0;
  2244.     int     iSY = 0;
  2245.     int     iEX = 0;
  2246.     int     iEY = 0;
  2247.     BOOL    fRackSelect = FALSE;
  2248.         POINT   pntEnd;
  2249.  
  2250.     SetCursor(curNormal);
  2251.  
  2252.     rGameState.fLMouseButtonDown = FALSE;
  2253.     pntEnd.x = x;
  2254.     pntEnd.y = y;
  2255.     
  2256.     vTranslateCurPosToSquare(pntStart, &iSX, &iSY);
  2257.         if ((iSX == 10) && (iSY >=2) && (iSY <= 6))
  2258.             fRackSelect = TRUE;
  2259.         else
  2260.         {
  2261.             fRackSelect = FALSE;
  2262.             vTranslateUIToEngineSquare(&iEngineStart, iSX, iSY);
  2263.         }
  2264.  
  2265.     vTranslateCurPosToSquare(pntEnd, &iEX, &iEY);
  2266.     vTranslateUIToEngineSquare(&iEngineEnd, iEX, iEY);
  2267.  
  2268.     TraceTag(tagUI, "Button up at x:%d - y:%d", pntEnd.x, pntEnd.y);
  2269.  
  2270.         if (iEngineStart != iEngineEnd)
  2271.         {
  2272.         if ((iEngineEnd != -1) && (iEngineStart != -1) && (!fRackSelect))
  2273.         {
  2274.             TraceTag(tagUI, "St: %d * End: %d", iEngineStart, iEngineEnd);
  2275.  
  2276.             AssertSz(!fRackSelect, "Trains, Planes, and Automobiles");
  2277.             AssertSz(iEngineEnd < SQRS_MAX,"what could be a train");
  2278.             AssertSz(iEngineEnd > 0,"what could be trains");
  2279.             AssertSz(iEngineStart < SQRS_MAX,"two what could be a train");
  2280.             AssertSz(iEngineStart > 0,"two what could be trains");
  2281.  
  2282.                 b[iEngineEnd] = b[iEngineStart];
  2283.  
  2284.             // If high-order bit is set, the control key is down, and I should
  2285.             // do a copy (not remove the source piece).
  2286.  
  2287.             if (!(GetKeyState(VK_CONTROL) & 0x8000))
  2288.                 b[iEngineStart] = EMPTY;
  2289.  
  2290.             
  2291.         }
  2292.             else
  2293.             {
  2294.             AssertSz(iEngineEnd < SQRS_MAX,"while (TRUE) fork();");
  2295.             AssertSz((iEngineEnd > 0) || (-1 == iEngineEnd),"while (TRUE) spoon();");
  2296.             
  2297.                 if ((iEngineEnd != -1) && (fRackSelect))
  2298.                 {
  2299.                     switch(iSY)
  2300.                     {
  2301.                         case 2:
  2302.                             b[iEngineEnd] = RED;
  2303.                             break;
  2304.                         case 3:
  2305.                             b[iEngineEnd] = BLACK;
  2306.                             break;
  2307.                         case 4:
  2308.                             b[iEngineEnd] = RED | KING;
  2309.                             break;
  2310.                         case 5:
  2311.                             b[iEngineEnd] = BLACK | KING;
  2312.                             break;
  2313.                         case 6:
  2314.                             b[iEngineEnd] = EMPTY;
  2315.                             break;
  2316.                         default:
  2317.                             AssertSz(FALSE, "Phenylketonurics: Contains Phenylalanine");
  2318.                             break;
  2319.                     }
  2320.                 }
  2321.         }
  2322.     }
  2323.     else
  2324.     {
  2325.         // This is what happens if we picked up a piece and dropped it on
  2326.         // the same square. Right now this is a no-op.
  2327.     }
  2328.                                                           
  2329.     DrawBoard(b);
  2330.     }
  2331.  
  2332.     rGameState.fLMouseButtonDown = FALSE;
  2333.     TraceTag(tagMouse, "rGameState.fLMouseButtonDown: %d", rGameState.fLMouseButtonDown);
  2334.     
  2335. }
  2336.  
  2337. void inline SetupRButtonUp(HWND hWnd, WPARAM uParam, int x, int y)
  2338. {
  2339.  
  2340.     TraceTag(tagMouse, "in SetupRButtonUp()");
  2341.  
  2342.     if (rGameState.fMoveInProgress)
  2343.     {
  2344.     int     iEngineStart=0;
  2345.     int     iEngineEnd=0;  
  2346.     int     iSX = 0;
  2347.     int     iSY = 0;
  2348.     int     iEX = 0;
  2349.     int     iEY = 0;
  2350.     BOOL    fRackSelect = FALSE;
  2351.         POINT   pntEnd;
  2352.  
  2353.     SetCursor(curNormal);
  2354.  
  2355.     rGameState.fRMouseButtonDown = FALSE;
  2356.     pntEnd.x = x;
  2357.     pntEnd.y = y;
  2358.     
  2359.     vTranslateCurPosToSquare(pntStart, &iSX, &iSY);
  2360.         if ((iSX == 10) && (iSY >=2) && (iSY <= 6))
  2361.             fRackSelect = TRUE;
  2362.         else
  2363.         {
  2364.             fRackSelect = FALSE;
  2365.             vTranslateUIToEngineSquare(&iEngineStart, iSX, iSY);
  2366.         }
  2367.  
  2368.     vTranslateCurPosToSquare(pntEnd, &iEX, &iEY);
  2369.     vTranslateUIToEngineSquare(&iEngineEnd, iEX, iEY);
  2370.  
  2371.     TraceTag(tagUI, "Button up at x:%d - y:%d", pntEnd.x, pntEnd.y);
  2372.  
  2373.         if (iEngineStart == iEngineEnd)
  2374.         {
  2375.         if ((iEngineStart != -1) && (!fRackSelect))
  2376.         {
  2377.             TraceTag(tagUI, "St: %d * End: %d", iEngineStart, iEngineEnd);
  2378.  
  2379.             AssertSz(!fRackSelect, "Trains, Planes, and Automobiles");
  2380.             AssertSz(iEngineEnd < SQRS_MAX,"what could be a train");
  2381.             AssertSz(iEngineEnd > 0,"what could be trains");
  2382.             AssertSz(iEngineStart < SQRS_MAX,"two what could be a train");
  2383.             AssertSz(iEngineStart > 0,"two what could be trains");
  2384.  
  2385.                 b[iEngineStart] = EMPTY;
  2386.         }
  2387.     }
  2388.     else
  2389.     {
  2390.         // This is what happens if we clicked on a piece but moved off of the
  2391.         // original square.. Right now this is a no-op.
  2392.     }
  2393.                                                           
  2394.     DrawBoard(b);
  2395.     }
  2396.     
  2397.     rGameState.fRMouseButtonDown = FALSE;
  2398.     TraceTag(tagMouse, "rGameState.fRMouseButtonDown: %d", rGameState.fRMouseButtonDown);
  2399.  
  2400. }
  2401.  
  2402.  
  2403. void inline NormalLButtonUp(HWND hWnd, WPARAM uParam, int x, int y)
  2404. {
  2405.     int iGameState = GAME_PLAYABLE;
  2406.  
  2407.     TraceTag(tagMouse, "in NormalLButtonUp()");
  2408.  
  2409.     if (rGameState.fMoveInProgress)
  2410.     {
  2411.     int     iEngineStart;                      
  2412.     int     iEngineEnd;
  2413.     int     iValid = 0;    // Valid move
  2414.     int     iSX = 0;
  2415.     int     iSY = 0;
  2416.     int     iEX = 0;
  2417.     int     iEY = 0;
  2418.     POINT   pntEnd;
  2419.  
  2420.     SetCursor(curNormal);
  2421.  
  2422.     rGameState.fLMouseButtonDown = FALSE;
  2423.     pntEnd.x = x;
  2424.     pntEnd.y = y;
  2425.     
  2426.     vTranslateCurPosToSquare(pntStart, &iSX, &iSY);
  2427.     vTranslateUIToEngineSquare(&iEngineStart, iSX, iSY);
  2428.     vTranslateCurPosToSquare(pntEnd, &iEX, &iEY);
  2429.     vTranslateUIToEngineSquare(&iEngineEnd, iEX, iEY);
  2430.  
  2431.     TraceTag(tagUI, "Button up at x:%d - y:%d", pntEnd.x, pntEnd.y);
  2432.  
  2433.     if ((iEngineEnd != -1) && (iEngineStart != -1))
  2434.     {
  2435.         TraceTag(tagUI, "St: %d * End: %d", iEngineStart, iEngineEnd);
  2436.  
  2437.         AssertSz(((BLACK == rGameState.iPlayerTurn) || 
  2438.               (RED == rGameState.iPlayerTurn)), "Fronk, lots!");
  2439.               
  2440.         if (HUMAN_PLAYER == rConfig.rPlayer[rGameState.iPlayerTurn].iPlayerType)
  2441.         {
  2442.         AssertSz(iEngineEnd < SQRS_MAX,"ugly players what could be a train");
  2443.         AssertSz(iEngineEnd >= 0,"ugly players what could be trains");
  2444.         AssertSz(iEngineStart < SQRS_MAX,"ugly players two what could be a train");
  2445.         AssertSz(iEngineStart >= 0,"ugly players two what could be trains");
  2446.         iValid = MoveValid(b, iEngineStart, iEngineEnd, rGameState.iPlayerTurn);
  2447.         }
  2448.     }
  2449.     else
  2450.         iValid = -1;
  2451.  
  2452.     DrawBoard(b);
  2453.  
  2454.         if (iValid == 1)
  2455.         {
  2456.         if (rGameState.iPlayerTurn == BLACK)
  2457.             rGameState.iPlayerTurn = RED;
  2458.         else
  2459.             rGameState.iPlayerTurn = BLACK;
  2460.     
  2461.         CMoves.NewMove(b, rGameState.iPlayerTurn);
  2462.             iGameState = GameOver(b, rGameState.iPlayerTurn);
  2463.             switch (iGameState)
  2464.             {
  2465.             case GAME_WON:
  2466.                     rGameState.fGameOver = TRUE;
  2467.                     DisplayGameOver(hMainWnd, rGameState.iPlayerTurn);
  2468.                 break;
  2469.                 case GAME_DRAWN:
  2470.                 rGameState.fGameOver = TRUE;
  2471.                 DisplayGameDrawn(hMainWnd, rGameState.iPlayerTurn);
  2472.                     break;            
  2473.                 case GAME_PLAYABLE:
  2474.             OnGamePlayableAfterMove();
  2475.                     break;         
  2476.                 default:
  2477.                     AssertSz(FALSE, "very dead");                      
  2478.             }
  2479.         }
  2480.     }
  2481.     rGameState.fMoveInProgress = FALSE;
  2482.     rGameState.fLMouseButtonDown = FALSE;
  2483.     TraceTag(tagMouse, "rGameState.fLMouseButtonDown: %d", rGameState.fLMouseButtonDown);
  2484.     
  2485. }
  2486.  
  2487. /****************************************************************************
  2488. *****************************************************************************
  2489. *****************************************************************************
  2490. ****************************************************************************/
  2491.  
  2492. BOOL CenterWindow (HWND hwndChild, HWND hwndParent)
  2493. {
  2494.     RECT    rChild, rParent;
  2495.     int     wChild, hChild, wParent, hParent;
  2496.     int     wScreen, hScreen, xNew, yNew;
  2497.     HDC     hdc;
  2498.  
  2499.     // Get the Height and Width of the child window
  2500.     GetWindowRect (hwndChild, &rChild);
  2501.     wChild = rChild.right - rChild.left;
  2502.     hChild = rChild.bottom - rChild.top;
  2503.  
  2504.     // Get the Height and Width of the parent window
  2505.     GetWindowRect (hwndParent, &rParent);
  2506.     wParent = rParent.right - rParent.left;
  2507.     hParent = rParent.bottom - rParent.top;
  2508.  
  2509.     // Get the display limits
  2510.     hdc = GetDC (hwndChild);
  2511.     wScreen = GetDeviceCaps (hdc, HORZRES);
  2512.     hScreen = GetDeviceCaps (hdc, VERTRES);
  2513.     ReleaseDC (hwndChild, hdc);
  2514.  
  2515.     // Calculate new X position, then adjust for screen
  2516.     xNew = rParent.left + ((wParent - wChild) /2);
  2517.     if (xNew < 0) {
  2518.         xNew = 0;
  2519.     } else if ((xNew+wChild) > wScreen) {
  2520.         xNew = wScreen - wChild;
  2521.     }
  2522.  
  2523.     // Calculate new Y position, then adjust for screen
  2524.     yNew = rParent.top  + ((hParent - hChild) /2);
  2525.     if (yNew < 0) {
  2526.         yNew = 0;
  2527.     } else if ((yNew+hChild) > hScreen) {
  2528.         yNew = hScreen - hChild;
  2529.     }
  2530.  
  2531.     // Set it, and return
  2532.     return SetWindowPos (hwndChild, NULL,
  2533.         xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
  2534. }
  2535.  
  2536. /****************************************************************************
  2537. *****************************************************************************
  2538. *****************************************************************************
  2539. ****************************************************************************/
  2540.  
  2541. BOOL FAR PASCAL ComputerSettingsDialogProc (HWND hDlg,
  2542.                     WORD wMsgID,
  2543.                     WPARAM wParam,
  2544.                     LPARAM lParam)
  2545. {
  2546.     static struct rPlayerRec *prPlayer;
  2547.  
  2548.     switch (wMsgID)
  2549.  
  2550.     {
  2551.     case WM_INITDIALOG:
  2552.         prPlayer = (struct rPlayerRec FAR *) lParam;
  2553.         Assert(prPlayer);
  2554.         SendDlgItemMessage(hDlg, IDCB_USE_OPENING_BOOK, BM_SETCHECK, prPlayer->iUseOpeningBook, 0L);
  2555.         SendDlgItemMessage(hDlg, IDCB_USE_MEM_POSITIONS, BM_SETCHECK, prPlayer->iMemPositions, 0L);
  2556.         SendDlgItemMessage(hDlg, IDCB_USE_MOVE_THEORY, BM_SETCHECK, prPlayer->iUseMoveTheory, 0L);
  2557.         SendDlgItemMessage(hDlg, IDCB_MOVE_SHUFFLING, BM_SETCHECK, prPlayer->iUseMoveShuffling, 0L);
  2558.         SendDlgItemMessage(hDlg, IDCB_GOOD_MOVE_SKIPPING, BM_SETCHECK, (int)prPlayer->lUseGoodMoveSkipping, 0L);
  2559.         SendDlgItemMessage(hDlg, IDCB_EQUAL_MOVE_SKIPPING, BM_SETCHECK, prPlayer->iUseEqualMoveSkipping, 0L);
  2560.         SendDlgItemMessage(hDlg, IDCB_ALPHA_BETA_PRUNING, BM_SETCHECK, prPlayer->iUseAlphaBetaPruning, 0L);
  2561.  
  2562.         // Set other edit controls
  2563.  
  2564.         SetDlgItemLong(hDlg, IDEC_RECURSION_DEPTH, prPlayer->iMaxRecursionDepth);
  2565.             SetDlgItemLong(hDlg, IDEC_PRUNING_DEPTH, prPlayer->lAlphaPruningOriginalDepth);
  2566.             SetDlgItemLong(hDlg, IDEC_PRUNING_WIDTH, prPlayer->lAlphaPruningWidth);
  2567.         return TRUE;
  2568.  
  2569.     case WM_COMMAND:
  2570.         switch (wParam)
  2571.         {
  2572.         case IDOK:
  2573.             EndDialog (hDlg, TRUE);
  2574.             
  2575.             // Get Checkbox values
  2576.             prPlayer->iUseOpeningBook = (int)SendDlgItemMessage(hDlg, IDCB_USE_OPENING_BOOK, BM_GETCHECK, 0, 0L);
  2577.             prPlayer->iMemPositions = (int)SendDlgItemMessage(hDlg, IDCB_USE_MEM_POSITIONS, BM_GETCHECK, 0, 0L);
  2578.             prPlayer->iUseMoveTheory = (int)SendDlgItemMessage(hDlg, IDCB_USE_MOVE_THEORY, BM_GETCHECK, 0, 0L);
  2579.             prPlayer->iUseMoveShuffling = (int)SendDlgItemMessage(hDlg, IDCB_MOVE_SHUFFLING, BM_GETCHECK, 0, 0L);
  2580.             prPlayer->lUseGoodMoveSkipping = (int)SendDlgItemMessage(hDlg, IDCB_GOOD_MOVE_SKIPPING, BM_GETCHECK, 0, 0L);
  2581.             prPlayer->iUseEqualMoveSkipping = (int)SendDlgItemMessage(hDlg, IDCB_EQUAL_MOVE_SKIPPING, BM_GETCHECK, 0, 0L);
  2582.             prPlayer->iUseAlphaBetaPruning = (int)SendDlgItemMessage(hDlg, IDCB_ALPHA_BETA_PRUNING, BM_GETCHECK, 0, 0L);
  2583.             prPlayer->iMemPositions = (int)SendDlgItemMessage(hDlg, IDCB_USE_MEM_POSITIONS, BM_GETCHECK, 0, 0L);
  2584.  
  2585.             // Get Edit Control Values
  2586.  
  2587.             prPlayer->iMaxRecursionDepth         = GetDlgItemInt(hDlg, IDEC_RECURSION_DEPTH);
  2588.                     prPlayer->lAlphaPruningOriginalDepth = GetDlgItemLong(hDlg, IDEC_PRUNING_DEPTH);
  2589.                     prPlayer->lAlphaPruningWidth         = GetDlgItemLong(hDlg, IDEC_PRUNING_WIDTH);
  2590.  
  2591.             return TRUE;
  2592.  
  2593.         case IDCANCEL:
  2594.             EndDialog (hDlg, TRUE);
  2595.             return TRUE;
  2596.         }                                    // end switch
  2597.         break;
  2598.     }
  2599.     return FALSE;
  2600. }
  2601.  
  2602. BOOL FAR PASCAL PlayersDialogProc (HWND hDlg,
  2603.                     WORD wMsgID,
  2604.                     WPARAM wParam,
  2605.                     LPARAM lParam)
  2606. {
  2607.     switch (wMsgID)
  2608.  
  2609.     {
  2610.     case WM_INITDIALOG:
  2611.         switch(rConfig.rPlayer[PLAYER1].iPlayerType)
  2612.         {
  2613.         case HUMAN_PLAYER:
  2614.             SendDlgItemMessage(hDlg, IDRB_P1_HUMAN, BM_SETCHECK, 1, 0L);
  2615.             break;
  2616.         case COMPUTER_PLAYER:
  2617.             SendDlgItemMessage(hDlg, IDRB_P1_COMPUTER, BM_SETCHECK, 1, 0L);
  2618.             break;
  2619.         case NETWORK_PLAYER:
  2620.             SendDlgItemMessage(hDlg, IDRB_P1_NETWORK, BM_SETCHECK, 1, 0L);
  2621.             break;
  2622.         default:
  2623.             AssertSz(FALSE, "rConfig.rPlayer[PLAYER1].iPlayerType not valid");
  2624.             break;
  2625.         }
  2626.         
  2627.         switch(rConfig.rPlayer[PLAYER2].iPlayerType)
  2628.         {
  2629.         case HUMAN_PLAYER:
  2630.             SendDlgItemMessage(hDlg, IDRB_P2_HUMAN, BM_SETCHECK, 1, 0L);
  2631.             break;
  2632.         case COMPUTER_PLAYER:
  2633.             SendDlgItemMessage(hDlg, IDRB_P2_COMPUTER, BM_SETCHECK, 1, 0L);
  2634.             break;
  2635.         case NETWORK_PLAYER:
  2636.             SendDlgItemMessage(hDlg, IDRB_P2_NETWORK, BM_SETCHECK, 1, 0L);
  2637.             break;
  2638.         default:
  2639.             AssertSz(FALSE, "rConfig.rPlayer[PLAYER2].iPlayerType not valid");
  2640.             break;
  2641.         }
  2642.  
  2643.         return TRUE;
  2644.  
  2645.     case WM_COMMAND:
  2646.         switch (wParam)
  2647.         {
  2648.         case IDB_P1_COMPUTER_SETUP:
  2649.  
  2650.             DialogBoxParam (hInst,       // current instance
  2651.                     "COMPUTER_SETUP_MASTER", // dlg resource to use
  2652.                     hDlg,        // parent handle
  2653.                     (DLGPROC)ComputerSettingsDialogProc, // Config() instance address
  2654.                     (LPARAM) (struct rPlayerRec *) (&(rConfig.rPlayer[PLAYER1])));
  2655.             break;
  2656.  
  2657.         case IDB_P2_COMPUTER_SETUP:
  2658.  
  2659.             DialogBoxParam (hInst,       // current instance
  2660.                     "COMPUTER_SETUP_MASTER", // dlg resource to use
  2661.                     hDlg,        // parent handle
  2662.                     (DLGPROC)ComputerSettingsDialogProc, // Config() instance address
  2663.                     (LPARAM) (struct rPlayerRec *) (&(rConfig.rPlayer[PLAYER2])));
  2664.             break;
  2665.         
  2666.         case IDB_P1_NETWORK_SETUP:
  2667.         case IDB_P2_NETWORK_SETUP:
  2668.             NYI("Player Network Setup");
  2669.             break;
  2670.  
  2671.         case IDOK:
  2672.             EndDialog (hDlg, TRUE);
  2673.             if (SendDlgItemMessage(hDlg, IDRB_P1_HUMAN, BM_GETCHECK, 0, 0L))
  2674.             rConfig.rPlayer[PLAYER1].iPlayerType = HUMAN_PLAYER;
  2675.             if (SendDlgItemMessage(hDlg, IDRB_P1_COMPUTER, BM_GETCHECK, 0, 0L))
  2676.             rConfig.rPlayer[PLAYER1].iPlayerType = COMPUTER_PLAYER;
  2677.             if (SendDlgItemMessage(hDlg, IDRB_P1_NETWORK, BM_GETCHECK, 0, 0L))
  2678.             rConfig.rPlayer[PLAYER1].iPlayerType = NETWORK_PLAYER;
  2679.             if (SendDlgItemMessage(hDlg, IDRB_P2_HUMAN, BM_GETCHECK, 0, 0L))
  2680.             rConfig.rPlayer[PLAYER2].iPlayerType = HUMAN_PLAYER;
  2681.             if (SendDlgItemMessage(hDlg, IDRB_P2_COMPUTER, BM_GETCHECK, 0, 0L))
  2682.             rConfig.rPlayer[PLAYER2].iPlayerType = COMPUTER_PLAYER;
  2683.             if (SendDlgItemMessage(hDlg, IDRB_P2_NETWORK, BM_GETCHECK, 0, 0L))
  2684.             rConfig.rPlayer[PLAYER2].iPlayerType = NETWORK_PLAYER;
  2685.             return TRUE;
  2686.  
  2687.         case IDCANCEL:
  2688.             EndDialog (hDlg, TRUE);
  2689.             return TRUE;
  2690.         }                                    // end switch
  2691.         break;
  2692.     }
  2693.     return FALSE;
  2694. }
  2695.  
  2696.  
  2697. BOOL FAR PASCAL DebugConfigDialogProc (HWND hDlg,
  2698.                     WORD wMsgID,
  2699.                     WPARAM wParam,
  2700.                     LPARAM lParam)
  2701. {
  2702.     switch (wMsgID)
  2703.  
  2704.     {
  2705.     case WM_INITDIALOG:
  2706.         SetDlgItemInt(hDlg, IDEC_MAX_MOVES, rConfig.iMaxMoves);
  2707.         return TRUE;
  2708.  
  2709.     case WM_COMMAND:
  2710.         switch (wParam)
  2711.         {
  2712.         case IDOK:
  2713.             EndDialog (hDlg, TRUE);
  2714.             rConfig.iMaxMoves = GetDlgItemInt(hDlg, IDEC_MAX_MOVES);
  2715.             return TRUE;
  2716.  
  2717.         case IDCANCEL:
  2718.             EndDialog (hDlg, TRUE);
  2719.             return TRUE;
  2720.         }                                    // end switch
  2721.         break;
  2722.     }
  2723.     return FALSE;
  2724. }
  2725.  
  2726.  
  2727. int FAR PASCAL PlayerTurnDialogProc (HWND hDlg,
  2728.                     WORD wMsgID,
  2729.                     WPARAM wParam,
  2730.                     LPARAM lParam)
  2731. {
  2732.     switch (wMsgID)
  2733.  
  2734.     {
  2735.     case WM_INITDIALOG:
  2736.             CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
  2737.         return TRUE;
  2738.  
  2739.     case WM_COMMAND:
  2740.         switch (wParam)
  2741.         {
  2742.         case IDB_PLAYER1:
  2743.             EndDialog (hDlg, PLAYER1);
  2744.             return TRUE;
  2745.  
  2746.         case IDB_PLAYER2:
  2747.             EndDialog (hDlg, PLAYER2);
  2748.             return TRUE;
  2749.         
  2750.         case IDCANCEL:
  2751.             // Return -1 so the calling function will know that the result
  2752.             // from the dialog call isn't equal to a player ID.
  2753.             
  2754.             EndDialog (hDlg, -1);
  2755.             break;    
  2756.         }                                    // end switch
  2757.         break;
  2758.     }
  2759.     return FALSE;
  2760. }
  2761.  
  2762.  
  2763. LRESULT CALLBACK About(
  2764.         HWND hDlg,           // window handle of the dialog box
  2765.         UINT message,        // type of message
  2766.         WPARAM wParam,       // message-specific information
  2767.         LPARAM lParam)
  2768. {
  2769.     static  HFONT hfontDlg;
  2770.     static  LPSTR   lpVersion;
  2771.     static  DWORD   dwVerInfoSize;
  2772.     static  DWORD   dwVerHnd;
  2773.     static  UINT    uVersionLen;
  2774.     static  WORD    wRootLen;
  2775.     BOOL    bRetCode;
  2776.     static  int     i;
  2777.     static  char    szFullPath[256];
  2778.     static  char    szResult[256];
  2779.     static  char    szGetName[256];
  2780.  
  2781.     switch (message) {
  2782.         case WM_INITDIALOG:  // message: initialize dialog box
  2783.             // Create a font to use
  2784.             hfontDlg = CreateFont(14, 0, 0, 0, 0, 0, 0, 0,
  2785.                 0, 0, 0, 0,
  2786.                 VARIABLE_PITCH | FF_SWISS, "");
  2787.  
  2788.             // Center the dialog over the application window
  2789.             CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
  2790.  
  2791.             // Get version information from the application
  2792.             GetModuleFileName (hInst, szFullPath, sizeof(szFullPath));
  2793.             dwVerInfoSize = GetFileVersionInfoSize(szFullPath, &dwVerHnd);
  2794.             if (dwVerInfoSize) {
  2795.                 // If we were able to get the information, process it:
  2796.                 LPSTR   lpstrVffInfo;
  2797.                 HANDLE  hMem;
  2798.                 hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
  2799.                 lpstrVffInfo  = (char *)GlobalLock(hMem);
  2800.                 GetFileVersionInfo(szFullPath, dwVerHnd, dwVerInfoSize, lpstrVffInfo);
  2801.                 lstrcpy(szGetName, "\\StringFileInfo\\040904E4\\");
  2802.                 wRootLen = lstrlen(szGetName);
  2803.  
  2804.                 // Walk through the dialog items that we want to replace:
  2805.                 for (i = DLG_VERFIRST; i <= DLG_VERLAST; i++) {
  2806.                     GetDlgItemText(hDlg, i, szResult, sizeof(szResult));
  2807.                     szGetName[wRootLen] = (char)0;
  2808.                     lstrcat (szGetName, szResult);
  2809.                     uVersionLen   = 0;
  2810.                     lpVersion     = NULL;
  2811.                       bRetCode      =  VerQueryValue((LPVOID)lpstrVffInfo,
  2812.                           (LPSTR)szGetName,
  2813.                           (LPVOID *)&lpVersion,
  2814. #if defined (_WIN32)
  2815.                           (PUINT)&uVersionLen); // For MIPS strictness
  2816. #else
  2817.                           (UINT FAR *)&uVersionLen);
  2818. #endif
  2819.  
  2820.                       if ( bRetCode && uVersionLen && lpVersion) {
  2821.                           // Replace dialog item text with version info
  2822.                           lstrcpy(szResult, lpVersion);
  2823.                           SetDlgItemText(hDlg, i, szResult);
  2824.                           SendMessage (GetDlgItem (hDlg, i), WM_SETFONT, (UINT)hfontDlg, TRUE);
  2825.                       }
  2826.                 } // for (i = DLG_VERFIRST; i <= DLG_VERLAST; i++)
  2827.  
  2828.                 GlobalUnlock(hMem);
  2829.                 GlobalFree(hMem);
  2830.             } // if (dwVerInfoSize)
  2831.  
  2832.             return (TRUE);
  2833.  
  2834.         case WM_COMMAND:                      // message: received a command
  2835.             if (LOWORD(wParam) == IDOK        // "OK" box selected?
  2836.             || LOWORD(wParam) == IDCANCEL) {  // System menu close command?
  2837.                 EndDialog(hDlg, TRUE);        // Exit the dialog
  2838.                 DeleteObject (hfontDlg);
  2839.                 return (TRUE);
  2840.             }
  2841.             break;
  2842.     }
  2843.     return (FALSE); // Didn't process the message
  2844.  
  2845.     lParam; // This will prevent 'unused formal parameter' warnings
  2846. }
  2847.  
  2848.