4 * Common display routines for GNU Shogi.
6 * ----------------------------------------------------------------------
7 * Copyright (c) 1993, 1994, 1995 Matthias Mutz
8 * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
10 * GNU SHOGI is based on GNU CHESS
12 * Copyright (c) 1988, 1989, 1990 John Stanback
13 * Copyright (c) 1992 Free Software Foundation
15 * This file is part of GNU SHOGI.
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.
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
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 * ----------------------------------------------------------------------
34 #if defined HAVE_GETTIMEOFDAY
41 #include <sys/param.h>
42 #include <sys/types.h>
49 int InBackground
= false;
50 struct display
*dsp
= &raw_display
;
56 movealgbr(short m
, char *s
)
59 short piece
= 0, flag
= 0;
72 piece
= f
- NO_SQUARES
;
74 if (piece
> NO_PIECES
)
77 flag
= (dropmask
| piece
);
124 #endif /* BOOKTEST */
128 * Generate move strings in different formats.
131 * - f piece to be moved
132 * - 0 < f < NO_SQUARES source square
133 * - NO_SQUARES <= f NO_SQUARES + 2*NO_PIECES dropped piece modulo NO_PIECES
134 * - t & 0x7f target square
135 * - t & 0x80 promotion flag
136 * - flag FIXME: must be zero ?
143 algbr(short f
, short t
, short flag
)
149 piece
= f
- NO_SQUARES
;
151 if (f
> (NO_SQUARES
+ NO_PIECES
))
154 flag
= (dropmask
| piece
);
163 if ((f
== t
) && ((f
!= 0) || (t
!= 0)))
166 dsp
->Printf("error in algbr: FROM=TO=%d, flag=0x%4x\n", t
, flag
);
169 mvstr
[0][0] = mvstr
[1][0] = mvstr
[2][0] = mvstr
[3][0] = '\0';
171 else if ((flag
& dropmask
) != 0)
173 short piece
= flag
& pmask
;
175 mvstr
[0][0] = pxx
[piece
];
177 mvstr
[0][2] = cxx
[column(t
)];
178 mvstr
[0][3] = rxx
[row(t
)];
180 strcpy(mvstr
[1], mvstr
[0]);
181 strcpy(mvstr
[2], mvstr
[0]);
182 strcpy(mvstr
[3], mvstr
[0]);
184 else if ((f
!= 0) || (t
!= 0))
186 /* algebraic notation */
187 mvstr
[0][0] = cxx
[column(f
)];
188 mvstr
[0][1] = rxx
[row(f
)];
189 mvstr
[0][2] = cxx
[column(t
)];
190 mvstr
[0][3] = rxx
[row(t
)];
191 mvstr
[0][4] = mvstr
[3][0] = '\0';
192 mvstr
[1][0] = pxx
[board
[f
]];
194 mvstr
[2][0] = mvstr
[1][0];
195 mvstr
[2][1] = mvstr
[0][1];
197 mvstr
[2][2] = mvstr
[1][1] = mvstr
[0][2]; /* to column */
198 mvstr
[2][3] = mvstr
[1][2] = mvstr
[0][3]; /* to row */
199 mvstr
[2][4] = mvstr
[1][3] = '\0';
200 strcpy(mvstr
[3], mvstr
[2]);
201 mvstr
[3][1] = mvstr
[0][0];
205 strcat(mvstr
[0], "+");
206 strcat(mvstr
[1], "+");
207 strcat(mvstr
[2], "+");
208 strcat(mvstr
[3], "+");
213 mvstr
[0][0] = mvstr
[1][0] = mvstr
[2][0] = mvstr
[3][0] = '\0';
219 * Compare the string 's' to the list of legal moves available for the
220 * opponent. If a match is found, make the move on the board.
224 VerifyMove(char *s
, VerifyMove_mode iop
, unsigned short *mv
)
226 static short pnt
, tempb
, tempc
, tempsf
, tempst
, cnt
;
227 static struct leaf xnode
;
229 short i
, l
, local_flags
;
232 /* check and remove quality flags */
233 for (i
= local_flags
= 0, l
= strlen(s
); i
< l
; i
++)
238 local_flags
|= badmove
;
243 local_flags
|= goodmove
;
249 local_flags
|= difficult
;
258 if (iop
== UNMAKE_MODE
)
260 UnmakeMove(opponent
, &xnode
, &tempb
, &tempc
, &tempsf
, &tempst
);
266 if (iop
== VERIFY_AND_MAKE_MODE
)
267 generate_move_flags
= true;
269 MoveList(opponent
, 2, -1, true);
270 generate_move_flags
= false;
273 while (pnt
< TrPnt
[3])
276 algbr(node
->f
, node
->t
, (short) node
->flags
);
278 if ((strcmp(s
, mvstr
[0]) == 0)
279 || (strcmp(s
, mvstr
[1]) == 0)
280 || (strcmp(s
, mvstr
[2]) == 0)
281 || (strcmp(s
, mvstr
[3]) == 0))
288 if ((cnt
== 1) && (xnode
.score
> DONTUSE
))
292 MakeMove(opponent
, &xnode
, &tempb
, &tempc
,
293 &tempsf
, &tempst
, &INCscore
);
295 if (SqAttacked(PieceList
[opponent
][0], computer
, &blocked
))
297 UnmakeMove(opponent
, &xnode
, &tempb
, &tempc
, &tempsf
, &tempst
);
298 dsp
->AlwaysShowMessage("Illegal move (in check) %s", s
);
303 if (iop
== VERIFY_AND_TRY_MODE
)
306 dsp
->UpdateDisplay(xnode
.f
, xnode
.t
, 0, (short) xnode
.flags
);
307 GameList
[GameCnt
].depth
= GameList
[GameCnt
].score
= 0;
308 GameList
[GameCnt
].nodes
= 0;
309 ElapsedTime(COMPUTE_AND_INIT_MODE
);
310 GameList
[GameCnt
].time
= (short) (et
+ 50)/100;
311 GameList
[GameCnt
].flags
|= local_flags
;
315 TimeControl
.clock
[opponent
] -= et
;
316 timeopp
[oppptr
] = et
;
317 --TimeControl
.moves
[opponent
];
320 *mv
= (xnode
.f
<< 8) | xnode
.t
;
321 algbr(xnode
.f
, xnode
.t
, false);
323 /* in force mode, check for mate conditions */
326 if (IsCheckmate(opponent
^ 1, -1, -1))
330 sprintf(buf
, "%s mates!\n", ColorStr
[opponent
]);
331 dsp
->ShowMessage(buf
);
340 dsp
->AlwaysShowMessage("Illegal move (no match) %s", s
);
342 if (!barebones
&& (cnt
> 1))
344 sprintf(buffer
, "Ambiguous Move %s!", s
);
345 dsp
->ShowMessage(buffer
);
353 parser(char *f
, short *fpiece
)
361 for (i
= 1, *fpiece
= no_piece
; i
< NO_PIECES
; i
++)
363 if (f
[0] == pxx
[i
] || f
[0] == qxx
[i
])
365 *fpiece
= (p
? promoted
[i
] : unpromoted
[i
]);
370 if (f
[1] == '*' || f
[1] == '\'')
375 return ((NO_SQUARES
+ *fpiece
) << 8) | locn(r2
, c2
);
383 p
= (f
[5] == '+') ? 0x80 : 0;
385 return (locn(r1
, c1
) << 8) | locn(r2
, c2
) | p
;
393 while (*InPtr
!= ' ')
396 while (*InPtr
== ' ')
404 while (*InPtr
== ' ')
409 void RequestInputString(char* buffer
, unsigned bufsize
)
412 int ret
= snprintf(fmt
, sizeof(fmt
), "%%%us", bufsize
);
414 perror("RequestInputString snprintf");
417 if (ret
>= sizeof(fmt
)) {
419 "Insufficient format-buffer size in %s for bufsize=%u\n",
420 __FUNCTION__
, bufsize
);
423 dsp
->doRequestInputString(fmt
, buffer
);
437 strcpy(fname
, savefile
);
439 dsp
->ShowMessage("Enter file name: ");
440 RequestInputString(fname
, sizeof(fname
)-1);
443 if (fname
[0] == '\0')
444 strcpy(fname
, "shogi.000");
446 if ((fd
= fopen(fname
, "r")) != NULL
)
449 fgets(fname
, 256, fd
);
450 computer
= opponent
= black
;
459 /* FIXME: write a skipn() function so that we can get
460 * 3 skips by doing skipn(3) */
464 Game50
= atoi(InPtr
);
466 flag
.force
= (*InPtr
== 'f');
467 fgets(fname
, 256, fd
); /* empty */
468 fgets(fname
, 256, fd
);
471 TCflag
= atoi(InPtr
);
475 OperatorTime
= atoi(InPtr
);
476 fgets(fname
, 256, fd
);
479 TimeControl
.clock
[black
] = atol(InPtr
);
482 TimeControl
.moves
[black
] = atoi(InPtr
);
483 fgets(fname
, 256, fd
);
486 TimeControl
.clock
[white
] = atol(InPtr
);
489 TimeControl
.moves
[white
] = atoi(InPtr
);
490 fgets(fname
, 256, fd
); /* empty */
492 for (i
= NO_ROWS
- 1; i
> -1; i
--)
494 fgets(fname
, 256, fd
);
498 for (j
= 0; j
< NO_COLS
; j
++)
500 sq
= i
* NO_COLS
+ j
;
506 board
[sq
] = no_piece
;
511 for (c
= 0; c
< NO_PIECES
; c
++)
516 board
[sq
] = promoted
[c
];
518 board
[sq
] = unpromoted
[c
];
524 for (c
= 0; c
< NO_PIECES
; c
++)
529 board
[sq
] = promoted
[c
];
531 board
[sq
] = unpromoted
[c
];
539 Mvboard
[sq
] = atoi(InPtr
);
544 fgets(fname
, 256, fd
); /* empty */
545 fgets(fname
, 256, fd
); /* 9 8 7 ... */
546 fgets(fname
, 256, fd
); /* empty */
547 fgets(fname
, 256, fd
); /* p l n ... */
550 for (side
= 0; side
<= 1; side
++)
552 fgets(fname
, 256, fd
);
556 Captured
[side
][pawn
] = atoi(InPtr
);
559 Captured
[side
][lance
] = atoi(InPtr
);
561 Captured
[side
][knight
] = atoi(InPtr
);
564 Captured
[side
][silver
] = atoi(InPtr
);
566 Captured
[side
][gold
] = atoi(InPtr
);
568 Captured
[side
][bishop
] = atoi(InPtr
);
570 Captured
[side
][rook
] = atoi(InPtr
);
572 Captured
[side
][king
] = atoi(InPtr
);
576 flag
.regularstart
= true;
578 fgets(fname
, 256, fd
); /* empty */
579 fgets(fname
, 256, fd
); /* move score ... */
581 while (fgets(fname
, 256, fd
))
590 g
= &GameList
[GameCnt
];
591 g
->gmove
= parser(InPtr
, &g
->fpiece
);
593 g
->score
= atoi(InPtr
);
595 g
->depth
= atoi(InPtr
);
597 g
->nodes
= atol(InPtr
);
599 g
->time
= atol(InPtr
);
601 g
->flags
= c
= atoi(InPtr
);
603 g
->hashkey
= strtol(InPtr
, (char **) NULL
, 16);
605 g
->hashbd
= strtol(InPtr
, (char **) NULL
, 16);
613 for (piece
= no_piece
, i
= 0; i
< NO_PIECES
; i
++)
615 if (pxx
[i
] == *InPtr
)
623 g
->color
= ((*InPtr
== 'W') ? white
: black
);
625 g
->piece
= (*InPtr
== '+'
627 : unpromoted
[piece
]);
636 if (TimeControl
.clock
[black
] > 0)
644 dsp
->UpdateDisplay(0, 0, 1, 0);
655 short sq
, i
, c
, f
, t
;
658 char empty
[2] = "\n";
661 strcpy(fname
, savefile
);
663 dsp
->ShowMessage("Enter file name: ");
664 RequestInputString(fname
, sizeof(fname
)-1);
667 if (fname
[0] == '\0')
668 strcpy(fname
, "shogi.000");
670 if ((fd
= fopen(fname
, "w")) != NULL
)
675 if (computer
== white
)
678 if (computer
== black
)
681 fprintf(fd
, "White %s Black %s %d %s\n", w
, b
, Game50
,
682 flag
.force
? "force" : "");
684 fprintf(fd
, "TimeControl %d Operator Time %d\n", TCflag
, OperatorTime
);
685 fprintf(fd
, "Black Clock %ld Moves %d\nWhite Clock %ld Moves %d\n",
686 TimeControl
.clock
[black
], TimeControl
.moves
[black
],
687 TimeControl
.clock
[white
], TimeControl
.moves
[white
]);
690 for (i
= NO_ROWS
- 1; i
> -1; i
--)
692 fprintf(fd
, "%c ", ROW_NAME(i
));
694 for (c
= 0; c
< NO_COLS
; c
++)
696 sq
= i
* NO_COLS
+ c
;
698 p
= is_promoted
[piece
] ? '+' : ' ';
699 fprintf(fd
, "%c", p
);
715 fprintf(fd
, "%c", p
);
720 for (f
= i
* NO_COLS
; f
< i
* NO_COLS
+ NO_ROWS
; f
++)
721 fprintf(fd
, " %d", Mvboard
[f
]);
728 fprintf(fd
, " 9 8 7 6 5 4 3 2 1\n");
730 fprintf(fd
, " p l n s g b r k\n");
732 fprintf(fd
, " 5 4 3 2 1\n");
734 fprintf(fd
, " p s g b r k\n");
737 for (side
= 0; side
<= 1; side
++)
739 fprintf(fd
, "%c", (side
== black
) ? 'B' : 'W');
740 fprintf(fd
, " %2d", Captured
[side
][pawn
]);
742 fprintf(fd
, " %2d", Captured
[side
][lance
]);
743 fprintf(fd
, " %2d", Captured
[side
][knight
]);
745 fprintf(fd
, " %2d", Captured
[side
][silver
]);
746 fprintf(fd
, " %2d", Captured
[side
][gold
]);
747 fprintf(fd
, " %2d", Captured
[side
][bishop
]);
748 fprintf(fd
, " %2d", Captured
[side
][rook
]);
749 fprintf(fd
, " %2d", Captured
[side
][king
]);
754 fputs(" move score depth nodes time flags capture\n", fd
);
756 for (i
= 1; i
<= GameCnt
; i
++)
758 struct GameRec
*g
= &GameList
[i
];
761 t
= (g
->gmove
& 0xFF);
762 algbr(f
, t
, g
->flags
);
764 fprintf(fd
, "%c%c%-5s %6d %5d %7ld %6ld %5d 0x%08lx 0x%08lx",
767 : (is_promoted
[g
->fpiece
] ? '+' : ' ')),
769 ((f
> NO_SQUARES
) ? &mvstr
[0][1] : mvstr
[0]),
771 g
->nodes
, g
->time
, g
->flags
,
772 g
->hashkey
, g
->hashbd
);
774 if (g
->piece
!= no_piece
)
776 fprintf(fd
, " %c %s %c\n",
777 pxx
[g
->piece
], ColorStr
[g
->color
],
778 (is_promoted
[g
->piece
] ? '+' : ' '));
788 dsp
->ShowMessage("Game saved");
792 dsp
->ShowMessage("Could not open file");
798 * GetXGame, SaveXGame and BookGame used to only be defined if
799 * xshogi wasn't defined -- wonder why?
811 dsp
->ShowMessage("Enter file name: ");
812 RequestInputString(fname
, sizeof(fname
)-1);
814 if (fname
[0] == '\0')
815 strcpy(fname
, "xshogi.position.read");
817 if ((fd
= fopen(fname
, "r")) != NULL
)
820 flag
.regularstart
= false;
823 /* xshogi position file ... */
824 fgets(fname
, 256, fd
);
829 if (strcmp(fname
, "xshogi"))
833 /* -- empty line -- */
834 fgets(fname
, 256, fd
);
835 /* -- empty line -- */
836 fgets(fname
, 256, fd
);
838 for (i
= NO_ROWS
- 1; i
> -1; i
--)
840 fgets(fname
, 256, fd
);
843 for (j
= 0; j
< NO_COLS
; j
++)
845 sq
= i
* NO_COLS
+ j
;
851 board
[sq
] = no_piece
;
856 for (c
= 0; c
< NO_PIECES
; c
++)
861 board
[sq
] = promoted
[c
];
863 board
[sq
] = unpromoted
[c
];
869 for (c
= 0; c
< NO_PIECES
; c
++)
874 board
[sq
] = promoted
[c
];
876 board
[sq
] = unpromoted
[c
];
889 for (side
= 0; side
<= 1; side
++)
891 fgets(fname
, 256, fd
);
893 Captured
[side
][pawn
] = atoi(InPtr
);
896 Captured
[side
][lance
] = atoi(InPtr
);
898 Captured
[side
][knight
] = atoi(InPtr
);
901 Captured
[side
][silver
] = atoi(InPtr
);
903 Captured
[side
][gold
] = atoi(InPtr
);
905 Captured
[side
][bishop
] = atoi(InPtr
);
907 Captured
[side
][rook
] = atoi(InPtr
);
909 Captured
[side
][king
] = atoi(InPtr
);
912 if (fgets(fname
, 256, fd
) != NULL
&& strncmp(fname
, "white", 5) == 0)
925 dsp
->UpdateDisplay(0, 0, 1, 0);
940 dsp
->ShowMessage("Enter file name: ");
941 RequestInputString(fname
, sizeof(fname
)-1);
943 if (fname
[0] == '\0')
944 strcpy(fname
, "xshogi.position.read");
946 if ((fd
= fopen(fname
, "w")) != NULL
)
948 fputs("# xshogi position file -- \n", fd
);
952 for (i
= NO_ROWS
- 1; i
> -1; i
--)
956 for (j
= 0; j
< NO_COLS
; j
++)
958 sq
= i
* NO_COLS
+ j
;
960 isp
= is_promoted
[piece
];
961 *p
= (isp
? '+' : ' ');
964 if (piece
== no_piece
)
966 else if (color
[sq
] == white
)
979 for (side
= 0; side
<= 1; side
++)
983 "%d %d %d %d %d %d %d %d\n",
985 "%d %d %d %d %d %d\n",
987 Captured
[side
][pawn
],
989 Captured
[side
][lance
],
990 Captured
[side
][knight
],
992 Captured
[side
][silver
],
993 Captured
[side
][gold
],
994 Captured
[side
][bishop
],
995 Captured
[side
][rook
],
996 Captured
[side
][king
]);
1001 if (computer
== black
)
1002 fputs("white to play\n", fd
);
1004 fputs("black to play\n", fd
);
1015 char fname
[256], sflags
[4];
1019 strcpy(fname
, savefile
);
1021 /* Enter file name */
1022 dsp
->ShowMessage("Enter file name: ");
1023 RequestInputString(fname
, sizeof(fname
)-1);
1026 if (fname
[0] == '\0')
1029 if ((fd
= fopen(fname
, "a")) != NULL
)
1033 for (i
= 1; i
<= GameCnt
; i
++)
1035 struct GameRec
*g
= &GameList
[i
];
1036 char mvnr
[20], mvs
[20];
1039 sprintf(mvnr
, "%d.", (i
+ 1)/2);
1044 t
= (g
->gmove
& 0xFF);
1045 algbr(f
, t
, g
->flags
);
1048 /* determine move quality string */
1049 if (g
->flags
& goodmove
)
1052 if (g
->flags
& badmove
)
1055 #ifdef EASY_OPENINGS
1056 if (g
->flags
& difficult
)
1062 /* determine move string */
1065 sprintf(mvs
, "%s%s ", &mvstr
[0][1], sflags
);
1069 sprintf(mvs
, "%c%c%c%c%c%s%s ",
1070 mvstr
[0][0], mvstr
[0][1],
1071 (g
->flags
& capture
) ? 'x' : '-',
1072 mvstr
[0][2], mvstr
[0][3],
1073 (mvstr
[0][4] == '+') ? "+" : "",
1077 fprintf(fd
, "%s%s%c%s",
1081 : (is_promoted
[g
->fpiece
] ? "+" : "")),
1094 dsp
->ShowMessage("Game saved");
1098 dsp
->ShowMessage("Could not open file");
1109 char fname
[256], dbuf
[256];
1113 strcpy(fname
, listfile
);
1118 strncpy(dbuf
, ctime(&when
), 20);
1125 /* use format "CL.Jan01-020304B" when
1128 program played white */
1130 sprintf(fname
, "CL.%s%s-%s%s%s%c",
1131 dbuf
+ 4, dbuf
+ 8, dbuf
+ 11, dbuf
+ 14,
1132 dbuf
+ 17, ColorStr
[computer
][0]);
1134 /* replace space padding with 0 */
1135 for (i
= 0; fname
[i
] != '\0'; i
++)
1137 if (fname
[i
] == ' ')
1142 fd
= fopen(fname
, "w");
1146 printf("Open failure for file: %s", fname
);
1150 fprintf(fd
, "gnushogi %s game\n", PACKAGE_VERSION
);
1151 fputs(" score depth nodes time ", fd
);
1152 fputs(" score depth nodes time\n", fd
);
1154 for (i
= 1; i
<= GameCnt
; i
++)
1156 f
= GameList
[i
].gmove
>> 8;
1157 t
= (GameList
[i
].gmove
& 0xFF);
1158 algbr(f
, t
, GameList
[i
].flags
);
1160 if (GameList
[i
].flags
& book
)
1162 fprintf(fd
, "%c%c%-5s %5d Book%7ld %5ld",
1165 : (is_promoted
[GameList
[i
].fpiece
] ? '+' : ' ')),
1166 pxx
[GameList
[i
].fpiece
],
1168 ? &mvstr
[0][1] : mvstr
[0]),
1175 fprintf(fd
, "%c%c%-5s %5d %2d %7ld %5ld",
1178 : (is_promoted
[GameList
[i
].fpiece
] ? '+' : ' ')),
1179 pxx
[GameList
[i
].fpiece
],
1180 (f
> NO_SQUARES
? &mvstr
[0][1] : mvstr
[0]),
1181 GameList
[i
].score
, GameList
[i
].depth
,
1182 GameList
[i
].nodes
, GameList
[i
].time
);
1195 fprintf(fd
, "\n\n");
1197 if (GameList
[GameCnt
].flags
& draw
)
1199 fprintf(fd
, "Draw %s\n", DRAW
);
1201 if (DRAW
== DRAW_REPETITION
)
1205 fprintf(fd
, "repetition by positions ");
1207 for (j
= GameCnt
- 1; j
>= Game50
; j
-= 2)
1209 if (GameList
[j
].hashkey
== hashkey
&&
1210 GameList
[j
].hashbd
== hashbd
)
1211 fprintf(fd
, "%d ", j
);
1217 else if (GameList
[GameCnt
].score
== -(SCORE_LIMIT
+ 999))
1219 fprintf(fd
, "%s\n", ColorStr
[player
]);
1221 else if (GameList
[GameCnt
].score
== (SCORE_LIMIT
+ 998))
1223 fprintf(fd
, "%s\n", ColorStr
[player
^ 1]);
1236 GameList
[GameCnt
].flags
|= badmove
;
1240 GameList
[GameCnt
].flags
|= goodmove
;
1243 #ifdef EASY_OPENINGS
1245 GameList
[GameCnt
].flags
|= difficult
;
1253 * Undo the most recent half-move.
1261 f
= GameList
[GameCnt
].gmove
>> 8;
1262 t
= GameList
[GameCnt
].gmove
& 0x7F;
1266 /* the move was a drop */
1267 Captured
[color
[t
]][board
[t
]]++;
1268 board
[t
] = no_piece
;
1274 if (GameList
[GameCnt
].flags
& promote
)
1275 board
[f
] = unpromoted
[board
[t
]];
1277 board
[f
] = board
[t
];
1279 color
[f
] = color
[t
];
1280 board
[t
] = GameList
[GameCnt
].piece
;
1281 color
[t
] = GameList
[GameCnt
].color
;
1283 if (board
[t
] != no_piece
)
1284 Captured
[color
[f
]][unpromoted
[board
[t
]]]--;
1286 if (color
[t
] != neutral
)
1294 if (TCflag
&& (TCmoves
> 1))
1295 ++TimeControl
.moves
[color
[f
]];
1297 hashkey
= GameList
[GameCnt
].hashkey
;
1298 hashbd
= GameList
[GameCnt
].hashbd
;
1300 computer
= computer
^ 1;
1301 opponent
= opponent
^ 1;
1304 player
= player
^ 1;
1305 dsp
->ShowSidetoMove();
1306 dsp
->UpdateDisplay(0, 0, 1, 0);
1308 if (flag
.regularstart
)
1314 FlagString(unsigned short flags
, char *s
)
1319 if (flags
& promote
)
1320 strcat(s
, " promote");
1322 if (flags
& dropmask
)
1323 strcat(s
, " drop:");
1325 if ((piece
= (flags
& pmask
)))
1329 if (is_promoted
[piece
])
1332 s
[l
++] = pxx
[piece
];
1336 if (flags
& capture
)
1337 strcat(s
, " capture");
1340 strcat(s
, " exact");
1343 strcat(s
, " tesuji");
1346 strcat(s
, " check");
1352 strcat(s
, " stupid");
1354 if (flags
& questionable
)
1355 strcat(s
, " questionable");
1357 if (flags
& kingattack
)
1358 strcat(s
, " kingattack");
1366 TestSpeed(void(*f
)(short side
, short ply
,
1367 short in_check
, short blockable
),
1377 #ifdef HAVE_GETTIMEOFDAY
1381 #ifdef HAVE_GETTIMEOFDAY
1382 gettimeofday(&tv
, NULL
);
1383 t1
= (tv
.tv_sec
*100 + (tv
.tv_usec
/10000));
1388 for (i
= 0; i
< j
; i
++)
1390 f(opponent
, 2, -1, true);
1393 for (jj
= TrPnt
[2]; i
< TrPnt
[3]; jj
++)
1395 if (!pick(jj
, TrPnt
[3] - 1))
1401 #ifdef HAVE_GETTIMEOFDAY
1402 gettimeofday(&tv
, NULL
);
1403 t2
= (tv
.tv_sec
* 100 + (tv
.tv_usec
/ 10000));
1408 cnt
= j
* (TrPnt
[3] - TrPnt
[2]);
1415 dsp
->ShowNodeCnt(cnt
);
1420 TestPSpeed(short(*f
) (short side
), unsigned j
)
1424 #ifdef HAVE_GETTIMEOFDAY
1428 #ifdef HAVE_GETTIMEOFDAY
1429 gettimeofday(&tv
, NULL
);
1430 t1
= (tv
.tv_sec
* 100 + (tv
.tv_usec
/ 10000));
1435 for (i
= 0; i
< j
; i
++)
1438 #ifdef HAVE_GETTIMEOFDAY
1439 gettimeofday(&tv
, NULL
);
1440 t2
= (tv
.tv_sec
* 100 + (tv
.tv_usec
/ 10000));
1452 dsp
->ShowNodeCnt(cnt
);
1463 time
= &s
[strlen("otime")];
1464 t
= (int)strtol(time
, &time
, 10);
1469 /* FIXME: sec is parsed but ignored */
1470 sec
= (int)strtol(time
, &time
, 10);
1473 m
= (int)strtol(time
, &time
, 10);
1476 TimeControl
.clock
[opponent
] = t
;
1479 TimeControl
.moves
[opponent
] = m
;
1481 ElapsedTime(COMPUTE_AND_INIT_MODE
);
1485 /* just to inform xshogi about availability of otime command */
1486 printf("otime %d %d\n", t
, m
);
1492 SetMachineTime(char *s
)
1497 time
= &s
[strlen("time")];
1499 t
= (int)strtol(time
, &time
, 10);
1504 /* FIXME: sec is parsed but ignored */
1505 sec
= (int)strtol(time
, &time
, 10);
1508 m
= (int)strtol(time
, &time
, 10);
1511 TimeControl
.clock
[computer
] = t
;
1514 TimeControl
.moves
[computer
] = m
;
1516 ElapsedTime(COMPUTE_AND_INIT_MODE
);
1520 /* just to inform xshogi about availability of time command */
1521 printf("time %d %d\n", t
, m
);
1526 /* FIXME! This is truly the function from hell! */
1529 * Process the user's command. If easy mode is OFF (the computer is thinking
1530 * on opponents time) and the program is out of book, then make the 'hint'
1531 * move on the board and call SelectMove() to find a response. The user
1532 * terminates the search by entering ^C (quit siqnal) before entering a
1533 * command. If the opponent does not make the hint move, then set Sdepth to
1538 InputCommand(char *command
)
1541 short have_shown_prompt
= false;
1542 short ok
, done
, is_move
= false;
1546 ok
= flag
.quit
= done
= false;
1550 if (TTadd
> ttbllimit
)
1554 if ((hint
> 0) && !flag
.easy
&& !flag
.force
)
1557 * A hint move for the player is available. Compute a move for the
1558 * opponent in background mode assuming that the hint move will be
1559 * selected by the player.
1562 ft
= time0
; /* Save reference time for the player. */
1564 algbr((short) hint
>> 8, (short) hint
& 0xff, false);
1565 strcpy(s
, mvstr
[0]);
1572 /* do the hint move */
1573 if (VerifyMove(s
, VERIFY_AND_TRY_MODE
, &mv
))
1577 #ifdef QUIETBACKGROUND
1579 have_shown_prompt
= true;
1580 #endif /* QUIETBACKGROUND */
1582 /* Start computing a move until the search is interrupted. */
1584 #ifdef INTERRUPT_TEST
1588 /* would love to put null move in here */
1589 /* after we make the hint move make a 2 ply search
1590 * with both plys our moves */
1591 /* think on opponents time */
1592 SelectMove(computer
, BACKGROUND_MODE
);
1594 #ifdef INTERRUPT_TEST
1595 ElapsedTime(COMPUTE_INTERRUPT_MODE
);
1599 printf("searching not terminated by interrupt!\n");
1603 printf("elapsed time from interrupt to "
1604 "terminating search: %ld\n", it
);
1608 /* undo the hint and carry on */
1609 VerifyMove(s
, UNMAKE_MODE
, &mv
);
1613 time0
= ft
; /* Restore reference time for the player. */
1616 while(!(ok
|| flag
.quit
|| done
))
1620 #ifdef QUIETBACKGROUND
1621 if (!have_shown_prompt
)
1623 #endif /* QUIETBACKGROUND */
1627 #ifdef QUIETBACKGROUND
1630 have_shown_prompt
= false;
1631 #endif /* QUIETBACKGROUND */
1633 if (command
== NULL
) {
1637 eof
= dsp
->GetString(sx
);
1639 strcpy(sx
, command
);
1643 sscanf(sx
, "%s", s
);
1651 if (strcmp(s
, "bd") == 0) /* bd -- display board */
1653 /* FIXME: Hack alert! */
1654 short old_xshogi
= XSHOGI
;
1657 display_type
= DISPLAY_RAW
;
1660 dsp
->UpdateDisplay(0, 0, 1, 0);
1663 display_type
= DISPLAY_X
;
1665 else if (strcmp(s
, "post") == 0)
1667 flag
.post
= !flag
.post
;
1669 else if (strcmp(s
, "alg") == 0)
1671 /* noop */ ; /* alg */
1673 else if ((strcmp(s
, "quit") == 0)
1674 || (strcmp(s
, "exit") == 0))
1679 else if (strcmp(s
, "post") == 0)
1681 flag
.post
= !flag
.post
;
1684 else if ((strcmp(s
, "set") == 0)
1685 || (strcmp(s
, "edit") == 0))
1689 else if ((strcmp(s
, "setup") == 0))
1693 else if (strcmp(s
, "first") == 0)
1697 else if (strcmp(s
, "go") == 0)
1702 if (computer
== black
)
1713 else if (strcmp(s
, "help") == 0)
1717 else if (strcmp(s
, "material") == 0)
1719 flag
.material
= !flag
.material
;
1721 else if (strcmp(s
, "force") == 0)
1726 flag
.bothsides
= false;
1730 flag
.force
= !flag
.force
;
1731 flag
.bothsides
= false;
1734 else if (strcmp(s
, "book") == 0)
1736 Book
= Book
? 0 : BOOKFAIL
;
1738 else if (strcmp(s
, "new") == 0)
1741 dsp
->UpdateDisplay(0, 0, 1, 0);
1743 else if (strcmp(s
, "list") == 0)
1747 else if ((strcmp(s
, "level") == 0)
1748 || (strcmp(s
, "clock") == 0))
1750 dsp
->SelectLevel(sx
);
1752 else if (strcmp(s
, "hash") == 0)
1754 flag
.hash
= !flag
.hash
;
1756 else if (strcmp(s
, "gamein") == 0)
1758 flag
.gamein
= !flag
.gamein
;
1760 else if (strcmp(s
, "beep") == 0)
1762 flag
.beep
= !flag
.beep
;
1764 else if (strcmp(s
, "time") == 0)
1768 else if (strcmp(s
, "otime") == 0)
1772 else if (strcmp(s
, "Awindow") == 0)
1774 dsp
->ChangeAlphaWindow();
1776 else if (strcmp(s
, "Bwindow") == 0)
1778 dsp
->ChangeBetaWindow();
1780 else if (strcmp(s
, "rcptr") == 0)
1782 flag
.rcptr
= !flag
.rcptr
;
1784 else if (strcmp(s
, "hint") == 0)
1788 else if (strcmp(s
, "both") == 0)
1790 flag
.bothsides
= !flag
.bothsides
;
1793 ElapsedTime(COMPUTE_AND_INIT_MODE
);
1794 SelectMove(opponent
, FOREGROUND_MODE
);
1797 else if (strcmp(s
, "reverse") == 0)
1799 flag
.reverse
= !flag
.reverse
;
1801 dsp
->UpdateDisplay(0, 0, 1, 0);
1803 else if (strcmp(s
, "switch") == 0)
1805 computer
= computer
^ 1;
1806 opponent
= opponent
^ 1;
1807 xwndw
= (computer
== black
) ? WXWNDW
: BXWNDW
;
1812 else if (strcmp(s
, "black") == 0)
1821 * ok = true; don't automatically start with black command
1824 else if (strcmp(s
, "white") == 0)
1833 * ok = true; don't automatically start with white command
1836 else if (strcmp(s
, "undo") == 0 && GameCnt
> 0)
1840 else if (strcmp(s
, "remove") == 0 && GameCnt
> 1)
1845 /* CHECKME: are these next three correct? */
1846 else if (!XSHOGI
&& strcmp(s
, "xget") == 0)
1850 else if (!XSHOGI
&& strcmp(s
, "xsave") == 0)
1854 else if (!XSHOGI
&& strcmp(s
, "bsave") == 0)
1858 #ifdef EASY_OPENINGS
1859 else if ((strcmp(s
, "?") == 0)
1860 || (strcmp(s
, "!") == 0)
1861 || (strcmp(s
, "~") == 0))
1863 else if ((strcmp(s
, "?") == 0)
1864 || (strcmp(s
, "!") == 0))
1869 else if (strcmp(s
, "get") == 0)
1873 else if (strcmp(s
, "save") == 0)
1877 else if (strcmp(s
, "depth") == 0)
1879 dsp
->ChangeSearchDepth();
1881 else if (strcmp(s
, "hashdepth") == 0)
1883 dsp
->ChangeHashDepth();
1885 else if (strcmp(s
, "random") == 0)
1889 else if (strcmp(s
, "hard") == 0)
1893 else if (strcmp(s
, "easy") == 0)
1895 flag
.easy
= !flag
.easy
;
1897 else if (strcmp(s
, "tsume") == 0)
1899 flag
.tsume
= !flag
.tsume
;
1901 else if (strcmp(s
, "contempt") == 0)
1905 else if (strcmp(s
, "xwndw") == 0)
1907 dsp
->ChangeXwindow();
1909 else if (strcmp(s
, "rv") == 0)
1912 dsp
->UpdateDisplay(0, 0, 1, 0);
1914 else if (strcmp(s
, "coords") == 0)
1916 flag
.coords
= !flag
.coords
;
1917 dsp
->UpdateDisplay(0, 0, 1, 0);
1919 else if (strcmp(s
, "stars") == 0)
1921 flag
.stars
= !flag
.stars
;
1922 dsp
->UpdateDisplay(0, 0, 1, 0);
1924 else if (!XSHOGI
&& strcmp(s
, "moves") == 0)
1931 extern unsigned short PrVar
[MAXDEPTH
];
1933 SwagHt
= (GameList
[GameCnt
].gmove
== PrVar
[1])
1940 dsp
->ShowMessage("Testing MoveList Speed");
1941 temp
= generate_move_flags
;
1942 generate_move_flags
= true;
1943 TestSpeed(MoveList
, 1);
1944 generate_move_flags
= temp
;
1945 dsp
->ShowMessage("Testing CaptureList Speed");
1946 TestSpeed(CaptureList
, 1);
1947 dsp
->ShowMessage("Testing Eval Speed");
1948 ExaminePosition(opponent
);
1949 TestPSpeed(ScorePosition
, 1);
1951 else if (!XSHOGI
&& strcmp(s
, "test") == 0)
1954 dsp
->ShowMessage("Testing MoveList Speed");
1955 TestSpeed(MoveList
, 2000);
1956 dsp
->ShowMessage("Testing CaptureList Speed");
1957 TestSpeed(CaptureList
, 3000);
1958 dsp
->ShowMessage("Testing Eval Speed");
1959 ExaminePosition(opponent
);
1960 TestPSpeed(ScorePosition
, 1500);
1962 dsp
->ShowMessage("Testing MoveList Speed");
1963 TestSpeed(MoveList
, 20000);
1964 dsp
->ShowMessage("Testing CaptureList Speed");
1965 TestSpeed(CaptureList
, 30000);
1966 dsp
->ShowMessage("Testing Eval Speed");
1967 ExaminePosition(opponent
);
1968 TestPSpeed(ScorePosition
, 15000);
1971 else if (!XSHOGI
&& strcmp(s
, "p") == 0)
1973 dsp
->ShowPostnValues();
1975 else if (!XSHOGI
&& strcmp(s
, "debug") == 0)
1985 else if ((ok
= VerifyMove(s
, VERIFY_AND_MAKE_MODE
, &mv
)))
1987 /* check for repetition */
1988 short rpt
= repetition();
1992 DRAW
= DRAW_REPETITION
;
1993 dsp
->ShowMessage(DRAW
);
1994 GameList
[GameCnt
].flags
|= draw
;
2008 ElapsedTime(COMPUTE_AND_INIT_MODE
);
2012 computer
= opponent
;
2013 opponent
= computer
^ 1;
2018 /* add remaining time in milliseconds for xshogi */
2021 printf("%d. %s %ld\n",
2022 ++mycnt2
, s
, TimeControl
.clock
[player
] * 10);
2025 #ifdef notdef /* optional pass best line to frontend with move */
2026 # if !defined NOPOST
2028 if (flag
.post
&& !flag
.mate
)
2032 printf(" %6d ", MSCORE
);
2034 for (i
= 1; MV
[i
] > 0; i
++)
2036 algbr((short) (MV
[i
] >> 8), (short) (MV
[i
] & 0xFF), false);
2037 printf("%5s ", mvstr
[0]);
2048 SetTimeControl(void)
2052 TimeControl
.moves
[black
] = TimeControl
.moves
[white
] = TCmoves
;
2053 TimeControl
.clock
[black
] += 6000L * TCminutes
+ TCseconds
* 100;
2054 TimeControl
.clock
[white
] += 6000L * TCminutes
+ TCseconds
* 100;
2058 TimeControl
.moves
[black
] = TimeControl
.moves
[white
] = 0;
2059 TimeControl
.clock
[black
] = TimeControl
.clock
[white
] = 0;
2062 flag
.onemove
= (TCmoves
== 1);
2064 ElapsedTime(COMPUTE_AND_INIT_MODE
);