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