////////////////////////////////////////////////////////////////////////////// // // This file is part of the Atari graphical interface for GNU Chess, // and is Copyright 1992 by Warwick W. Allison. // // You are free to copy and modify these sources, provided you acknowledge // the origin by retaining this notice, and adhere to the conditions // of the CHESS General Public License described in the main chess file // gnuchess.cc. // ////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include static char* ColorStr[2] = {"White", "Black"}; #include "gnuchess.h" #include "uisupport.h" #include "ui.h" #define pxx " PNBRQK" #define qxx " pnbrqk" #define RV(x) (WhiteFromTop ? 7-(x) : (x)) #include #include #include #include #include #include #include #include "Cursor.h" #include "Buttons.h" #include "Piece.h" #include "Beeps.h" #include "Timer.h" #include "Help.h" const int BoardX=127; const int BoardY=5; const int SquareWidth=24; const int SquareHeight=23; const int FeatureX=0; const int FeatureY=95; const int FeatureW=8; const int FeatureH=15; const int PiecesX=96; const int PiecesY=5; const int PiecesW=12; const int PiecesH=15; static bool WhiteFromTop=FALSE; static char CurrentFilename[100]="gnuchess.sav"; static int CurrentColour=white; static Sprite* SquareHighlight; static Sprite* FeatureLight; static bool DoShowLegalMoves=TRUE; static bool DoReverseTheArrow=TRUE; static bool DoAnimateComputerMoves=TRUE; static bool DoShowContextHelp=TRUE; static bool ComputerIsBlack=TRUE; static int CheckMate=0; char* const ConfigFile="gnuchess.cnf"; char AlgebraicName[8][8][4]; void SetAlgebraicNames() { for (int y=0; y<8; y++) { for (int x=0; x<8; x++) { AlgebraicName[x][y][0]=RV(x)+'a'; AlgebraicName[x][y][1]='8'-RV(y); AlgebraicName[x][y][2]=0; } } } void LoadCNF() { FILE* fd=fopen(ConfigFile,"r"); if (fd) { fscanf(fd,"%d %d %d %d", &DoShowLegalMoves, &DoReverseTheArrow, &DoAnimateComputerMoves, &DoShowContextHelp); fclose(fd); } } void SaveCNF() { FILE* fd=fopen(ConfigFile,"w"); if (fd) { fprintf(fd,"%d %d %d %d (Show legal, Arrow rev, Move animate, Help)\n", DoShowLegalMoves, DoReverseTheArrow, DoAnimateComputerMoves, DoShowContextHelp); fclose(fd); } } bool XYScreenToBoard(int X,int Y,int& x,int& y) { x=X-BoardX; y=Y-BoardY; if (x<0 || y<0) return 0; x=x/SquareWidth; y=7-y/SquareHeight; if (WhiteFromTop) { x=7-x; y=7-y; } return x<8 && y<8; } bool XYCursorToBoard(int& x,int& y) { x=Cursor->X(); y=Cursor->Y(); //CorrectForCursor(x,y); x-=BoardX; y-=BoardY; if (x<0 || y<0) return FALSE; x=x/SquareWidth; y=y/SquareHeight; if (x>=8 && y>=8) return FALSE; y=7-y; if (WhiteFromTop) { x=7-x; y=7-y; } return TRUE; } void XYBoardToScreen(int X,int Y,int& x,int& y,bool Rev) { if (Rev) { X=7-X; Y=7-Y; } x=BoardX+X*SquareWidth; y=BoardY+(7-Y)*SquareHeight; } void SetCursorShape(bool FromBottom) { if (FromBottom || !DoReverseTheArrow) { Cursor->ShapeTo(0); Mouse.Bound(0,0,320-11,200-16); } else { Cursor->ShapeTo(1); Mouse.Bound(11,15,320-16,200-16); } } void ShowFeatures() { for (int x=0; x<4; x++) { bool Now; switch (x) { case 0: Now=DoShowLegalMoves; break; case 1: Now=DoReverseTheArrow; break; case 2: Now=DoAnimateComputerMoves; break; case 3: Now=DoShowContextHelp; break; default: Now=FALSE; } FeatureLight->ShapeTo(Now); FeatureLight->MoveTo(x*FeatureW+FeatureX,FeatureY); FeatureLight->Draw(); Pages->Flip(); FeatureLight->Draw(); Pages->Flop(); } } ResolutionChange *OriginalResolution; Screen *OriginalScreen; void ui_Initialize() { LoadCNF(); Mouse.Bound(0,0,320-16,200-16); Mouse.MoveTo(160,100); // Load images, sprites, etc. OriginalResolution=new ResolutionChange(STLow); OriginalScreen=new Screen(DESKSCREEN); // Set-up DoubleBuffer (must be done before all sprite stuff) Screen *This=new Screen; This->LoadCrackArt("pic\\scene.ca1"); Screen *That=new Screen(*This); Pages=new DoubleBuffer(*This,*That); This->ShowPalette(); Pages->Flop(); Screen ImageBank; ImageBank.LoadCrackArt("pic\\sprites.ca1"); InitPiece(ImageBank); InitCursor(ImageBank); InitClock(ImageBank); InitButtons(ImageBank); // The following implemented with EasySprites SquareHighlight=GetSprite(ImageBank,288,117,SquareHeight,SP_WIDE|SP_COLOUR); FeatureLight=GetSprite(ImageBank,304,158,4,SP_COLOUR,2,0,4); ShowFeatures(); // Help // Edit pieces AddHelp(PiecesX,PiecesY,PiecesW*2,PiecesH*6,"Pieces - for editing"); AddHelp(PiecesX,PiecesY+PiecesH*6,PiecesW,PiecesH,"Blank piece"); AddHelp(PiecesX+PiecesW,PiecesY+PiecesH*6,PiecesW,PiecesH,"Blank board"); // Features AddHelp(FeatureX+FeatureW*0,FeatureY,FeatureW,FeatureH,"Show legal moves"); AddHelp(FeatureX+FeatureW*1,FeatureY,FeatureW,FeatureH,"Reversible arrow"); AddHelp(FeatureX+FeatureW*2,FeatureY,FeatureW,FeatureH,"Animate CPU moves"); AddHelp(FeatureX+FeatureW*3,FeatureY,FeatureW,FeatureH,"Show this help"); // Messages AddHelp(37,126,13,15,"GNU's Not Unix"); AddHelp(66,176,57,5,"warwick@cs.uq.oz.au"); // Clock AddHelp(32,95,64,15,"Play timer"); // Algebraic names SetAlgebraicNames(); for (int y=0; y<8; y++) { for (int x=0; x<8; x++) { AddHelp(BoardX+x*SquareWidth,BoardY+y*SquareHeight,SquareWidth,SquareHeight,AlgebraicName[x][y]); } } // Context-free help messages AddHelp(9999,0,1,1,"Choose promotion"); } void ui_Finalize() { // delete stuff, restore resources OriginalScreen->ShowPalette(); OriginalScreen->Show(); delete OriginalScreen; delete OriginalResolution; } void ui_GiveHelp (int compiswhite,int level,int easy,int maxdep,int dither,int hash) { OriginalScreen->Show(); OriginalScreen->ShowPalette(); ResolutionChange MediumForThisTextStuff(STMedium); while (1) { printf("\033E"); printf("GNU Chess v3.1 - Atari port (version 1) by Warwick Allison\n\n"); printf("Current filename: %s\n\n",CurrentFilename); printf("\nInformation items:\n"); printf("W = Warranty information\n"); printf("C = Copying policy\n"); printf("L = Level descriptions\n"); printf("A = Acknowledgements\n"); printf("N = Notes\n"); printf("F = Current filename\n"); printf("\n\nChoose function, or click to return\n"); while (!Mouse.LeftButton() && !Mouse.RightButton() && !Cconis()); printf("\033E"); if (Cconis()) { char ch=Cnecin(); switch (toupper(ch)) { case 'F': char NewFilename[256]; printf("Current filename = %s\n",CurrentFilename); printf("New filename: \033e"); // Cursor on gets(NewFilename); if (NewFilename[0]) strcpy(CurrentFilename,NewFilename); printf("\033f\n"); // Cursor off printf("Current filename = %s\n",CurrentFilename); break; case 'C': printf("GNU Chess is Copyright 1992 by the Free Software Federation,\n"); printf(" and Copyright 1992 by John Stanback.\n\n"); printf("The Atari graphical interface sources are Copyright 1992\n"); printf(" by Warwick W. Allison.\n\n"); printf("GNU Chess, and this port, are licensed free of charge. For full details,\n"); printf("read the file COPYING, which should have been included with this program.\n\n"); break; case 'A': printf("You can thank these people:\n\n"); printf(" John Stanback, and all the other GNUChess authors,\n"); printf(" The GNU crowd for G++,\n"); printf(" Jwahar Bammi for [repeatedly] porting G++ to the ST,\n"); printf(" and the Beta Testers:\n"); printf(" Mika Kukkonen, Joshua Kronengold, Doug Shaw, Clive Salvidge.\n"); break; case 'W': printf(" NO WARRANTY\n\n"); printf("BECAUSE GNU CHESS IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO\n"); printf("WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.\n\n"); printf("For full details, read the file called COPYING, which should have been with\n"); printf("this program.\n"); break; case 'N': printf("Load & Save use the current filename.\n"); printf("If the variable $HOME is set, it saves there rather than the current directory.\n\n"); printf("Book disable stops the computer from using \"canned\" moves to start the game.\n"); break; case 'l': case 'L': printf(" 1. 60 moves in 5 minutes\n"); printf(" 2. 60 moves in 15 minutes\n"); printf(" 3. 60 moves in 30 minutes\n"); printf(" 4. 40 moves in 30 minutes\n"); printf(" 5. 40 moves in 60 minutes\n"); printf(" 6. 40 moves in 120 minutes\n"); printf(" 7. 40 moves in 240 minutes\n"); printf(" 8. 1 move in 15 minutes\n"); printf(" 9. 1 move in 60 minutes\n"); printf("10. 1 move in 600 minutes\n"); } while (!Mouse.LeftButton() && !Mouse.RightButton() && !Cconis()); if (Cconis()) Cnecin(); else break; } else break; } Pages->Current().ShowPalette(); Pages->Flip(); while (Mouse.LeftButton() || Mouse.RightButton()); if (Cconis()) Cnecin(); } void ui_ShowEditHelp() { } static CurrentEditColour=0; void ui_ShowEditColor(int col) { CurrentEditColour=col; } int ChoosePiece(int& P) { int x=Cursor->X(); int y=Cursor->Y(); x-=PiecesX; y-=PiecesY; if (x<0 || y<0) return 0; x/=PiecesW; y/=PiecesH; if (y==6) { switch (x) { case 0: P=0; return 0; break; case 1: return 2; } } else if (x>=0 && x<=1 && y>=0 && y<=5) { int NewCol; if (y>=3) { NewCol=black; y-=3; } else { NewCol=white; } P=1+x+y*2; int TmpColour=CurrentEditColour; CurrentEditColour=NewCol; return NewCol!=TmpColour; } return 0; } void ui_GetPieceAndLocation(char *s) { static int CurrentPiece=0; bool done=FALSE; int x,y; while (!done) { Cursor->Wipe(); Cursor->MoveTo(Mouse.X(),Mouse.Y()); if (DoShowContextHelp) ShowContextHelp(Cursor->X(), Cursor->Y()); if (Mouse.LeftButton()) { if (XYCursorToBoard(x,y)) { s[0]=pxx[CurrentPiece]; s[1]='a'+x; s[2]='1'+y; s[3]=0; done=TRUE; } else { switch (ChoosePiece(CurrentPiece)) { case 0: break; case 1: s[0]='C'; s[1]=0; done=TRUE; break; case 2: s[0]='#'; s[1]=0; done=TRUE; break; case 3: s[0]='.'; s[1]=0; done=TRUE; } } while (Mouse.LeftButton()); } else if (Mouse.RightButton()) { s[0]='.'; s[1]=0; done=TRUE; while (Mouse.RightButton()); } if (!done) Cursor->Draw(); Pages->Flip(); } Cursor->Wipe(); } bool OnBoard(int x, int y) { return (x>=0 && x<=7 && y>=0 && y<=7); } void AnimateMove(int Speed,int ifx,int ify,int itx,int ity) { XYBoardToScreen(ifx,ify,ifx,ify,FALSE); XYBoardToScreen(itx,ity,itx,ity,FALSE); double fx=ifx+SquareWidth/2; double fy=ify+SquareHeight/2; double tx=itx+SquareWidth/2; double ty=ity+SquareHeight/2; double dx=(tx-fx)/Speed; double dy=(ty-fy)/Speed; while (--Speed) { Cursor->Wipe(); Cursor->MoveTo((int)fx,(int)fy); Cursor->Draw(); Pages->Flip(); fx+=dx; fy+=dy; } Cursor->Wipe(); Pages->Flop(); Cursor->Wipe(); } void ui_ShowComputerMove(char *move, int feature) { if (DoAnimateComputerMoves) { int ifx=move[0]-'a'; int ify=move[1]-'1'; int itx=move[2]-'a'; int ity=move[3]-'1'; if (!OnBoard(ifx,ify) || !OnBoard(itx,ity)) return; Cursor->ShapeTo(RankAt(itx,ity) + (CurrentColour==white ? 3 : 9)); if (WhiteFromTop) { ifx=7-ifx; ify=7-ify; itx=7-itx; ity=7-ity; } ui_DrawPiece(FALSE,(ifx^ify)&2,ifx,ify,no_piece); AnimateMove(45,ifx,ify,itx,ity); } switch (feature) { case 1:; // Draw break; case 2: CheckMate=1; break; case 3: CheckMate=2; break; case 4:; // Near win break; case 5:; // Near loss } } void ui_DrawPiece(bool used, bool isblack, int x, int y, int piece) { //ui_DrawSquare(x,y,(x+y)%2); Piece->Colour((x+y)%2 ? FALSE : TRUE); XYBoardToScreen(x,y,x,y,FALSE); // Middle of square x+=SquareWidth/2; y+=SquareHeight/2; Piece->Rank(no_piece); Pages->Flop(); Piece->Draw(x,y); Pages->Flop(); Piece->Draw(x,y); if (used) { Piece->Rank(piece); Piece->Colour(isblack); Pages->Flop(); Piece->Draw(x,y); Pages->Flop(); Piece->Draw(x,y); } } void ui_DrawSquare(int x, int y, bool isblack) { } void ui_GetFilename(char *prompt,char *name) { strcpy(name,CurrentFilename); } void ui_LoadDone() { //Chime(); } void ui_LoadFailed() { Raspberry(); } void ui_SaveDone() { //Chime(); } void ui_SaveFailed() { Raspberry(); } void ui_ChangeLevel(int *newlevel) { *newlevel=MyLevel; } bool ToggleFeature(int x,int y) { x-=FeatureX; y-=FeatureY; if (x<0 || y<0) return FALSE; x/=FeatureW; y/=FeatureH; if (y) return FALSE; bool Now; switch (x) { case 0: Now=DoShowLegalMoves=!DoShowLegalMoves; break; case 1: Now=DoReverseTheArrow=!DoReverseTheArrow; SetCursorShape(ComputerIsBlack^WhiteFromTop); break; case 2: Now=DoAnimateComputerMoves=!DoAnimateComputerMoves; break; case 3: Now=DoShowContextHelp=!DoShowContextHelp; break; default: return FALSE; } FeatureLight->ShapeTo(Now); FeatureLight->MoveTo(x*FeatureW+FeatureX,FeatureY); FeatureLight->Draw(); Pages->Flip(); Cursor->Wipe(); FeatureLight->Draw(); Cursor->Draw(); Pages->Flop(); return TRUE; } int ChoosePromotion() { int P=0; bool done=FALSE; int x,y; Mouse.MoveTo(108,50); while (Mouse.LeftButton()); while (!done) { Cursor->Wipe(); Cursor->MoveTo(Mouse.X(),Mouse.Y()); if (DoShowContextHelp) ShowContextHelp(9999,0); if (Mouse.LeftButton()) { ChoosePiece(P); done=TRUE; while (Mouse.LeftButton()); } if (!done) Cursor->Draw(); Pages->Flip(); } Cursor->Wipe(); return P; } void ui_GetMove(char *s) { bool done=FALSE; bool from=TRUE; bool WaitingFor=TRUE; bool Legal,Moved=FALSE; int fromx=0,fromy=0,tox,toy,FromMouseX,FromMouseY; if (Cconis()) Cnecin(); ReleaseButton(); while (!done) { Cursor->Wipe(); SquareHighlight->Wipe(); Cursor->MoveTo(Mouse.X(),Mouse.Y()); if (DoShowContextHelp) ShowContextHelp(Cursor->X(), Cursor->Y()); else NoHelp(); Legal=FALSE; if (!CheckMate && XYCursorToBoard(tox,toy)) { if (!from && abs(FromMouseX-Cursor->X()) +abs(FromMouseY-Cursor->Y()) > 4) { Moved = TRUE; } if (!from && DoShowLegalMoves && (LegalMove(tox,toy) || tox==fromx && toy==fromy)) { int x,y; XYBoardToScreen(tox,toy,x,y,WhiteFromTop); SquareHighlight->MoveTo(x,y); Legal=TRUE; } if (Mouse.LeftButton()==WaitingFor) { if (from) { if (ColourAt(tox,toy)==CurrentColour) { FromMouseX=Cursor->X(); FromMouseY=Cursor->Y(); fromx=tox; fromy=toy; from=FALSE; Pages->Flop(); Cursor->Wipe(); SquareHighlight->Wipe(); ui_DrawPiece(false,(fromx^fromy)%2,RV(fromx),RV(fromy),no_piece); Cursor->ShapeTo(RankAt(fromx,fromy) + (CurrentColour==white ? 3 : 9)); Mouse.Bound(BoardX+6,BoardY+10,SquareWidth*8-11,SquareHeight*8-20); CalculateLegalMoves(fromx,fromy); } WaitingFor=!WaitingFor; } else { WaitingFor=TRUE; if (Moved) { if (tox==fromx && toy==fromy) { Pages->Flop(); Cursor->Wipe(); SquareHighlight->Wipe(); ui_DrawPiece(TRUE,CurrentColour,RV(fromx),RV(fromy),RankAt(fromx,fromy)); SetCursorShape(ComputerIsBlack^WhiteFromTop); from=TRUE; } else { if (LegalMove(tox,toy)) { done=TRUE; s[0]='a'+fromx; s[1]='1'+fromy; s[2]='a'+tox; s[3]='1'+toy; s[4]=0; if (NeedPromotion(fromx,fromy)) { SetCursorShape(ComputerIsBlack^WhiteFromTop); s[4]=qxx[ChoosePromotion()]; s[5]=0; } } } } Moved=TRUE; } } } else if (Mouse.LeftButton()) { Pages->Flop(); SquareHighlight->Wipe(); Cursor->Wipe(); tox=Cursor->X(); toy=Cursor->Y(); //CorrectForCursor(tox,toy); if (PressButton(tox,toy,s)) { done=TRUE; if (strcmp(s,"new")==0 || strcmp(s,"undo")==0 || strcmp(s,"remove")==0 || strcmp(s,"save")==0 || strcmp(s,"edit")==0 || strcmp(s,"edit")==0 ) CheckMate=0; // Should be ui_ callback if (strcmp(s,"savecnf")==0) { done=FALSE; // Local function SaveCNF(); ReleaseButton(); } } else if (ToggleFeature(tox,toy)) { // So what. } while (Mouse.LeftButton()); } if (!done) { if (CheckMate) { if (XYCursorToBoard(tox,toy)) Cursor->ShapeTo(CheckMate+1); else SetCursorShape(ComputerIsBlack^WhiteFromTop); } } if (!done) { if (Mouse.RightButton() && !from) { Pages->Flop(); Cursor->Wipe(); SquareHighlight->Wipe(); ui_DrawPiece(TRUE,CurrentColour,RV(fromx),RV(fromy),RankAt(fromx,fromy)); SetCursorShape(ComputerIsBlack^WhiteFromTop); from=TRUE; WaitingFor=TRUE; Moved=FALSE; while (Mouse.RightButton()); } if (Legal) SquareHighlight->Draw(); Cursor->Draw(); } Pages->Flip(); } Cursor->Wipe(); SquareHighlight->Wipe(); Pages->Flop(); Cursor->Wipe(); SquareHighlight->Wipe(); } void ui_ShowHint(char *move) { int ifx=move[0]-'a'; int ify=move[1]-'1'; int itx=move[2]-'a'; int ity=move[3]-'1'; if (!OnBoard(ifx,ify) || !OnBoard(itx,ity)) return; Cursor->ShapeTo(RankAt(ifx,ify) + (CurrentColour==white ? 3 : 9)); if (WhiteFromTop) { ifx=7-ifx; ify=7-ify; itx=7-itx; ity=7-ity; } ui_DrawPiece(FALSE,(ifx^ify)&2,ifx,ify,no_piece); AnimateMove(25,ifx,ify,itx,ity); AnimateMove(25,itx,ity,ifx,ify); ui_DrawPiece(TRUE,CurrentColour,ifx,ify,RankAt(RV(ifx),RV(ify))); } void ui_ShowPlayers(bool Reverse,int CompIsBlack) { WhiteFromTop=Reverse; SetAlgebraicNames(); ComputerIsBlack=CompIsBlack; } void ui_ShowSideToMove(int movenum, int who) { CurrentColour=who; if ((who==white) == WhiteFromTop) { SetCursorShape(FALSE); } else { SetCursorShape(TRUE); } } void ui_RejectMove(char *move) { Raspberry(); int ifx=move[0]-'a'; int ify=move[1]-'1'; int itx=move[2]-'a'; int ity=move[3]-'1'; if (!OnBoard(ifx,ify) || !OnBoard(itx,ity)) return; ui_DrawPiece(TRUE,CurrentColour,RV(ifx),RV(ify),RankAt(ifx,ify)); } void ui_ShowClock(bool OnWhiteSide, int minutes, int seconds) { Minutes->Set(minutes); Seconds->Set(seconds); Minutes->Draw(); Seconds->Draw(); Pages->Flop(); Minutes->Draw(); Seconds->Draw(); Pages->Flop(); if (Cconis()) TerminateSearch(0); } void ui_ShowMessage(char *msg) { } // Unused interface hooks... void ui_PromptForMove() {} void ui_ToggleRV() {} void ui_ToggleStars() {} void ui_ToggleShade() {} int ui_AskAbort() { return 0; } void ui_ClearEditHelp() {} void ui_RefreshEarly() {} void ui_ChoosePiece(char *s) {} void ui_ChangeSearchDepth(int *newdepth) {} void ui_ChangeContempt(int *newcontempt) {} void ui_ShowFileSaving(char *name) {} void ui_ShowFileLoading(char *name) {} void ui_DrawCoords() {} void ui_ShowPosnValue(short sq, int score) {} void ui_ShowMaxTree(int maxtree) {} void ui_ClrScreen() {} void ClrScreen() {} void ui_ShowDepth(int depth, char ch) {} void ui_ShowScore(int score) {} void ui_ClearMessage() {} void ui_ShowCurrentMove(int pnt, char *move) {} void ui_ShowTitle() {} void ui_ShowNodeCnt(long int NodeCnt, long int evrate) {} void ui_ShowPlyMove(int ply,char *move) {} void ui_NoMorePly(int ply) {} void ui_SearchStartStuff(int side) {}