home *** CD-ROM | disk | FTP | other *** search
/ Chip 1997 December / CHIP_CD_1997_12_PL.iso / software / szachy / gnuchess / src / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-07  |  31.6 KB  |  1,013 lines

  1. /*
  2.  * main.c - C source for GNU CHESS for Windows
  3.  *
  4.  * Copyright (c) 1988,1989,1990 John Stanback
  5.  * Copyright (c) 1992-1995 Free Software Foundation
  6.  * Modified by Conor McCarthy for the Windows environment
  7.  * Additions for the Windows version Copyright (c) 1996 Conor McCarthy
  8.  *
  9.  * This file is part of GNU CHESS.
  10.  *
  11.  * GNU Chess is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2, or (at your option)
  14.  * any later version.
  15.  *
  16.  * GNU Chess is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GNU Chess; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25. #ifdef WIN386
  26.  #define INCLUDE_COMMDLG_H
  27. #endif
  28. #include "gnuchess.h"
  29. #ifndef WIN386
  30.  #include <commdlg.h>
  31. #endif
  32. #include "version.h"
  33. #include "ttable.h"
  34. #include <dos.h>
  35. #include <signal.h>
  36. #if defined Think_C && defined Window_Events
  37. #include <console.h>
  38. #endif
  39. CHAR *ColorStr[2];
  40. CHAR *CP[CPSIZE];
  41.  
  42. UTSHORT ETABLE = DEFETABLE;
  43. CHAR savefile[128] = "";
  44. CHAR listfile[128] = "";
  45. #ifdef HISTORY
  46. UTSHORT history[32768];
  47. #endif
  48. tshort svalue[64];
  49. struct leaf Tree[TREE], *root;
  50. SHORT TrPnt[MAXDEPTH+1];
  51. SHORT PieceList[2][64], PawnCnt[2][8];
  52. SHORT castld[2], Mvboard[64];
  53. struct flags flag;
  54. SHORT opponent, computer, dither;
  55. tshort  WAwindow, WBwindow, WXwindow, BAwindow, BBwindow, BXwindow;
  56. SHORT  INCscore;
  57. long ResponseTime, ExtraTime, MaxResponseTime, et, et0, time0, ft;
  58. unsigned long GenCnt, NodeCnt, ETnodes, EvalNodes;
  59. long replus, reminus;
  60. tshort HashDepth = HASHDEPTH, HashMoveLimit = HASHMOVELIMIT;
  61. SHORT player;
  62. struct GameRec GameList[MAXMOVES + MAXDEPTH];
  63. SHORT Sdepth, Game50, MaxSearchDepth;
  64. SHORT GameCnt = 0;
  65. SHORT epsquare;
  66. tshort  contempt, xwndw;
  67. int Book;
  68. struct TimeControlRec TimeControl;
  69. int TCadd = 0;
  70. SHORT TCflag, TCmoves, TCminutes, TCseconds, OperatorTime;
  71. SHORT XCmoves[3], XCminutes[3], XCseconds[3],XCadd[3], XC, XCmore;
  72. const SHORT otherside[3] =
  73. {black, white, neutral};
  74. SHORT hint;
  75. SHORT TOflag;     /* force search re-init if we backup search */
  76.  
  77. SHORT mtl[2], pmtl[2], hung[2];
  78. SHORT Pindex[64];
  79. SHORT PieceCnt[2];
  80. SHORT FROMsquare, TOsquare;
  81. SHORT HasKnight[2], HasBishop[2], HasRook[2], HasQueen[2];
  82. SHORT ChkFlag[MAXDEPTH], CptrFlag[MAXDEPTH], PawnThreat[MAXDEPTH];
  83. SHORT QueenCheck[MAXDEPTH]; /* tom@izf.tno.nl */
  84. SHORT NMoves[MAXDEPTH]; /* tom@izf.tno.nl */
  85. SHORT Threat[MAXDEPTH]; /* tom@izf.tno.nl */
  86. SHORT ThreatSave[MAXDEPTH]; /* tom@izf.tno.nl */
  87. SHORT Pscore[MAXDEPTH], Tscore[MAXDEPTH];
  88. const SHORT qrook[3] =
  89. {0, 56, 0};
  90. const SHORT krook[3] =
  91. {7, 63, 0};
  92. const SHORT kingP[3] =
  93. {4, 60, 0};
  94. const SHORT rank7[3] =
  95. {6, 1, 0};
  96. const SHORT sweep[8] =
  97. {false, false, false, true, true, true, false, false};
  98. UTSHORT killr0[MAXDEPTH+1], killr1[MAXDEPTH+1], killr2[MAXDEPTH+1];
  99. UTSHORT PV, SwagHt, Swag0, Swag1, Swag2, Swag4, sidebit;
  100. #ifdef KILLT
  101. tshort killt[0x4000];
  102. #endif
  103. const SHORT value[7] =
  104. {0, valueP, valueN, valueB, valueR, valueQ, valueK};
  105. const SHORT control[7] =
  106. {0, ctlP, ctlN, ctlB, ctlR, ctlQ, ctlK};
  107. SHORT stage, stage2, Developed[2];
  108. unsigned int starttime;
  109. SHORT PCRASH, PCENTER;
  110.  
  111. char szAppName[]="GNU Chess";
  112. char szChess[]="CHESS";
  113. char szHelpFile[]="gnuchess.hlp";
  114. char move[6];
  115. SHORT command=0;
  116. SHORT LineSpace,SLineSpace,CharWidth,CompColorExt,WhoseTurnExt,
  117.      CompMoveExt,squarebd;
  118. HWND hWnd;
  119. HFONT hFont;
  120. char msg[200];
  121. SHORT selected;
  122. SHORT selectX,selectY;
  123. HANDLE hInst;
  124. HBRUSH hBrushBackGround,hDlgBkgrnd;
  125. HWND hComputerColor,hWhoseTurn,hInCheck,hComputerMove,hClockBlack,
  126.      hClockWhite,hBlack,hWhite,hDepth,hStats;
  127. HACCEL hAccel;
  128. SHORT ok;
  129. DWORD CustCols[16];
  130. CHOOSECOLOR cc;
  131. extern char *lpszTitle;
  132. extern tshort DlgInt1,DlgInt2,DlgInt3,DlgInt4,DlgInt5,DlgInt6;
  133. extern long size;
  134. extern int Znodes;
  135. char szBtnBar[]="btnbar";
  136. extern SHORT button;
  137. extern SHORT WinSizeX,WinSizeY,WinPosX,WinPosY;
  138. extern HWND hBtnWnd;
  139. extern SHORT origbrd[64],origcol[64];
  140. SHORT OrigGameCnt;
  141. extern RECT wr;
  142. extern SHORT maximized,forcing;
  143. BOOL CALLBACK (*lpfnDlgProc)(HWND, unsigned, WORD, LONG);
  144.  
  145.  
  146. LRESULT WINAPI WndProc(HWND, UINT, WPARAM, LPARAM) ;
  147. LRESULT WINAPI BtnWndProc(HWND, UINT, WPARAM, LPARAM) ;
  148. void SizeWindow(int);
  149. BOOL GetColor(DWORD);
  150. void LoadDefaultColors(void);
  151. BOOL LoadSettings(void);
  152. void SaveSettings(void);
  153. BOOL CALLBACK ChangeWinDlgProc (HWND, UINT, WPARAM, LPARAM);
  154. BOOL CALLBACK HashDepthDlgProc (HWND, UINT, WPARAM, LPARAM);
  155. BOOL CALLBACK GetNumDlgProc (HWND, UINT, WPARAM, LPARAM);
  156. BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM);
  157. BOOL CALLBACK TimeDlgProc (HWND, UINT, WPARAM, LPARAM);
  158. BOOL CALLBACK StatDlgProc (HWND, UINT, WPARAM, LPARAM);
  159. BOOL CALLBACK TypeMoveDlgProc (HWND, UINT, WPARAM, LPARAM);
  160. BOOL CALLBACK PromoteDlgProc (HWND, UINT, WPARAM, LPARAM);
  161. BOOL CALLBACK CreateHashDlgProc (HWND, UINT, WPARAM, LPARAM);
  162.  
  163. int timeopp[MINGAMEIN], timecomp[MINGAMEIN];
  164. int compptr, oppptr;
  165. inline void
  166. TimeCalc ()
  167. {
  168. /* adjust number of moves remaining in gamein games */
  169.   int increment = 0;
  170.   int topsum = 0;
  171.   int tcompsum = 0;
  172.   int me,him;
  173.   int i;
  174. /* dont do anything til you have enough numbers */
  175.   if (GameCnt < (MINGAMEIN * 2)) return;
  176. /* calculate average time in sec for last MINGAMEIN moves */
  177.   for (i = 0; i < MINGAMEIN; i++)
  178.     {
  179.       tcompsum += timecomp[i];
  180.       topsum += timeopp[i];
  181.     }
  182.   topsum /= (100 * MINGAMEIN);
  183.   tcompsum /= (100 * MINGAMEIN);
  184. /* if I have less time than opponent add another move */
  185.    me = TimeControl.clock[computer]/100; 
  186.    him = TimeControl.clock[opponent]/100;
  187.    if(me < him) increment += 2;
  188. /* if I am > 60 sec behind increment or if I am less and in last 2 min */
  189.    if((him - me) > 60 || (me<him && me < 120))increment++;
  190. /* if I am losing more time with each move add another */
  191.   if ( ((me - him) > 60) && tcompsum < topsum) increment--;
  192.   if ( tcompsum > topsum) increment +=2;
  193. /* if I am doing really well use more time per move */
  194.   else if (me > him && tcompsum < topsum) increment = -1;
  195.   if (me > (him+60) ) increment = -1;
  196.   TimeControl.moves[computer] += increment;
  197. /* but dont let moves go below MINMOVES */
  198.   if (TimeControl.moves[computer] < MINMOVES )TimeControl.moves[computer] = MINMOVES;
  199. }
  200.  
  201. int PASCAL WinMain (HANDLE hInstance, HANDLE
  202. hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
  203. {
  204.   WNDCLASS   wndClass;
  205.  
  206.   if (LoadSettings()) nCmdShow = SW_SHOWMAXIMIZED;
  207.   hBrushBackGround=CreateSolidBrush(clrBackGround);
  208.   hDlgBkgrnd=CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  209.  
  210.   wndClass.style        =0;
  211.   wndClass.lpfnWndProc  =WndProc;
  212.   wndClass.cbClsExtra   =0;
  213.   wndClass.cbWndExtra   =0;
  214.   wndClass.hInstance    =hInstance;
  215.   wndClass.hIcon        =LoadIcon(hInstance,szChess);
  216.   wndClass.hCursor      =LoadCursor(NULL,IDC_ARROW);
  217.   wndClass.hbrBackground=0;
  218.   wndClass.lpszMenuName =szChess;
  219.   wndClass.lpszClassName=szAppName;
  220.   if (!RegisterClass(&wndClass))return FALSE;
  221.   wndClass.style=0;
  222.   wndClass.lpfnWndProc=BtnWndProc;
  223.   wndClass.hbrBackground=GetStockObject(LTGRAY_BRUSH);
  224.   wndClass.lpszMenuName=0;
  225.   wndClass.lpszClassName=szBtnBar;
  226.   if (!RegisterClass(&wndClass))return false;
  227.  
  228.   hInst=hInstance;
  229.   InitConst (0);
  230.   GetMetrics();
  231.   InitScreen();
  232.   hAccel=LoadAccelerators(hInstance,szChess);
  233.   hWnd = CreateWindow(szAppName,szAppName,WS_OVERLAPPEDWINDOW,
  234.              WinPosX,WinPosY,WinSizeX,WinSizeY,NULL,NULL,hInstance,NULL);
  235.   if (!WinSizeX || !WinSizeY) SizeWindow(1);
  236.   ShowWindow(hWnd, nCmdShow);
  237.   CheckMenuItem ( GetMenu(hWnd), boardsize/12+IDM_SMALL, MF_CHECKED);
  238.   CreateStatics();
  239.   {
  240.     long t;        /*rough speed test to calculate Znodes*/
  241.     SHORT i;
  242.     t=GetTickCount();
  243.     while(GetTickCount()-t<250) {Znodes++; for(i=0;i<5000;i++);}
  244.   }
  245.   gsrand (starttime = ((unsigned int) time ((long *) 0)));  /* init urand */
  246. #ifdef ttblsz
  247.   ttblsize = ttblsz;
  248.   rehash = -1;
  249. #endif /* ttblsz */
  250.   ColorStr[0] = CP[40];
  251.   ColorStr[1] = CP[41];
  252.   TCflag = false;
  253.  
  254.  {
  255.   SHORT i;
  256.   for ( i=pawn; i<=king; i++ )
  257.    {
  258.      pieces[i].detail = LoadBitmap (hInst, MAKEINTRESOURCE(i+boardsize));
  259.      pieces[i].mask = LoadBitmap (hInst, MAKEINTRESOURCE(i+boardsize+6));
  260.    }
  261.  }
  262.  
  263.   Initialize_dist ();
  264.   Initialize_moves ();
  265.   NewGame ();
  266.  
  267.   if (flag.post) /*if post is set in the ini file*/
  268.    {
  269.     flag.post=false;
  270.     SendMessage(hWnd,WM_COMMAND,IDM_POST,0L);
  271.    }
  272.  
  273.   OpenHashFile(); /* Open persistent transposition table */
  274.   while (!(flag.quit))
  275.     {
  276.       oppptr = (oppptr + 1) % MINGAMEIN;
  277.       if (flag.bothsides && !flag.mate && !flag.quit)
  278.        {
  279.         SaveBoard();
  280.         SelectMove (opponent, 1);
  281.         if (flag.abort || command) {command|=0x8000; InputCommand(); }
  282.        }
  283.       else
  284.     InputCommand ();
  285.       if (opponent == black)
  286.    if (flag.gamein || TCadd)
  287.      {
  288.        TimeCalc ();
  289.      }
  290.    else if (TimeControl.moves[opponent] == 0 && TCflag)
  291.      {
  292.        SetTimeControl ();
  293.      }
  294.  
  295.       compptr = (compptr + 1) % MINGAMEIN;
  296.       if (!(flag.quit || flag.mate || flag.force))
  297.    {
  298.      SaveBoard();
  299.      SelectMove (computer, 1);
  300.      if (computer == black)
  301.        if (flag.gamein)
  302.          {
  303.       TimeCalc ();
  304.          }
  305.        else if (TimeControl.moves[computer] == 0 && TCflag)
  306.          {
  307.       SetTimeControl ();
  308.          }
  309.    }
  310.     }
  311.         CloseHashFile();
  312.  
  313.   Exit(0);
  314.   return 0;
  315. }
  316.  
  317. LRESULT WINAPI WndProc(HWND hWnd, UINT Message,
  318.                        WPARAM wParam, LPARAM lParam)
  319. {
  320.   HDC hDC;
  321.   HANDLE hOld;
  322.   PAINTSTRUCT ps;
  323.   short y;
  324.  
  325.   switch(Message)
  326.   { case WM_PAINT:
  327.       hDC=BeginPaint(hWnd,&ps);
  328.       UpdateDisplay(0,0,1,0,hDC);
  329.       if (selected)
  330.        {
  331.          HRGN hRgn;
  332.  
  333.          hRgn=CreatePolygonRgn(&squares[selectX][selectY][0],
  334.                  4, ALTERNATE);
  335.          InvertRgn(hDC,hRgn);
  336.          DeleteObject(hRgn);
  337.        }
  338.       EndPaint(hWnd,&ps);
  339.       return 0;
  340.  
  341.     case WM_KEYDOWN:
  342.       switch (wParam)
  343.        {
  344.         case VK_CANCEL:
  345.           flag.timeout=true;
  346.           break;
  347.         case 13:
  348.           if (flag.replay) command=1;
  349.           break;
  350.         case VK_F2:
  351.           if (player==opponent || flag.editing || flag.force)
  352.            {
  353.             lpfnDlgProc = MakeProcInstance ( TypeMoveDlgProc, hInst);
  354.             if (DialogBox ( hInst, MAKEINTRESOURCE(NUMDLG), hWnd,
  355.                 lpfnDlgProc))
  356.               {
  357.                command=1;
  358.                if (flag.bothsides && !flag.editing)
  359.                 {
  360.                  flag.bothsides=false;
  361.                  flag.abort=flag.timeout=true;
  362.                 }
  363.               }
  364.             FreeProcInstance ( lpfnDlgProc);
  365.            }
  366.           else ShowMessage(CP[62]);
  367.           break;
  368.         default: if (flag.editing && wParam>='0' && wParam<='9')
  369.           {
  370.             wParam-='0';
  371.             if (!wParam)wParam=10;
  372.             PostMessage(hBtnWnd,WM_LBUTTONDOWN,0,--wParam*(bmsize+5)+pawn);
  373.           }
  374.          else return 1;
  375.        }
  376.       return 0;
  377.  
  378. #ifdef WIN32
  379.     case WM_CTLCOLORSTATIC:
  380.       SetTextColor((HDC)wParam,clrText);
  381.       SetBkMode((HDC)wParam,TRANSPARENT);
  382.       return hBrushBackGround;
  383. #else
  384.     case WM_CTLCOLOR:
  385.       switch(HIWORD(lParam))
  386.         {
  387.          case CTLCOLOR_STATIC:
  388.            SetTextColor((HDC)wParam,clrText);
  389.            SetBkMode((HDC)wParam,TRANSPARENT);
  390.            return hBrushBackGround;
  391.         }
  392.     return 0;
  393. #endif
  394.  
  395.     case WM_LBUTTONDOWN:
  396.      if (player==opponent || flag.force)
  397.      {
  398.       UINT xsq,ysq,width,margin;
  399.       SHORT x,y;
  400.       HRGN hRgn;
  401.  
  402.       if (flag.replay) {command=1;return 0;}
  403.       x=LOWORD(lParam);
  404.       y=HIWORD(lParam);
  405.       if (y<BACKMARGIN || y>BACKMARGIN+sqdepth*8)return 0;/*is y o the board?*/
  406.       width=sqwidthB*8+deltaX*(y-BACKMARGIN)/(sqdepth*8);
  407.       margin=((sqwidthF*8-width)>>1)+LEFTMARGIN;
  408.       if (x<margin || x>=width+margin) return 0;  /*is x on the board?*/
  409.       xsq=8*(x-margin)/width;
  410.       ysq=7-(y-BACKMARGIN)/sqdepth;
  411.       if (!selected && !button)
  412.        {
  413.         selected=1;
  414.         selectX=xsq;
  415.         selectY=ysq;
  416.         hRgn=CreatePolygonRgn(&squares[xsq][ysq][0],4, ALTERNATE);
  417.         hDC=GetDC(hWnd);
  418.         InvertRgn(hDC,hRgn);
  419.         ReleaseDC(hWnd,hDC);
  420.         DeleteObject(hRgn);
  421.        }
  422.       else
  423.        {
  424.         if (!button) /*no squares are highlighted if a button is down*/
  425.          {
  426.           hRgn=CreatePolygonRgn(&squares[selectX][selectY][0],
  427.                  4, ALTERNATE);
  428.           hDC=GetDC(hWnd);
  429.           InvertRgn(hDC,hRgn);  /*restore square to normal*/
  430.           ReleaseDC(hWnd,hDC);
  431.           DeleteObject(hRgn);
  432.          }
  433.         selected=0;
  434.         if (xsq==selectX && ysq==selectY && !flag.editing)return 0;
  435.         if (flag.reverse)
  436.          {
  437.            selectX = 7-selectX;
  438.            xsq = 7-xsq;
  439.            selectY = 7-selectY;
  440.            ysq = 7-ysq;
  441.          }
  442.         move[0]=(char)selectX+'a';
  443.         move[2]=(char)xsq+'a';
  444.         move[1]='1'+(char)selectY;
  445.         move[3]='1'+(char)ysq;
  446.         move[4]=0;
  447.         if (!flag.editing
  448.             && ((ysq==0 && selectY==1)||(ysq==7 && selectY==6))
  449.             && abs(selectX-xsq)<=1
  450.             && (player==white ? ysq>selectY : ysq<selectY) )
  451.          {
  452.            SHORT *brdptr,*colptr;
  453.            if (flag.searching) {brdptr=&origbrd; colptr=&origcol;}
  454.            else {brdptr=&board; colptr=&color;}
  455.            if (*(brdptr+selectX+selectY*8)==pawn
  456.             && *(colptr+selectX+selectY*8)==player
  457.             && ( abs(selectX-xsq)==0 ? *(brdptr+xsq+ysq*8)==no_piece
  458.                                      : *(colptr+xsq+ysq*8)==!player ) )
  459.             {
  460.              lpfnDlgProc = MakeProcInstance(PromoteDlgProc, hInst);
  461.              move[4] = CP[1][DialogBox(hInst, MAKEINTRESOURCE(PROMOTE),
  462.                 hWnd, lpfnDlgProc)];  /*promotion*/
  463.              FreeProcInstance(lpfnDlgProc);
  464.              move[5]=0;
  465.             }
  466.          }
  467.         if (button) move[0]=0; /*editing - allow delete with right button
  468.                                  while a piece button is down*/
  469.         if (!flag.editing)
  470.          {
  471.            if ((!flag.easy || flag.bothsides) && player==opponent)
  472.               flag.timeout = true;
  473.            if (flag.bothsides) {flag.abort=true; flag.bothsides = false; }
  474.          }
  475.         command=1;
  476.        }
  477.      }
  478.      return 0;
  479.  
  480.     case WM_RBUTTONDOWN:
  481.       if (flag.replay) {command=1; return 0;}
  482.       if (flag.editing)
  483.       {
  484.        SHORT x,y;
  485.        UINT width,margin;
  486.        x=LOWORD(lParam);
  487.        y=HIWORD(lParam);
  488.        if (y<BACKMARGIN || y>BACKMARGIN+sqdepth*8)return 0;
  489.        width=sqwidthB*8+deltaX*(y-BACKMARGIN)/(sqdepth*8);
  490.        margin=((sqwidthF*8-width)>>1)+LEFTMARGIN;
  491.        if (x<margin || x>=width+margin) return 0;
  492.        if (flag.reverse)
  493.         {
  494.          move[0]='h'-8*(x-margin)/width;
  495.          move[1]='1'+(y-BACKMARGIN)/sqdepth;
  496.         }
  497.        else
  498.         {
  499.          move[0]='a'+8*(x-margin)/width;
  500.          move[1]='8'-(y-BACKMARGIN)/sqdepth;
  501.         }
  502.        move[2]=move[0];
  503.        move[3]=move[1];
  504.        move[4]=0;
  505.        command=1;
  506.       }
  507.       return 0;
  508.  
  509.     case WM_ERASEBKGND:
  510.       {
  511.          RECT rect;
  512.          UnrealizeObject ( hBrushBackGround);
  513.          GetClientRect ( hWnd, &rect);
  514.          FillRect ( (HDC)wParam, &rect, hBrushBackGround);
  515.          return 1;
  516.       }
  517.  
  518.     case WM_COMMAND:
  519.       switch (LOWORD(wParam))
  520.        {
  521.         case IDM_QUIT:
  522.           flag.quit=true;
  523.           GetWindowRect(hWnd,&wr);
  524.           maximized=IsZoomed(hWnd);
  525.           if (IsIconic(hWnd)) wr.right = 0;
  526.           WinHelp(hWnd,szHelpFile,HELP_QUIT,0L);
  527.         case IDM_GET:
  528.         case IDM_NEW:
  529.         case IDM_LIST:
  530.         case IDM_EDIT:
  531.         case IDM_REVIEW:
  532.         case IDM_REMOVE:
  533.         case IDM_UNDO:
  534.         case IDM_FORCE:
  535.         case IDM_SWITCH:
  536.         case IDM_SWITCHDM:
  537.         case IDM_WHITE:
  538.         case IDM_BLACK:
  539.         case IDM_COMPILE:
  540.           flag.timeout=flag.abort=true;
  541.           flag.bothsides=false;
  542.           command=LOWORD(wParam);
  543.           break;
  544.         case IDM_SAVE:
  545.           flag.timeout=true;
  546.           flag.bothsides=false;
  547.           command=LOWORD(wParam);
  548.           break;
  549.  
  550.         case IDM_BOTH:
  551.           if (!flag.searching)
  552.            {
  553.             command=LOWORD(wParam);
  554.             break;
  555.            }
  556.           if (flag.bothsides)
  557.            {
  558.             flag.bothsides=false;
  559.             if (player==opponent)   /*computer is making opponents move*/
  560.                flag.abort=flag.timeout=true; /*so abort it*/
  561.            }
  562.           else
  563.            if (player==opponent) /*computer is thinking on opponent's time*/
  564.             {
  565.               flag.timeout=true;
  566.               command=LOWORD(wParam);
  567.             }
  568.            else flag.bothsides=true;
  569.           break;
  570.         case IDM_WTM:
  571.         case IDM_BTM:
  572.           if (player==(LOWORD(wParam)==IDM_WTM)? white : black) break;
  573.           flag.timeout=flag.abort=true;
  574.           flag.bothsides=false;
  575.           command=LOWORD(wParam);
  576.           break;
  577.  
  578.         case IDM_BEEP:
  579.           flag.beep=!flag.beep;
  580.           break;
  581.         case IDM_COORD:
  582.           flag.coords=!flag.coords;
  583.           InvalidateRect(hWnd,0,true);
  584.           break;
  585.         case IDM_POST:
  586.           if ( flag.post )
  587.            {
  588.             SendMessage ( hStats, WM_COMMAND, IDOK, 0 );
  589.             flag.post = false;
  590.            }
  591.           else
  592.            {
  593.             lpfnDlgProc = MakeProcInstance(StatDlgProc, hInst);
  594.             hStats = CreateDialog (hInst, MAKEINTRESOURCE(STATS),
  595.                 hWnd, lpfnDlgProc);
  596.             flag.post = true;
  597.            }
  598.           break;
  599.         case IDM_ANIMATE:
  600.           flag.animate=!flag.animate;
  601.           if (!flag.animate)
  602.            {
  603.             UpdateDisplay(0,0,1,0,0);
  604.             Znodes<<=4;
  605.            }
  606.           else Znodes>>=4;
  607.           break;
  608.         case IDM_HASH:
  609.           flag.hash=!flag.hash;
  610.           break;
  611.         case IDM_BOOK:
  612.           flag.usebook=!flag.usebook;
  613.           Book = flag.usebook ? BOOKFAIL : 0;
  614.           break;
  615.         case IDM_HDEPTH:
  616.           lpfnDlgProc = MakeProcInstance ( HashDepthDlgProc, hInst);
  617.           if (DialogBox ( hInst, MAKEINTRESOURCE(HASHDEPTHDLG), hWnd,
  618.                 lpfnDlgProc))
  619.            {
  620.             HashDepth=DlgInt1;
  621.             HashMoveLimit=DlgInt2;
  622.            }
  623.           FreeProcInstance ( lpfnDlgProc);
  624.           break;
  625.         case IDM_HFILE:
  626.           lpfnDlgProc = MakeProcInstance ( CreateHashDlgProc, hInst);
  627.           if (DialogBox ( hInst, MAKEINTRESOURCE(CREATEHASH), hWnd,
  628.                 lpfnDlgProc))
  629.            {
  630.             if (size < 24)
  631.                 size = (1 << size);
  632.             if (size>0) CreateHashFile(size);
  633.            }
  634.           FreeProcInstance ( lpfnDlgProc);
  635.           break;
  636.         case IDM_WIN:
  637.           lpfnDlgProc = MakeProcInstance ( ChangeWinDlgProc, hInst);
  638.           if (DialogBox ( hInst, MAKEINTRESOURCE(CHANGEWINDOW), hWnd,
  639.                 lpfnDlgProc))
  640.           {
  641.             WAwindow=DlgInt1;
  642.             WBwindow=DlgInt2;
  643.             WXwindow=DlgInt3;
  644.             BAwindow=DlgInt4;
  645.             BBwindow=DlgInt5;
  646.             BXwindow=DlgInt6;
  647.             xwndw = (computer == white) ? WXwindow : BXwindow;
  648.           }
  649.           FreeProcInstance ( lpfnDlgProc);
  650.           break;
  651.         case IDM_CONTEMP:
  652.           lpszTitle=CP[64];
  653.           DlgInt1=contempt;
  654.           lpfnDlgProc = MakeProcInstance ( GetNumDlgProc, hInst);
  655.           if (DialogBoxParam ( hInst, MAKEINTRESOURCE(NUMDLG), hWnd,
  656.                 lpfnDlgProc,46L)) contempt=DlgInt1;
  657.           FreeProcInstance ( lpfnDlgProc);
  658.           break;
  659.         case IDM_MATERIAL:
  660.           flag.material=!flag.material;
  661.           break;
  662.         case IDM_RCPTR:
  663.           flag.rcptr=!flag.rcptr;
  664.           break;
  665.         case IDM_THREAT:
  666.           flag.threat=!flag.threat;
  667.           break;
  668.         case IDM_PVS:
  669.           flag.pvs=!flag.pvs;
  670.           break;
  671.         case IDM_NEWEVAL:
  672.           flag.neweval=!flag.neweval;
  673.           break;
  674.         case IDM_GAMEIN:
  675.           flag.gamein=!flag.gamein;
  676.           break;
  677.  
  678.         case IDM_TIME:
  679.           lpfnDlgProc = MakeProcInstance ( TimeDlgProc, hInst);
  680.           DialogBox ( hInst, MAKEINTRESOURCE(TIME), hWnd, lpfnDlgProc);
  681.           FreeProcInstance ( lpfnDlgProc);
  682.           break;
  683.         case IDM_RANDOM:
  684.           dither = (dither)?0:DITHER;
  685.           break;
  686.         case IDM_EASY:
  687.           flag.easy = !flag.easy;
  688.           if (flag.easy && flag.searching && player==opponent)
  689.               flag.timeout=true;
  690.           break;
  691.         case IDM_DEPTH:
  692.           lpszTitle=CP[61];
  693.           DlgInt1=MaxSearchDepth;
  694.           lpfnDlgProc = MakeProcInstance ( GetNumDlgProc, hInst);
  695.           if (DialogBoxParam ( hInst, MAKEINTRESOURCE(NUMDLG), hWnd,
  696.                    lpfnDlgProc,47L)) MaxSearchDepth=DlgInt1;
  697.           FreeProcInstance ( lpfnDlgProc);
  698.           TCflag = !(MaxSearchDepth > 0);
  699.           break;
  700.  
  701.         case IDM_REVERSE:
  702.           flag.reverse=!flag.reverse;
  703.           if(selected) {selectX=7-selectX; selectY=7-selectY;}
  704.           InvalidateRect(hWnd,0,true);
  705.           break;
  706.  
  707.         case IDM_BACKGROUND:
  708.           if (GetColor(clrBackGround))
  709.            {
  710.             clrBackGround=cc.rgbResult;
  711.             InvalidateRect(hWnd,0,true);
  712.             DeleteObject (hBrushBackGround);
  713.             hBrushBackGround = CreateSolidBrush ( clrBackGround );
  714.            }
  715.           break;
  716.         case IDM_BLACKSQUARE:
  717.           if (GetColor(clrBlackSquare))
  718.            {
  719.             clrBlackSquare=cc.rgbResult;
  720.             UpdateDisplay(0, 0, 1, 0, 0);
  721.            }
  722.           break;
  723.         case IDM_WHITESQUARE:
  724.           if (GetColor(clrWhiteSquare))
  725.            {
  726.             clrWhiteSquare=cc.rgbResult;
  727.             UpdateDisplay(0, 0, 1, 0, 0);
  728.            }
  729.           break;
  730.         case IDM_BLACKPIECE:
  731.           if (GetColor(clrBlackPiece))
  732.            {
  733.             clrBlackPiece=cc.rgbResult;
  734.             UpdateDisplay(0, 0, 1, 0, 0);
  735.            }
  736.           break;
  737.         case IDM_WHITEPIECE:
  738.           if (GetColor(clrWhitePiece))
  739.            {
  740.             clrWhitePiece=cc.rgbResult;
  741.             UpdateDisplay(0, 0, 1, 0, 0);
  742.            }
  743.           break;
  744.         case IDM_TEXT:
  745.           if (GetColor(clrText))
  746.            {
  747.             clrText=cc.rgbResult;
  748.             InvalidateRect (hWnd, NULL, TRUE);
  749.            }
  750.           break;
  751.         case IDM_EDGE:
  752.           if (GetColor(clrEdge))
  753.            {
  754.             clrEdge=cc.rgbResult;
  755.             UpdateDisplay(0, 0, 1, 0, 0);
  756.            }
  757.           break;
  758.         case IDM_DEFAULT:
  759.           LoadDefaultColors();
  760.           DeleteObject(hBrushBackGround);
  761.           hBrushBackGround=CreateSolidBrush(clrBackGround);
  762.           InvalidateRect(hWnd,0,true);
  763.           break;
  764.  
  765.         case IDM_SMALL:
  766.         case IDM_MEDIUM:
  767.         case IDM_LARGE:
  768.          {
  769.           SHORT i;
  770.  
  771.           CheckMenuItem ( GetMenu(hWnd), boardsize/12+IDM_SMALL,
  772.                      MF_UNCHECKED);
  773.           boardsize=(LOWORD(wParam)-IDM_SMALL)*12;
  774.           CheckMenuItem ( GetMenu(hWnd), LOWORD(wParam), MF_CHECKED);
  775.           for (i=pawn;i<=king;i++)
  776.           { DeleteObject(pieces[i].detail);
  777.             DeleteObject(pieces[i].mask);
  778.             pieces[i].detail = LoadBitmap (hInst, MAKEINTRESOURCE(i+boardsize));
  779.             pieces[i].mask = LoadBitmap (hInst, MAKEINTRESOURCE(i+boardsize+6));
  780.           }
  781.           InitScreen();
  782.           MoveStatics();
  783.           SizeWindow(0);
  784.           InvalidateRect(hWnd,0,TRUE);
  785.           break;
  786.          }
  787.         case IDM_3D:
  788.           squarebd=0;
  789.           goto changebd;
  790.         case IDM_SQUARE:
  791.           squarebd=1;
  792. changebd:
  793.           InitScreen();
  794.           MoveStatics();
  795.           SizeWindow(0);
  796.           InvalidateRect(hWnd,0,TRUE);
  797.           break;
  798.         case IDM_HINT:
  799.           GiveHint();
  800.           break;
  801.  
  802.         case IDM_INDEX:
  803.           if (!WinHelp(hWnd,szHelpFile,HELP_CONTENTS,0L))
  804.              ShowMessage("Could not open gnuchess.hlp");
  805.           break;
  806.         case IDM_HELP:
  807.           if (!WinHelp(hWnd,"winhelp.hlp",HELP_HELPONHELP,0L))
  808.              ShowMessage("Could not open winhelp.hlp");
  809.           break;
  810.         case IDM_ABOUT:
  811.           lpfnDlgProc = MakeProcInstance ( AboutDlgProc, hInst);
  812.           DialogBox (hInst,MAKEINTRESOURCE(ABOUT),hWnd,lpfnDlgProc);
  813.           FreeProcInstance ( lpfnDlgProc);
  814.           break;
  815.  
  816.         case IDM_CLEAR:     /*editing*/
  817.           {
  818.            short i;
  819.            for (i=0;i<64;i++){board[i]=no_piece;color[i]=neutral;}
  820.           }
  821.           board[4]=board[60]=king;
  822.           color[4]=white;
  823.           color[60]=black;
  824.           selected=0;
  825.           UpdateDisplay(0,0,1,0,0);
  826.           break;
  827.         case IDM_RESTORE:     /*editing*/
  828.           {
  829.            short i;
  830.            for (i=0;i<64;i++)
  831.             {
  832.              board[i]=Stboard[i];
  833.              color[i]=Stcolor[i];
  834.             }
  835.            selected=0;
  836.            UpdateDisplay(0,0,1,0,0);
  837.            break;
  838.           }
  839.         case IDM_PREV:        /*replay*/
  840.         case IDM_NEXT:
  841.         case IDM_DONE:        /*editing*/
  842.           command=LOWORD(wParam);
  843.        }
  844.       return 0;
  845.  
  846.     case WM_INITMENUPOPUP:
  847.       if (!flag.editing) switch (lParam)
  848.       {
  849.        case 0:       /*Game menu*/
  850.             EnableMenuItem ( (HMENU)wParam, IDM_SAVE,
  851.                              (GameCnt>0 ? MF_ENABLED : MF_GRAYED) );
  852.             EnableMenuItem ( (HMENU)wParam, IDM_LIST,
  853.                              (GameCnt>0 ? MF_ENABLED : MF_GRAYED) );
  854.             break;
  855.        case 1:       /*Edit Menu */
  856.             EnableMenuItem ( (HMENU)wParam, IDM_REVIEW,
  857.                              (GameCnt>0 ? MF_ENABLED : MF_GRAYED) );
  858.             EnableMenuItem ( (HMENU)wParam, IDM_UNDO,
  859.                              (GameCnt>0 ? MF_ENABLED : MF_GRAYED) );
  860.             EnableMenuItem ( (HMENU)wParam, IDM_REMOVE,
  861.                           ((flag.searching ? OrigGameCnt : GameCnt)>1
  862.                            ? MF_ENABLED : MF_GRAYED) );
  863.             break;
  864.        case 2:  /* Options Menu */
  865.             CheckMenuItem ( (HMENU)wParam, IDM_HASH,
  866.                      flag.hash?MF_CHECKED:MF_UNCHECKED);
  867.             EnableMenuItem ( (HMENU)wParam, IDM_HASH,
  868.                      (hashfile ? MF_ENABLED : MF_GRAYED) );
  869.             CheckMenuItem ( (HMENU)wParam, IDM_COORD,
  870.                      flag.coords?MF_CHECKED:MF_UNCHECKED);
  871.             CheckMenuItem ( (HMENU)wParam, IDM_BEEP,
  872.                      flag.beep?MF_CHECKED:MF_UNCHECKED);
  873.             CheckMenuItem ( (HMENU)wParam, IDM_BOOK,
  874.                      flag.usebook?MF_CHECKED:MF_UNCHECKED);
  875.             CheckMenuItem ( (HMENU)wParam, IDM_POST,
  876.                      flag.post?MF_CHECKED:MF_UNCHECKED);
  877.             CheckMenuItem ( (HMENU)wParam, IDM_ANIMATE,
  878.                      flag.animate?MF_CHECKED:MF_UNCHECKED);
  879.             CheckMenuItem ( (HMENU)wParam, IDM_MATERIAL,
  880.                      flag.material?MF_CHECKED:MF_UNCHECKED);
  881.             CheckMenuItem ( (HMENU)wParam, IDM_RCPTR,
  882.                      flag.rcptr?MF_CHECKED:MF_UNCHECKED);
  883.             CheckMenuItem ( (HMENU)wParam, IDM_THREAT,
  884.                      flag.threat?MF_CHECKED:MF_UNCHECKED);
  885.             CheckMenuItem ( (HMENU)wParam, IDM_PVS,
  886.                      flag.pvs?MF_CHECKED:MF_UNCHECKED);
  887.             CheckMenuItem ( (HMENU)wParam, IDM_NEWEVAL,
  888.                      flag.neweval?MF_CHECKED:MF_UNCHECKED);
  889.             CheckMenuItem ( (HMENU)wParam, IDM_GAMEIN,
  890.                      flag.gamein?MF_CHECKED:MF_UNCHECKED);
  891.             break;
  892.        case 3:   /*skill menu*/
  893.             CheckMenuItem ( (HMENU)wParam, IDM_RANDOM,
  894.                      dither?MF_CHECKED:MF_UNCHECKED);
  895.             CheckMenuItem ( (HMENU)wParam, IDM_EASY,
  896.                      flag.easy?MF_CHECKED:MF_UNCHECKED);
  897.             break;
  898.        case 4:   /*Side menu*/
  899.           {
  900.             int color=flag.bothsides ? 2
  901.                       : computer^(flag.force & forcing);
  902.             CheckMenuItem ( (HMENU)wParam, IDM_REVERSE,
  903.                      flag.reverse?MF_CHECKED:MF_UNCHECKED);
  904.             CheckMenuItem ( (HMENU)wParam, IDM_BLACK,
  905.                  (color==black)?MF_CHECKED:MF_UNCHECKED);
  906.             CheckMenuItem ( (HMENU)wParam, IDM_WHITE,
  907.                  (color==white)?MF_CHECKED:MF_UNCHECKED);
  908.             CheckMenuItem ( (HMENU)wParam, IDM_BOTH,
  909.                      flag.bothsides?MF_CHECKED:MF_UNCHECKED);
  910.             CheckMenuItem ( (HMENU)wParam, IDM_WTM,
  911.                      player==white?MF_CHECKED:MF_UNCHECKED);
  912.             CheckMenuItem ( (HMENU)wParam, IDM_BTM,
  913.                      player==black?MF_CHECKED:MF_UNCHECKED);
  914.             CheckMenuItem ( (HMENU)wParam, IDM_FORCE,
  915.                    flag.force == false ? MF_UNCHECKED : MF_CHECKED);
  916.           }
  917.        case 5: /*Board menu */
  918.          CheckMenuItem ( (HMENU)wParam, IDM_SQUARE,
  919.                     squarebd?MF_CHECKED:MF_UNCHECKED);
  920.          CheckMenuItem ( (HMENU)wParam, IDM_3D,
  921.                     squarebd?MF_UNCHECKED:MF_CHECKED);
  922.       }
  923.       return 0;
  924.  
  925.     case WM_SYSCOLORCHANGE:
  926.       DeleteObject(hDlgBkgrnd);
  927.       hDlgBkgrnd=CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  928.       return 0;
  929.  
  930.     case WM_DESTROY:
  931.       flag.quit=true;
  932.       flag.timeout=flag.abort=true;
  933.       flag.bothsides=false;
  934.       command=IDM_QUIT;
  935.       GetWindowRect(hWnd,&wr);
  936.       maximized=IsZoomed(hWnd);
  937.       if (IsIconic(hWnd)) wr.right = 0;
  938.       WinHelp(hWnd,szHelpFile,HELP_QUIT,0L);
  939.       return 0;
  940.   }
  941.   return DefWindowProc(hWnd,Message,wParam,lParam);
  942. }
  943.  
  944. void SizeWindow(int move)
  945.   {
  946.     RECT wr;
  947.     WinSizeX=LEFTMARGIN+sqwidthB*8+deltaX/2+20+CompMoveExt
  948.           +GetSystemMetrics(SM_CXFRAME)*2;
  949.     WinSizeY=BACKMARGIN+sqdepth*8+BRD_EDGE+LineSpace+SLineSpace+5
  950.           +GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYFRAME)*2
  951.           +GetSystemMetrics(SM_CYMENU);
  952.     GetWindowRect(GetDesktopWindow(),&wr);
  953.     if (wr.right-wr.left > WinSizeX) WinPosX = (wr.right-WinSizeX)/2;
  954.     else { WinPosX=0; WinSizeX=wr.right-wr.left; }
  955.     if (wr.bottom-wr.top > WinSizeY) WinPosY = (wr.bottom-WinSizeY)/2;
  956.     else { WinPosY=0; WinSizeY=wr.bottom-wr.top; }
  957.     if (!move)
  958.      {
  959.       GetWindowRect(hWnd,&wr);
  960.       WinPosX=wr.left;
  961.       WinPosY=wr.top;
  962.      }
  963.     MoveWindow(hWnd, WinPosX, WinPosY, WinSizeX, WinSizeY, TRUE);
  964.   }
  965.  
  966. void CheckMessage(void)
  967.  {
  968.   MSG msg;
  969.  
  970.   if ( PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  971.     if ( !TranslateAccelerator (hWnd, hAccel, &msg) )
  972.      {    TranslateMessage(&msg);
  973.        DispatchMessage(&msg); }
  974.  }
  975.  
  976. BOOL GetColor(DWORD current)
  977. {
  978.   cc.lStructSize=sizeof(cc);
  979.   cc.hwndOwner=hWnd;
  980.   cc.rgbResult=current;
  981.   cc.lpCustColors=&CustCols;
  982.   cc.Flags=CC_FULLOPEN|CC_RGBINIT;
  983.   return ChooseColor(&cc);
  984. }
  985.  
  986. void LoadDefaultColors()
  987.  {
  988.   clrBackGround  = BROWN;
  989.   clrBlackSquare = DARKGREEN;
  990.   clrWhiteSquare = PALEGRAY;
  991.   clrBlackPiece  = DARKRED;
  992.   clrWhitePiece  = CWHITE;
  993.   clrText        = CBLACK;
  994.   clrEdge        = CBLACK;
  995.  }
  996.  
  997. void
  998. Exit (int code)
  999. {
  1000.   SHORT bm;
  1001.  
  1002.   for (bm=pawn;bm<=king;bm++)
  1003.    {
  1004.     DeleteObject(pieces[bm].mask);
  1005.     DeleteObject(pieces[bm].detail);
  1006.    }
  1007.   DeleteObject(hBrushBackGround);
  1008.   DeleteObject(hFont);
  1009.   if (!code) SaveSettings();
  1010.   exit (code);
  1011. }
  1012.  
  1013.