Changing license to GPL3 (and bumping version to 1.4.0).
[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) ? (8 - column(s)) : column(s))
49 #define VIR_R(s)  ((flag.reverse) ? (8 - 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);
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) ? 23 : 2));
179     printw("%s", (computer == white) ? CP[218] : CP[74]);
180     gotoXY(5, ((flag.reverse) ? 2 : 23));
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 = '9' - s[1];
502             r = 'i' - 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++)
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 * (8 - 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)));
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
811     if (redraw)
812     {
813         ShowHeader();
814         ShowPlayers();
815
816         i = 2;
817         gotoXY(3, ++i);
818
819         printw("    +----+----+----+----+----+----+----+----+----+");
820
821         while (i < 20)
822         {
823             gotoXY(1, ++i);
824
825             if (flag.reverse)
826                 z = (i / 2) - 1;
827             else
828                 z = 11 - ((i + 1) / 2);
829
830             printw("    %c |    |    |    |    |    |"
831                    "    |    |    |    |", 'a' + 9 - z);
832
833             gotoXY(3, ++i);
834
835             if (i < 20)
836             {
837                 printw("    +----+----+----+----+----+----+----+----+----+");
838             }
839         }
840
841         printw("    +----+----+----+----+----+----+----+----+----+");
842
843         gotoXY(3, 22);
844         printw("    ");
845
846         if (flag.reverse)
847             printw(CP[16]);
848         else
849             printw(CP[15]);
850
851         for (sq = 0; sq < NO_SQUARES; sq++)
852             DrawPiece(sq);
853     }
854     else /* not redraw */
855     {
856         if (f < NO_SQUARES)
857             DrawPiece(f);
858
859         DrawPiece(t & 0x7f);
860     }
861
862     if ((isspec & capture) || (isspec & dropmask) || redraw)
863     {
864         short side;
865
866         for (side = black; side <= white; side++)
867         {
868             short x, y, piece, cside, k;
869             cside = flag.reverse ? (side ^ 1) : side;
870             x = x0[cside];
871             y = y0[cside];
872             k = 0;
873
874             for (piece = pawn; piece <= king; piece++)
875             {
876                 short n;
877
878                 if ((n = Captured[side][piece]))
879                 {
880                     gotoXY(x, y); 
881                     printw("%i%c", n, pxx[piece]);
882
883                     if (cside == black) y--; else y++;
884                 }
885                 else
886                 {
887                     k++;
888                 }
889             }
890
891             while (k)
892             {
893                 k--;
894                 gotoXY(x, y);
895                 printw("  ");
896
897                 if (cside == black) 
898                     y--;
899                 else 
900                     y++;
901             }
902         }
903     }
904
905     refresh();
906 }
907
908
909 extern char *InPtr;
910
911
912 void
913 Curses_ChangeAlphaWindow(void)
914 {
915     Curses_ShowMessage(CP[114]);
916     FLUSH_SCANW("%hd", &WAwindow);
917     Curses_ShowMessage(CP[34]);
918     FLUSH_SCANW("%hd", &BAwindow);
919 }
920
921
922
923 void
924 Curses_ChangeBetaWindow(void)
925 {
926     Curses_ShowMessage(CP[115]);
927     FLUSH_SCANW("%hd", &WBwindow);
928     Curses_ShowMessage(CP[35]);
929     FLUSH_SCANW("%hd", &BBwindow);
930 }
931
932
933
934 void
935 Curses_GiveHint(void)
936 {
937     char s[40];
938
939     if (hint)
940     {
941         algbr((short) (hint >> 8), (short) (hint & 0xFF), false);
942         strcpy(s, CP[198]);  /* try */
943         strcat(s, mvstr[0]);
944         Curses_ShowMessage(s);
945     }
946     else
947     {
948         Curses_ShowMessage(CP[223]);
949     }
950 }
951
952
953
954 void
955 Curses_ChangeSearchDepth(void)
956 {
957     Curses_ShowMessage(CP[150]);
958     FLUSH_SCANW("%hd", &MaxSearchDepth);
959     TCflag = !(MaxSearchDepth > 0);
960 }
961
962
963 void
964 Curses_ChangeHashDepth(void)
965 {
966     Curses_ShowMessage(CP[163]);
967     FLUSH_SCANW("%hd", &HashDepth);
968     Curses_ShowMessage(CP[82]);
969     FLUSH_SCANW("%hd", &HashMoveLimit);
970 }
971
972
973 void
974 Curses_SetContempt(void)
975 {
976     Curses_ShowMessage(CP[142]);
977     FLUSH_SCANW("%hd", &contempt);
978 }
979
980
981
982 void
983 Curses_ChangeXwindow(void)
984 {
985     Curses_ShowMessage(CP[208]);
986     FLUSH_SCANW("%hd", &xwndw);
987 }
988
989
990
991 void
992 Curses_SelectLevel(char *sx)
993 {
994     int item;
995
996     Curses_ClearScreen();
997     gotoXY(32, 2);
998     printw(CP[41], version, patchlevel);
999     gotoXY(20, 4);
1000     printw(CP[18]);
1001     gotoXY(20, 5);
1002     printw(CP[19]);
1003     gotoXY(20, 6);
1004     printw(CP[20]);
1005     gotoXY(20, 7);
1006     printw(CP[21]);
1007     gotoXY(20, 8);
1008     printw(CP[22]);
1009     gotoXY(20, 9);
1010     printw(CP[23]);
1011     gotoXY(20, 10);
1012     printw(CP[24]);
1013     gotoXY(20, 11);
1014     printw(CP[25]);
1015     gotoXY(20, 12);
1016     printw(CP[26]);
1017     gotoXY(20, 13);
1018     printw(CP[27]);
1019
1020     OperatorTime = 0;
1021     TCmoves = 40;
1022     TCminutes = 5;
1023     TCseconds = 0;
1024
1025     gotoXY(20, 17);
1026     printw(CP[62]);
1027     refresh();
1028     FLUSH_SCANW("%d", &item);
1029
1030     switch(item)
1031     {
1032     case 1:
1033         TCmoves = 40;
1034         TCminutes = 5;
1035         break;
1036
1037     case 2:
1038         TCmoves = 40;
1039         TCminutes = 15;
1040         break;
1041
1042     case 3:
1043         TCmoves = 40;
1044         TCminutes = 30;
1045         break;
1046
1047     case 4:
1048         TCmoves = 80;
1049         TCminutes = 15;
1050         flag.gamein = true;
1051         break;
1052
1053     case 5:
1054         TCmoves = 80;
1055         TCminutes = 30;
1056         flag.gamein = true;
1057         break;
1058
1059     case 6:
1060         TCmoves = 80;
1061         TCminutes = 15;
1062         TCadd = 3000;
1063         flag.gamein = true;
1064         break;
1065
1066     case 7:
1067         TCmoves = 80;
1068         TCminutes = 30;
1069         TCadd = 3000;
1070         break;
1071
1072     case 8:
1073         TCmoves = 1;
1074         TCminutes = 1;
1075         flag.onemove = true;
1076         break;
1077
1078     case 9:
1079         TCmoves = 1;
1080         TCminutes = 15;
1081         flag.onemove = true;
1082         break;
1083
1084     case 10:
1085         TCmoves = 1;
1086         TCminutes = 30;
1087         flag.onemove = true;
1088         break;
1089     }
1090
1091     TCflag = (TCmoves > 0);
1092
1093     TimeControl.clock[black] = TimeControl.clock[white] = 0; 
1094
1095     SetTimeControl();
1096     Curses_ClearScreen();
1097     Curses_UpdateDisplay(0, 0, 1, 0);
1098 }
1099
1100
1101
1102 void
1103 Curses_DoDebug(void)
1104 {
1105     short c, p, sq, tp, tc, tsq, score;
1106     char s[40];
1107
1108     ExaminePosition(opponent);
1109     Curses_ShowMessage(CP[65]);
1110     FLUSH_SCANW("%s", s);
1111     c = neutral;
1112
1113     if ((s[0] == CP[9][0]) || (s[0] == CP[9][1])) /* b B */
1114         c = black;
1115
1116     if ((s[0] == CP[9][2]) || (s[0] == CP[9][3])) /* w W */
1117         c = white;
1118
1119     for (p = king; p > no_piece; p--)
1120     {
1121         if ((s[1] == pxx[p]) || (s[1] == qxx[p]))
1122             break;
1123     }
1124
1125     for (sq = 0; sq < NO_SQUARES; sq++)
1126     {
1127         tp = board[sq];
1128         tc = color[sq];
1129         board[sq] = p;
1130         color[sq] = c;
1131         tsq = PieceList[c][1];
1132         PieceList[c][1] = sq;
1133         Curses_ShowPostnValue(sq);
1134         PieceList[c][1] = tsq;
1135         board[sq] = tp;
1136         color[sq] = tc;
1137     }
1138
1139     score = ScorePosition(opponent);
1140     gotoXY(TAB, 5);
1141     printw(CP[103], score, 
1142            mtl[computer], pscore[computer], GameType[computer],
1143            mtl[opponent], pscore[opponent], GameType[opponent]);
1144
1145     ClearEoln();
1146 }
1147
1148
1149
1150 void
1151 Curses_DoTable(short table[NO_SQUARES])
1152 {
1153     short  sq;
1154     ExaminePosition(opponent);
1155
1156     for (sq = 0; sq < NO_SQUARES; sq++)
1157     {
1158         gotoXY(4 + 5 * VIR_C(sq), 5 + 2 * (7 - VIR_R(sq)));
1159         printw("%3d ", table[sq]);
1160     }
1161
1162
1163
1164