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