home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / sharew / spiele / denker / gnuchess.gem / src / gemgui.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-15  |  24.8 KB  |  1,102 lines

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  This file is part of the Atari GEM interface for GNU Chess,
  4. //  and is Copyright 1993 by Warwick W. Allison.
  5. //
  6. //  You are free to copy and modify these sources, provided you acknowledge
  7. //  the origin by retaining this notice, and adhere to the conditions
  8. //  of the CHESS General Public License described in the main chess file
  9. //  gnuchess.cc.
  10. //
  11. //////////////////////////////////////////////////////////////////////////////
  12.  
  13.  
  14. char* gui_version="0.9"; // 3 characters unless RSC updated.
  15. extern char *version, *patchlevel;
  16.  
  17. #include <string.h>
  18.  
  19. #include "gnuchess.h"
  20. #undef TRUE
  21. #undef FALSE
  22. #undef bool
  23. #include "uisupport.h"
  24. #include "ui.h"
  25. #include "gem_rsc.h"
  26.  
  27. #define RV(x) (WhiteFromTop ? (7-(x)) : (x))
  28.  
  29. #include <gemap.h>
  30. #include <gema.h>
  31. #include <geme.h>
  32. #include <gemr.h>
  33. #include <gemfs.h>
  34. #include <gemrubo.h>
  35. #include <gemm.h>
  36. #include <gemfiw.h>
  37. #include <gemal.h>
  38. #include <vdi.h>
  39. #include "popcolor.h"
  40. #include "poppattn.h"
  41.  
  42. static bool WhiteFromTop=FALSE;
  43. static int CurrentColour=white;
  44. static bool ComputerIsBlack=TRUE;
  45. static int CheckMate=0;
  46. static char* const CONFIGFILE="data\\gnuchess.cnf";
  47.  
  48.  
  49. class ChessBoard;
  50.  
  51. class ColourWindow : public GEMformwindow {
  52. public:
  53.     ColourWindow(GEMactivity& act, const GEMrsc& rsc, ChessBoard& brd) :
  54.         GEMformwindow(act,rsc,COLOUR),
  55.         board(brd),
  56.         popup(rsc,CHOICELIST,CHOICE1,CHOICEN,CHOICESCROLLBAR),
  57.         whitepiecedatacolour(*this,WHITEDATACOLOUR,popup),
  58.         blackpiecedatacolour(*this,BLACKDATACOLOUR,popup),
  59.         whitepiecemaskcolour(*this,WHITEMASKCOLOUR,popup),
  60.         blackpiecemaskcolour(*this,BLACKMASKCOLOUR,popup),
  61.         whitesquarecolour(*this,WHITESQUARECOLOUR,popup),
  62.         blacksquarecolour(*this,BLACKSQUARECOLOUR,popup),
  63.         blacksquarepattern(*this,BLACKSQUAREPATTERN,popup),
  64.         whitesquarepattern(*this,WHITESQUAREPATTERN,popup),
  65.         cursorcolour(*this,CURSORCOLOUR,popup),
  66.         highlightcolour(*this,HIGHLIGHTCOLOUR,popup),
  67.         boardbordercolour(*this,BOARDBORDERCOLOUR,popup),
  68.         surroundcolour(*this,SURROUNDCOLOUR,popup),
  69.         surroundpattern(*this,BOARDSURROUNDPATTERN,popup)
  70.     {
  71.         SetName(rsc.String(COLOURWINTITLE));
  72.     }
  73.  
  74.     int SquarePatternFor(bool isblack) const
  75.     {
  76.         return Object(isblack ? BLACKSQUARE : WHITESQUARE).FillPattern();
  77.     }
  78.  
  79.     int SquareForeColFor(bool isblack) const
  80.     {
  81.         return Object(isblack ? BLACKSQUARE : WHITESQUARE).ForeCol();
  82.     }
  83.  
  84.     int SquareBackColFor(bool isblack) const
  85.     {
  86.         return Object(isblack ? BLACKSQUARE : WHITESQUARE).BackCol();
  87.     }
  88.  
  89.     int PieceForeColFor(bool isblack) const
  90.     {
  91.         return Object(isblack ? BLACKPIECE : WHITEPIECE).ForeCol();
  92.     }
  93.  
  94.     int PieceBackColFor(bool isblack) const
  95.     {
  96.         return Object(isblack ? BLACKPIECE : WHITEPIECE).BackCol();
  97.     }
  98.  
  99.     int CursorColour() const
  100.     {
  101.         return Object(CURSORBORDER).BorderCol();
  102.     }
  103.  
  104.     int CursorBorder() const
  105.     {
  106.         return Object(CURSORBORDER).BorderWidth();
  107.     }
  108.  
  109.     int HighlightColour() const
  110.     {
  111.         return Object(HIGHLIGHTBORDER).BorderCol();
  112.     }
  113.  
  114.     int HighlightBorder() const
  115.     {
  116.         return Object(HIGHLIGHTBORDER).BorderWidth();
  117.     }
  118.  
  119.     int BoardBorderColour() const
  120.     {
  121.         return Object(BOARDBORDERBORDER).BorderCol();
  122.     }
  123.  
  124.     int SurroundColour() const
  125.     {
  126.         return Object(SURROUNDPATTERN).BackCol();
  127.     }
  128.  
  129.     int SurroundPattern() const
  130.     {
  131.         return Object(SURROUNDPATTERN).FillPattern();
  132.     }
  133.  
  134.  
  135.     void SetPieceForeColFor(bool forblack, int colour)
  136.     {
  137.         Object(forblack ? BLACKPIECE : WHITEPIECE).ForeCol(colour);
  138.         RedrawObject(forblack ? BLACKPIECE : WHITEPIECE);
  139.     }
  140.  
  141.     void SetPieceBackColFor(bool forblack, int colour)
  142.     {
  143.         Object(forblack ? BLACKPIECE : WHITEPIECE).BackCol(colour);
  144.         RedrawObject(forblack ? BLACKPIECE : WHITEPIECE);
  145.     }
  146.  
  147.     void SetSquareColFor(bool forblack, int colour)
  148.     {
  149.         Object(forblack ? BLACKSQUARE : WHITESQUARE).BackCol(colour);
  150.         RedrawObject(forblack ? BLACKSQUARE : WHITESQUARE);
  151.     }
  152.  
  153.     void SetSquarePatternFor(bool forblack, int pattern)
  154.     {
  155.         Object(forblack ? BLACKSQUARE : WHITESQUARE).FillPattern(pattern);
  156.         RedrawObject(forblack ? BLACKSQUARE : WHITESQUARE);
  157.     }
  158.  
  159.  
  160.     void SetCursorColour(int colour)
  161.     {
  162.         Object(CURSORBORDER).BorderCol(colour);
  163.         RedrawObject(CURSORBORDER);
  164.     }
  165.  
  166.     void SetCursorBorder(int width)
  167.     {
  168.         Object(CURSORBORDER).BorderWidth(width);
  169.         RedrawObject(CURSORBORDER);
  170.     }
  171.  
  172.     void SetHighlightColour(int colour)
  173.     {
  174.         Object(HIGHLIGHTBORDER).BorderCol(colour);
  175.         RedrawObject(HIGHLIGHTBORDER);
  176.     }
  177.  
  178.     void SetHighlightBorder(int width)
  179.     {
  180.         Object(HIGHLIGHTBORDER).BorderWidth(width);
  181.         RedrawObject(HIGHLIGHTBORDER);
  182.     }
  183.  
  184.     void SetBoardBorderColour(int colour);
  185.     void SetSurroundColour(int colour);
  186.     void SetSurroundPattern(int pattern);
  187.  
  188.  
  189.  
  190.     virtual GEMfeedback DoItem(int item, const GEMevent& e);
  191.  
  192.  
  193.     void ReadConfig(FILE* file);
  194.     void WriteConfig(FILE* file);
  195.  
  196.  
  197. private:
  198.     PopupList popup;
  199.     PopupColourChoice whitepiecedatacolour;
  200.     PopupColourChoice blackpiecedatacolour;
  201.     PopupColourChoice whitepiecemaskcolour;
  202.     PopupColourChoice blackpiecemaskcolour;
  203.     PopupColourChoice whitesquarecolour;
  204.     PopupColourChoice blacksquarecolour;
  205.     PopupPatternChoice blacksquarepattern;
  206.     PopupPatternChoice whitesquarepattern;
  207.     PopupColourChoice cursorcolour;
  208.     PopupColourChoice highlightcolour;
  209.     PopupColourChoice boardbordercolour;
  210.     PopupColourChoice surroundcolour;
  211.     PopupPatternChoice surroundpattern;
  212.  
  213.     ChessBoard& board;
  214. };
  215.  
  216. class GEM_GNUChess_GUI;
  217.  
  218. class ChessBoard : public GEMformiconwindow {
  219. public:
  220.     ChessBoard(GEMactivity& act, const GEMrsc& rsc, GEM_GNUChess_GUI* g, ColourWindow& col) :
  221.         GEMformiconwindow(act,rsc,BOARD,BOARDICON,MOVER|NAME|FULLER|INFO),
  222.         gui(g),
  223.         colour(col),
  224.         chosen(FALSE),
  225.         sizer(rsc,SIZE),
  226.         pieces_sml(rsc,PIECES_SML),
  227.         pieces_mid(rsc,PIECES_MID),
  228.         pieces_lrg(rsc,PIECES_LRG),
  229.         pieces(&pieces_mid),
  230.         hl_fx(-1)
  231.     {
  232.         SetName(rsc.String(BOARDWINTITLE));
  233.         for (int x=0; x<8; x++) {
  234.             for (int y=0; y<8; y++) {
  235.                 Piece(x,y).Type(G_ICON);
  236.                 Piece(x,y).ObjectSpecific(long(new ICONBLK));
  237.                 Square(x,y).BorderWidth(0);
  238.             }
  239.         }
  240.         sizer[SQUARE_SML+1].Type(G_ICON);
  241.         sizer[SQUARE_SML+1].ObjectSpecific(long(new ICONBLK));
  242.         sizer[SQUARE_MID+1].Type(G_ICON);
  243.         sizer[SQUARE_MID+1].ObjectSpecific(long(new ICONBLK));
  244.         sizer[SQUARE_LRG+1].Type(G_ICON);
  245.         sizer[SQUARE_LRG+1].ObjectSpecific(long(new ICONBLK));
  246.     }
  247.  
  248.     int SquareIndex(int x, int y) const
  249.     {
  250.         return R1C1+x*(R1C2-R1C1)+(7-y)*(R2C1-R1C1);
  251.     }
  252.  
  253.     GEMrawobject& Piece(int x, int y) const
  254.     {
  255.         return Object(SquareIndex(x,y)+1); // Immediate child == +1
  256.     }
  257.  
  258.     GEMrawobject& Square(int x, int y) const
  259.     {
  260.         return Object(SquareIndex(x,y));
  261.     }
  262.  
  263.     void SetSquare(int x,int y,bool isblack)
  264.     {
  265.         Square(x,y).FillPattern(colour.SquarePatternFor(isblack));
  266.         Square(x,y).ForeCol(colour.SquareForeColFor(isblack));
  267.         Square(x,y).BackCol(colour.SquareBackColFor(isblack));
  268.     }
  269.  
  270.     GEMrawobject& SelectPiece(int rscindex, int size) const
  271.     {
  272.         switch (size) {
  273.          case -1:
  274.             return pieces->Object(rscindex);
  275.         break; case 0:
  276.             return pieces_sml.Object(rscindex);
  277.         break; case 1:
  278.             return pieces_mid.Object(rscindex);
  279.         break; default:
  280.             return pieces_lrg.Object(rscindex);
  281.         }
  282.     }
  283.  
  284.     void SetPiece(bool used,bool isblack,int x,int y,int piece)
  285.     {
  286.         if (used && piece) {
  287.             SetPieceImage(Piece(x,y),piece,isblack);
  288.             Piece(x,y).HideTree(FALSE);
  289.         } else {
  290.             Piece(x,y).HideTree(TRUE);
  291.         }
  292.         RedrawObject(SquareIndex(x,y));
  293.     }
  294.  
  295.     void HighlightMove(char* move,bool redraw)
  296.     {
  297.         Unhighlight();
  298.  
  299.         hl_fx=move[0]-'a';
  300.         hl_fy=move[1]-'1';
  301.         hl_tx=move[2]-'a';
  302.         hl_ty=move[3]-'1';
  303.  
  304.         Square(RV(hl_fx),RV(hl_fy)).BorderWidth(colour.HighlightBorder());
  305.         Square(RV(hl_tx),RV(hl_ty)).BorderWidth(colour.HighlightBorder());
  306.         Square(RV(hl_fx),RV(hl_fy)).BorderCol(colour.HighlightColour());
  307.         Square(RV(hl_tx),RV(hl_ty)).BorderCol(colour.HighlightColour());
  308.  
  309.         if (redraw) {
  310.             RedrawObject(SquareIndex(RV(hl_fx),RV(hl_fy)));
  311.             RedrawObject(SquareIndex(RV(hl_tx),RV(hl_ty)));
  312.         }
  313.     }
  314.  
  315.     void Unhighlight()
  316.     {
  317.         if (hl_fx>-1) {
  318.             Square(RV(hl_fx),RV(hl_fy)).BorderWidth(0);
  319.             Square(RV(hl_tx),RV(hl_ty)).BorderWidth(0);
  320.             RedrawObject(SquareIndex(RV(hl_fx),RV(hl_fy)));
  321.             RedrawObject(SquareIndex(RV(hl_tx),RV(hl_ty)));
  322.             hl_fx=-1;
  323.         }
  324.         if (chosen) {
  325.             Square(RV(chosenx),RV(choseny)).BorderWidth(0);
  326.             RedrawObject(SquareIndex(RV(chosenx),RV(choseny)));
  327.             chosen=FALSE;
  328.         }
  329.     }
  330.  
  331.     int ChoosePromotion()
  332.     {
  333.         // Can't choose king or pawn.
  334.         pieces->Object(PAWN).HideTree(TRUE);
  335.         pieces->Object(KING).HideTree(TRUE);
  336.  
  337.         int result=PAWN+1-pieces->Do();
  338.  
  339.         pieces->Object(PAWN).HideTree(FALSE);
  340.         pieces->Object(KING).HideTree(FALSE);
  341.  
  342.         return result;
  343.     }
  344.  
  345.     void Refresh(bool outline);
  346.  
  347.     void SetSize();
  348.  
  349.     void SetSize(int size); // 0, 1, 2
  350.  
  351.     int Size()
  352.     {
  353.         return pieces==&pieces_sml ? 0 : pieces==&pieces_mid ? 1 : 2;
  354.     }
  355.  
  356.     void SetPieceImage(GEMrawobject& obj, int piece, bool isblack, int size=-1)
  357.     {
  358.         *((ICONBLK*)obj.ObjectSpecific())=
  359.             *((ICONBLK*)SelectPiece(PAWN+1-piece,size).ObjectSpecific());
  360.         obj.ForeCol(colour.PieceForeColFor(isblack));
  361.         obj.BackCol(colour.PieceBackColFor(isblack));
  362.     }
  363.  
  364. private:
  365.     int hl_fx,hl_fy,hl_tx,hl_ty;
  366.     GEM_GNUChess_GUI* gui;
  367.     GEMform pieces_sml;
  368.     GEMform pieces_mid;
  369.     GEMform pieces_lrg;
  370.     GEMform* pieces;
  371.     GEMform sizer;
  372.     ColourWindow& colour;
  373.  
  374.     bool chosen;
  375.     int chosenx;
  376.     int choseny;
  377.  
  378.     virtual GEMfeedback DoItem(int item, const GEMevent& e);
  379. };
  380.  
  381. void ColourWindow::ReadConfig(FILE* file)
  382. {
  383.     int value;
  384.  
  385.     fscanf(file,"%d",&value); SetPieceForeColFor(TRUE, value);
  386.     fscanf(file,"%d",&value); SetPieceForeColFor(FALSE, value);
  387.     fscanf(file,"%d",&value); SetPieceBackColFor(TRUE, value);
  388.     fscanf(file,"%d",&value); SetPieceBackColFor(FALSE, value);
  389.     fscanf(file,"%d",&value); SetSquareColFor(TRUE, value);
  390.     fscanf(file,"%d",&value); SetSquareColFor(FALSE, value);
  391.     fscanf(file,"%d",&value); SetSquarePatternFor(TRUE, value);
  392.     fscanf(file,"%d",&value); SetSquarePatternFor(FALSE, value);
  393.     fscanf(file,"%d",&value); SetCursorColour(value);
  394.     fscanf(file,"%d",&value); SetCursorBorder(value);
  395.     fscanf(file,"%d",&value); SetHighlightColour(value);
  396.     fscanf(file,"%d",&value); SetHighlightBorder(value);
  397.     fscanf(file,"%d",&value); SetBoardBorderColour(value);
  398.     fscanf(file,"%d",&value); SetSurroundColour(value);
  399.     fscanf(file,"%d",&value); SetSurroundPattern(value);
  400. }
  401.  
  402. void ColourWindow::WriteConfig(FILE* file)
  403. {
  404.     fprintf(file,"%d\n",PieceForeColFor(TRUE));
  405.     fprintf(file,"%d\n",PieceForeColFor(FALSE));
  406.     fprintf(file,"%d\n",PieceBackColFor(TRUE));
  407.     fprintf(file,"%d\n",PieceBackColFor(FALSE));
  408.     fprintf(file,"%d\n",SquareBackColFor(TRUE));
  409.     fprintf(file,"%d\n",SquareBackColFor(FALSE));
  410.     fprintf(file,"%d\n",SquarePatternFor(TRUE));
  411.     fprintf(file,"%d\n",SquarePatternFor(FALSE));
  412.     fprintf(file,"%d\n",CursorColour());
  413.     fprintf(file,"%d\n",CursorBorder());
  414.     fprintf(file,"%d\n",HighlightColour());
  415.     fprintf(file,"%d\n",HighlightBorder());
  416.     fprintf(file,"%d\n",BoardBorderColour());
  417.     fprintf(file,"%d\n",SurroundColour());
  418.     fprintf(file,"%d\n",SurroundPattern());
  419. }
  420.  
  421. void ColourWindow::SetBoardBorderColour(int colour)
  422. {
  423.     Object(BOARDBORDERBORDER).BorderCol(colour);
  424.     RedrawObject(BOARDBORDERBORDER);
  425.     board[BOARDBORDER].BorderCol(colour);
  426. }
  427.  
  428. void ColourWindow::SetSurroundColour(int colour)
  429. {
  430.     Object(SURROUNDPATTERN).BackCol(colour);
  431.     RedrawObject(SURROUNDPATTERN);
  432.     board[BOARDSURROUND].BackCol(colour);
  433. }
  434.  
  435. void ColourWindow::SetSurroundPattern(int pattern)
  436. {
  437.     Object(SURROUNDPATTERN).FillPattern(pattern);
  438.     RedrawObject(SURROUNDPATTERN);
  439.     board[BOARDSURROUND].FillPattern(pattern);
  440. }
  441.  
  442. GEMfeedback ColourWindow::DoItem(int item, const GEMevent& e)
  443. {
  444.     // Deal with simple buttons.
  445.  
  446.     switch (item) {
  447.      case HIGHLIGHTBORDERMINUS:
  448.         if (HighlightBorder()>1) SetHighlightBorder(HighlightBorder()-1);
  449.     break; case HIGHLIGHTBORDERPLUS:
  450.         if (HighlightBorder()<100) SetHighlightBorder(HighlightBorder()+1);
  451.     break; case CURSORBORDERMINUS:
  452.         if (CursorBorder()>1) SetCursorBorder(CursorBorder()-1);
  453.     break; case CURSORBORDERPLUS:
  454.         if (CursorBorder()<100) SetCursorBorder(CursorBorder()+1);
  455.     break; case BOARDBORDERMINUS:
  456.         // It's an outside border, so -ve everything.
  457.         if (board[BOARDBORDER].BorderWidth()<0) {
  458.             board[BOARDBORDER].BorderWidth(board[BOARDBORDER].BorderWidth()+1);
  459.             Object(BOARDBORDERBORDER).BorderWidth(board[BOARDBORDER].BorderWidth());
  460.             RedrawObject(SURROUNDPATTERN);
  461.             board.Refresh(TRUE);
  462.         }
  463.     break; case BOARDBORDERPLUS:
  464.         if (board[BOARDBORDER].BorderWidth()>-20) {
  465.             board[BOARDBORDER].BorderWidth(board[BOARDBORDER].BorderWidth()-1);
  466.             Object(BOARDBORDERBORDER).BorderWidth(board[BOARDBORDER].BorderWidth());
  467.             RedrawObject(SURROUNDPATTERN);
  468.             board.Refresh(TRUE);
  469.         }
  470.     break; default:
  471.         // Deal with fancy popups..
  472.         GEMformwindow::DoItem(item,e);
  473.  
  474.         // Look up until we see something we recognize.
  475.         bool recog=FALSE;
  476.         while (item && !recog) {
  477.             recog=TRUE;
  478.             switch (item) {
  479.              case WHITEDATACOLOUR:
  480.                 SetPieceForeColFor(FALSE,whitepiecedatacolour.Choice());
  481.                 board.Refresh(FALSE);
  482.             break; case BLACKDATACOLOUR:
  483.                 SetPieceForeColFor(TRUE,blackpiecedatacolour.Choice());
  484.                 board.Refresh(FALSE);
  485.             break; case WHITEMASKCOLOUR:
  486.                 SetPieceBackColFor(FALSE,whitepiecemaskcolour.Choice());
  487.                 board.Refresh(FALSE);
  488.             break; case BLACKMASKCOLOUR:
  489.                 SetPieceBackColFor(TRUE,blackpiecemaskcolour.Choice());
  490.                 board.Refresh(FALSE);
  491.             break; case WHITESQUARECOLOUR:
  492.                 SetSquareColFor(FALSE,whitesquarecolour.Choice());
  493.                 board.Refresh(FALSE);
  494.             break; case BLACKSQUARECOLOUR:
  495.                 SetSquareColFor(TRUE,blacksquarecolour.Choice());
  496.                 board.Refresh(FALSE);
  497.             break; case BLACKSQUAREPATTERN:
  498.                 SetSquarePatternFor(TRUE,blacksquarepattern.Choice());
  499.                 board.Refresh(FALSE);
  500.             break; case WHITESQUAREPATTERN:
  501.                 SetSquarePatternFor(FALSE,whitesquarepattern.Choice());
  502.                 board.Refresh(FALSE);
  503.             break; case CURSORCOLOUR:
  504.                 SetCursorColour(cursorcolour.Choice());
  505.                 board.Refresh(TRUE);
  506.             break; case HIGHLIGHTCOLOUR:
  507.                 SetHighlightColour(highlightcolour.Choice());
  508.                 board.Refresh(TRUE);
  509.             break; case BOARDBORDERCOLOUR:
  510.                 SetBoardBorderColour(boardbordercolour.Choice());
  511.                 board.Refresh(TRUE);
  512.             break; case SURROUNDCOLOUR:
  513.                 SetSurroundColour(surroundcolour.Choice());
  514.                 board.Refresh(TRUE);
  515.             break; case BOARDSURROUNDPATTERN:
  516.                 SetSurroundPattern(surroundpattern.Choice());
  517.                 board.Refresh(TRUE);
  518.             break; default:
  519.                 recog=FALSE;
  520.             }
  521.             item=Parent(item);
  522.         }
  523.     }
  524.  
  525.     return ContinueInteraction;
  526. }
  527.  
  528.  
  529. class GEM_GNUChess_GUI : GEMactivity, GEMmenu {
  530. public:
  531.     GEM_GNUChess_GUI(GEMrsc& rsc) :
  532.         GEMactivity(),
  533.         GEMmenu(*this,rsc,MENUBAR),
  534.         board(*this,rsc,this,colour),
  535.         colour(*this,rsc,board),
  536.         about(rsc,ABOUT),
  537.         levellist(rsc,LEVEL),
  538.         message(rsc,MESSAGE_F),
  539.         lastchosenlevel(-1),
  540.         loadfailed(rsc,LOADFAILED),
  541.         savefailed(rsc,SAVEFAILED),
  542.         bookwarn(rsc,BOOKWARN)
  543.     {
  544.         about[GUIVERSION].SetText(gui_version);
  545.         about[CHESSVERSION].SetText(version);
  546.         about[CHESSPATCHLEVEL].SetText(patchlevel);
  547.  
  548.         if (!LoadConfiguration(CONFIGFILE)) {
  549.             GEMalert noconfig(rsc,NOCONFIG);
  550.             noconfig.Alert();
  551.             colour.Open();
  552.         }
  553.         Object(EDITCLEAR).Disable();
  554.         BeginDo();
  555.     }
  556.  
  557.     ~GEM_GNUChess_GUI()
  558.     {
  559.         EndDo();
  560.     }
  561.  
  562.     bool LoadConfiguration(const char* cnffile)
  563.     {
  564.         FILE* file=fopen(cnffile,"r");
  565.         if (!file) return FALSE;
  566.         colour.ReadConfig(file);
  567.         int value,value2;
  568.         fscanf(file,"%d",&value);
  569.         board.SetSize(value);
  570.         fscanf(file,"%d",&value);
  571.         fscanf(file,"%d",&value2); board.Move(value,value2);
  572.         fclose(file);
  573.         return TRUE;
  574.     }
  575.  
  576.     void SaveConfiguration(const char* cnffile)
  577.     {
  578.         FILE* file=fopen(cnffile,"w");
  579.         if (!file) return;
  580.         colour.WriteConfig(file);
  581.         fprintf(file,"%d\n",board.Size());
  582.         GRect boardpos=board.BorderRect();
  583.         fprintf(file,"%d\n%d\n",boardpos.g_x,boardpos.g_y);
  584.         fclose(file);
  585.     }
  586.  
  587.     bool InEditMode() const
  588.     {
  589.         return Object(EDITTOGGLE).Checked();
  590.     }
  591.  
  592.     bool HumanIsWhite() const
  593.     {
  594.         return Object(HUMANVSCPU).Checked();
  595.     }
  596.  
  597.     void SetEditColour(int item)
  598.     {
  599.         if (!Object(item).Checked()) {
  600.             Object(EDITWHITE).Uncheck();
  601.             Object(EDITBLACK).Uncheck();
  602.             Object(item).Checked(item);
  603.             SetMove("C");
  604.         }
  605.     }
  606.  
  607.     int ChosenPiece()
  608.     {
  609.         for (int i=EDITKING; i<=EDITPAWN; i++) {
  610.             if (Object(i).Checked()) {
  611.                 return EDITPAWN+1-i;
  612.             }
  613.         }
  614.  
  615.         return 0; // EDITNONE
  616.     }
  617.  
  618.     void SetEditPiece(int item)
  619.     {
  620.         for (int i=EDITKING; i<=EDITNONE; i++) {
  621.             Object(i).Checked(i==item);
  622.         }
  623.     }
  624.  
  625.     void DrawPiece(bool used,bool isblack,int x,int y,int piece)
  626.     {
  627.         board.SetPiece(used,isblack,x,y,piece);
  628.     }
  629.  
  630.     void DrawSquare(int x, int y, bool isblack)
  631.     {
  632.         board.SetSquare(x,y,isblack);
  633.     }
  634.  
  635.     int ChooseLevel()
  636.     {
  637.         if (lastchosenlevel<=0) {
  638.             lastchosenlevel=levellist.Do()-LEVEL1+1;
  639.         }
  640.         return lastchosenlevel;
  641.     }
  642.  
  643.     void GetMove(char* m)
  644.     {
  645.         if (!board.IsOpen()) board.Open(); // Keep it open, but don't top.
  646.  
  647.         move[0]=0;
  648.         while (!move[0]) OneDo();
  649.         strcpy(m,move);
  650.  
  651.         Unhighlight();
  652.     }
  653.  
  654.     void SetMove(const char* m)
  655.     {
  656.         strcpy(move,m);
  657.     }
  658.  
  659.     void Message(char* msg)
  660.     {
  661.         char info[128];
  662.         sprintf(info," %02d:%02d  %s",minutes,seconds,msg);
  663.         board.SetInfoText(info);
  664.     }
  665.  
  666.     void SetTime(int mins, int secs)
  667.     {
  668.         minutes=mins;
  669.         seconds=secs;
  670.         Message("");
  671.     }
  672.  
  673.     void HighlightMove(char* move,bool redraw)
  674.     {
  675.         board.HighlightMove(move,redraw);
  676.     }
  677.  
  678.     void Unhighlight()
  679.     {
  680.         board.Unhighlight();
  681.     }
  682.  
  683.     void LoadFailed()
  684.     {
  685.         loadfailed.Alert();
  686.     }
  687.  
  688.     void SaveFailed()
  689.     {
  690.         savefailed.Alert();
  691.     }
  692.  
  693.     void SetReverse(bool yes)
  694.     {
  695.         Object(DOREVERSE).Checked(yes);
  696.     }
  697.  
  698. private:
  699.     int lastchosenlevel;
  700.     int minutes,seconds;
  701.     char move[32];
  702.     GEMalert loadfailed,savefailed;
  703.  
  704.     // Menu override.
  705.     virtual GEMfeedback DoItem(int item, const GEMevent& e)
  706.     {
  707.         switch (item) {
  708.          case DOABOUT:
  709.             about.Do();
  710.         break; case DONEW:
  711.             SetMove("new");
  712.         break; case DORANDOM:
  713.             SetMove("random");
  714.         break; case DOLOAD:
  715.             SetMove("get");
  716.         break; case DOSAVE:
  717.             SetMove("save");
  718.         break; case DOLIST:
  719.             SetMove("list");
  720.         break; case DOQUIT:
  721.             SetMove("quit");
  722.         break; case EDITTOGGLE:
  723.             if (Object(EDITTOGGLE).Checked()) {
  724.                 Object(EDITTOGGLE).Uncheck();
  725.                 Object(EDITCLEAR).Disable();
  726.  
  727.                 for (int i=FIRSTMENUTITLE; i<=LASTMENUTITLE; i++) {
  728.                     if (i!=EDITMENUTITLE) {
  729.                         Object(i).Enable();
  730.                         RedrawObject(i);
  731.                     }
  732.                 }
  733.  
  734.                 SetMove(".");
  735.             } else {
  736.                 Object(EDITTOGGLE).Check();
  737.                 Object(EDITCLEAR).Enable();
  738.  
  739.                 for (int i=FIRSTMENUTITLE; i<=LASTMENUTITLE; i++) {
  740.                     if (i!=EDITMENUTITLE) {
  741.                         Object(i).Disable();
  742.                         RedrawObject(i);
  743.                     }
  744.                 }
  745.  
  746.                 SetMove("edit");
  747.             }
  748.         break; case EDITWHITE:
  749.             SetEditColour(item);
  750.         break; case EDITBLACK:
  751.             SetEditColour(item);
  752.         break; case EDITKING: case EDITQUEEN: case EDITBISHOP:
  753.                 case EDITKNIGHT: case EDITROOK: case EDITPAWN: case EDITNONE:
  754.             SetEditPiece(item);
  755.         break; case EDITCLEAR:
  756.             SetMove("#");
  757.         break; case HUMANVSCPU: case CPUVSHUMAN: case CPUVSCPU:
  758.             if (!Object(item).Checked()) {
  759.                 Object(HUMANVSCPU).Checked(item==HUMANVSCPU);
  760.                 Object(CPUVSHUMAN).Checked(item==CPUVSHUMAN);
  761.                 Object(CPUVSCPU).Checked(item==CPUVSCPU);
  762.  
  763.                 switch (item) {
  764.                  case HUMANVSCPU:
  765.                     SetMove("black");
  766.                 break; case CPUVSHUMAN:
  767.                     SetMove("white");
  768.                 break; case CPUVSCPU:
  769.                     SetMove("both");
  770.                 }
  771.             }
  772.         break; case DOREVERSE:
  773.             SetMove("reverse");
  774.         break; case DOLEVEL:
  775.             lastchosenlevel=levellist.Do(e.X()-8,e.Y()-8)-LEVEL1+1;
  776.             if (lastchosenlevel>0) SetMove("level");
  777.         break; case DOSIZE:
  778.             board.SetSize();
  779.         break; case DOHINT:
  780.             SetMove("hint");
  781.         break; case BACK1MOVE:
  782.             SetMove("undo");
  783.         break; case BACK2MOVES:
  784.             SetMove("remove");
  785.         break; case DOCOLOUR:
  786.             colour.Open();
  787.         break; case DISABLEBOOK:
  788.             if (bookwarn.Alert()==2) {
  789.                 SetMove("book");
  790.             }
  791.         break; case DOSAVECONFIG:
  792.             SaveConfiguration(CONFIGFILE);
  793.         }
  794.  
  795.         return ContinueInteraction;
  796.     }
  797.  
  798. private:
  799.     ChessBoard board;
  800.     ColourWindow colour;
  801.     GEMform about;
  802.     GEMhotform levellist;
  803.     GEMalert message;
  804.     GEMalert bookwarn;
  805. };
  806.  
  807. void ChessBoard::Refresh(bool outline)
  808. {
  809.     if (outline) {
  810.         RedrawObject(0);
  811.     } else {
  812.         gui->SetMove("bd");
  813.     }
  814. }
  815.  
  816. void ChessBoard::SetSize()
  817. {
  818.     bool isblack=!gui->HumanIsWhite();
  819.  
  820.     SetPieceImage(sizer[SQUARE_SML+1],king,isblack,0);
  821.     SetPieceImage(sizer[SQUARE_MID+1],king,isblack,1);
  822.     SetPieceImage(sizer[SQUARE_LRG+1],king,isblack,2);
  823.  
  824.     int size=sizer.Do();
  825.     if (size>0) {
  826.         while (!sizer[size].Selectable())
  827.             size=sizer.Parent(size);
  828.         SetSize(size==SQUARE_SML ? 0 : size==SQUARE_MID ? 1 : 2);
  829.     }
  830. }
  831.  
  832. void ChessBoard::SetSize(int size)
  833. {
  834.     int RSCsize;
  835.  
  836.     switch (size) {
  837.      case 0:
  838.         pieces=&pieces_sml;
  839.         RSCsize=SQUARE_SML;
  840.     break; case 1:
  841.         pieces=&pieces_mid;
  842.         RSCsize=SQUARE_MID;
  843.     break; default:
  844.         pieces=&pieces_lrg;
  845.         RSCsize=SQUARE_LRG;
  846.     }
  847.  
  848.     GEMrawobject& sized=sizer.Object(RSCsize);
  849.  
  850.     for (int x=0; x<8; x++) {
  851.         for (int y=0; y<8; y++) {
  852.             Square(x,y).Resize(sized.Width(),sized.Height());
  853.             Square(x,y).MoveTo(0,(7-y)*sized.Height());
  854.             Piece(x,y).MoveTo(sizer.Object(RSCsize+1).X(),sizer.Object(RSCsize+1).Y());
  855.             Piece(x,y).HideTree(TRUE); // Go away - come back on refresh.
  856.         }
  857.         GEMrubberobject colmn(*this,C1+(C2-C1)*x);
  858.         colmn.MoveTo(x*sized.Width(),0);
  859.         colmn.Fit(0);
  860.     }
  861.  
  862.     GEMrubberobject box(*this,BOARDBORDER);
  863.     box.Fit(0);
  864.  
  865.     GEMrubberobject root(*this,BOARDSURROUND);
  866.     root.Fit(box.X());
  867.  
  868.     GRect rect(root.X(),root.Y(),root.Width(),root.Height());
  869.  
  870.     // XXX Excessive redraws here.
  871.     SetWorkRect(rect);
  872.     RedrawObject(0);
  873.     Refresh(FALSE);
  874. }
  875.  
  876. GEMfeedback ChessBoard::DoItem(int item, const GEMevent& e)
  877. {
  878.     item-=R1C1;
  879.  
  880.     int x=item/(R1C2-R1C1);
  881.     int y=(item-x*(R1C2-R1C1))/(R2C1-R1C1);
  882.  
  883.     x=RV(x);
  884.     y=RV(7-y);
  885.  
  886.     if (gui->InEditMode()) {
  887.         char move[4];
  888.         move[0]=pxx[gui->ChosenPiece()];
  889.         move[1]='a'+x;
  890.         move[2]='1'+y;
  891.         move[3]=0;
  892.         gui->SetMove(move);
  893.     } else {
  894.         if (chosen) {
  895.             char move[5];
  896.             move[0]='a'+chosenx;
  897.             move[1]='1'+choseny;
  898.             move[2]='a'+x;
  899.             move[3]='1'+y;
  900.             move[4]=0;
  901.             if (NeedPromotion(chosenx,choseny)) {
  902.                 move[4]=qxx[ChoosePromotion()];
  903.                 move[5]=0;
  904.             }
  905.             gui->SetMove(move);
  906.             chosen=FALSE;
  907.         } else {
  908.             chosen=TRUE;
  909.             chosenx=x;
  910.             choseny=y;
  911.         }
  912.  
  913.         Square(RV(chosenx),RV(choseny)).BorderWidth(chosen ? colour.CursorBorder() : 0);
  914.         Square(RV(chosenx),RV(choseny)).BorderCol(colour.CursorColour());
  915.         RedrawObject(SquareIndex(RV(chosenx),RV(choseny)));
  916.     }
  917.  
  918.     GEMevent event;
  919.     event.Button(1,0); // leftbutton release
  920.     event.Get(MU_BUTTON);
  921.  
  922.     return ContinueInteraction;
  923. }
  924.  
  925. static GEMapplication* app;
  926. static GEMrsc* rsc;
  927. static GEM_GNUChess_GUI* gem_gui;
  928.  
  929. void ui_Initialize()
  930. {
  931.     app=new GEMapplication;
  932.  
  933.     {
  934.         VDI vdi;
  935.         if (vdi.CharCellHeight()<=8) {
  936.             rsc=new GEMrsc("data\\low_rsc.rsc");
  937.         } else {
  938.             rsc=new GEMrsc("data\\gem_rsc.rsc");
  939.         }
  940.     }
  941.  
  942.     gem_gui=new GEM_GNUChess_GUI(*rsc);
  943. }
  944.  
  945. void ui_Finalize()
  946. {
  947.     delete gem_gui;
  948.     delete rsc;
  949.     delete app;
  950. }
  951.  
  952.  
  953. void ui_GiveHelp (int compiswhite,int level,int easy,int maxdep,int dither,int hash)
  954. {
  955. }
  956.  
  957. void ui_ShowEditHelp()
  958. {
  959. }
  960.  
  961. void ui_ShowEditColor(int col)
  962. {
  963.     gem_gui->SetEditColour(col+EDITWHITE);
  964. }
  965.  
  966. void ui_GetPieceAndLocation(char *s)
  967. {
  968.     gem_gui->GetMove(s);
  969. }
  970.  
  971. void ui_ShowComputerMove(char *move, int feature)
  972. {
  973.     switch (feature) {
  974.      case 1:; // Draw
  975.     break; case 2:
  976.         CheckMate=1;
  977.         ui_ShowMessage("Mate");
  978.     break; case 3:
  979.         CheckMate=2;
  980.         ui_ShowMessage("Mate");
  981.     break; case 4:; // Near win
  982.         //ui_ShowMessage("Oh dear.");
  983.     break; case 5:; // Near loss
  984.         //ui_ShowMessage("Watch out.");
  985.     }
  986.  
  987.     gem_gui->HighlightMove(move,FALSE/*DrawPiece called anyway*/);
  988. }
  989.  
  990. void ui_DrawPiece(bool used, bool isblack, int x, int y, int piece)
  991. {
  992.     gem_gui->DrawPiece(used,isblack,x,y,piece);
  993. }
  994.  
  995. void ui_DrawSquare(int x, int y, bool isblack)
  996. {
  997.     gem_gui->DrawSquare(x,y,isblack);
  998. }
  999.  
  1000. void ui_GetFilename(char *prompt,char *name)
  1001. {
  1002.     GEMfileselector* filesource=0;
  1003.  
  1004.     if (!filesource) filesource=new GEMfileselector;
  1005.  
  1006.     if (!filesource->Get(prompt,name))
  1007.         name[0]=-1;
  1008. }
  1009.  
  1010. void ui_LoadDone()
  1011. {
  1012. }
  1013.  
  1014. void ui_LoadFailed()
  1015. {
  1016.     gem_gui->LoadFailed();
  1017. }
  1018.  
  1019. void ui_SaveDone()
  1020. {
  1021. }
  1022.  
  1023. void ui_SaveFailed()
  1024. {
  1025.     gem_gui->SaveFailed();
  1026. }
  1027.  
  1028. void ui_ChangeLevel(int *newlevel)
  1029. {
  1030.     *newlevel=gem_gui->ChooseLevel();
  1031. }
  1032.  
  1033. void ui_GetMove(char *s)
  1034. {
  1035.     gem_gui->GetMove(s);
  1036. }
  1037.  
  1038. void ui_ShowHint(char *move)
  1039. {
  1040.     gem_gui->HighlightMove(move,TRUE);
  1041. }
  1042.  
  1043. void ui_ShowPlayers(bool Reverse,int CompIsBlack)
  1044. {
  1045.     WhiteFromTop=Reverse;
  1046.     ComputerIsBlack=CompIsBlack;
  1047.     gem_gui->SetReverse(Reverse);
  1048. }
  1049.  
  1050. void ui_ShowSideToMove(int movenum, int who)
  1051. {
  1052.     CurrentColour=who;
  1053. }
  1054.  
  1055. void ui_RejectMove(char *move)
  1056. {
  1057.     int ifx=move[0]-'a';
  1058.     int ify=move[1]-'1';
  1059.     int itx=move[2]-'a';
  1060.     int ity=move[3]-'1';
  1061.  
  1062.     ui_DrawPiece(TRUE,ColourAt(ifx,ify),RV(ifx),RV(ify),RankAt(ifx,ify));
  1063. }
  1064.  
  1065. void ui_ShowClock(bool OnWhiteSide, int minutes, int seconds)
  1066. {
  1067.     gem_gui->SetTime(minutes,seconds);
  1068. }
  1069.  
  1070. void ui_ShowMessage(char *msg)
  1071. {
  1072.     gem_gui->Message(msg);
  1073. }
  1074.  
  1075. // Unused interface hooks...
  1076.  
  1077. void ui_PromptForMove() {}
  1078. void ui_ToggleRV() {}
  1079. void ui_ToggleStars() {}
  1080. void ui_ToggleShade() {}
  1081. int ui_AskAbort() { return 0; }
  1082. void ui_ClearEditHelp() {}
  1083. void ui_RefreshEarly() {}
  1084. void ui_ChoosePiece(char *s) {}
  1085. void ui_ChangeSearchDepth(int *newdepth) {}
  1086. void ui_ChangeContempt(int *newcontempt) {}
  1087. void ui_ShowFileSaving(char *name) {}
  1088. void ui_ShowFileLoading(char *name) {}
  1089. void ui_DrawCoords() {}
  1090. void ui_ShowPosnValue(short sq, int score) {}
  1091. void ui_ShowMaxTree(int maxtree) {}
  1092. void ui_ClrScreen() {}
  1093. void ui_ShowDepth(int depth, char ch) {}
  1094. void ui_ShowScore(int score) {}
  1095. void ui_ClearMessage() { gem_gui->Message(""); gem_gui->Unhighlight(); }
  1096. void ui_ShowCurrentMove(int pnt, char *move) {}
  1097. void ui_ShowTitle() {}
  1098. void ui_ShowNodeCnt(long int NodeCnt, long int evrate) {}
  1099. void ui_ShowPlyMove(int ply,char *move) {}
  1100. void ui_NoMorePly(int ply) {}
  1101. void ui_SearchStartStuff(int side) {}
  1102.