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();
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]);