home *** CD-ROM | disk | FTP | other *** search
/ Más de 2,500 Juegos / CD1.iso / ZIPDAT / 0153 / 0153.ZIP / SRC / MAIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-05  |  31.6 KB  |  1,011 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.   PAINTSTRUCT ps;
  322.  
  323.   switch(Message)
  324.   { case WM_PAINT:
  325.       hDC=BeginPaint(hWnd,&ps);
  326.       UpdateDisplay(0,0,1,0,hDC);
  327.       if (selected)
  328.        {
  329.          HRGN hRgn;
  330.  
  331.          hRgn=CreatePolygonRgn(&squares[selectX][selectY][0],
  332.                  4, ALTERNATE);
  333.          InvertRgn(hDC,hRgn);
  334.          DeleteObject(hRgn);
  335.        }
  336.       EndPaint(hWnd,&ps);
  337.       return 0;
  338.  
  339.     case WM_KEYDOWN:
  340.       switch (wParam)
  341.        {
  342.         case VK_CANCEL:
  343.           flag.timeout=true;
  344.           break;
  345.         case 13:
  346.           if (flag.replay) command=1;
  347.           break;
  348.         case VK_F2:
  349.           if (player==opponent || flag.editing || flag.force)
  350.            {
  351.             lpfnDlgProc = MakeProcInstance ( TypeMoveDlgProc, hInst);
  352.             if (DialogBox ( hInst, MAKEINTRESOURCE(NUMDLG), hWnd,
  353.                 lpfnDlgProc))
  354.               {
  355.                command=1;
  356.                if (flag.bothsides && !flag.editing)
  357.                 {
  358.                  flag.bothsides=false;
  359.                  flag.abort=flag.timeout=true;
  360.                 }
  361.               }
  362.             FreeProcInstance ( lpfnDlgProc);
  363.            }
  364.           else ShowMessage(CP[62]);
  365.           break;
  366.         default: if (flag.editing && wParam>='0' && wParam<='9')
  367.           {
  368.             wParam-='0';
  369.             if (!wParam)wParam=10;
  370.             PostMessage(hBtnWnd,WM_LBUTTONDOWN,0,--wParam*(bmsize+5)+pawn);
  371.           }
  372.          else return 1;
  373.        }
  374.       return 0;
  375.  
  376. #ifdef WIN32
  377.     case WM_CTLCOLORSTATIC:
  378.       SetTextColor((HDC)wParam,clrText);
  379.       SetBkMode((HDC)wParam,TRANSPARENT);
  380.       return hBrushBackGround;
  381. #else
  382.     case WM_CTLCOLOR:
  383.       switch(HIWORD(lParam))
  384.         {
  385.          case CTLCOLOR_STATIC:
  386.            SetTextColor((HDC)wParam,clrText);
  387.            SetBkMode((HDC)wParam,TRANSPARENT);
  388.            return hBrushBackGround;
  389.         }
  390.     return 0;
  391. #endif
  392.  
  393.     case WM_LBUTTONDOWN:
  394.      if (player==opponent || flag.force)
  395.      {
  396.       UINT xsq,ysq,width,margin;
  397.       SHORT x,y;
  398.       HRGN hRgn;
  399.  
  400.       if (flag.replay) {command=1;return 0;}
  401.       x=LOWORD(lParam);
  402.       y=HIWORD(lParam);
  403.       if (y<BACKMARGIN || y>BACKMARGIN+sqdepth*8)return 0;/*is y o the board?*/
  404.       width=sqwidthB*8+deltaX*(y-BACKMARGIN)/(sqdepth*8);
  405.       margin=((sqwidthF*8-width)>>1)+LEFTMARGIN;
  406.       if (x<margin || x>=width+margin) return 0;  /*is x on the board?*/
  407.       xsq=8*(x-margin)/width;
  408.       ysq=7-(y-BACKMARGIN)/sqdepth;
  409.       if (!selected && !button)
  410.        {
  411.         selected=1;
  412.         selectX=xsq;
  413.         selectY=ysq;
  414.         hRgn=CreatePolygonRgn(&squares[xsq][ysq][0],4, ALTERNATE);
  415.         hDC=GetDC(hWnd);
  416.         InvertRgn(hDC,hRgn);
  417.         ReleaseDC(hWnd,hDC);
  418.         DeleteObject(hRgn);
  419.        }
  420.       else
  421.        {
  422.         if (!button) /*no squares are highlighted if a button is down*/
  423.          {
  424.           hRgn=CreatePolygonRgn(&squares[selectX][selectY][0],
  425.                  4, ALTERNATE);
  426.           hDC=GetDC(hWnd);
  427.           InvertRgn(hDC,hRgn);  /*restore square to normal*/
  428.           ReleaseDC(hWnd,hDC);
  429.           DeleteObject(hRgn);
  430.          }
  431.         selected=0;
  432.         if (xsq==selectX && ysq==selectY && !flag.editing)return 0;
  433.         if (flag.reverse)
  434.          {
  435.            selectX = 7-selectX;
  436.            xsq = 7-xsq;
  437.            selectY = 7-selectY;
  438.            ysq = 7-ysq;
  439.          }
  440.         move[0]=(char)selectX+'a';
  441.         move[2]=(char)xsq+'a';
  442.         move[1]='1'+(char)selectY;
  443.         move[3]='1'+(char)ysq;
  444.         move[4]=0;
  445.         if (!flag.editing
  446.             && ((ysq==0 && selectY==1)||(ysq==7 && selectY==6))
  447.             && abs(selectX-xsq)<=1
  448.             && (player==white ? ysq>selectY : ysq<selectY) )
  449.          {
  450.            SHORT *brdptr,*colptr;
  451.            if (flag.searching) {brdptr=&origbrd; colptr=&origcol;}
  452.            else {brdptr=&board; colptr=&color;}
  453.            if (*(brdptr+selectX+selectY*8)==pawn
  454.             && *(colptr+selectX+selectY*8)==player
  455.             && ( abs(selectX-xsq)==0 ? *(brdptr+xsq+ysq*8)==no_piece
  456.                                      : *(colptr+xsq+ysq*8)==!player ) )
  457.             {
  458.              lpfnDlgProc = MakeProcInstance(PromoteDlgProc, hInst);
  459.              move[4] = CP[1][DialogBox(hInst, MAKEINTRESOURCE(PROMOTE),
  460.                 hWnd, lpfnDlgProc)];  /*promotion*/
  461.              FreeProcInstance(lpfnDlgProc);
  462.              move[5]=0;
  463.             }
  464.          }
  465.         if (button) move[0]=0; /*editing - allow delete with right button
  466.                                  while a piece button is down*/
  467.         if (!flag.editing)
  468.          {
  469.            if ((!flag.easy || flag.bothsides) && player==opponent)
  470.               flag.timeout = true;
  471.            if (flag.bothsides) {flag.abort=true; flag.bothsides = false; }
  472.          }
  473.         command=1;
  474.        }
  475.      }
  476.      return 0;
  477.  
  478.     case WM_RBUTTONDOWN:
  479.       if (flag.replay) {command=1; return 0;}
  480.       if (flag.editing)
  481.       {
  482.        SHORT x,y;
  483.        UINT width,margin;
  484.        x=LOWORD(lParam);
  485.        y=HIWORD(lParam);
  486.        if (y<BACKMARGIN || y>BACKMARGIN+sqdepth*8)return 0;
  487.        width=sqwidthB*8+deltaX*(y-BACKMARGIN)/(sqdepth*8);
  488.        margin=((sqwidthF*8-width)>>1)+LEFTMARGIN;
  489.        if (x<margin || x>=width+margin) return 0;
  490.        if (flag.reverse)
  491.         {
  492.          move[0]='h'-8*(x-margin)/width;
  493.          move[1]='1'+(y-BACKMARGIN)/sqdepth;
  494.         }
  495.        else
  496.         {
  497.          move[0]='a'+8*(x-margin)/width;
  498.          move[1]='8'-(y-BACKMARGIN)/sqdepth;
  499.         }
  500.        move[2]=move[0];
  501.        move[3]=move[1];
  502.        move[4]=0;
  503.        command=1;
  504.       }
  505.       return 0;
  506.  
  507.     case WM_ERASEBKGND:
  508.       {
  509.          RECT rect;
  510.          UnrealizeObject ( hBrushBackGround);
  511.          GetClientRect ( hWnd, &rect);
  512.          FillRect ( (HDC)wParam, &rect, hBrushBackGround);
  513.          return 1;
  514.       }
  515.  
  516.     case WM_COMMAND:
  517.       switch (LOWORD(wParam))
  518.        {
  519.         case IDM_QUIT:
  520.           flag.quit=true;
  521.           GetWindowRect(hWnd,&wr);
  522.           maximized=IsZoomed(hWnd);
  523.           if (IsIconic(hWnd)) wr.right = 0;
  524.           WinHelp(hWnd,szHelpFile,HELP_QUIT,0L);
  525.         case IDM_GET:
  526.         case IDM_NEW:
  527.         case IDM_LIST:
  528.         case IDM_EDIT:
  529.         case IDM_REVIEW:
  530.         case IDM_REMOVE:
  531.         case IDM_UNDO:
  532.         case IDM_FORCE:
  533.         case IDM_SWITCH:
  534.         case IDM_SWITCHDM:
  535.         case IDM_WHITE:
  536.         case IDM_BLACK:
  537.         case IDM_COMPILE:
  538.           flag.timeout=flag.abort=true;
  539.           flag.bothsides=false;
  540.           command=LOWORD(wParam);
  541.           break;
  542.         case IDM_SAVE:
  543.           flag.timeout=true;
  544.           flag.bothsides=false;
  545.           command=LOWORD(wParam);
  546.           break;
  547.  
  548.         case IDM_BOTH:
  549.           if (!flag.searching)
  550.            {
  551.             command=LOWORD(wParam);
  552.             break;
  553.            }
  554.           if (flag.bothsides)
  555.            {
  556.             flag.bothsides=false;
  557.             if (player==opponent)   /*computer is making opponents move*/
  558.                flag.abort=flag.timeout=true; /*so abort it*/
  559.            }
  560.           else
  561.            if (player==opponent) /*computer is thinking on opponent's time*/
  562.             {
  563.               flag.timeout=true;
  564.               command=LOWORD(wParam);
  565.             }
  566.            else flag.bothsides=true;
  567.           break;
  568.         case IDM_WTM:
  569.         case IDM_BTM:
  570.           if (player==(LOWORD(wParam)==IDM_WTM)? white : black) break;
  571.           flag.timeout=flag.abort=true;
  572.           flag.bothsides=false;
  573.           command=LOWORD(wParam);
  574.           break;
  575.  
  576.         case IDM_BEEP:
  577.           flag.beep=!flag.beep;
  578.           break;
  579.         case IDM_COORD:
  580.           flag.coords=!flag.coords;
  581.           InvalidateRect(hWnd,0,true);
  582.           break;
  583.         case IDM_POST:
  584.           if ( flag.post )
  585.            {
  586.             SendMessage ( hStats, WM_COMMAND, IDOK, 0 );
  587.             flag.post = false;
  588.            }
  589.           else
  590.            {
  591.             lpfnDlgProc = MakeProcInstance(StatDlgProc, hInst);
  592.             hStats = CreateDialog (hInst, MAKEINTRESOURCE(STATS),
  593.                 hWnd, lpfnDlgProc);
  594.             flag.post = true;
  595.            }
  596.           break;
  597.         case IDM_ANIMATE:
  598.           flag.animate=!flag.animate;
  599.           if (!flag.animate)
  600.            {
  601.             UpdateDisplay(0,0,1,0,0);
  602.             Znodes<<=4;
  603.            }
  604.           else Znodes>>=4;
  605.           break;
  606.         case IDM_HASH:
  607.           flag.hash=!flag.hash;
  608.           break;
  609.         case IDM_BOOK:
  610.           flag.usebook=!flag.usebook;
  611.           Book = flag.usebook ? BOOKFAIL : 0;
  612.           break;
  613.         case IDM_HDEPTH:
  614.           lpfnDlgProc = MakeProcInstance ( HashDepthDlgProc, hInst);
  615.           if (DialogBox ( hInst, MAKEINTRESOURCE(HASHDEPTHDLG), hWnd,
  616.                 lpfnDlgProc))
  617.            {
  618.             HashDepth=DlgInt1;
  619.             HashMoveLimit=DlgInt2;
  620.            }
  621.           FreeProcInstance ( lpfnDlgProc);
  622.           break;
  623.         case IDM_HFILE:
  624.           lpfnDlgProc = MakeProcInstance ( CreateHashDlgProc, hInst);
  625.           if (DialogBox ( hInst, MAKEINTRESOURCE(CREATEHASH), hWnd,
  626.                 lpfnDlgProc))
  627.            {
  628.             if (size < 24)
  629.                 size = (1 << size);
  630.             if (size>0) CreateHashFile(size);
  631.            }
  632.           FreeProcInstance ( lpfnDlgProc);
  633.           break;
  634.         case IDM_WIN:
  635.           lpfnDlgProc = MakeProcInstance ( ChangeWinDlgProc, hInst);
  636.           if (DialogBox ( hInst, MAKEINTRESOURCE(CHANGEWINDOW), hWnd,
  637.                 lpfnDlgProc))
  638.           {
  639.             WAwindow=DlgInt1;
  640.             WBwindow=DlgInt2;
  641.             WXwindow=DlgInt3;
  642.             BAwindow=DlgInt4;
  643.             BBwindow=DlgInt5;
  644.             BXwindow=DlgInt6;
  645.             xwndw = (computer == white) ? WXwindow : BXwindow;
  646.           }
  647.           FreeProcInstance ( lpfnDlgProc);
  648.           break;
  649.         case IDM_CONTEMP:
  650.           lpszTitle=CP[64];
  651.           DlgInt1=contempt;
  652.           lpfnDlgProc = MakeProcInstance ( GetNumDlgProc, hInst);
  653.           if (DialogBoxParam ( hInst, MAKEINTRESOURCE(NUMDLG), hWnd,
  654.                 lpfnDlgProc,46L)) contempt=DlgInt1;
  655.           FreeProcInstance ( lpfnDlgProc);
  656.           break;
  657.         case IDM_MATERIAL:
  658.           flag.material=!flag.material;
  659.           break;
  660.         case IDM_RCPTR:
  661.           flag.rcptr=!flag.rcptr;
  662.           break;
  663.         case IDM_THREAT:
  664.           flag.threat=!flag.threat;
  665.           break;
  666.         case IDM_PVS:
  667.           flag.pvs=!flag.pvs;
  668.           break;
  669.         case IDM_NEWEVAL:
  670.           flag.neweval=!flag.neweval;
  671.           break;
  672.         case IDM_GAMEIN:
  673.           flag.gamein=!flag.gamein;
  674.           break;
  675.  
  676.         case IDM_TIME:
  677.           lpfnDlgProc = MakeProcInstance ( TimeDlgProc, hInst);
  678.           DialogBox ( hInst, MAKEINTRESOURCE(TIME), hWnd, lpfnDlgProc);
  679.           FreeProcInstance ( lpfnDlgProc);
  680.           break;
  681.         case IDM_RANDOM:
  682.           dither = (dither)?0:DITHER;
  683.           break;
  684.         case IDM_EASY:
  685.           flag.easy = !flag.easy;
  686.           if (flag.easy && flag.searching && player==opponent)
  687.               flag.timeout=true;
  688.           break;
  689.         case IDM_DEPTH:
  690.           lpszTitle=CP[61];
  691.           DlgInt1=MaxSearchDepth;
  692.           lpfnDlgProc = MakeProcInstance ( GetNumDlgProc, hInst);
  693.           if (DialogBoxParam ( hInst, MAKEINTRESOURCE(NUMDLG), hWnd,
  694.                    lpfnDlgProc,47L)) MaxSearchDepth=DlgInt1;
  695.           FreeProcInstance ( lpfnDlgProc);
  696.           TCflag = !(MaxSearchDepth > 0);
  697.           break;
  698.  
  699.         case IDM_REVERSE:
  700.           flag.reverse=!flag.reverse;
  701.           if(selected) {selectX=7-selectX; selectY=7-selectY;}
  702.           InvalidateRect(hWnd,0,true);
  703.           break;
  704.  
  705.         case IDM_BACKGROUND:
  706.           if (GetColor(clrBackGround))
  707.            {
  708.             clrBackGround=cc.rgbResult;
  709.             InvalidateRect(hWnd,0,true);
  710.             DeleteObject (hBrushBackGround);
  711.             hBrushBackGround = CreateSolidBrush ( clrBackGround );
  712.            }
  713.           break;
  714.         case IDM_BLACKSQUARE:
  715.           if (GetColor(clrBlackSquare))
  716.            {
  717.             clrBlackSquare=cc.rgbResult;
  718.             UpdateDisplay(0, 0, 1, 0, 0);
  719.            }
  720.           break;
  721.         case IDM_WHITESQUARE:
  722.           if (GetColor(clrWhiteSquare))
  723.            {
  724.             clrWhiteSquare=cc.rgbResult;
  725.             UpdateDisplay(0, 0, 1, 0, 0);
  726.            }
  727.           break;
  728.         case IDM_BLACKPIECE:
  729.           if (GetColor(clrBlackPiece))
  730.            {
  731.             clrBlackPiece=cc.rgbResult;
  732.             UpdateDisplay(0, 0, 1, 0, 0);
  733.            }
  734.           break;
  735.         case IDM_WHITEPIECE:
  736.           if (GetColor(clrWhitePiece))
  737.            {
  738.             clrWhitePiece=cc.rgbResult;
  739.             UpdateDisplay(0, 0, 1, 0, 0);
  740.            }
  741.           break;
  742.         case IDM_TEXT:
  743.           if (GetColor(clrText))
  744.            {
  745.             clrText=cc.rgbResult;
  746.             InvalidateRect (hWnd, NULL, TRUE);
  747.            }
  748.           break;
  749.         case IDM_EDGE:
  750.           if (GetColor(clrEdge))
  751.            {
  752.             clrEdge=cc.rgbResult;
  753.             UpdateDisplay(0, 0, 1, 0, 0);
  754.            }
  755.           break;
  756.         case IDM_DEFAULT:
  757.           LoadDefaultColors();
  758.           DeleteObject(hBrushBackGround);
  759.           hBrushBackGround=CreateSolidBrush(clrBackGround);
  760.           InvalidateRect(hWnd,0,true);
  761.           break;
  762.  
  763.         case IDM_SMALL:
  764.         case IDM_MEDIUM:
  765.         case IDM_LARGE:
  766.          {
  767.           SHORT i;
  768.  
  769.           CheckMenuItem ( GetMenu(hWnd), boardsize/12+IDM_SMALL,
  770.                      MF_UNCHECKED);
  771.           boardsize=(LOWORD(wParam)-IDM_SMALL)*12;
  772.           CheckMenuItem ( GetMenu(hWnd), LOWORD(wParam), MF_CHECKED);
  773.           for (i=pawn;i<=king;i++)
  774.           { DeleteObject(pieces[i].detail);
  775.             DeleteObject(pieces[i].mask);
  776.             pieces[i].detail = LoadBitmap (hInst, MAKEINTRESOURCE(i+boardsize));
  777.             pieces[i].mask = LoadBitmap (hInst, MAKEINTRESOURCE(i+boardsize+6));
  778.           }
  779.           InitScreen();
  780.           MoveStatics();
  781.           SizeWindow(0);
  782.           InvalidateRect(hWnd,0,TRUE);
  783.           break;
  784.          }
  785.         case IDM_3D:
  786.           squarebd=0;
  787.           goto changebd;
  788.         case IDM_SQUARE:
  789.           squarebd=1;
  790. changebd:
  791.           InitScreen();
  792.           MoveStatics();
  793.           SizeWindow(0);
  794.           InvalidateRect(hWnd,0,TRUE);
  795.           break;
  796.         case IDM_HINT:
  797.           GiveHint();
  798.           break;
  799.  
  800.         case IDM_INDEX:
  801.           if (!WinHelp(hWnd,szHelpFile,HELP_CONTENTS,0L))
  802.              ShowMessage("Could not open gnuchess.hlp");
  803.           break;
  804.         case IDM_HELP:
  805.           if (!WinHelp(hWnd,"winhelp.hlp",HELP_HELPONHELP,0L))
  806.              ShowMessage("Could not open winhelp.hlp");
  807.           break;
  808.         case IDM_ABOUT:
  809.           lpfnDlgProc = MakeProcInstance ( AboutDlgProc, hInst);
  810.           DialogBox (hInst,MAKEINTRESOURCE(ABOUT),hWnd,lpfnDlgProc);
  811.           FreeProcInstance ( lpfnDlgProc);
  812.           break;
  813.  
  814.         case IDM_CLEAR:     /*editing*/
  815.           {
  816.            short i;
  817.            for (i=0;i<64;i++){board[i]=no_piece;color[i]=neutral;}
  818.           }
  819.           board[4]=board[60]=king;
  820.           color[4]=white;
  821.           color[60]=black;
  822.           selected=0;
  823.           UpdateDisplay(0,0,1,0,0);
  824.           break;
  825.         case IDM_RESTORE:     /*editing*/
  826.           {
  827.            short i;
  828.            for (i=0;i<64;i++)
  829.             {
  830.              board[i]=Stboard[i];
  831.              color[i]=Stcolor[i];
  832.             }
  833.            selected=0;
  834.            UpdateDisplay(0,0,1,0,0);
  835.            break;
  836.           }
  837.         case IDM_PREV:        /*replay*/
  838.         case IDM_NEXT:
  839.         case IDM_DONE:        /*editing*/
  840.           command=LOWORD(wParam);
  841.        }
  842.       return 0;
  843.  
  844.     case WM_INITMENUPOPUP:
  845.       if (!flag.editing) switch (lParam)
  846.       {
  847.        case 0:       /*Game menu*/
  848.             EnableMenuItem ( (HMENU)wParam, IDM_SAVE,
  849.                              (GameCnt>0 ? MF_ENABLED : MF_GRAYED) );
  850.             EnableMenuItem ( (HMENU)wParam, IDM_LIST,
  851.                              (GameCnt>0 ? MF_ENABLED : MF_GRAYED) );
  852.             break;
  853.        case 1:       /*Edit Menu */
  854.             EnableMenuItem ( (HMENU)wParam, IDM_REVIEW,
  855.                              (GameCnt>0 ? MF_ENABLED : MF_GRAYED) );
  856.             EnableMenuItem ( (HMENU)wParam, IDM_UNDO,
  857.                              (GameCnt>0 ? MF_ENABLED : MF_GRAYED) );
  858.             EnableMenuItem ( (HMENU)wParam, IDM_REMOVE,
  859.                           ((flag.searching ? OrigGameCnt : GameCnt)>1
  860.                            ? MF_ENABLED : MF_GRAYED) );
  861.             break;
  862.        case 2:  /* Options Menu */
  863.             CheckMenuItem ( (HMENU)wParam, IDM_HASH,
  864.                      flag.hash?MF_CHECKED:MF_UNCHECKED);
  865.             EnableMenuItem ( (HMENU)wParam, IDM_HASH,
  866.                      (hashfile ? MF_ENABLED : MF_GRAYED) );
  867.             CheckMenuItem ( (HMENU)wParam, IDM_COORD,
  868.                      flag.coords?MF_CHECKED:MF_UNCHECKED);
  869.             CheckMenuItem ( (HMENU)wParam, IDM_BEEP,
  870.                      flag.beep?MF_CHECKED:MF_UNCHECKED);
  871.             CheckMenuItem ( (HMENU)wParam, IDM_BOOK,
  872.                      flag.usebook?MF_CHECKED:MF_UNCHECKED);
  873.             CheckMenuItem ( (HMENU)wParam, IDM_POST,
  874.                      flag.post?MF_CHECKED:MF_UNCHECKED);
  875.             CheckMenuItem ( (HMENU)wParam, IDM_ANIMATE,
  876.                      flag.animate?MF_CHECKED:MF_UNCHECKED);
  877.             CheckMenuItem ( (HMENU)wParam, IDM_MATERIAL,
  878.                      flag.material?MF_CHECKED:MF_UNCHECKED);
  879.             CheckMenuItem ( (HMENU)wParam, IDM_RCPTR,
  880.                      flag.rcptr?MF_CHECKED:MF_UNCHECKED);
  881.             CheckMenuItem ( (HMENU)wParam, IDM_THREAT,
  882.                      flag.threat?MF_CHECKED:MF_UNCHECKED);
  883.             CheckMenuItem ( (HMENU)wParam, IDM_PVS,
  884.                      flag.pvs?MF_CHECKED:MF_UNCHECKED);
  885.             CheckMenuItem ( (HMENU)wParam, IDM_NEWEVAL,
  886.                      flag.neweval?MF_CHECKED:MF_UNCHECKED);
  887.             CheckMenuItem ( (HMENU)wParam, IDM_GAMEIN,
  888.                      flag.gamein?MF_CHECKED:MF_UNCHECKED);
  889.             break;
  890.        case 3:   /*skill menu*/
  891.             CheckMenuItem ( (HMENU)wParam, IDM_RANDOM,
  892.                      dither?MF_CHECKED:MF_UNCHECKED);
  893.             CheckMenuItem ( (HMENU)wParam, IDM_EASY,
  894.                      flag.easy?MF_CHECKED:MF_UNCHECKED);
  895.             break;
  896.        case 4:   /*Side menu*/
  897.           {
  898.             int color=flag.bothsides ? 2
  899.                       : computer^(flag.force & forcing);
  900.             CheckMenuItem ( (HMENU)wParam, IDM_REVERSE,
  901.                      flag.reverse?MF_CHECKED:MF_UNCHECKED);
  902.             CheckMenuItem ( (HMENU)wParam, IDM_BLACK,
  903.                  (color==black)?MF_CHECKED:MF_UNCHECKED);
  904.             CheckMenuItem ( (HMENU)wParam, IDM_WHITE,
  905.                  (color==white)?MF_CHECKED:MF_UNCHECKED);
  906.             CheckMenuItem ( (HMENU)wParam, IDM_BOTH,
  907.                      flag.bothsides?MF_CHECKED:MF_UNCHECKED);
  908.             CheckMenuItem ( (HMENU)wParam, IDM_WTM,
  909.                      player==white?MF_CHECKED:MF_UNCHECKED);
  910.             CheckMenuItem ( (HMENU)wParam, IDM_BTM,
  911.                      player==black?MF_CHECKED:MF_UNCHECKED);
  912.             CheckMenuItem ( (HMENU)wParam, IDM_FORCE,
  913.                    flag.force == false ? MF_UNCHECKED : MF_CHECKED);
  914.           }
  915.        case 5: /*Board menu */
  916.          CheckMenuItem ( (HMENU)wParam, IDM_SQUARE,
  917.                     squarebd?MF_CHECKED:MF_UNCHECKED);
  918.          CheckMenuItem ( (HMENU)wParam, IDM_3D,
  919.                     squarebd?MF_UNCHECKED:MF_CHECKED);
  920.       }
  921.       return 0;
  922.  
  923.     case WM_SYSCOLORCHANGE:
  924.       DeleteObject(hDlgBkgrnd);
  925.       hDlgBkgrnd=CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  926.       return 0;
  927.  
  928.     case WM_DESTROY:
  929.       flag.quit=true;
  930.       flag.timeout=flag.abort=true;
  931.       flag.bothsides=false;
  932.       command=IDM_QUIT;
  933.       GetWindowRect(hWnd,&wr);
  934.       maximized=IsZoomed(hWnd);
  935.       if (IsIconic(hWnd)) wr.right = 0;
  936.       WinHelp(hWnd,szHelpFile,HELP_QUIT,0L);
  937.       return 0;
  938.   }
  939.   return DefWindowProc(hWnd,Message,wParam,lParam);
  940. }
  941.  
  942. void SizeWindow(int move)
  943.   {
  944.     RECT wr;
  945.     WinSizeX=LEFTMARGIN+sqwidthB*8+deltaX/2+20+CompMoveExt
  946.           +GetSystemMetrics(SM_CXFRAME)*2;
  947.     WinSizeY=BACKMARGIN+sqdepth*8+BRD_EDGE+LineSpace+SLineSpace+5
  948.           +GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYFRAME)*2
  949.           +GetSystemMetrics(SM_CYMENU);
  950.     GetWindowRect(GetDesktopWindow(),&wr);
  951.     if (wr.right-wr.left > WinSizeX) WinPosX = (wr.right-WinSizeX)/2;
  952.     else { WinPosX=0; WinSizeX=wr.right-wr.left; }
  953.     if (wr.bottom-wr.top > WinSizeY) WinPosY = (wr.bottom-WinSizeY)/2;
  954.     else { WinPosY=0; WinSizeY=wr.bottom-wr.top; }
  955.     if (!move)
  956.      {
  957.       GetWindowRect(hWnd,&wr);
  958.       WinPosX=wr.left;
  959.       WinPosY=wr.top;
  960.      }
  961.     MoveWindow(hWnd, WinPosX, WinPosY, WinSizeX, WinSizeY, TRUE);
  962.   }
  963.  
  964. void CheckMessage(void)
  965.  {
  966.   MSG msg;
  967.  
  968.   if ( PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  969.     if ( !TranslateAccelerator (hWnd, hAccel, &msg) )
  970.      {    TranslateMessage(&msg);
  971.        DispatchMessage(&msg); }
  972.  }
  973.  
  974. BOOL GetColor(DWORD current)
  975. {
  976.   cc.lStructSize=sizeof(cc);
  977.   cc.hwndOwner=hWnd;
  978.   cc.rgbResult=current;
  979.   cc.lpCustColors=&CustCols;
  980.   cc.Flags=CC_FULLOPEN|CC_RGBINIT;
  981.   return ChooseColor(&cc);
  982. }
  983.  
  984. void LoadDefaultColors()
  985.  {
  986.   clrBackGround  = BROWN;
  987.   clrBlackSquare = DARKGREEN;
  988.   clrWhiteSquare = PALEGRAY;
  989.   clrBlackPiece  = DARKRED;
  990.   clrWhitePiece  = CWHITE;
  991.   clrText        = CBLACK;
  992.   clrEdge        = CBLACK;
  993.  }
  994.  
  995. void
  996. Exit (int code)
  997. {
  998.   SHORT bm;
  999.  
  1000.   for (bm=pawn;bm<=king;bm++)
  1001.    {
  1002.     DeleteObject(pieces[bm].mask);
  1003.     DeleteObject(pieces[bm].detail);
  1004.    }
  1005.   DeleteObject(hBrushBackGround);
  1006.   DeleteObject(hFont);
  1007.   if (!code) SaveSettings();
  1008.   exit (code);
  1009. }
  1010.  
  1011.