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