1 /* 2 ALPHA interface for CHESS 3 4 Revision: 4-25-88 5 6 Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. 7 Copyright (c) 1988 John Stanback 8 9 This file is part of CHESS. 10 11 CHESS is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY. No author or distributor 13 accepts responsibility to anyone for the consequences of using it 14 or for whether it serves any particular purpose or works at all, 15 unless he says so in writing. Refer to the CHESS General Public 16 License for full details. 17 18 Everyone is granted permission to copy, modify and redistribute 19 CHESS, but only under the conditions described in the 20 CHESS General Public License. A copy of this license is 21 supposed to have been given to you along with CHESS so you 22 can know your rights and responsibilities. It should be in a 23 file named COPYING. Among other things, the copyright notice 24 and this notice must be preserved on all copies. 25 */ 26 27 28 #include <stdio.h> 29 #include <ctype.h> 30 #include <sys/param.h> 31 #include <sys/times.h> 32 #include <sys/file.h> 33 #include <curses.h> 34 #include <signal.h> 35 #include "gnuchess.h" 36 #ifdef NEWMOVE 37 #include "move.h" 38 #endif 39 #include "pathnames.h" 40 41 struct tms tmbuf1,tmbuf2; 42 void TerminateSearch(),Die(); 43 44 #define scanz fflush(stdout),scanw 45 #define printz printw 46 47 48 Initialize() 49 { 50 signal(SIGINT,Die); signal(SIGQUIT,Die); 51 initscr(); 52 crmode(); 53 } 54 55 56 ExitChess() 57 { 58 nocrmode(); 59 endwin(); 60 exit(0); 61 } 62 63 64 void 65 Die() 66 { 67 char s[80]; 68 signal(SIGINT,SIG_IGN); 69 signal(SIGQUIT,SIG_IGN); 70 ShowMessage("Abort? "); 71 scanz("%s",s); 72 if (strcmp(s,"yes") == 0) ExitChess(); 73 signal(SIGINT,Die); signal(SIGQUIT,Die); 74 } 75 76 77 void 78 TerminateSearch() 79 { 80 signal(SIGINT,SIG_IGN); 81 signal(SIGQUIT,SIG_IGN); 82 timeout = true; 83 bothsides = false; 84 signal(SIGINT,Die); signal(SIGQUIT,Die); 85 } 86 87 88 InputCommand() 89 90 /* 91 Process the users command. If easy mode is OFF (the computer is 92 thinking on opponents time) and the program is out of book, then make 93 the 'hint' move on the board and call SelectMove() to find a response. 94 The user terminates the search by entering ^C (quit siqnal) before 95 entering a command. If the opponent does not make the hint move, then 96 set Sdepth to zero. 97 */ 98 99 { 100 short ok,i,tmp; 101 long cnt,rate,t1,t2; 102 unsigned short mv; 103 char s[80]; 104 105 ok = quit = false; 106 player = opponent; 107 ShowSidetomove(); 108 ft = 0; 109 if (hint > 0 && !easy && Book == NULL) 110 { 111 fflush(stdout); 112 time0 = time((long *)0); 113 algbr(hint>>8,hint & 0xFF,false); 114 strcpy(s,mvstr1); 115 tmp = epsquare; 116 if (VerifyMove(s,1,&mv)) 117 { 118 PromptForMove(); 119 SelectMove(computer,2); 120 VerifyMove(mvstr1,2,&mv); 121 if (Sdepth > 0) Sdepth--; 122 } 123 ft = time((time_t *)0) - time0; 124 epsquare = tmp; 125 } 126 127 signal(SIGINT,Die); signal(SIGQUIT,Die); 128 while (!(ok || quit)) 129 { 130 PromptForMove(); 131 scanz("%s",s); 132 player = opponent; 133 ok = VerifyMove(s,0,&mv); 134 if (ok && mv != hint) 135 { 136 Sdepth = 0; 137 ft = 0; 138 } 139 140 if (strcmp(s,"bd") == 0) 141 { 142 ClrScreen(); 143 UpdateDisplay(0,0,1,0); 144 } 145 if (strcmp(s,"quit") == 0) quit = true; 146 if (strcmp(s,"post") == 0) post = !post; 147 if (strcmp(s,"edit") == 0) EditBoard(); 148 if (strcmp(s,"go") == 0) ok = true; 149 if (strcmp(s,"help") == 0) help(); 150 if (strcmp(s,"force") == 0) force = !force; 151 if (strcmp(s,"book") == 0) Book = NULL; 152 if (strcmp(s,"undo") == 0 && GameCnt >= 0) Undo(); 153 if (strcmp(s,"new") == 0) NewGame(); 154 if (strcmp(s,"list") == 0) ListGame(); 155 if (strcmp(s,"level") == 0) SelectLevel(); 156 if (strcmp(s,"hash") == 0) hashflag = !hashflag; 157 if (strcmp(s,"beep") == 0) beep = !beep; 158 if (strcmp(s,"Awindow") == 0) ChangeAlphaWindow(); 159 if (strcmp(s,"Bwindow") == 0) ChangeBetaWindow(); 160 if (strcmp(s,"hint") == 0) GiveHint(); 161 if (strcmp(s,"both") == 0) 162 { 163 bothsides = !bothsides; 164 Sdepth = 0; 165 SelectMove(opponent,1); 166 ok = true; 167 } 168 if (strcmp(s,"reverse") == 0) 169 { 170 reverse = !reverse; 171 ClrScreen(); 172 UpdateDisplay(0,0,1,0); 173 } 174 if (strcmp(s,"switch") == 0) 175 { 176 computer = otherside[computer]; 177 opponent = otherside[opponent]; 178 force = false; 179 Sdepth = 0; 180 ok = true; 181 } 182 if (strcmp(s,"white") == 0) 183 { 184 computer = white; opponent = black; 185 ok = true; force = false; 186 Sdepth = 0; 187 } 188 if (strcmp(s,"black") == 0) 189 { 190 computer = black; opponent = white; 191 ok = true; force = false; 192 Sdepth = 0; 193 } 194 if (strcmp(s,"remove") == 0 && GameCnt >= 1) 195 { 196 Undo(); Undo(); 197 } 198 if (strcmp(s,"get") == 0) GetGame(); 199 if (strcmp(s,"save") == 0) SaveGame(); 200 if (strcmp(s,"depth") == 0) ChangeSearchDepth(); 201 if (strcmp(s,"random") == 0) dither = 6; 202 if (strcmp(s,"easy") == 0) easy = !easy; 203 if (strcmp(s,"contempt") == 0) SetContempt(); 204 if (strcmp(s,"xwndw") == 0) ChangeXwindow(); 205 if (strcmp(s,"test") == 0) 206 { 207 t1 = time(0); 208 cnt = 0; 209 for (i = 0; i < 10000; i++) 210 { 211 MoveList(opponent,2); 212 cnt += TrPnt[3] - TrPnt[2]; 213 } 214 t2 = time(0); 215 rate = cnt / (t2-t1); 216 gotoXY(50,24); 217 printz("cnt= %ld rate= %ld",cnt,rate); 218 ClrEoln(); 219 } 220 if (strcmp(s,"p") == 0) ShowPostnValues(); 221 if (strcmp(s,"debug") == 0) DoDebug(); 222 } 223 224 ClearMessage(); 225 ElapsedTime(1); 226 if (force) 227 { 228 computer = opponent; opponent = otherside[computer]; 229 } 230 (void) times(&tmbuf1); 231 signal(SIGINT,TerminateSearch); signal(SIGQUIT,TerminateSearch); 232 } 233 234 235 EditBoard() 236 237 /* 238 Set up a board position. Pieces are entered by typing the piece 239 followed by the location. For example, Nf3 will place a knight on 240 square f3. 241 */ 242 243 { 244 short a,r,c,sq; 245 char s[80]; 246 247 ClrScreen(); 248 UpdateDisplay(0,0,1,0); 249 gotoXY(50,2); printz(". Exit to main"); 250 gotoXY(50,3); printz("# Clear board"); 251 gotoXY(49,5); printz("Enter piece & location: "); 252 a = white; 253 do 254 { 255 gotoXY(73,5); ClrEoln(); scanz("%s",s); 256 if (s[0] == '#') 257 { 258 for (sq = 0; sq < 64; sq++) 259 { 260 board[sq] = no_piece; color[sq] = neutral; 261 } 262 UpdateDisplay(0,0,1,0); 263 } 264 if (s[0] == 'c' || s[0] == 'C') a = otherside[a]; 265 c = s[1]-'a'; r = s[2]-'1'; 266 if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8)) 267 { 268 sq = locn[r][c]; 269 color[sq] = a; 270 if (s[0] == 'p') board[sq] = pawn; 271 else if (s[0] == 'n') board[sq] = knight; 272 else if (s[0] == 'b') board[sq] = bishop; 273 else if (s[0] == 'r') board[sq] = rook; 274 else if (s[0] == 'q') board[sq] = queen; 275 else if (s[0] == 'k') board[sq] = king; 276 else { board[sq] = no_piece; color[sq] = neutral; } 277 DrawPiece(sq); 278 } 279 } 280 while (s[0] != '.'); 281 if (board[4] != king) kingmoved[white] = 10; 282 if (board[60] != king) kingmoved[black] = 10; 283 GameCnt = -1; Game50 = 0; Sdepth = 0; 284 InitializeStats(); 285 ClrScreen(); 286 UpdateDisplay(0,0,1,0); 287 } 288 289 290 help() 291 { 292 ClrScreen(); 293 gotoXY(28,1); printz("CHESS command summary"); 294 gotoXY(1,3); printz("g1f3 move from g1 to f3"); 295 gotoXY(1,4); printz("nf3 move knight to f3"); 296 gotoXY(1,5); printz("o-o castle king side"); 297 gotoXY(1,6); printz("o-o-o castle queen side"); 298 gotoXY(1,7); printz("edit edit board"); 299 gotoXY(1,8); printz("switch sides with computer"); 300 gotoXY(1,9); printz("white computer plays white"); 301 gotoXY(1,10); printz("black computer plays black"); 302 gotoXY(1,11); printz("reverse board display"); 303 gotoXY(1,12); printz("both computer match"); 304 gotoXY(1,13); printz("random randomize play"); 305 gotoXY(1,14); printz("undo undo last move"); 306 gotoXY(42,3); printz("level change level"); 307 gotoXY(42,4); printz("depth set search depth"); 308 gotoXY(42,5); printz("post principle variation"); 309 gotoXY(42,6); printz("hint suggest a move"); 310 gotoXY(42,7); printz("bd redraw board"); 311 gotoXY(42,8); printz("force enter game moves"); 312 gotoXY(42,9); printz("list game to chess.lst"); 313 gotoXY(42,10); printz("save game to file"); 314 gotoXY(42,11); printz("get game from file"); 315 gotoXY(42,12); printz("new start new game"); 316 gotoXY(42,13); printz("quit exit CHESS"); 317 gotoXY(10,21); printz("Computer: "); 318 if (computer == white) printz("WHITE"); else printz("BLACK"); 319 gotoXY(10,22); printz("Opponent: "); 320 if (opponent == white) printz("WHITE"); else printz("BLACK"); 321 gotoXY(10,23); printz("Level: %ld",Level," sec."); 322 gotoXY(10,24); printz("Easy mode: "); 323 if (easy) printz("ON"); else printz("OFF"); 324 gotoXY(40,21); printz("Depth: %d",MaxSearchDepth); 325 gotoXY(40,22); printz("Random: "); 326 if (dither) printz("ON"); else printz("OFF"); 327 gotoXY(40,23); printz("Transposition table: "); 328 if (hashflag) printz("ON"); else printz("OFF"); 329 refresh(); 330 while (getchar() != 27); 331 ClrScreen(); 332 UpdateDisplay(0,0,1,0); 333 } 334 335 336 ShowDepth(ch) 337 char ch; 338 { 339 gotoXY(50,4); printz("Depth= %d%c ",Sdepth,ch); ClrEoln(); 340 } 341 342 343 ShowResults(score,bstline,ch) 344 short score; 345 unsigned short bstline[]; 346 char ch; 347 { 348 short d,e,ply; 349 if (post && player == computer) 350 { 351 e = lpost; 352 gotoXY(50,5); printz("Score= %d",score); ClrEoln(); 353 d = 8; gotoXY(50,d); ClrEoln(); 354 for (ply = 1; bstline[ply] > 0; ply++) 355 { 356 algbr(bstline[ply] >> 8,bstline[ply] & 0xFF,false); 357 if (ply == 5 || ply == 9 || ply == 13 || ply == 17) 358 { 359 gotoXY(50,++d); ClrEoln(); 360 } 361 printz("%5s ",mvstr1); 362 } 363 ClrEoln(); 364 lpost = d; 365 while (++d <= e) 366 { 367 gotoXY(50,d); ClrEoln(); 368 } 369 } 370 } 371 372 373 SearchStartStuff(side) 374 short side; 375 { 376 short i; 377 signal(SIGINT,TerminateSearch); signal(SIGQUIT,TerminateSearch); 378 if (player == computer) 379 for (i = 5; i < 14; i++) 380 { 381 gotoXY(50,i); ClrEoln(); 382 } 383 } 384 385 386 OutputMove() 387 { 388 if (root->flags & epmask) UpdateDisplay(0,0,1,0); 389 else UpdateDisplay(root->f,root->t,0,root->flags & cstlmask); 390 gotoXY(50,17); printz("My move is: %s",mvstr1); 391 if (beep) putchar(7); 392 ClrEoln(); 393 394 gotoXY(50,24); 395 if (root->flags & draw) printz("Draw game!"); 396 else if (root->score == -9999) printz("opponent mates!"); 397 else if (root->score == 9998) printz("computer mates!"); 398 else if (root->score < -9000) printz("opponent will soon mate!"); 399 else if (root->score > 9000) printz("computer will soon mate!"); 400 ClrEoln(); 401 402 if (post) 403 { 404 gotoXY(50,22); printz("Nodes= %6ld",NodeCnt); ClrEoln(); 405 gotoXY(50,23); printz("Nodes/Sec= %4ld",evrate); ClrEoln(); 406 } 407 } 408 409 410 ElapsedTime(iop) 411 412 /* 413 Determine the time that has passed since the search was started. If 414 the elapsed time exceeds the target (ResponseTime+ExtraTime) then set 415 timeout to true which will terminate the search. 416 */ 417 418 short iop; 419 { 420 et = time((time_t *)0) - time0; 421 if (et < 0) et = 0; 422 ETnodes += 50; 423 if (et > et0 || iop == 1) 424 { 425 if (et > ResponseTime+ExtraTime && Sdepth > 1) timeout = true; 426 et0 = et; 427 if (iop == 1) 428 { 429 time0 = time((time_t *)0); et0 = 0; 430 } 431 (void) times(&tmbuf2); 432 cputimer = 100*(tmbuf2.tms_utime - tmbuf1.tms_utime) / HZ; 433 if (cputimer > 0) evrate = (100*NodeCnt)/(cputimer+100*ft); 434 else evrate = 0; 435 ETnodes = NodeCnt + 50; 436 UpdateClocks(); 437 } 438 } 439 440 441 UpdateClocks() 442 { 443 short m,s; 444 m = et/60; s = (et - 60*m); 445 if (TCflag) 446 { 447 m = (TimeControl.clock[player] - et) / 60; 448 s = TimeControl.clock[player] - et - 60*m; 449 } 450 if (m < 0) m = 0; 451 if (s < 0) s = 0; 452 if (player == white) 453 if (reverse) gotoXY(20,2); else gotoXY(20,23); 454 else 455 if (reverse) gotoXY(20,23); else gotoXY(20,2); 456 printz("%d:%2d ",m,s); 457 if (post) 458 { 459 gotoXY(50,22); printz("Nodes= %6ld",NodeCnt); 460 gotoXY(50,23); printz("Nodes/Sec= %4ld",evrate); 461 } 462 refresh(); 463 } 464 465 466 467 SetTimeControl() 468 { 469 if (TCflag) 470 { 471 TimeControl.moves[white] = TimeControl.moves[black] = TCmoves; 472 TimeControl.clock[white] = TimeControl.clock[black] = 60*(long)TCminutes; 473 } 474 else 475 { 476 TimeControl.moves[white] = TimeControl.moves[black] = 0; 477 TimeControl.clock[white] = TimeControl.clock[black] = 0; 478 Level = 60*(long)TCminutes; 479 } 480 et = 0; 481 ElapsedTime(1); 482 } 483 484 485 gotoXY(x,y) 486 short x,y; 487 { 488 move(y-1,x-1); 489 } 490 491 492 ClrScreen() 493 { 494 clear(); refresh(); 495 } 496 497 498 ClrEoln() 499 { 500 clrtoeol(); refresh(); 501 } 502 503 504 DrawPiece(sq) 505 short sq; 506 { 507 short r,c; char x; 508 if (reverse) r = 7-row[sq]; else r = row[sq]; 509 if (reverse) c = 7-column[sq]; else c = column[sq]; 510 if (color[sq] == black) x = '*'; else x = ' '; 511 gotoXY(5+5*c,5+2*(7-r)); printz("%c%c ",x,pxx[board[sq]]); 512 } 513 514 515 UpdateDisplay(f,t,flag,iscastle) 516 short f,t,flag,iscastle; 517 { 518 short i,l,z,m = 0, j; 519 if (flag) 520 { 521 gotoXY(56,2); printz("CHESS"); 522 i = 3; 523 gotoXY(3,++i); 524 printz("|----|----|----|----|----|----|----|----|"); 525 while (i<19) 526 { 527 gotoXY(1,++i); 528 if (reverse) z = (i/2)-1; else z = 10-(i/2); 529 printz("%d ", z); 530 for (j = 0; j < 8; j++) { 531 printz("|"); 532 if (j % 2 == m) 533 printz("#"); 534 else 535 printz(" "); 536 printz(" "); 537 } 538 printz("|"); 539 m = (m + 1) % 2; 540 gotoXY(3,++i); 541 if (i < 19) 542 printz("+----+----+----+----+----+----+----+----+"); 543 } 544 printz("|----|----|----|----|----|----|----|----|"); 545 gotoXY(3,21); 546 if (reverse) printz(" h g f e d c b a"); 547 else printz(" a b c d e f g h"); 548 if (reverse) gotoXY(5,23); else gotoXY(5,2); 549 if (computer == black) printz("Computer"); else printz("Human "); 550 if (reverse) gotoXY(5,2); else gotoXY(5,23); 551 if (computer == white) printz("Computer"); else printz("Human "); 552 for (l = 0; l < 64; l++) DrawPiece(l); 553 } 554 else 555 { 556 DrawPiece(f); DrawPiece(t); 557 if (iscastle) 558 if (t > f) 559 { DrawPiece(f+3); DrawPiece(t-1); } 560 else 561 { DrawPiece(f-4); DrawPiece(t+1); } 562 } 563 refresh(); 564 } 565 566 567 GetOpenings() 568 569 /* 570 Read in the Opening Book file and parse the algebraic notation for a 571 move into an unsigned integer format indicating the from and to 572 square. Create a linked list of opening lines of play, with 573 entry->next pointing to the next line and entry->move pointing to a 574 chunk of memory containing the moves. More Opening lines of up to 256 575 half moves may be added to gnuchess.book. 576 */ 577 578 { 579 FILE *fd; 580 int c,i,j,side; 581 struct BookEntry *entry; 582 unsigned short mv,*mp,tmp[100]; 583 584 if ((fd = fopen(_PATH_CHESSBOOK,"r")) != NULL) 585 { 586 Book = NULL; 587 i = 0; side = white; 588 while ((c = parse(fd,&mv,side)) >= 0) 589 if (c == 1) 590 { 591 tmp[++i] = mv; 592 side = otherside[side]; 593 } 594 else if (c == 0 && i > 0) 595 { 596 entry = (struct BookEntry *)malloc(sizeof(struct BookEntry)); 597 mp = (unsigned short *)malloc((i+1)*sizeof(unsigned short)); 598 entry->mv = mp; 599 entry->next = Book; 600 Book = entry; 601 for (j = 1; j <= i; j++) *(mp++) = tmp[j]; 602 *mp = 0; 603 i = 0; side = white; 604 } 605 fclose(fd); 606 } 607 else 608 { 609 fprintf(stderr, "\nchess: can't read %s.\n", _PATH_CHESSBOOK); 610 exit(1); 611 } 612 } 613 614 615 int parse(fd,mv,side) 616 FILE *fd; 617 unsigned short *mv; 618 short side; 619 { 620 int c,i,r1,r2,c1,c2; 621 char s[100]; 622 while ((c = getc(fd)) == ' '); 623 i = 0; s[0] = c; 624 while (c != ' ' && c != '\n' && c != EOF) s[++i] = c = getc(fd); 625 s[++i] = '\0'; 626 if (c == EOF) return(-1); 627 if (s[0] == '!' || i < 3) 628 { 629 while (c != '\n' && c != EOF) c = getc(fd); 630 return(0); 631 } 632 if (s[4] == 'o') 633 if (side == black) *mv = 0x3C3A; else *mv = 0x0402; 634 else if (s[0] == 'o') 635 if (side == black) *mv = 0x3C3E; else *mv = 0x0406; 636 else 637 { 638 c1 = s[0] - 'a'; r1 = s[1] - '1'; 639 c2 = s[2] - 'a'; r2 = s[3] - '1'; 640 *mv = (locn[r1][c1]<<8) + locn[r2][c2]; 641 } 642 return(1); 643 } 644 645 646 GetGame() 647 { 648 FILE *fd; 649 char fname[40]; 650 int c; 651 short sq; 652 unsigned short m; 653 654 ShowMessage("File name: "); 655 scanz("%s",fname); 656 if (fname[0] == '\0') strcpy(fname,"chess.000"); 657 if ((fd = fopen(fname,"r")) != NULL) 658 { 659 fscanf(fd,"%hd%hd%hd",&computer,&opponent,&Game50); 660 fscanf(fd,"%hd%hd%hd%hd", 661 &castld[white],&castld[black], 662 &kingmoved[white],&kingmoved[black]); 663 fscanf(fd,"%hd%hd",&TCflag,&OperatorTime); 664 fscanf(fd,"%ld%ld%hd%hd", 665 &TimeControl.clock[white],&TimeControl.clock[black], 666 &TimeControl.moves[white],&TimeControl.moves[black]); 667 for (sq = 0; sq < 64; sq++) 668 { 669 fscanf(fd,"%hd",&m); 670 board[sq] = (m >> 8); color[sq] = (m & 0xFF); 671 if (color[sq] == 0) color[sq] = neutral; else --color[sq]; 672 } 673 GameCnt = -1; c = '?'; 674 while (c != EOF) 675 { 676 ++GameCnt; 677 c = fscanf(fd,"%hd%hd%hd%ld%hd%hd%hd",&GameList[GameCnt].gmove, 678 &GameList[GameCnt].score,&GameList[GameCnt].depth, 679 &GameList[GameCnt].nodes,&GameList[GameCnt].time, 680 &GameList[GameCnt].piece,&GameList[GameCnt].color); 681 if (GameList[GameCnt].color == 0) GameList[GameCnt].color = neutral; 682 else --GameList[GameCnt].color; 683 } 684 GameCnt--; 685 if (TimeControl.clock[white] > 0) TCflag = true; 686 computer--; opponent--; 687 } 688 fclose(fd); 689 InitializeStats(); 690 UpdateDisplay(0,0,1,0); 691 Sdepth = 0; 692 } 693 694 695 SaveGame() 696 { 697 FILE *fd; 698 char fname[40]; 699 short sq,i,c; 700 701 ShowMessage("File name: "); 702 scanz("%s",fname); 703 704 if (fname[0] == '\0' || access(fname,W_OK) == -1) strcpy(fname,"chess.000"); 705 fd = fopen(fname,"w"); 706 fprintf(fd,"%d %d %d\n",computer+1,opponent+1,Game50); 707 fprintf(fd,"%d %d %d %d\n", 708 castld[white],castld[black],kingmoved[white],kingmoved[black]); 709 fprintf(fd,"%d %d\n",TCflag,OperatorTime); 710 fprintf(fd,"%ld %ld %d %d\n", 711 TimeControl.clock[white],TimeControl.clock[black], 712 TimeControl.moves[white],TimeControl.moves[black]); 713 for (sq = 0; sq < 64; sq++) 714 { 715 if (color[sq] == neutral) c = 0; else c = color[sq]+1; 716 fprintf(fd,"%d\n",256*board[sq] + c); 717 } 718 for (i = 0; i <= GameCnt; i++) 719 { 720 if (GameList[i].color == neutral) c = 0; 721 else c = GameList[i].color + 1; 722 fprintf(fd,"%d %d %d %ld %d %d %d\n", 723 GameList[i].gmove,GameList[i].score,GameList[i].depth, 724 GameList[i].nodes,GameList[i].time, 725 GameList[i].piece,c); 726 } 727 fclose(fd); 728 } 729 730 731 ListGame() 732 { 733 FILE *fd; 734 short i,f,t; 735 fd = fopen("chess.lst","w"); 736 fprintf(fd,"\n"); 737 fprintf(fd," score depth nodes time "); 738 fprintf(fd," score depth nodes time\n"); 739 for (i = 0; i <= GameCnt; i++) 740 { 741 f = GameList[i].gmove>>8; t = (GameList[i].gmove & 0xFF); 742 algbr(f,t,false); 743 if ((i % 2) == 0) fprintf(fd,"\n"); else fprintf(fd," "); 744 fprintf(fd,"%5s %5d %2d %6ld %5d",mvstr1, 745 GameList[i].score,GameList[i].depth, 746 GameList[i].nodes,GameList[i].time); 747 } 748 fprintf(fd,"\n\n"); 749 fclose(fd); 750 } 751 752 753 Undo() 754 755 /* 756 Undo the most recent half-move. 757 */ 758 759 { 760 short f,t; 761 f = GameList[GameCnt].gmove>>8; 762 t = GameList[GameCnt].gmove & 0xFF; 763 if (board[t] == king && distance(t,f) > 1) 764 castle(GameList[GameCnt].color,f,t,2); 765 else 766 { 767 board[f] = board[t]; color[f] = color[t]; 768 board[t] = GameList[GameCnt].piece; 769 color[t] = GameList[GameCnt].color; 770 if (board[f] == king) --kingmoved[color[f]]; 771 } 772 if (TCflag) ++TimeControl.moves[color[f]]; 773 GameCnt--; mate = false; Sdepth = 0; 774 UpdateDisplay(0,0,1,0); 775 InitializeStats(); 776 } 777 778 779 ShowMessage(s) 780 char *s; 781 { 782 gotoXY(50,24); printz("%s",s); ClrEoln(); 783 } 784 785 ClearMessage() 786 { 787 gotoXY(50,24); ClrEoln(); 788 } 789 790 ShowSidetomove() 791 { 792 gotoXY(50,14); 793 if (player == white) printz("%2d: WHITE",1+(GameCnt+1)/2); 794 else printz("%2d: BLACK",1+(GameCnt+1)/2); 795 ClrEoln(); 796 } 797 798 PromptForMove() 799 { 800 gotoXY(50,19); printz("Your move is? "); ClrEoln(); 801 } 802 803 ShowCurrentMove(pnt,f,t) 804 short pnt,f,t; 805 { 806 algbr(f,t,false); 807 gotoXY(50,7); printz("(%2d) %4s",pnt,mvstr1); 808 } 809 810 ChangeAlphaWindow() 811 { 812 ShowMessage("window: "); 813 scanz("%hd",&Awindow); 814 } 815 816 ChangeBetaWindow() 817 { 818 ShowMessage("window: "); 819 scanz("%hd",&Bwindow); 820 } 821 822 GiveHint() 823 { 824 char s[40]; 825 algbr((short)(hint>>8),(short)(hint & 0xFF),false); 826 strcpy(s,"try "); 827 strcat(s,mvstr1); 828 ShowMessage(s); 829 } 830 831 ChangeSearchDepth() 832 { 833 ShowMessage("depth= "); 834 scanz("%hd",&MaxSearchDepth); 835 } 836 837 SetContempt() 838 { 839 ShowMessage("contempt= "); 840 scanz("%hd",&contempt); 841 } 842 843 ChangeXwindow() 844 { 845 ShowMessage("xwndw= "); 846 scanz("%hd",&xwndw); 847 } 848 849 850 SelectLevel() 851 { 852 ClrScreen(); 853 gotoXY(32,2); printz("CHESS"); 854 gotoXY(20,4); printz(" 1. 60 moves in 5 minutes"); 855 gotoXY(20,5); printz(" 2. 60 moves in 15 minutes"); 856 gotoXY(20,6); printz(" 3. 60 moves in 30 minutes"); 857 gotoXY(20,7); printz(" 4. 40 moves in 30 minutes"); 858 gotoXY(20,8); printz(" 5. 40 moves in 60 minutes"); 859 gotoXY(20,9); printz(" 6. 40 moves in 120 minutes"); 860 gotoXY(20,10); printz(" 7. 40 moves in 240 minutes"); 861 gotoXY(20,11); printz(" 8. 1 move in 15 minutes"); 862 gotoXY(20,12); printz(" 9. 1 move in 60 minutes"); 863 gotoXY(20,13); printz("10. 1 move in 600 minutes"); 864 865 OperatorTime = 0; TCmoves = 60; TCminutes = 5; 866 867 gotoXY(20,17); printz("Enter Level: "); 868 refresh(); 869 scanz("%ld",&Level); 870 switch (Level) 871 { 872 case 1 : TCmoves = 60; TCminutes = 5; break; 873 case 2 : TCmoves = 60; TCminutes = 15; break; 874 case 3 : TCmoves = 60; TCminutes = 30; break; 875 case 4 : TCmoves = 40; TCminutes = 30; break; 876 case 5 : TCmoves = 40; TCminutes = 60; break; 877 case 6 : TCmoves = 40; TCminutes = 120; break; 878 case 7 : TCmoves = 40; TCminutes = 240; break; 879 case 8 : TCmoves = 1; TCminutes = 15; break; 880 case 9 : TCmoves = 1; TCminutes = 60; break; 881 case 10 : TCmoves = 1; TCminutes = 600; break; 882 } 883 884 TCflag = (TCmoves > 1); 885 SetTimeControl(); 886 ClrScreen(); 887 UpdateDisplay(0,0,1,0); 888 } 889 890 891 ShowPostnValues() 892 { 893 short i,r,c; 894 ExaminePosition(); 895 for (i = 0; i < 64; i++) 896 { 897 if (reverse) r = 7-row[i]; else r = row[i]; 898 if (reverse) c = 7-column[i]; else c = column[i]; 899 gotoXY(4+5*c,5+2*(7-r)); 900 c1 = color[i]; c2 = otherside[c1]; 901 PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2]; 902 atk1 = atak[c1]; atk2 = atak[c2]; 903 if (color[i] == neutral) printz(" "); 904 else printz("%3d ",SqValue(i,opponent)); 905 } 906 ScorePosition(opponent,&i); 907 gotoXY(50,24); 908 printz("Score= %d",i); ClrEoln(); 909 } 910 911 912 DoDebug() 913 { 914 short k,p,i,r,c,tp,tc; 915 char s[40]; 916 ExaminePosition(); 917 ShowMessage("Enter piece: "); 918 scanz("%s",s); 919 if (s[0] == 'w') k = white; else k = black; 920 if (s[1] == 'p') p = pawn; 921 else if (s[1] == 'n') p = knight; 922 else if (s[1] == 'b') p = bishop; 923 else if (s[1] == 'r') p = rook; 924 else if (s[1] == 'q') p = queen; 925 else if (s[1] == 'k') p = king; 926 else p = no_piece; 927 for (i = 0; i < 64; i++) 928 { 929 if (reverse) r = 7-row[i]; else r = row[i]; 930 if (reverse) c = 7-column[i]; else c = column[i]; 931 gotoXY(4+5*c,5+2*(7-r)); 932 tp = board[i]; tc = color[i]; 933 board[i] = p; color[i] = k; 934 c1 = k; c2 = otherside[c1]; 935 PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2]; 936 atk1 = atak[c1]; atk2 = atak[c2]; 937 printz("%3d ",SqValue(i,opponent)); 938 board[i] = tp; color[i] = tc; 939 } 940 ScorePosition(opponent,&i); 941 gotoXY(50,24); 942 printz("Score= %d",i); ClrEoln(); 943 } 944