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