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