/* nuxui.c - (new) Unix user interface for CHESS This file was extracted from the original GNU Chess file nuxui.c and converted to C++ by Warwick Allison. It represents the ASCII interface requirements to implement ui.h. Revision: 1990-05-09 Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc. Copyright (c) 1988, 1989, 1990 John Stanback Modified extensively Nov 1989 Christopher North-Keys 40x24 two-colour display option for shading black squares expanded game save, list, and restore features using $HOME option to disable display of coordinates optional auto-updating of positional information optional starring of black side mass toggle for reverse-video functions This file is part of CHESS. CHESS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the CHESS General Public License for full details. Everyone is granted permission to copy, modify and redistribute CHESS, but only under the conditions described in the CHESS General Public License. A copy of this license is supposed to have been given to you along with CHESS so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #ifdef MSDOS #include #include #include #include #include #define ESC 0x1B #define refresh() fflush(stdout) int mycntl1, mycntl2; static void param (short n); #else //#define refresh() #include #include #include #include #undef bool // Curses defines it as char !!! #undef TRUE #undef FALSE #include #endif /* MSDOS */ static char* ColorStr[2] = {"White", "Black"}; #include "ui.h" #include "gnuchess.h" #define pxx " PNBRQK" #define qxx " pnbrqk" #define rxx "12345678" #define cxx "abcdefgh" #define TAB (43) /* coordinates within a square for the following are ([1,5],[1,3]) */ #define SQW (5) #define SQH (3) #define VIR_C(s) ((flag.reverse) ? 7-column(s) : column(s)) #define VIR_R(s) ((flag.reverse) ? 7-row(s) : row(s)) #define VSQ_X(x) ((flag.reverse) ? SQW + 1 - (x) : (x)) #define VSQ_Y(y) ((flag.reverse) ? SQH + 1 - (y) : (y)) #define Vblack(s) (!((VIR_C(s) + VIR_R(s)) % 2)) /* Squares swapped */ #define Vcoord(s,x,y) \ ((SQW)*(VIR_C(s)))+(x),((SQH)*(7-VIR_R(s))+(y)) #define XYcoord(X,Y,x,y) \ (((SQW)*(X))+(x)),((SQH)*(7-(Y))+(y)) /* Squares and internal locations swapped */ #define VcoordI(s,x,y) \ ((SQW)*(VIR_C(s)))+(VSQ_X(x)),((SQH)*(7-VIR_R(s))+(VSQ_Y(y))) /* Squares and internal rows swapped */ #define VcoordR(s,x,y) \ ((SQW)*(VIR_C(s)))+(x),((SQH)*(7-VIR_R(s))+(VSQ_Y(y))) #if defined(MSDOS) && !defined(SEVENBIT) short rv = 0; static void ONormal (void); static void OReverse (void); #else short stars = 0; short rv = 1; short shade = 0; static void ONormal (void); static void OReverse (void); #endif /* MSDOS && !SEVENBIT */ //#define standout() wstandout(stdscr) //#define standend() wstandend(stdscr) //#define clear() wclear(stdscr) //#define move(x,y) wmove(stdscr,x,y) //#define clrtoeol() wclrtoeol(stdscr) void TerminateSearch (int); void ui_Initialize() { #ifndef MSDOS initscr (); crmode (); #else mycntl1 = mycntl2 = 0; #endif /* MSDOS */ } void ui_Finalize() { gotoXY (1, 24); #ifndef MSDOS nocrmode (); endwin (); #endif /* MSDOS */ } void ui_GiveHelp (int compiswhite,int level,int easy,int maxdep,int dither,int hash) { ClrScreen (); wprintw(stdscr,"CHESS command summary\n"); wprintw(stdscr,"g1f3 move from g1 to f3 quit Exit Chess\n"); wprintw(stdscr,"Nf3 move knight to f3 beep on/off\n"); wprintw(stdscr,"o-o castle king side easy on/off\n"); wprintw(stdscr,"o-o-o castle queen side hash on/off\n"); wprintw(stdscr,"bd redraw board reverse board display\n"); wprintw(stdscr,"list game to chess.lst book on/off\n"); wprintw(stdscr,"undo undo last ply remove take back a move\n"); wprintw(stdscr,"edit edit board force enter game moves\n"); wprintw(stdscr,"switch sides with computer both computer match\n"); wprintw(stdscr,"white computer plays white black computer plays black\n"); wprintw(stdscr,"depth set search depth level select level\n"); wprintw(stdscr,"post principle variation hint suggest a move\n"); wprintw(stdscr,"save game to file get game from file\n"); wprintw(stdscr,"random randomize play new start new game\n"); wprintw(stdscr,"rv toggle reverse video coords toggle coords\n"); #if !defined(MSDOS) || defined(SEVENBIT) wprintw(stdscr,"shade toggle shade black stars toggle stars\n"); #endif /* !MSDOS || SEVENBIT */ wprintw(stdscr,"p show coordinate values\n"); gotoXY (10, 21); wprintw(stdscr,"Computer: %s", ColorStr[compiswhite]); gotoXY (10, 22); wprintw(stdscr,"Opponent: %s", ColorStr[!compiswhite]); gotoXY (10, 23); wprintw(stdscr,"Level: %ld", level); gotoXY (10, 24); wprintw(stdscr,"Easy mode: %s", easy ? "ON" : "OFF"); gotoXY (40, 21); wprintw(stdscr,"Depth: %d", maxdep); gotoXY (40, 22); wprintw(stdscr,"Random: %s", (dither) ? "ON" : "OFF"); gotoXY (40, 23); wprintw(stdscr,"Transposition table: %s", hash ? "ON" : "OFF"); gotoXY (40, 24); wprintw(stdscr,"Hit to return: "); refresh (); fflush(stdin); getchar(); ClrScreen (); UpdateDisplay (0, 0, 1, 0); } void ui_ShowEditHelp() { ClrScreen (); UpdateDisplay (0, 0, 1, 0); gotoXY (TAB, 3); wprintw(stdscr,". Exit to main"); gotoXY (TAB, 4); wprintw(stdscr,"# Clear board"); gotoXY (TAB, 5); wprintw(stdscr,"c Change sides"); gotoXY (TAB, 7); wprintw(stdscr,"Enter piece & location: "); } void ui_ShowEditColor(int col) { gotoXY (TAB, 6); wprintw(stdscr,"Editing: %s", ColorStr[col]); gotoXY (TAB + 24, 7); ClrEoln (); } void ui_GetPieceAndLocation(char *s) { wrefresh(stdscr); wscanw(stdscr,"%s", s); } void ui_ShowPlayers(bool reverse,int CompIsBlack) { gotoXY (TAB, ((reverse) ? 23 : 2)); wprintw(stdscr,"%s", (CompIsBlack) ? "Computer" : "Human "); gotoXY (TAB, ((reverse) ? 2 : 23)); wprintw(stdscr,"%s", (!CompIsBlack) ? "Computer" : "Human "); } void ui_ShowDepth(int depth, char ch) { gotoXY (TAB, 4); wprintw(stdscr,"Depth= %d%c ", depth, ch); ClrEoln (); } void ui_ShowScore(int score) { gotoXY (TAB, 5); wprintw(stdscr,"Score= %d", score); ClrEoln (); } void ui_ShowMessage(char *msg) { gotoXY (TAB, 6); wprintw(stdscr,"%s", msg); ClrEoln (); } void ui_ClearMessage() { gotoXY (TAB, 6); ClrEoln (); } void ui_ShowCurrentMove(int pnt, char *move) { gotoXY (TAB, 7); wprintw(stdscr,"(%2d) %4s", pnt, move); } void ui_ShowTitle() { gotoXY (TAB, 10); #ifdef MSDOS wprintw(stdscr,"GNU Chess display (MS-DOS, Mar 90)"); #else wprintw(stdscr,"GNU Chess display (Nov 89)"); #endif /* MSDOS */ } void ui_ShowSideToMove(int movenum, int who) { gotoXY (TAB, 14); wprintw(stdscr,"%2d: %s", movenum,ColorStr[who]); ClrEoln (); } void ui_PromptForMove() { gotoXY (TAB, 19); wprintw(stdscr,"Your move is? "); ClrEoln (); } void ui_ShowNodeCnt(long int NodeCnt, long int evrate) { gotoXY (TAB, 21); wprintw(stdscr,"Nodes= %8ld, Nodes/Sec= %5ld", NodeCnt, evrate); ClrEoln (); } void ui_ShowPlyMove(int ply,char *move) { if (ply % 4 == 1) { gotoXY (TAB, 8+ply/4); ClrEoln (); } wprintw(stdscr,"%5s ", move); } void ui_NoMorePly(int ply) { ClrEoln (); while (ply < 52) { if (ply % 4 == 1) { gotoXY (TAB, 8+ply/4); ClrEoln (); } ply++; } } void ui_SearchStartStuff(int side) { int i; signal (SIGINT, TerminateSearch); #ifdef MSDOS side++; /* shut up the compiler */ #else signal (SIGQUIT, TerminateSearch); #endif /* MSDOS */ for (i = 4; i < 14; i++) { gotoXY (TAB, i); ClrEoln (); } } void ui_ShowComputerMove(char *move, int feature) { gotoXY (TAB, 17); wprintw(stdscr,"My move is: %s", move); if (flag.beep) putchar (7); ClrEoln (); gotoXY (TAB, 24); switch (feature) { case 1: wprintw(stdscr,"Drawn game!"); break; case 2: wprintw(stdscr,"Opponent mates!"); break; case 3: wprintw(stdscr,"Computer mates!"); break; case 4: wprintw(stdscr,"Opponent will soon mate!"); break; case 5: wprintw(stdscr,"Computer will soon mate!"); } ClrEoln (); } void ui_ShowMaxTree(int maxtree) { gotoXY (TAB, 22); wprintw(stdscr,"Max Tree= %5d", maxtree); ClrEoln (); } void ui_ShowClock(bool OnWhiteSide, int minutes, int seconds) { if (OnWhiteSide) gotoXY (60, 23); else gotoXY (60, 2); wprintw(stdscr,"%d:%2d ", minutes, seconds); } void ui_ClrScreen() { #ifdef MSDOS putchar(ESC); putchar('['); putchar('2'); putchar('J'); #else clear (); #endif /* MSDOS */ refresh (); } void ui_DrawPiece(bool used, bool isblack, int x, int y, int piece) { gotoXY (2+SQW*x, 2+SQH*(7-y)); if (used) { if (isblack) { if (rv) OReverse (); #if defined(MSDOS) && !defined(SEVENBIT) wprintw(stdscr," %c ", qxx[piece]); #else wprintw(stdscr,(stars ? "*%c*" : " %c "), qxx[piece]); #endif /* MSDOS && !SEVENBIT */ ONormal (); } else { #if defined(MSDOS) && !defined(SEVENBIT) if (!rv) OReverse (); wprintw(stdscr," %c ", qxx[piece]); ONormal (); #else wprintw(stdscr," %c ", qxx[piece]); #endif /* MSDOS && !SEVENBIT */ } } else { #if defined(MSDOS) && !defined(SEVENBIT) if (rv) wprintw(stdscr,Vblack (sq) ? "\262\262\262" : "\260\260\260"); else wprintw(stdscr,Vblack (sq) ? "\260\260\260" : "\262\262\262"); #else if (shade) /*wprintw(stdscr,Vblack (sq) ? "///" : " ");*/ wprintw(stdscr,(!((x + y) % 2)) ? "///" : " "); else { /*if (Vblack (sq))*/ if (!((x + y) % 2)) OReverse (); wprintw(stdscr," "); ONormal (); } #endif /* MSDOS && !SEVENBIT */ } } void ui_DrawSquare(int x, int y, bool isblack) { #if defined(MSDOS) && !defined(SEVENBIT) if (rv) { gotoXY (XYcoord (x,y, 1, 1)); wprintw(stdscr,isblack ? "\262\262\262\262\262" : "\260\260\260\260\260"); gotoXY (XYcoord (x,y, 1, 2)); wprintw(stdscr,isblack ? "\262\262\262\262\262" : "\260\260\260\260\260"); gotoXY (XYcoord (x,y, 1, 3)); wprintw(stdscr,isblack ? "\262\262\262\262\262" : "\260\260\260\260\260"); } else { gotoXY (XYcoord (x,y, 1, 1)); wprintw(stdscr,isblack ? "\260\260\260\260\260" : "\262\262\262\262\262"); gotoXY (XYcoord (x,y, 1, 2)); wprintw(stdscr,isblack ? "\260\260\260\260\260" : "\262\262\262\262\262"); gotoXY (XYcoord (x,y, 1, 3)); wprintw(stdscr,isblack ? "\260\260\260\260\260" : "\262\262\262\262\262"); } #else if (shade) { gotoXY (XYcoord (x,y, 1, 1)); wprintw(stdscr,isblack ? "/////" : " "); gotoXY (XYcoord (x,y, 1, 2)); wprintw(stdscr,isblack ? "/////" : " "); gotoXY (XYcoord (x,y, 1, 3)); wprintw(stdscr,isblack ? "/////" : " "); } else { if (isblack) OReverse (); gotoXY (XYcoord (x,y, 1, 1)); wprintw(stdscr," "); gotoXY (XYcoord (x,y, 1, 2)); wprintw(stdscr," "); gotoXY (XYcoord (x,y, 1, 3)); wprintw(stdscr," "); ONormal (); } #endif /* MSDOS && !SEVENBIT */ } void ui_DrawCoords() { short z; for (z = 0; z <= 7; z++) { short sq; sq = z << 3; gotoXY (VcoordI (sq, 1, 1)); #if !defined(MSDOS) || defined(SEVENBIT) if ((Vblack (sq) || shade) && rv) #endif /* !MSDOS || SEVENBIT */ OReverse (); wprintw(stdscr,"%d", 1 + z); ONormal (); } for (z = 0; z <= 7; z++) { short sq; sq = z; gotoXY (VcoordI (sq, SQW, SQH)); #if !defined(MSDOS) || defined(SEVENBIT) if ((Vblack (sq) || shade) && rv) #endif /* !MSDOS || SEVENBIT */ OReverse (); wprintw(stdscr,"%c", cxx[z]); ONormal (); } #if !defined(MSDOS) || defined(SEVENBIT) for (z = 1; z <= (8 * SQH); z++) { gotoXY ((8 * SQW) + 1, z); wprintw(stdscr,"|"); } #endif /* MSDOS && !SEVENBIT */ } void ui_ShowPosnValue(short sq, int score) { gotoXY (VcoordR (sq, 2, 1)); #if !defined(MSDOS) || defined(SEVENBIT) if (Vblack (sq) && !shade) OReverse (); #endif /* !MSDOS || SEVENBIT */ if (color[sq] != neutral) wprintw(stdscr,"%3d", svalue[sq]); else #if defined(MSDOS) && !defined(SEVENBIT) { if (rv) wprintw(stdscr,Vblack (sq) ? "\262\262\262" : "\260\260\260"); else wprintw(stdscr,Vblack (sq) ? "\260\260\260" : "\262\262\262"); } #else wprintw(stdscr,shade && Vblack (sq) ? "///" : " "); #endif /* MSDOS && !SEVENBIT */ ONormal (); } void ui_GetFilename(char *prompt,char *name) { ShowMessage ("File name: "); wrefresh(stdscr); wscanw(stdscr,"%s", name); } void ui_ShowFileLoading(char *name) { ShowMessage("Loading "); wprintw(stdscr,"%s", name); } void ui_LoadDone() { ShowMessage ("Load done. Press "); fflush (stdin); getchar (); } void ui_LoadFailed() { ShowMessage ("Load failed"); return; } void ui_ShowFileSaving(char *name) { ShowMessage("Saving "); wprintw(stdscr,"%s", name); } void ui_SaveFailed() { ShowMessage ("Not saved"); return; } void ui_SaveDone() { ShowMessage ("Save done. Press "); fflush (stdin); getchar (); } void ui_ChangeSearchDepth(int *newdepth) { ShowMessage ("depth= "); wrefresh(stdscr); wscanw(stdscr,"%hd", newdepth); } void ui_ChangeContempt(int *newcontempt) { ShowMessage ("contempt= "); wrefresh(stdscr); wscanw(stdscr,"%hd", newcontempt); } void ui_ChangeLevel(int *newlevel) { ClrScreen (); gotoXY (32, 2); wprintw(stdscr,"CHESS"); gotoXY (20, 4); wprintw(stdscr," 1. 60 moves in 5 minutes"); gotoXY (20, 5); wprintw(stdscr," 2. 60 moves in 15 minutes"); gotoXY (20, 6); wprintw(stdscr," 3. 60 moves in 30 minutes"); gotoXY (20, 7); wprintw(stdscr," 4. 40 moves in 30 minutes"); gotoXY (20, 8); wprintw(stdscr," 5. 40 moves in 60 minutes"); gotoXY (20, 9); wprintw(stdscr," 6. 40 moves in 120 minutes"); gotoXY (20, 10); wprintw(stdscr," 7. 40 moves in 240 minutes"); gotoXY (20, 11); wprintw(stdscr," 8. 1 move in 15 minutes"); gotoXY (20, 12); wprintw(stdscr," 9. 1 move in 60 minutes"); gotoXY (20, 13); wprintw(stdscr,"10. 1 move in 600 minutes"); gotoXY (20, 17); wprintw(stdscr,"Enter Level: "); refresh (); wrefresh(stdscr); wscanw(stdscr,"%ld", &Level); ClrScreen (); } void ui_ChoosePiece(char *s) { ShowMessage ("Enter piece: "); wrefresh(stdscr); wscanw(stdscr,"%s", s); } void ui_GetMove(char *s) { ui_PromptForMove(); wrefresh(stdscr); wscanw(stdscr,"%s", s); } void ui_ToggleRV() { rv = !rv; #if !defined(MSDOS) || defined(SEVENBIT) shade = !rv; stars = !rv; #endif /* MSDOS && !SEVENBIT */ UpdateDisplay (0, 0, 1, 0); } void OReverse() { #ifdef MSDOS putchar (ESC); putchar ('['); param (7); putchar ('m'); #else standout (); /* attron (A_REVERSE); */ #endif /* MSDOS */ } void ONormal() { #ifdef MSDOS putchar (ESC); putchar ('['); param (0); putchar ('m'); #else standend (); /* attroff (A_REVERSE);*/ #endif /* MSDOS */ } void ui_ToggleStars() { stars = !stars; UpdateDisplay (0, 0, 1, 0); } void ui_ToggleShade() { shade = !shade; ClrScreen (); UpdateDisplay (0, 0, 1, 0); } void gotoXY (short int x, short int y) { #ifdef MSDOS putchar(ESC); putchar('['); param(y); putchar(';'); param(x); putchar('H'); #else move (y - 1, x - 1); #endif /* MSDOS */ } void ClrScreen (void) { ui_ClrScreen(); } void ClrEoln (void) { #ifdef MSDOS putchar(ESC); putchar('['); putchar('K'); #else clrtoeol (); #endif /* MSDOS */ refresh (); } #ifdef MSDOS void param(short n) { if (n >= 10) { register short d, q; q = n/10; d = n%10; putchar(q + '0'); putchar(d + '0'); } else putchar(n + '0'); } #endif /* MSDOS */ int ui_AskAbort() { char s[80]; ShowMessage ("Abort? "); wrefresh(stdscr); wscanw(stdscr,"%s", s); return (strcmp (s, "yes") == 0); } void ui_ClearEditHelp() { ClrScreen(); } void ui_RefreshEarly() { wrefresh(stdscr); } void ui_ShowHint(char *move) { gotoXY (TAB, 6); wprintw(stdscr,"Try: %s", move); ClrEoln (); } void ui_RejectMove(char *move) { ui_ShowMessage("Illegal move"); }