Add safeguard against buffer overflow when calling scanf.
[gnushogi.git] / gnushogi / cursesdsp.c
1 /*
2  * FILE: cursesdsp.c
3  *
4  *     Curses interface for GNU Shogi
5  *
6  * ----------------------------------------------------------------------
7  * Copyright (c) 1993, 1994, 1995 Matthias Mutz
8  * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
9  *
10  * GNU SHOGI is based on GNU CHESS
11  *
12  * Copyright (c) 1988, 1989, 1990 John Stanback
13  * Copyright (c) 1992 Free Software Foundation
14  *
15  * This file is part of GNU SHOGI.
16  *
17  * GNU Shogi is free software; you can redistribute it and/or modify it
18  * under the terms of the GNU General Public License as published by the
19  * Free Software Foundation; either version 3 of the License,
20  * or (at your option) any later version.
21  *
22  * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
23  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
24  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25  * for more details.
26  *
27  * You should have received a copy of the GNU General Public License along
28  * with GNU Shogi; see the file COPYING. If not, see
29  * <http://www.gnu.org/licenses/>.
30  * ----------------------------------------------------------------------
31  */
32
33
34 #include <ctype.h>
35 #include <signal.h>
36 #include <stdio.h>
37
38 #include <sys/param.h>
39 #include <sys/types.h>
40 #include <sys/file.h>
41 #include <curses.h>
42
43 #include "gnushogi.h"
44 #include "cursesdsp.h"
45
46 #define FLUSH_SCANW fflush(stdout), scanw
47
48 int mycnt1, mycnt2;
49
50 #define TAB (58)
51
52 #define VIR_C(s)  ((flag.reverse) ? (NO_COLS - 1 - column(s)) : column(s))
53 #define VIR_R(s)  ((flag.reverse) ? (NO_ROWS - 1 - row(s)) : row(s))
54
55 unsigned short MV[MAXDEPTH];
56 int MSCORE;
57 char *DRAW;
58
59 /* Forward declarations. */
60 /* FIXME: change this name, puh-leeze! */
61
62 static void UpdateCatched(void);
63
64
65 /****************************************
66  * Trivial output functions.
67  ****************************************/
68
69 void
70 ClearEoln(void)
71 {
72     clrtoeol();
73     refresh();
74 }
75
76
77 void
78 Curses_ClearScreen(void)
79 {
80     clear();
81     refresh();
82 }
83
84
85 void
86 ClearMessage(void)
87 {
88     gotoXY(TAB, 6);
89     ClearEoln();
90 }
91
92
93
94 void
95 gotoXY(short x, short y)
96 {
97     move(y - 1, x - 1);
98 }
99
100
101 void
102 Curses_ShowCurrentMove(short pnt, short f, short t)
103 {
104     algbr(f, t, false);
105     gotoXY(TAB, 7);
106     printw("(%2d) %5s ", pnt, mvstr[0]);
107 }
108
109
110 void
111 Curses_ShowDepth(char ch)
112 {
113     gotoXY(TAB, 4);
114     printw(CP[53], Sdepth, ch);   /* Depth = %d%c */
115     ClearEoln();
116 }
117
118
119 void
120 Curses_ShowGameType(void)
121 {
122     if (flag.post)
123     {
124         gotoXY(TAB, 20);
125         printw("%c vs. %c", GameType[black], GameType[white]);
126     }
127 }
128
129
130 void
131 ShowHeader(void)
132 {
133     gotoXY(TAB, 2);
134     printw(CP[69], version, patchlevel);
135 }
136
137
138 void
139 Curses_ShowLine(unsigned short *bstline)
140 {
141 }
142
143
144 void
145 Curses_ShowMessage(char *s)
146 {
147     gotoXY(TAB, 6);
148     printw("%s", s);
149     ClearEoln();
150 }
151
152
153 void
154 Curses_Printf(const char *format, ...)
155 {
156     static char buffer[60];
157     va_list ap;
158     va_start(ap, format);
159     vsnprintf(buffer, sizeof(buffer), format, ap);
160     printw("%s", buffer);
161     va_end(ap);
162 }
163
164
165 void
166 Curses_doRequestInputString(const char* fmt, char* buffer)
167 {
168     FLUSH_SCANW(fmt, buffer);
169 }
170
171
172 void
173 ShowNodeCnt(long NodeCnt)
174 {
175     gotoXY(TAB, 22);
176     /* printw(CP[90], NodeCnt, (et > 100) ? NodeCnt / (et / 100) : 0); */
177     printw("n = %ld n/s = %ld", 
178            NodeCnt, (et > 100) ? NodeCnt / (et / 100) : 0);
179     ClearEoln();
180 }
181
182
183 void
184 Curses_ShowPatternCount(short side, short n)
185 {
186     if (flag.post)
187     {
188         gotoXY(TAB + 10 + 3 * side, 20);          /* CHECKME */
189
190         if (n >= 0)
191             printw("%3d", n);
192         else
193             printw("   ");
194     }
195 }
196
197
198 void
199 ShowPlayers(void)
200 {
201     gotoXY(5, ((flag.reverse) ? (5 + 2*NO_ROWS) : 2));
202     printw("%s", (computer == white) ? CP[218] : CP[74]);
203     gotoXY(5, ((flag.reverse) ? 2 : (5 + 2*NO_ROWS)));
204     printw("%s", (computer == black) ? CP[218] : CP[74]);
205 }
206
207
208 void
209 ShowPrompt(void)
210 {
211     gotoXY(TAB, 17);
212     printw(CP[121]);     /* Your move is? */
213     ClearEoln();
214 }
215
216
217 void
218 Curses_ShowResponseTime(void)
219 {
220     if (flag.post)
221     {
222         short TCC = TCcount;
223         gotoXY(TAB, 21);
224         /* printw("RT = %ld TCC = %d TCL = %ld EX = %ld ET = %ld TO = %d",
225            ResponseTime, TCC, TCleft, ExtraTime, et, flag.timeout); */
226         printw("%ld, %d, %ld, %ld, %ld, %d",
227                ResponseTime, TCC, TCleft, ExtraTime, et, flag.timeout);
228         ClearEoln();
229     }
230 }
231
232
233 void
234 Curses_ShowResults(short score, unsigned short *bstline, char ch)
235 {
236     unsigned char d, ply;
237
238     if (flag.post)
239     {
240         Curses_ShowDepth(ch);
241         ShowScore(score);
242         d = 7;
243
244         for (ply = 1; bstline[ply] > 0; ply++)
245         {
246             if (ply % 2 == 1)
247             {
248                 gotoXY(TAB, ++d);
249                 ClearEoln();
250             }
251
252             algbr((short) bstline[ply] >> 8, 
253                   (short) bstline[ply] & 0xFF, false);
254             printw("%5s ", mvstr[0]);
255         }
256
257         ClearEoln();
258
259         while (d < 13)
260         {
261             gotoXY(TAB, ++d);
262             ClearEoln();
263         }
264     }
265 }
266
267
268 void
269 ShowScore(short score)
270 {
271     gotoXY(TAB, 5);
272     printw(CP[104], score);
273     ClearEoln();
274 }
275
276
277 void
278 Curses_ShowSidetoMove(void)
279 {
280     gotoXY(TAB, 14);
281     printw("%2d:   %s", 1 + GameCnt / 2, ColorStr[player]);
282     ClearEoln();
283 }
284
285
286 void
287 Curses_ShowStage(void)
288 {
289     gotoXY(TAB, 19);
290     printw("Stage= %2d%c B= %2d W= %2d",
291            stage, flag.tsume?'T':' ', balance[black], balance[white]);
292     ClearEoln();
293 }
294
295
296 /****************************************
297  * End of trivial output routines.
298  ****************************************/
299
300
301 void
302 Curses_Initialize(void)
303 {
304     signal(SIGINT, Curses_Die);
305     signal(SIGQUIT, Curses_Die);
306     initscr();
307     crmode();
308 }
309
310
311 void
312 Curses_ExitShogi(void)
313
314     if (!nolist)
315         ListGame();
316
317     gotoXY(1, 24);
318
319     refresh();
320     nocrmode();
321     endwin();
322
323     exit(0);
324 }
325
326
327
328 void
329 Curses_Die(int sig)
330 {
331     char s[80];
332
333     signal(SIGINT, SIG_IGN);
334     signal(SIGQUIT, SIG_IGN);
335
336     Curses_ShowMessage(CP[31]);     /* Abort? */
337     FLUSH_SCANW("%s", s);
338
339     if (strcmp(s, CP[210]) == 0) /* yes */
340         Curses_ExitShogi();
341
342     signal(SIGINT, Curses_Die);
343     signal(SIGQUIT, Curses_Die);
344 }
345
346
347
348 void
349 Curses_TerminateSearch(int sig)
350 {
351     signal(SIGINT, SIG_IGN);
352     signal(SIGQUIT, SIG_IGN);
353
354     if (!flag.timeout)
355         flag.musttimeout = true;
356
357     Curses_ShowMessage("Terminate Search");
358     flag.bothsides = false;
359     signal(SIGINT, Curses_Die);
360     signal(SIGQUIT, Curses_Die);
361 }
362
363
364
365 void
366 Curses_help(void)
367 {
368     Curses_ClearScreen();
369     /* printw("GNU Shogi ??p? command summary\n"); */
370     printw(CP[40], version, patchlevel);
371     printw("-------------------------------"
372            "---------------------------------\n");
373     /* printw("7g7f      move from 7g to 7f      quit      
374      * Exit Shogi\n"); */
375     printw(CP[158]);
376     /* printw("S6h       move silver to 6h       beep      
377      * turn %s\n", (flag.beep) ? "off" : "on"); */
378     printw(CP[86], (flag.beep) ? CP[92] : CP[93]);
379     /* printw("2d2c+     move to 2c and promote\n"); */
380     printw(CP[128], (flag.material) ? CP[92] : CP[93]);
381     /* printw("P*5e      drop a pawn to 5e       easy      
382      * turn %s\n", (flag.easy) ? "off" : "on"); */
383     printw(CP[173], (flag.easy) ? CP[92] : CP[93]);
384     /* printw("                                  hash      
385      * turn %s\n", (flag.hash) ? "off" : "on"); */
386     printw(CP[174], (flag.hash) ? CP[92] : CP[93]);
387     /* printw("bd        redraw board            reverse   
388      * board display\n"); */
389     printw(CP[130]);
390     /* printw("list      game to shogi.lst       book      
391      * turn %s used %d of %d\n", (Book) ? "off" : "on", book
392       count, booksize); */
393     printw(CP[170], (Book) ? CP[92] : CP[93], bookcount, BOOKSIZE);
394     /* printw("undo      undo last ply           remove    
395      * take back a move\n"); */
396     printw(CP[200]);
397     /* printw("edit      edit board              force     
398      * enter game moves\n"); */
399     printw(CP[153]);
400     /* printw("switch    sides with computer     both      
401      * computer match\n"); */
402     printw(CP[194]);
403     /* printw("black     computer plays black    white     
404      * computer plays white\n"); */
405     printw(CP[202]);
406     /* printw("depth     set search depth        clock     
407      * set time control\n"); */
408     printw(CP[149]);
409     /* printw("hint      suggest a move         post      
410      * turn %s principle variation\n", (flag.post) ? "off" :
411      * "on"); */
412     printw(CP[177], (flag.post) ? CP[92] : CP[93]);
413     /* printw("save      game to file            get       
414      * game from file\n"); */
415     printw(CP[188]);
416     /* printw("random    randomize play          new       
417      * start new game\n"); */
418     printw(CP[181]);
419     gotoXY(10, 20);
420     printw(CP[47], ColorStr[computer]);
421     gotoXY(10, 21);
422     printw(CP[97], ColorStr[opponent]);
423     gotoXY(10, 22);
424     printw(CP[79], MaxResponseTime/100);
425     gotoXY(10, 23);
426     printw(CP[59], (flag.easy) ? CP[93] : CP[92]);
427     gotoXY(25, 23);
428     printw(CP[231], (flag.tsume) ? CP[93] : CP[92]);
429     gotoXY(40, 20);
430     printw(CP[52], MaxSearchDepth);
431     gotoXY(40, 21);
432     printw(CP[100], (dither) ? CP[93] : CP[92]);
433     gotoXY(40, 22);
434     printw(CP[112], (flag.hash) ? CP[93] : CP[92]);
435     gotoXY(40, 23);
436     printw(CP[73]);
437     gotoXY(10, 24);
438     printw(CP[110], (TCflag) ? CP[93] : CP[92],
439            TimeControl.moves[black], 
440            TimeControl.clock[black] / 100, 
441            OperatorTime, MaxSearchDepth);
442
443     refresh();
444
445 #ifdef BOGUS
446     fflush(stdin); /* what is this supposed to do?? */
447 #endif /* BOGUS */
448
449     getchar();
450     Curses_ClearScreen();
451     Curses_UpdateDisplay(0, 0, 1, 0);
452 }
453
454
455 static const short x0[2] = { 54, 2 };
456 static const short y0[2] = { 20, 4 };
457
458
459 /*
460  * Set up a board position. Pieces are entered by typing the piece followed
461  * by the location. For example, N3f will place a knight on square 3f.
462  * P* will put a pawn to the captured pieces.
463  */
464
465 void
466 Curses_EditBoard(void)
467 {
468     short a, c, sq, i;
469     short r = 0;
470     char s[80];
471
472     flag.regularstart = true;
473     Book = BOOKFAIL;
474     Curses_ClearScreen();
475     Curses_UpdateDisplay(0, 0, 1, 0);
476     gotoXY(TAB, 3);
477     printw(CP[29]);
478     gotoXY(TAB, 4);
479     printw(CP[28]);
480     gotoXY(TAB, 5);
481     printw(CP[136]);
482     gotoXY(TAB, 7);
483     printw(CP[64]);
484     a = black;
485
486     do
487     {
488         gotoXY(TAB, 6);
489         printw(CP[60], ColorStr[a]); /* Editing %s */
490         gotoXY(TAB + 24, 7);
491         ClearEoln();
492         FLUSH_SCANW("%s", s);
493
494         if (s[0] == CP[28][0])    /* # */
495         {
496             for (sq = 0; sq < NO_SQUARES; sq++)
497             {
498                 board[sq] = no_piece;
499                 color[sq] = neutral;
500                 DrawPiece(sq);
501             }
502
503             ClearCaptured();
504             UpdateCatched();
505         }
506
507         if (s[0] == CP[136][0])   /* c */
508             a = otherside[a];
509
510         if (s[1] == '*')
511         {
512             for (i = NO_PIECES; i > no_piece; i--)
513             {
514                 if ((s[0] == pxx[i]) || (s[0] == qxx[i]))
515                     break;
516             }
517
518             Captured[a][unpromoted[i]]++;
519             UpdateCatched();
520             c = -1;
521         }
522         else
523         {
524             c = COL_NAME(s[1]);
525             r = ROW_NAME(s[2]);
526         }
527
528         if ((c >= 0) && (c < NO_COLS) && (r >= 0) && (r < NO_ROWS))
529         {
530             sq = locn(r, c);
531
532             for (i = NO_PIECES; i > no_piece; i--)
533             {
534                 if ((s[0] == pxx[i]) || (s[0] == qxx[i]))
535                     break;
536             }
537
538             if (s[3] == '+')
539                 i = promoted[i];
540             else
541                 i = unpromoted[i];
542
543             board[sq] = i;
544             color[sq] = ((board[sq] == no_piece) ? neutral : a);
545             DrawPiece(sq);
546         }
547     }
548     while (s[0] != CP[29][0]);  /* . */
549
550     for (sq = 0; sq < NO_SQUARES; sq++)
551         Mvboard[sq] = ((board[sq] != Stboard[sq]) ? 10 : 0);
552
553     GameCnt = 0;
554     Game50 = 1;
555     ZeroRPT();
556     Sdepth = 0;
557     InitializeStats();
558     Curses_ClearScreen();
559     Curses_UpdateDisplay(0, 0, 1, 0);
560 }
561
562
563
564 static void 
565 UpdateCatched()
566 {
567     short side;
568
569     for (side = black; side <= white; side++)
570     { 
571         short x, y, piece, cside, k;
572
573         cside = flag.reverse ? (side ^ 1) : side;
574         x = x0[cside];
575         y = y0[cside];
576         k = 0;
577
578         for (piece = pawn; piece <= king; piece++)
579         {
580             short n;
581
582             if ((n = Captured[side][piece]))
583             {
584                 gotoXY(x, y); 
585                 printw("%i%c", n, pxx[piece]);
586
587                 if (cside == black) 
588                     y--; 
589                 else 
590                     y++;
591             }
592             else
593             {
594                 k++;
595             }
596         }
597
598         while (k)
599         {
600             k--;
601             gotoXY(x, y);
602             printw("  ");
603
604             if (cside == black) 
605                 y--; 
606             else 
607                 y++;
608         }
609     }
610
611     refresh();
612 }
613
614
615
616 void
617 Curses_SearchStartStuff(short side)
618 {
619     short i;
620
621     signal(SIGINT, Curses_TerminateSearch);
622     signal(SIGQUIT, Curses_TerminateSearch);
623
624     for (i = 4; i < 14; i++)                      /* CHECKME */
625     {
626         gotoXY(TAB, i);
627         ClearEoln();
628     }
629 }
630
631
632
633 void
634 Curses_OutputMove(void)
635 {
636
637     Curses_UpdateDisplay(root->f, root->t, 0, (short) root->flags);
638     gotoXY(TAB, 16);
639
640     if (flag.illegal) 
641     {
642         printw(CP[225]);
643         return;
644     }
645
646     printw(CP[84], mvstr[0]);    /* My move is %s */
647
648     if (flag.beep)
649         putchar(7);
650
651     ClearEoln();
652
653     gotoXY(TAB, 18);
654
655     if (root->flags & draw)
656         printw(CP[58]);
657     else if (root->score == -(SCORE_LIMIT + 999))
658         printw(CP[95]);
659     else if (root->score == SCORE_LIMIT + 998)
660         printw(CP[44]);
661 #ifdef VERYBUGGY
662     else if (root->score < -SCORE_LIMIT)
663         printw(CP[96], SCORE_LIMIT + 999 + root->score - 1);
664     else if (root->score > SCORE_LIMIT)
665         printw(CP[45], SCORE_LIMIT + 998 - root->score - 1);
666 #endif /* VERYBUGGY */
667
668     ClearEoln();
669
670     if (flag.post)
671     {
672         short h, l, t;
673
674         h = TREE;
675         l = 0;
676         t = TREE >> 1;
677
678         while (l != t)
679         {
680             if (Tree[t].f || Tree[t].t)
681                 l = t;
682             else
683                 h = t;
684
685             t = (l + h) >> 1;
686         }
687
688         ShowNodeCnt(NodeCnt);
689         gotoXY(TAB, 23);
690         printw(CP[81], t); /* Max Tree= */
691         ClearEoln();
692     }
693
694     Curses_ShowSidetoMove();
695 }
696
697
698
699 void
700 UpdateClocks(void)
701 {
702     short m, s;
703     long dt;
704
705     if (TCflag)
706     {
707         m = (short) ((dt = (TimeControl.clock[player] - et)) / 6000);
708         s = (short) ((dt - 6000 * (long) m) / 100);
709     }
710     else
711     {
712         m = (short) ((dt = et) / 6000);
713         s = (short) (et - 6000 * (long) m) / 100;
714     }
715
716     if (m < 0)
717         m = 0;
718
719     if (s < 0)
720         s = 0;
721
722     if (player == black)
723         gotoXY(20, (flag.reverse) ? 2 : 23);
724     else
725         gotoXY(20, (flag.reverse) ? 23 : 2);
726
727     /* printw("%d:%02d %ld  ", m, s, dt); */
728     printw("%d:%02d  ", m, s); 
729
730     if (flag.post)
731         ShowNodeCnt(NodeCnt);
732
733     refresh();
734 }
735
736
737
738 void
739 DrawPiece(short sq)
740 {
741     char y;
742     char piece, l, r, p; 
743
744     if (color[sq] == neutral)
745     {
746         l = r = ' ';
747     }
748     else if (flag.reverse ^ (color[sq] == black))
749     {
750         l = '/';
751         r = '\\';
752     } 
753     else
754     {
755         l = '\\', r = '/';
756     }
757
758     piece = board[sq];
759
760     if (is_promoted[(int)piece])
761     {
762         p = '+';
763         y = pxx[unpromoted[(int)piece]];
764     } 
765     else
766     {
767         p = ' ';
768         y = pxx[(int)piece];
769     }
770
771     gotoXY(8 + 5 * VIR_C(sq), 4 + 2 * ((NO_ROWS - 1) - VIR_R(sq)));
772     printw("%c%c%c%c", l, p, y, r);
773 }
774
775
776
777
778 /*
779  * Curses_ShowPostnValue(): must have called ExaminePosition() first
780  */
781
782 void
783 Curses_ShowPostnValue(short sq)
784 {
785     short score;
786
787     gotoXY(4 + 5 * VIR_C(sq), 5 + 2 * (7 - VIR_R(sq))); /* CHECKME */
788     score = ScorePosition(color[sq]);
789
790     if (color[sq] != neutral)
791 #if defined SAVE_SVALUE
792     {
793         printw("??? ");
794     }
795 #else
796     {
797         printw("%3d ", svalue[sq]);
798     }
799 #endif
800     else
801     {
802         printw("   ");
803     }
804 }
805
806
807
808 void
809 Curses_ShowPostnValues(void)
810 {
811     short sq, score;
812
813     ExaminePosition(opponent);
814
815     for (sq = 0; sq < NO_SQUARES; sq++)
816         Curses_ShowPostnValue(sq);
817
818     score = ScorePosition(opponent);
819     gotoXY(TAB, 5);
820     printw(CP[103], score, 
821            mtl[computer], pscore[computer], GameType[computer],
822            mtl[opponent], pscore[opponent], GameType[opponent]);
823
824     ClearEoln();
825 }
826
827
828
829 void
830 Curses_UpdateDisplay(short f, short t, short redraw, short isspec)
831 {
832     short i, sq, z;
833     int j;
834
835     if (redraw)
836     {
837         ShowHeader();
838         ShowPlayers();
839
840         i = 2;
841         gotoXY(3, ++i);
842
843         printw("    +");
844         for (j=0; j<NO_COLS; j++)
845             printw("----+");
846
847         while (i <= 1 + 2*NO_ROWS)
848         {
849             gotoXY(1, ++i);
850
851             if (flag.reverse)
852                 z = (i / 2) - 1;
853             else
854                 z = NO_ROWS + 2 - ((i + 1) / 2);
855
856             printw("    %c |", ROW_NAME(z+1));
857             for (j=0; j<NO_COLS; j++)
858                 printw("    |");
859
860             gotoXY(3, ++i);
861
862             if (i < 2 + 2*NO_ROWS)
863             {
864                 printw("    +");
865                 for (j=0; j<NO_COLS; j++)
866                     printw("----+");
867             }
868         }
869
870         printw("    +");
871         for (j=0; j<NO_COLS; j++)
872             printw("----+");
873
874         gotoXY(3, 4 + 2*NO_ROWS);
875         printw("    ");
876
877         if (flag.reverse)
878             printw(CP[16]);
879         else
880             printw(CP[15]);
881
882         for (sq = 0; sq < NO_SQUARES; sq++)
883             DrawPiece(sq);
884     }
885     else /* not redraw */
886     {
887         if (f < NO_SQUARES)
888             DrawPiece(f);
889
890         DrawPiece(t & 0x7f);
891     }
892
893     if ((isspec & capture) || (isspec & dropmask) || redraw)
894     {
895         short side;
896
897         for (side = black; side <= white; side++)
898         {
899             short x, y, piece, cside, k;
900             cside = flag.reverse ? (side ^ 1) : side;
901             x = x0[cside];
902             y = y0[cside];
903             k = 0;
904
905             for (piece = pawn; piece <= king; piece++)
906             {
907                 short n;
908
909                 if ((n = Captured[side][piece]))
910                 {
911                     gotoXY(x, y); 
912                     printw("%i%c", n, pxx[piece]);
913
914                     if (cside == black) y--; else y++;
915                 }
916                 else
917                 {
918                     k++;
919                 }
920             }
921
922             while (k)
923             {
924                 k--;
925                 gotoXY(x, y);
926                 printw("  ");
927
928                 if (cside == black) 
929                     y--;
930                 else 
931                     y++;
932             }
933         }
934     }
935
936     refresh();
937 }
938
939
940 extern char *InPtr;
941
942
943 void
944 Curses_ChangeAlphaWindow(void)
945 {
946     Curses_ShowMessage(CP[114]);
947     FLUSH_SCANW("%hd", &WAwindow);
948     Curses_ShowMessage(CP[34]);
949     FLUSH_SCANW("%hd", &BAwindow);
950 }
951
952
953
954 void
955 Curses_ChangeBetaWindow(void)
956 {
957     Curses_ShowMessage(CP[115]);
958     FLUSH_SCANW("%hd", &WBwindow);
959     Curses_ShowMessage(CP[35]);
960     FLUSH_SCANW("%hd", &BBwindow);
961 }
962
963
964
965 void
966 Curses_GiveHint(void)
967 {
968     char s[40];
969
970     if (hint)
971     {
972         algbr((short) (hint >> 8), (short) (hint & 0xFF), false);
973         strcpy(s, CP[198]);  /* try */
974         strcat(s, mvstr[0]);
975         Curses_ShowMessage(s);
976     }
977     else
978     {
979         Curses_ShowMessage(CP[223]);
980     }
981 }
982
983
984
985 void
986 Curses_ChangeSearchDepth(void)
987 {
988     Curses_ShowMessage(CP[150]);
989     FLUSH_SCANW("%hd", &MaxSearchDepth);
990     TCflag = !(MaxSearchDepth > 0);
991 }
992
993
994 void
995 Curses_ChangeHashDepth(void)
996 {
997     Curses_ShowMessage(CP[163]);
998     FLUSH_SCANW("%hd", &HashDepth);
999     Curses_ShowMessage(CP[82]);
1000     FLUSH_SCANW("%hd", &HashMoveLimit);
1001 }
1002
1003
1004 void
1005 Curses_SetContempt(void)
1006 {
1007     Curses_ShowMessage(CP[142]);
1008     FLUSH_SCANW("%hd", &contempt);
1009 }
1010
1011
1012
1013 void
1014 Curses_ChangeXwindow(void)
1015 {
1016     Curses_ShowMessage(CP[208]);
1017     FLUSH_SCANW("%hd", &xwndw);
1018 }
1019
1020
1021
1022 void
1023 Curses_SelectLevel(char *sx)
1024 {
1025     int item;
1026
1027     Curses_ClearScreen();
1028     gotoXY(32, 2);
1029     printw(CP[41], version, patchlevel);
1030     gotoXY(20, 4);
1031     printw(CP[18]);
1032     gotoXY(20, 5);
1033     printw(CP[19]);
1034     gotoXY(20, 6);
1035     printw(CP[20]);
1036     gotoXY(20, 7);
1037     printw(CP[21]);
1038     gotoXY(20, 8);
1039     printw(CP[22]);
1040     gotoXY(20, 9);
1041     printw(CP[23]);
1042     gotoXY(20, 10);
1043     printw(CP[24]);
1044     gotoXY(20, 11);
1045     printw(CP[25]);
1046     gotoXY(20, 12);
1047     printw(CP[26]);
1048     gotoXY(20, 13);
1049     printw(CP[27]);
1050
1051     OperatorTime = 0;
1052     TCmoves = 40;
1053     TCminutes = 5;
1054     TCseconds = 0;
1055
1056     gotoXY(20, 17);
1057     printw(CP[62]);
1058     refresh();
1059     FLUSH_SCANW("%d", &item);
1060
1061     switch(item)
1062     {
1063     case 1:
1064         TCmoves = 40;
1065         TCminutes = 5;
1066         break;
1067
1068     case 2:
1069         TCmoves = 40;
1070         TCminutes = 15;
1071         break;
1072
1073     case 3:
1074         TCmoves = 40;
1075         TCminutes = 30;
1076         break;
1077
1078     case 4:
1079         TCmoves = 80;
1080         TCminutes = 15;
1081         flag.gamein = true;
1082         break;
1083
1084     case 5:
1085         TCmoves = 80;
1086         TCminutes = 30;
1087         flag.gamein = true;
1088         break;
1089
1090     case 6:
1091         TCmoves = 80;
1092         TCminutes = 15;
1093         TCadd = 3000;
1094         flag.gamein = true;
1095         break;
1096
1097     case 7:
1098         TCmoves = 80;
1099         TCminutes = 30;
1100         TCadd = 3000;
1101         break;
1102
1103     case 8:
1104         TCmoves = 1;
1105         TCminutes = 1;
1106         flag.onemove = true;
1107         break;
1108
1109     case 9:
1110         TCmoves = 1;
1111         TCminutes = 15;
1112         flag.onemove = true;
1113         break;
1114
1115     case 10:
1116         TCmoves = 1;
1117         TCminutes = 30;
1118         flag.onemove = true;
1119         break;
1120     }
1121
1122     TCflag = (TCmoves > 0);
1123
1124     TimeControl.clock[black] = TimeControl.clock[white] = 0; 
1125
1126     SetTimeControl();
1127     Curses_ClearScreen();
1128     Curses_UpdateDisplay(0, 0, 1, 0);
1129 }
1130
1131
1132
1133 void
1134 Curses_DoDebug(void)
1135 {
1136     short c, p, sq, tp, tc, tsq, score;
1137     char s[40];
1138
1139     ExaminePosition(opponent);
1140     Curses_ShowMessage(CP[65]);
1141     FLUSH_SCANW("%s", s);
1142     c = neutral;
1143
1144     if ((s[0] == CP[9][0]) || (s[0] == CP[9][1])) /* b B */
1145         c = black;
1146
1147     if ((s[0] == CP[9][2]) || (s[0] == CP[9][3])) /* w W */
1148         c = white;
1149
1150     for (p = king; p > no_piece; p--)
1151     {
1152         if ((s[1] == pxx[p]) || (s[1] == qxx[p]))
1153             break;
1154     }
1155
1156     for (sq = 0; sq < NO_SQUARES; sq++)
1157     {
1158         tp = board[sq];
1159         tc = color[sq];
1160         board[sq] = p;
1161         color[sq] = c;
1162         tsq = PieceList[c][1];
1163         PieceList[c][1] = sq;
1164         Curses_ShowPostnValue(sq);
1165         PieceList[c][1] = tsq;
1166         board[sq] = tp;
1167         color[sq] = tc;
1168     }
1169
1170     score = ScorePosition(opponent);
1171     gotoXY(TAB, 5);
1172     printw(CP[103], score, 
1173            mtl[computer], pscore[computer], GameType[computer],
1174            mtl[opponent], pscore[opponent], GameType[opponent]);
1175
1176     ClearEoln();
1177 }
1178
1179
1180
1181 void
1182 Curses_DoTable(short table[NO_SQUARES])
1183 {
1184     short  sq;
1185     ExaminePosition(opponent);
1186
1187     for (sq = 0; sq < NO_SQUARES; sq++)
1188     {
1189         gotoXY(4 + 5 * VIR_C(sq), 5 + 2 * (7 - VIR_R(sq)));
1190         printw("%3d ", table[sq]);
1191     }
1192
1193
1194
1195