4 * Curses interface for GNU Shogi
6 * ----------------------------------------------------------------------
7 * Copyright (c) 1993, 1994, 1995 Matthias Mutz
8 * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
10 * GNU SHOGI is based on GNU CHESS
12 * Copyright (c) 1988, 1989, 1990 John Stanback
13 * Copyright (c) 1992 Free Software Foundation
15 * This file is part of GNU SHOGI.
17 * GNU Shogi is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 1, or (at your option)
22 * GNU Shogi is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with GNU Shogi; see the file COPYING. If not, write to
29 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
36 #include <sys/param.h>
37 #include <sys/types.h>
42 #include "cursesdsp.h"
44 #define FLUSH_SCANW fflush(stdout), scanw
50 #define VIR_C(s) ((flag.reverse) ? (8 - column(s)) : column(s))
51 #define VIR_R(s) ((flag.reverse) ? (8 - row(s)) : row(s))
53 unsigned short MV[MAXDEPTH];
57 /* Forward declarations. */
58 /* FIXME: change this name, puh-leeze! */
60 static void UpdateCatched(void);
63 /****************************************
64 * Trivial output functions.
65 ****************************************/
76 Curses_ClearScreen(void)
93 gotoXY(short x, short y)
100 Curses_ShowCurrentMove(short pnt, short f, short t)
104 printw("(%2d) %5s ", pnt, mvstr[0]);
109 Curses_ShowDepth(char ch)
112 printw(CP[53], Sdepth, ch); /* Depth = %d%c */
118 Curses_ShowGameType(void)
123 printw("%c vs. %c", GameType[black], GameType[white]);
132 printw(CP[69], version, patchlevel);
137 Curses_ShowLine(unsigned short *bstline)
143 Curses_ShowMessage(char *s)
152 ShowNodeCnt(long NodeCnt)
155 /* printw(CP[90], NodeCnt, (et > 100) ? NodeCnt / (et / 100) : 0); */
156 printw("n = %ld n/s = %ld",
157 NodeCnt, (et > 100) ? NodeCnt / (et / 100) : 0);
163 Curses_ShowPatternCount(short side, short n)
167 gotoXY(TAB + 10 + 3 * side, 20);
180 gotoXY(5, ((flag.reverse) ? 23 : 2));
181 printw("%s", (computer == white) ? CP[218] : CP[74]);
182 gotoXY(5, ((flag.reverse) ? 2 : 23));
183 printw("%s", (computer == black) ? CP[218] : CP[74]);
191 printw(CP[121]); /* Your move is? */
197 Curses_ShowResponseTime(void)
203 /* printw("RT = %ld TCC = %d TCL = %ld EX = %ld ET = %ld TO = %d",
204 ResponseTime, TCC, TCleft, ExtraTime, et, flag.timeout); */
205 printw("%ld, %d, %ld, %ld, %ld, %d",
206 ResponseTime, TCC, TCleft, ExtraTime, et, flag.timeout);
213 Curses_ShowResults(short score, unsigned short *bstline, char ch)
215 unsigned char d, ply;
219 Curses_ShowDepth(ch);
223 for (ply = 1; bstline[ply] > 0; ply++)
231 algbr((short) bstline[ply] >> 8,
232 (short) bstline[ply] & 0xFF, false);
233 printw("%5s ", mvstr[0]);
248 ShowScore(short score)
251 printw(CP[104], score);
257 Curses_ShowSidetoMove(void)
260 printw("%2d: %s", 1 + GameCnt / 2, ColorStr[player]);
266 Curses_ShowStage(void)
269 printw("Stage= %2d%c B= %2d W= %2d",
270 stage, flag.tsume?'T':' ', balance[black], balance[white]);
275 /****************************************
276 * End of trivial output routines.
277 ****************************************/
281 Curses_Initialize(void)
283 signal(SIGINT, Curses_Die);
284 signal(SIGQUIT, Curses_Die);
291 Curses_ExitShogi(void)
312 signal(SIGINT, SIG_IGN);
313 signal(SIGQUIT, SIG_IGN);
315 Curses_ShowMessage(CP[31]); /* Abort? */
316 FLUSH_SCANW("%s", s);
318 if (strcmp(s, CP[210]) == 0) /* yes */
321 signal(SIGINT, Curses_Die);
322 signal(SIGQUIT, Curses_Die);
328 Curses_TerminateSearch(int sig)
330 signal(SIGINT, SIG_IGN);
331 signal(SIGQUIT, SIG_IGN);
334 flag.musttimeout = true;
336 Curses_ShowMessage("Terminate Search");
337 flag.bothsides = false;
338 signal(SIGINT, Curses_Die);
339 signal(SIGQUIT, Curses_Die);
347 Curses_ClearScreen();
348 /* printw("GNU Shogi ??p? command summary\n"); */
349 printw(CP[40], version, patchlevel);
350 printw("-------------------------------"
351 "---------------------------------\n");
352 /* printw("7g7f move from 7g to 7f quit
355 /* printw("S6h move silver to 6h beep
356 * turn %s\n", (flag.beep) ? "off" : "on"); */
357 printw(CP[86], (flag.beep) ? CP[92] : CP[93]);
358 /* printw("2d2c+ move to 2c and promote\n"); */
359 printw(CP[128], (flag.material) ? CP[92] : CP[93]);
360 /* printw("P*5e drop a pawn to 5e easy
361 * turn %s\n", (flag.easy) ? "off" : "on"); */
362 printw(CP[173], (flag.easy) ? CP[92] : CP[93]);
364 * turn %s\n", (flag.hash) ? "off" : "on"); */
365 printw(CP[174], (flag.hash) ? CP[92] : CP[93]);
366 /* printw("bd redraw board reverse
367 * board display\n"); */
369 /* printw("list game to shogi.lst book
370 * turn %s used %d of %d\n", (Book) ? "off" : "on", book
372 printw(CP[170], (Book) ? CP[92] : CP[93], bookcount, BOOKSIZE);
373 /* printw("undo undo last ply remove
374 * take back a move\n"); */
376 /* printw("edit edit board force
377 * enter game moves\n"); */
379 /* printw("switch sides with computer both
380 * computer match\n"); */
382 /* printw("black computer plays black white
383 * computer plays white\n"); */
385 /* printw("depth set search depth clock
386 * set time control\n"); */
388 /* printw("hint suggest a move post
389 * turn %s principle variation\n", (flag.post) ? "off" :
391 printw(CP[177], (flag.post) ? CP[92] : CP[93]);
392 /* printw("save game to file get
393 * game from file\n"); */
395 /* printw("random randomize play new
396 * start new game\n"); */
399 printw(CP[47], ColorStr[computer]);
401 printw(CP[97], ColorStr[opponent]);
403 printw(CP[79], MaxResponseTime/100);
405 printw(CP[59], (flag.easy) ? CP[93] : CP[92]);
407 printw(CP[231], (flag.tsume) ? CP[93] : CP[92]);
409 printw(CP[52], MaxSearchDepth);
411 printw(CP[100], (dither) ? CP[93] : CP[92]);
413 printw(CP[112], (flag.hash) ? CP[93] : CP[92]);
417 printw(CP[110], (TCflag) ? CP[93] : CP[92],
418 TimeControl.moves[black],
419 TimeControl.clock[black] / 100,
420 OperatorTime, MaxSearchDepth);
425 fflush(stdin); /* what is this supposed to do?? */
429 Curses_ClearScreen();
430 Curses_UpdateDisplay(0, 0, 1, 0);
434 static const short x0[2] = { 54, 2 };
435 static const short y0[2] = { 20, 4 };
439 * Set up a board position. Pieces are entered by typing the piece followed
440 * by the location. For example, N3f will place a knight on square 3f.
441 * P* will put a pawn to the captured pieces.
445 Curses_EditBoard(void)
451 flag.regularstart = true;
453 Curses_ClearScreen();
454 Curses_UpdateDisplay(0, 0, 1, 0);
468 printw(CP[60], ColorStr[a]); /* Editing %s */
471 FLUSH_SCANW("%s", s);
473 if (s[0] == CP[28][0]) /* # */
475 for (sq = 0; sq < NO_SQUARES; sq++)
477 board[sq] = no_piece;
486 if (s[0] == CP[136][0]) /* c */
491 for (i = NO_PIECES; i > no_piece; i--)
493 if ((s[0] == pxx[i]) || (s[0] == qxx[i]))
497 Captured[a][unpromoted[i]]++;
507 if ((c >= 0) && (c < NO_COLS) && (r >= 0) && (r < NO_ROWS))
511 for (i = NO_PIECES; i > no_piece; i--)
513 if ((s[0] == pxx[i]) || (s[0] == qxx[i]))
523 color[sq] = ((board[sq] == no_piece) ? neutral : a);
527 while (s[0] != CP[29][0]); /* . */
529 for (sq = 0; sq < NO_SQUARES; sq++)
530 Mvboard[sq] = ((board[sq] != Stboard[sq]) ? 10 : 0);
537 Curses_ClearScreen();
538 Curses_UpdateDisplay(0, 0, 1, 0);
548 for (side = black; side <= white; side++)
550 short x, y, piece, cside, k;
552 cside = flag.reverse ? (side ^ 1) : side;
557 for (piece = pawn; piece <= king; piece++)
561 if ((n = Captured[side][piece]))
564 printw("%i%c", n, pxx[piece]);
596 Curses_SearchStartStuff(short side)
600 signal(SIGINT, Curses_TerminateSearch);
601 signal(SIGQUIT, Curses_TerminateSearch);
603 for (i = 4; i < 14; i++)
613 Curses_OutputMove(void)
616 Curses_UpdateDisplay(root->f, root->t, 0, (short) root->flags);
625 printw(CP[84], mvstr[0]); /* My move is %s */
634 if (root->flags & draw)
636 else if (root->score == -(SCORE_LIMIT + 999))
638 else if (root->score == SCORE_LIMIT + 998)
641 else if (root->score < -SCORE_LIMIT)
642 printw(CP[96], SCORE_LIMIT + 999 + root->score - 1);
643 else if (root->score > SCORE_LIMIT)
644 printw(CP[45], SCORE_LIMIT + 998 - root->score - 1);
645 #endif /* VERYBUGGY */
659 if (Tree[t].f || Tree[t].t)
667 ShowNodeCnt(NodeCnt);
669 printw(CP[81], t); /* Max Tree= */
673 Curses_ShowSidetoMove();
686 m = (short) ((dt = (TimeControl.clock[player] - et)) / 6000);
687 s = (short) ((dt - 6000 * (long) m) / 100);
691 m = (short) ((dt = et) / 6000);
692 s = (short) (et - 6000 * (long) m) / 100;
702 gotoXY(20, (flag.reverse) ? 2 : 23);
704 gotoXY(20, (flag.reverse) ? 23 : 2);
706 /* printw("%d:%02d %ld ", m, s, dt); */
707 printw("%d:%02d ", m, s);
710 ShowNodeCnt(NodeCnt);
723 if (color[sq] == neutral)
727 else if (flag.reverse ^ (color[sq] == black))
739 if (is_promoted[(int)piece])
742 y = pxx[unpromoted[(int)piece]];
750 gotoXY(8 + 5 * VIR_C(sq), 4 + 2 * (8 - VIR_R(sq)));
751 printw("%c%c%c%c", l, p, y, r);
758 * Curses_ShowPostnValue(): must have called ExaminePosition() first
762 Curses_ShowPostnValue(short sq)
766 gotoXY(4 + 5 * VIR_C(sq), 5 + 2 * (7 - VIR_R(sq)));
767 score = ScorePosition(color[sq]);
769 if (color[sq] != neutral)
770 #if defined SAVE_SVALUE
776 printw("%3d ", svalue[sq]);
788 Curses_ShowPostnValues(void)
792 ExaminePosition(opponent);
794 for (sq = 0; sq < NO_SQUARES; sq++)
795 Curses_ShowPostnValue(sq);
797 score = ScorePosition(opponent);
799 printw(CP[103], score,
800 mtl[computer], pscore[computer], GameType[computer],
801 mtl[opponent], pscore[opponent], GameType[opponent]);
809 Curses_UpdateDisplay(short f, short t, short redraw, short isspec)
821 printw(" +----+----+----+----+----+----+----+----+----+");
830 z = 11 - ((i + 1) / 2);
832 printw(" %c | | | | | |"
833 " | | | |", 'a' + 9 - z);
839 printw(" +----+----+----+----+----+----+----+----+----+");
843 printw(" +----+----+----+----+----+----+----+----+----+");
853 for (sq = 0; sq < NO_SQUARES; sq++)
856 else /* not redraw */
864 if ((isspec & capture) || (isspec & dropmask) || redraw)
868 for (side = black; side <= white; side++)
870 short x, y, piece, cside, k;
871 cside = flag.reverse ? (side ^ 1) : side;
876 for (piece = pawn; piece <= king; piece++)
880 if ((n = Captured[side][piece]))
883 printw("%i%c", n, pxx[piece]);
885 if (cside == black) y--; else y++;
915 Curses_ChangeAlphaWindow(void)
917 Curses_ShowMessage(CP[114]);
918 FLUSH_SCANW("%hd", &WAwindow);
919 Curses_ShowMessage(CP[34]);
920 FLUSH_SCANW("%hd", &BAwindow);
926 Curses_ChangeBetaWindow(void)
928 Curses_ShowMessage(CP[115]);
929 FLUSH_SCANW("%hd", &WBwindow);
930 Curses_ShowMessage(CP[35]);
931 FLUSH_SCANW("%hd", &BBwindow);
937 Curses_GiveHint(void)
943 algbr((short) (hint >> 8), (short) (hint & 0xFF), false);
944 strcpy(s, CP[198]); /* try */
946 Curses_ShowMessage(s);
950 Curses_ShowMessage(CP[223]);
957 Curses_ChangeSearchDepth(void)
959 Curses_ShowMessage(CP[150]);
960 FLUSH_SCANW("%hd", &MaxSearchDepth);
961 TCflag = !(MaxSearchDepth > 0);
966 Curses_ChangeHashDepth(void)
968 Curses_ShowMessage(CP[163]);
969 FLUSH_SCANW("%hd", &HashDepth);
970 Curses_ShowMessage(CP[82]);
971 FLUSH_SCANW("%hd", &HashMoveLimit);
976 Curses_SetContempt(void)
978 Curses_ShowMessage(CP[142]);
979 FLUSH_SCANW("%hd", &contempt);
985 Curses_ChangeXwindow(void)
987 Curses_ShowMessage(CP[208]);
988 FLUSH_SCANW("%hd", &xwndw);
994 Curses_SelectLevel(char *sx)
998 Curses_ClearScreen();
1000 printw(CP[41], version, patchlevel);
1030 FLUSH_SCANW("%d", &item);
1077 flag.onemove = true;
1083 flag.onemove = true;
1089 flag.onemove = true;
1093 TCflag = (TCmoves > 0);
1095 TimeControl.clock[black] = TimeControl.clock[white] = 0;
1098 Curses_ClearScreen();
1099 Curses_UpdateDisplay(0, 0, 1, 0);
1105 Curses_DoDebug(void)
1107 short c, p, sq, tp, tc, tsq, score;
1110 ExaminePosition(opponent);
1111 Curses_ShowMessage(CP[65]);
1112 FLUSH_SCANW("%s", s);
1115 if ((s[0] == CP[9][0]) || (s[0] == CP[9][1])) /* b B */
1118 if ((s[0] == CP[9][2]) || (s[0] == CP[9][3])) /* w W */
1121 for (p = king; p > no_piece; p--)
1123 if ((s[1] == pxx[p]) || (s[1] == qxx[p]))
1127 for (sq = 0; sq < NO_SQUARES; sq++)
1133 tsq = PieceList[c][1];
1134 PieceList[c][1] = sq;
1135 Curses_ShowPostnValue(sq);
1136 PieceList[c][1] = tsq;
1141 score = ScorePosition(opponent);
1143 printw(CP[103], score,
1144 mtl[computer], pscore[computer], GameType[computer],
1145 mtl[opponent], pscore[opponent], GameType[opponent]);
1153 Curses_DoTable(short table[NO_SQUARES])
1156 ExaminePosition(opponent);
1158 for (sq = 0; sq < NO_SQUARES; sq++)
1160 gotoXY(4 + 5 * VIR_C(sq), 5 + 2 * (7 - VIR_R(sq)));
1161 printw("%3d ", table[sq]);