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