sears@decwrl.dec.com (Chris Sears) (12/18/90)
Submitted-by: sears@decwrl.dec.com (Chris Sears) Posting-number: Volume 10, Issue 63 Archive-name: xboard/part03 X } X} X X/* X * MakeMove() executes moves after they have been checked by GNU Chess. X */ Xvoid XMakeMove(move_type, from_x, from_y, to_x, to_y) X int *move_type, from_x, from_y, to_x, to_y; X{ X if (gameMode != PlayFromGameFile) X DisplayTimers(SwitchTimers); X CopyBoard(boards[currentMove + 1], boards[currentMove]); X forwardMostMove = ++currentMove; X X if (from_y == 0 && from_x == 4 /* white king-side castle */ X && boards[currentMove][from_y][from_x] == WhiteKing X && to_y == 0 && to_x == 6) { X *move_type = WhiteKingSideCastle; X boards[currentMove][0][7] = EmptySquare; X boards[currentMove][0][6] = WhiteKing; X boards[currentMove][0][5] = WhiteRook; X boards[currentMove][0][4] = EmptySquare; X DrawSquare(0, 7, boards[currentMove][0][7]); X DrawSquare(0, 6, boards[currentMove][0][6]); X DrawSquare(0, 5, boards[currentMove][0][5]); X DrawSquare(0, 4, boards[currentMove][0][4]); X } else if (from_y == 0 && from_x == 4 /* white queen-side castle */ X && boards[currentMove][from_y][from_x] == WhiteKing X && to_y == 0 && to_x == 2) { X *move_type = WhiteQueenSideCastle; X boards[currentMove][0][0] = EmptySquare; X boards[currentMove][0][2] = WhiteKing; X boards[currentMove][0][3] = WhiteRook; X boards[currentMove][0][4] = EmptySquare; X DrawSquare(0, 0, boards[currentMove][0][0]); X DrawSquare(0, 2, boards[currentMove][0][2]); X DrawSquare(0, 3, boards[currentMove][0][3]); X DrawSquare(0, 4, boards[currentMove][0][4]); X } else if (from_y == 6 /* white pawn promotion */ X && boards[currentMove][from_y][from_x] == WhitePawn && to_y == 7) { X *move_type = WhitePromotion; X boards[currentMove][6][from_x] = EmptySquare; X boards[currentMove][7][to_x] = WhiteQueen; X DrawSquare(6, from_x, boards[currentMove][6][from_x]); X DrawSquare(7, to_x, boards[currentMove][7][to_x]); X } else if ((from_y == 4) /* white captures en passant */ X && (to_x != from_x) X && (boards[currentMove][from_y][from_x] == WhitePawn) X && (boards[currentMove][to_y][to_x] == EmptySquare)) { X *move_type = WhiteCapturesEnPassant; X boards[currentMove][from_y][from_x] = EmptySquare; X boards[currentMove][to_y][to_x] = WhitePawn; X boards[currentMove][to_y - 1][to_x] = EmptySquare; X DrawSquare(from_y, from_x, boards[currentMove][from_y][from_x]); X DrawSquare(to_y, to_x, boards[currentMove][to_y][to_x]); X DrawSquare(to_y - 1, to_x, boards[currentMove][to_y - 1][to_x]); X } else if (from_y == 7 && from_x == 4 /* black king-side castle */ X && boards[currentMove][from_y][from_x] == BlackKing X && to_y == 7 && to_x == 6) { X *move_type = BlackKingSideCastle; X boards[currentMove][7][4] = EmptySquare; X boards[currentMove][7][5] = BlackRook; X boards[currentMove][7][6] = BlackKing; X boards[currentMove][7][7] = EmptySquare; X DrawSquare(7, 7, boards[currentMove][7][7]); X DrawSquare(7, 6, boards[currentMove][7][6]); X DrawSquare(7, 5, boards[currentMove][7][5]); X DrawSquare(7, 4, boards[currentMove][7][4]); X } else if (from_y == 7 && from_x == 4 /* black queen-side castle */ X && boards[currentMove][from_y][from_x] == BlackKing X && to_y == 7 && to_x == 2) { X *move_type = BlackQueenSideCastle; X boards[currentMove][7][0] = EmptySquare; X boards[currentMove][7][2] = BlackKing; X boards[currentMove][7][3] = BlackRook; X boards[currentMove][7][4] = EmptySquare; X DrawSquare(7, 0, boards[currentMove][7][0]); X DrawSquare(7, 2, boards[currentMove][7][2]); X DrawSquare(7, 3, boards[currentMove][7][3]); X DrawSquare(7, 4, boards[currentMove][7][4]); X } else if (from_y == 1 /* black pawn promotion */ X && boards[currentMove][from_y][from_x] == BlackPawn && to_y == 0) { X *move_type = BlackPromotion; X boards[currentMove][1][from_x] = EmptySquare; X boards[currentMove][0][to_x] = BlackQueen; X DrawSquare(1, from_x, boards[currentMove][1][from_x]); X DrawSquare(0, to_x, boards[currentMove][0][to_x]); X } else if ((from_y == 3) /* black captures en passant */ X && (to_x != from_x) X && (boards[currentMove][from_y][from_x] == BlackPawn) X && (boards[currentMove][to_y][to_x] == EmptySquare)) { X *move_type = BlackCapturesEnPassant; X boards[currentMove][from_y][from_x] = EmptySquare; X boards[currentMove][to_y][to_x] = BlackPawn; X boards[currentMove][to_y + 1][to_x] = EmptySquare; X DrawSquare(from_y, from_x, boards[currentMove][from_y][from_x]); X DrawSquare(to_y, to_x, boards[currentMove][to_y][to_x]); X DrawSquare(to_y + 1, to_x, boards[currentMove][to_y + 1][to_x]); X } else { X *move_type = NormalMove; X boards[currentMove][to_y][to_x] = boards[currentMove][from_y][from_x]; X boards[currentMove][from_y][from_x] = EmptySquare; X DrawSquare(to_y, to_x, boards[currentMove][to_y][to_x]); X DrawSquare(from_y, from_x, boards[currentMove][from_y][from_x]); X } X X XSync(xDisplay, False); X} X Xvoid XInitPosition() X{ X currentMove = forwardMostMove = 0; X CopyBoard(boards[0], initialPosition); X DrawPosition(boardWidget, NULL); X} X Xvoid XCopyBoard(to, from) X Board to, from; X{ X int i, j; X X for (i = 0; i < BOARD_SIZE; i++) X for (j = 0; j < BOARD_SIZE; j++) X to[i][j] = from[i][j]; X} X X/* X * event handler for updating board state X */ Xvoid XDrawPosition(w, event) X Widget w; X XExposeEvent *event; X{ X int i, j; X X /* X * It would be simpler to clear the window or fill a rectangle, X * but that causes a very distracting flicker. X */ X XDrawSegments(xDisplay, xBoardWindow, lineGC, X gridSegments, (BOARD_SIZE + 1) * 2); X X for (i = 0; i < BOARD_SIZE; i++) X for (j = 0; j < BOARD_SIZE; j++) X DrawSquare(i, j, boards[currentMove][i][j]); X X XSync(xDisplay, False); X} X X/* X * event handler for parsing user moves X * TODO: ignore a ButtonRelease without a valid corresponding ButtonPress. X */ Xvoid XHandleUserMove(w, event) X Widget w; X XEvent *event; X{ X static int from_x, from_y; X int move_type, to_x, to_y; X char user_move[MSG_SIZ]; X X if ((gameMode == PlayFromGameFile) || (gameMode == PauseGame)) X return; X X DisplayMessage(""); X X switch (event->type) { X case ButtonPress: X if ((from_x = EventToOrdinal(event->xbutton.x)) < 0) X break; X if ((from_y = EventToOrdinal(event->xbutton.y)) < 0) X break; X if (flipView) X from_x = BOARD_SIZE - 1 - from_x; X else X from_y = BOARD_SIZE - 1 - from_y; X break; X case ButtonRelease: X if ((to_x = EventToOrdinal(event->xbutton.x)) < 0) X break; X if ((to_y = EventToOrdinal(event->xbutton.y)) < 0) X break; X if (flipView) X to_x = BOARD_SIZE - 1 - to_x; X else X to_y = BOARD_SIZE - 1 - to_y; X X MakeMove(&move_type, from_x, from_y, to_x, to_y); X X switch (move_type) { X case WhitePromotion: X case BlackPromotion: /* GNU Chess limitation of only Q promotion */ X sprintf(user_move, "%c%c%c%c(Q)\n", /* GNU Chess limitation */ X 'a' + from_x, '1' + from_y, 'a' + to_x, '1' + to_y); X break; X case NormalMove: X case WhiteKingSideCastle: X case WhiteQueenSideCastle: X case WhiteCapturesEnPassant: X case BlackKingSideCastle: X case BlackQueenSideCastle: X case BlackCapturesEnPassant: X sprintf(user_move, "%c%c%c%c\n", X 'a' + from_x, '1' + from_y, 'a' + to_x, '1' + to_y); X break; X } X X SendToProgram(user_move, toFirstProgFP); X strcpy(moveList[currentMove - 1], user_move); X X switch (gameMode) { X case ForceMoves: X forwardForce = False; X break; X case PlayFromGameFile: X SendToProgram("black\n", toFirstProgFP); X case BeginningOfGame: X case SetupPosition: X gameMode = MachinePlaysBlack; X default: X break; X } X break; X } X} X Xvoid XHandleMachineMove(message) X char *message; X{ X int i, j, move_type, from_x, from_y, to_x, to_y; X char machine_move[MSG_SIZ], tmp_move[MSG_SIZ], buf1[MSG_SIZ], buf2[MSG_SIZ]; X X /* X * If the move is illegal, cancel it and redraw the board. X */ X if (strstr(message, "Illegal move") != NULL) { X if (gameMode == PlayFromGameFile) X gameMode = BeginningOfGame; X else { X currentMove--; X DisplayTimers(SwitchTimers); X } X DisplayMessage(message); X X for (i = 0; i < BOARD_SIZE; i++) X for (j = 0; j < BOARD_SIZE; j++) X if (boards[currentMove][i][j] != boards[currentMove + 1][i][j]) X DrawSquare(i, j, boards[currentMove][i][j]); X X XSync(xDisplay, False); X return; X } X X if (strstr(message, "Hint:") != NULL) { X DisplayMessage(message); X return; X } X X /* X * win, lose or draw X */ X if (strstr(message, "White") != NULL) X EndOfGameProc("White wins"); X else if (strstr(message, "Black") != NULL) X EndOfGameProc("Black wins"); X else if (strstr(message, "Draw") != NULL) X EndOfGameProc("Draw"); X X /* X * normal move X */ X if (strstr(message, "...") != NULL) { X bzero(machine_move, MSG_SIZ); X sscanf(message, "%s %s %s", buf1, buf2, machine_move); X if (strlen(machine_move) == 0) X return; X } else X return; /* ignore noise */ X X strcpy(moveList[currentMove], machine_move); X X from_x = machine_move[0] - 'a'; X from_y = machine_move[1] - '1'; X to_x = machine_move[2] - 'a'; X to_y = machine_move[3] - '1'; X X MakeMove(&move_type, from_x, from_y, to_x, to_y); X X switch (gameMode) { X case EndOfGame: X case SetupPosition: X break; X case ForceMoves: X case PlayFromGameFile: X strcpy(tmp_move, machine_move); X strcat(tmp_move, "\n"); X SendToProgram(tmp_move, toFirstProgFP); X break; X case TwoMachinesPlay: X strcpy(tmp_move, machine_move); X strcat(tmp_move, "\n"); X X if (currentMove % 2) X SendToProgram(tmp_move, toFirstProgFP); X else X SendToProgram(tmp_move, toSecondProgFP); X X /* X * need white's move before sending "black" to first program X */ X if (firstMove) { X firstMove = False; X SendToProgram("black\n", toFirstProgFP); X } X break; X } X} X XXtCallbackProc XSelectCommand(w, client_data, call_data) X Widget w; X XtPointer client_data; X XtPointer call_data; X{ X XawListReturnStruct *list_return; X X list_return = XawListShowCurrent(w); X X switch (list_return->list_index) { X case ButtonQuit: X EndOfGameProc("Quitting"); X QuitProc(); X break; X case ButtonBackward: X BackwardProc(); X break; X case ButtonForward: X ForwardProc(); X break; X case ButtonFlip: X FlipProc(); X break; X case ButtonReset: X ResetProc(); X break; X case ButtonSaveGame: X SaveGameProc(); X break; X case ButtonSavePosition: X SavePositionProc(); X break; X case ButtonHint: X HintProc(); X break; X case ButtonSwitch: X SwitchProc(); X break; X case ButtonSetupFromFile: X SetupPositionFromFileProc(); X break; X case ButtonPlayFromFile: X PlayFromGameFileProc(); X break; X case ButtonMachinePlaysBlack: X MachinePlaysBlackProc(); X break; X case ButtonMachinePlaysWhite: X MachinePlaysWhiteProc(); X break; X case ButtonTwoMachinesPlay: X TwoMachinesPlayProc(); X break; X case ButtonForce: X ForceProc(); X break; X case ButtonPause: X PauseProc(); X break; X } X X XawListUnhighlight(w); X} X Xvoid XEndOfGameProc(message) X char *message; X{ X DisplayMessage(message); X X if (firstProgPID != 0) { X fclose(fromFirstProgFP); X fclose(toFirstProgFP); X fromFirstProgFP = toFirstProgFP = NULL; X kill(firstProgPID, SIGTERM); X } X if (secondProgPID != 0) { X fclose(fromSecondProgFP); X fclose(toSecondProgFP); X fromSecondProgFP = toSecondProgFP = NULL; X kill(secondProgPID, SIGTERM); X } X if (firstProgXID != 0) X XtRemoveInput(firstProgXID); X if (secondProgXID != 0) X XtRemoveInput(secondProgXID); X firstProgXID = secondProgXID = NULL; X X if (appData.matchMode != MatchFalse) { X SaveGameProc(); X SavePositionProc(); X QuitProc(); X } else X DisplayTimers(StopTimers); X} X Xvoid XQuitProc() X{ X XFreePixmap(xDisplay, solidRookBitmap); X XFreePixmap(xDisplay, solidKnightBitmap); X XFreePixmap(xDisplay, solidBishopBitmap); X XFreePixmap(xDisplay, solidQueenBitmap); X XFreePixmap(xDisplay, solidKingBitmap); X XFreePixmap(xDisplay, solidPawnBitmap); X X XFreeGC(xDisplay, lightSquareGC); X XFreeGC(xDisplay, darkSquareGC); X XFreeGC(xDisplay, lineGC); X X if (appData.monoMode) { X XFreePixmap(xDisplay, outlinePawnBitmap); X XFreePixmap(xDisplay, outlineRookBitmap); X XFreePixmap(xDisplay, outlineKnightBitmap); X XFreePixmap(xDisplay, outlineBishopBitmap); X XFreePixmap(xDisplay, outlineQueenBitmap); X XFreePixmap(xDisplay, outlineKingBitmap); X X XFreeGC(xDisplay, wbPieceGC); X XFreeGC(xDisplay, wwPieceGC); X XFreeGC(xDisplay, bbPieceGC); X XFreeGC(xDisplay, bwPieceGC); X } else { X XFreeGC(xDisplay, wdPieceGC); X XFreeGC(xDisplay, wlPieceGC); X XFreeGC(xDisplay, bdPieceGC); X XFreeGC(xDisplay, blPieceGC); X } X X XtDestroyApplicationContext(XtWidgetToApplicationContext(shellWidget)); X exit(0); X} X Xvoid XBackwardProc() X{ X int i, j; X X if ((gameMode == PlayFromGameFile) || (currentMove <= 0)) X return; X X SendToProgram("undo\n", toFirstProgFP); X currentMove--; X X for (i = 0; i < BOARD_SIZE; i++) X for (j = 0; j < BOARD_SIZE; j++) X if (boards[currentMove][i][j] != boards[currentMove + 1][i][j]) X DrawSquare(i, j, boards[currentMove][i][j]); X} X Xvoid XForwardProc() X{ X char buf[MSG_SIZ]; X int i, j; X X if ((gameMode == PlayFromGameFile) X || ((currentMove == 0) && (forwardMostMove == 0)) X || (currentMove >= forwardMostMove)) X return; X X if (forwardForce == False) { X forwardForce = True; X SendToProgram("force\n", toFirstProgFP); X } X X if (currentMove <= forwardMostMove) X for (i = 0; i < BOARD_SIZE; i++) X for (j = 0; j < BOARD_SIZE; j++) X if (boards[currentMove + 1][i][j] != boards[currentMove][i][j]) X DrawSquare(i, j, boards[currentMove + 1][i][j]); X X strcpy(moveList[currentMove++], buf); X strcat(buf, "\n"); X SendToProgram(buf, toFirstProgFP); X} X Xvoid XFlipProc() X{ X flipView = !flipView; X DrawPosition(boardWidget, NULL); X} X Xvoid XResetProc() X{ X gameMode = BeginningOfGame; X flipView = forwardForce = False; X wCount = bCount = currentMove = forwardMostMove = 0; X firstMove = True; X X EndOfGameProc("Resetting"); X InitPosition(); X InitChessProgram(); X DisplayMessage(""); X DisplayTimers(ResetTimers); X if (readGameXID != NULL) { X XtRemoveTimeOut(readGameXID); X readGameXID = NULL; X } X X /* X * Initialize GNU Chess. X * "beep" prevents GNU Chess from sending a ^G. X * X * ResetProc() only resets toFirstProgFP X * since toSecondProgFP is reset in TwoMachinesProc() X */ X SendToProgram(appData.initString, toFirstProgFP); X} X Xvoid XSaveGameProc() X{ X time_t tm; X int i = 0, move = 1; X char buf[MSG_SIZ], host_name[MSG_SIZ], X white_move[MSG_SIZ], black_move[MSG_SIZ]; X FILE *game_file_fp; X X if (!(game_file_fp = fopen(appData.saveGameFile, "w"))) { X sprintf(buf, "Can't open %s", appData.saveGameFile); X DisplayMessage(buf); X return; X } X X tm = time((time_t *) NULL); X gethostname(host_name, MSG_SIZ); X X fprintf(game_file_fp, "xboard game file -- %s", ctime(&tm)); X switch (gameMode) { X case MachinePlaysWhite: X fprintf(game_file_fp, "\t%s@%s vs. %s@%s\n", X appData.firstChessProgram, appData.firstHost, X getlogin(), host_name); X break; X case MachinePlaysBlack: X fprintf(game_file_fp, "\t%s@%s vs. %s@%s\n", X getlogin(), host_name, X appData.firstChessProgram, appData.firstHost); X break; X case TwoMachinesPlay: X fprintf(game_file_fp, "\t%s@%s vs. %s@%s\n", X appData.secondChessProgram, appData.secondHost, X appData.firstChessProgram, appData.firstHost); X break; X default: X fprintf(game_file_fp, "\n"); X break; X } X fprintf(game_file_fp, "\talgebraic\n"); X X while (True) { X if (strlen(moveList[i]) == 0) X break; X /* X * get rid of '\n' added to send the move to GNU Chess X */ X strcpy(white_move, moveList[i++]); X if (white_move[strlen(white_move) - 1] == '\n') X white_move[strlen(white_move) - 1] = NULL; X fprintf(game_file_fp, "%d. %s ", move++, white_move); X X if (strlen(moveList[i]) == 0) { X fprintf(game_file_fp, "\n"); X break; X } X strcpy(black_move, moveList[i++]); X if (black_move[strlen(black_move) - 1] == '\n') X black_move[strlen(black_move) - 1] = NULL; X fprintf(game_file_fp, "%s\n", black_move); X } X fclose(game_file_fp); X} X Xvoid XSavePositionProc() X{ X time_t tm; X int i, j; X char buf[MSG_SIZ], host_name[MSG_SIZ]; X FILE *position_file_fp; X X if (!(position_file_fp = fopen(appData.savePositionFile, "w"))) { X sprintf(buf, "Can't open %s", appData.savePositionFile); X DisplayMessage(buf); X return; X } X X tm = time((time_t *) NULL); X gethostname(host_name, MSG_SIZ); X X fprintf(position_file_fp, "xboard position file -- %s", ctime(&tm)); X switch (gameMode) { X case MachinePlaysWhite: X fprintf(position_file_fp, "\t%s@%s vs. %s@%s\n", X appData.firstChessProgram, appData.firstHost, X getlogin(), host_name); X break; X case MachinePlaysBlack: X fprintf(position_file_fp, "\t%s@%s vs. %s@%s\n", X getlogin(), host_name, X appData.firstChessProgram, appData.firstHost); X break; X case TwoMachinesPlay: X fprintf(position_file_fp, "\t%s@%s vs. %s@%s\n", X appData.secondChessProgram, appData.secondHost, X appData.firstChessProgram, appData.firstHost); X break; X default: X fprintf(position_file_fp, "\n"); X break; X } X fprintf(position_file_fp, "\n"); X X for (i = BOARD_SIZE - 1; i >= 0; i--) { X for (j = 0; j < BOARD_SIZE; j++) { X fprintf(position_file_fp, "%s", X pieceToString[boards[currentMove][i][j]]); X if (j == BOARD_SIZE - 1) X fprintf(position_file_fp, "\n"); X else X fprintf(position_file_fp, " "); X } X } X X fclose(position_file_fp); X} X Xvoid XHintProc() X{ X if (gameMode == PlayFromGameFile) X return; X SendToProgram("hint\n", toFirstProgFP); X} X Xvoid XSwitchProc() X{ X switch (gameMode) { X default: X return; X case MachinePlaysWhite: X gameMode = MachinePlaysBlack; X break; X case MachinePlaysBlack: X gameMode = MachinePlaysWhite; X break; X } X X SendToProgram("switch\n", toFirstProgFP); X} X Xvoid XSetupPositionFromFileProc() X{ X int i, j; X char c, *p, line[MSG_SIZ], buf[MSG_SIZ]; X Board initial_position; X FILE *position_file_fp; X X if (gameMode == PlayFromGameFile) X return; X X gameMode = SetupPosition; X currentMove = forwardMostMove = 0; X X if (!(position_file_fp = fopen(appData.readPositionFile, "r"))) { X sprintf(buf, "Can't open %s", appData.readPositionFile); X DisplayMessage(buf); X return; X } X X /* X * skip header information in position file X */ X fgets(line, MSG_SIZ, position_file_fp); X fgets(line, MSG_SIZ, position_file_fp); X fgets(line, MSG_SIZ, position_file_fp); X X for (i = BOARD_SIZE - 1; i >= 0; i--) { X fgets(line, MSG_SIZ, position_file_fp); X p = line; X for (j = 0; j < BOARD_SIZE; p++) { X if ((c = *p) == ' ') X continue; X switch (c) { X case 'p': X sprintf(blackPieces[bCount++], X "P%c%c", 'a' + j, '1' + i); X initial_position[i][j] = BlackPawn; X break; X case 'r': X sprintf(blackPieces[bCount++], X "R%c%c", 'a' + j, '1' + i); X initial_position[i][j] = BlackRook; X break; X case 'n': X sprintf(blackPieces[bCount++], X "N%c%c", 'a' + j, '1' + i); X initial_position[i][j] = BlackKnight; X break; X case 'b': X sprintf(blackPieces[bCount++], X "B%c%c", 'a' + j, '1' + i); X initial_position[i][j] = BlackBishop; X break; X case 'q': X sprintf(blackPieces[bCount++], X "Q%c%c", 'a' + j, '1' + i); X initial_position[i][j] = BlackQueen; X break; X case 'k': X sprintf(blackPieces[bCount++], X "K%c%c", 'a' + j, '1' + i); X initial_position[i][j] = BlackKing; X break; X case 'P': X sprintf(whitePieces[wCount++], X "P%c%c", 'a' + j, '1' + i); X initial_position[i][j] = WhitePawn; X break; X case 'R': X sprintf(whitePieces[wCount++], X "R%c%c", 'a' + j, '1' + i); X initial_position[i][j] = WhiteRook; X break; X case 'N': X sprintf(whitePieces[wCount++], X "N%c%c", 'a' + j, '1' + i); X initial_position[i][j] = WhiteKnight; X break; X case 'B': X sprintf(whitePieces[wCount++], X "B%c%c", 'a' + j, '1' + i); X initial_position[i][j] = WhiteBishop; X break; X case 'Q': X sprintf(whitePieces[wCount++], X "Q%c%c", 'a' + j, '1' + i); X initial_position[i][j] = WhiteQueen; X break; X case 'K': X sprintf(whitePieces[wCount++], X "K%c%c", 'a' + j, '1' + i); X initial_position[i][j] = WhiteKing; X break; X case '.': X initial_position[i][j] = EmptySquare; X break; X } X X j++; X } X } X X SendPosition(toFirstProgFP); X CopyBoard(boards[0], initial_position); X DrawPosition(boardWidget, NULL); X fclose(position_file_fp); X} X Xvoid XSendPosition(fp) X FILE *fp; X{ X int i; X char message[MSG_SIZ]; X X DisplayTimers(StopTimers); X SendToProgram("edit\n", fp); X X SendToProgram("#\n", fp); X for (i = 0; i < wCount; i++) { X sprintf(message, "%s\n", whitePieces[i]); X SendToProgram(message, fp); X bzero(message, MSG_SIZ); X } X X SendToProgram("c\n", fp); X for (i = 0; i < bCount; i++) { X sprintf(message, "%s\n", blackPieces[i]); X SendToProgram(message, fp); X bzero(message, MSG_SIZ); X } X X SendToProgram(".\n", fp); X} X Xvoid XPlayFromGameFileProc() X{ X char buf[MSG_SIZ]; X FILE *game_file_fp; X X gameMode = PlayFromGameFile; X InitPosition(); X DisplayTimers(StopTimers); X SendToProgram(appData.initString, toFirstProgFP); X SendToProgram("force\n", toFirstProgFP); X X if (!(game_file_fp = fopen(appData.readGameFile, "r"))) { X sprintf(buf, "Can't open %s", appData.readGameFile); X DisplayMessage(buf); X return; X } X X /* X * skip header information in game record file X */ X fgets(buf, MSG_SIZ, game_file_fp); X fgets(buf, MSG_SIZ, game_file_fp); X fgets(buf, MSG_SIZ, game_file_fp); X X ReadGameFile(game_file_fp); X} X XXtTimerCallbackProc XReadGameFile(fp) X FILE *fp; X{ X int i, move_type, from_x, from_y, to_x, to_y; X static char move_number[MSG_SIZ], white_move[MSG_SIZ], black_move[MSG_SIZ]; X char move[MSG_SIZ]; X X if (gameMode == PauseGame) { X readGameXID = XtAddTimeOut((int) (1000 * appData.timeDelay), X ReadGameFile, fp); X return; X } X X if (gameMode == BeginningOfGame) { X fclose(fp); X return; X } X X if (currentMove % 2 == 0) { Xnext_line: X if (fgets(move, sizeof(move), fp) == (char *) EOF) { Xend_parse: X if (readGameXID != NULL) { X XtRemoveTimeOut(readGameXID); X readGameXID = NULL; X } X fclose(fp); X DisplayTimers(StopTimers); X gameMode = BeginningOfGame; X return; X } X X if ((move[0] == '%') || (move[0] == '!')) X goto next_line; X X move_number[0] = white_move[0] = black_move[0] = NULL; X X if (sscanf(move, "%s %s %s", move_number, X white_move, black_move) == EOF) X goto end_parse; X X if (strlen(white_move) == 0) { X if (strlen(move_number) != 0) X strcpy(white_move, move_number); X else { X DisplayMessage("End of Game"); X goto end_parse; X } X } X X if ((strcmp(white_move, "draw") == 0) X || (strcmp(white_move, "Draw") == 0) X || (strcmp(white_move, "DRAW") == 0) X || (strcmp(white_move, "Resign") == 0) X || (strcmp(white_move, "resign") == 0) X || (strcmp(white_move, "RESIGN") == 0) X || (strcmp(white_move, "0-1") == 0) X || (strcmp(white_move, "1-0") == 0)) { X DisplayMessage(white_move); X goto end_parse; X } if (strcmp(white_move, "o-o-o") == 0) { X from_x = 4; X from_y = 0; X to_x = 2; X to_y = 0; X } else if (strcmp(white_move, "o-o") == 0) { X from_x = 4; X from_y = 0; X to_x = 6; X to_y = 0; X } else { X from_x = white_move[0] - 'a'; X from_y = white_move[1] - '1'; X to_x = white_move[2] - 'a'; X to_y = white_move[3] - '1'; X } X X sprintf(move, "%s %s", move_number, white_move); X DisplayMessage(move); X strcat(white_move, "\n"); X SendToProgram(white_move, toFirstProgFP); X MakeMove(&move_type, from_x, from_y, to_x, to_y); X strcpy(moveList[currentMove], white_move); X } else { X if (strlen(black_move) == 0) { X DisplayMessage("End of Game"); X goto end_parse; X } if ((strcmp(black_move, "draw") == 0) X || (strcmp(black_move, "Draw") == 0) X || (strcmp(black_move, "DRAW") == 0) X || (strcmp(black_move, "Resign") == 0) X || (strcmp(black_move, "resign") == 0) X || (strcmp(black_move, "RESIGN") == 0) X || (strcmp(black_move, "0-1") == 0) X || (strcmp(black_move, "1-0") == 0)) { X DisplayMessage(black_move); X goto end_parse; X } if (strcmp(black_move, "o-o-o") == 0) { X from_x = 4; X from_y = 7; X to_x = 2; X to_y = 7; X } else if (strcmp(black_move, "o-o") == 0) { X from_x = 4; X from_y = 7; X to_x = 6; X to_y = 7; X } else { X from_x = black_move[0] - 'a'; X from_y = black_move[1] - '1'; X to_x = black_move[2] - 'a'; X to_y = black_move[3] - '1'; X } X X sprintf(move, "%s ... %s", move_number, black_move); X DisplayMessage(move); X strcat(black_move, "\n"); X SendToProgram(black_move, toFirstProgFP); X MakeMove(&move_type, from_x, from_y, to_x, to_y); X strcpy(moveList[currentMove], black_move); X } X X readGameXID = XtAddTimeOut((int) (1000 * appData.timeDelay), X ReadGameFile, fp); X} X Xvoid XMachinePlaysBlackProc() X{ X if ((gameMode == PlayFromGameFile) || ((currentMove % 2) == 0)) X return; X X gameMode = MachinePlaysBlack; X DisplayTimers(SwitchTimers); X SendToProgram("black\n", toFirstProgFP); X} X Xvoid XMachinePlaysWhiteProc() X{ X if ((gameMode == PlayFromGameFile) || ((currentMove % 2) == 1)) X return; X X gameMode = MachinePlaysWhite; X DisplayTimers(SwitchTimers); X SendToProgram("white\n", toFirstProgFP); X} X Xvoid XTwoMachinesPlayProc() X{ X int i; X X switch (gameMode) { X case PlayFromGameFile: X case ForceMoves: X gameMode = TwoMachinesPlay; X InitChessProgram(); X SendToProgram(appData.initString, toSecondProgFP); X SendToProgram("force\n", toSecondProgFP); X for (i = 0; i <= currentMove; i++) X SendToProgram(moveList[i], toSecondProgFP); X SendToProgram("white\n", toSecondProgFP); X break; X case SetupPosition: X gameMode = TwoMachinesPlay; X InitChessProgram(); X SendToProgram(appData.initString, toSecondProgFP); X SendPosition(toSecondProgFP); X SendToProgram("white\n", toSecondProgFP); X firstMove = False; X break; X default: X gameMode = TwoMachinesPlay; X InitChessProgram(); X firstMove = False; X SendToProgram(appData.initString, toSecondProgFP); X SendToProgram("white\n", toSecondProgFP); X break; X } X} X Xvoid XForceProc() X{ X if (gameMode == PlayFromGameFile) X return; X X gameMode = ForceMoves; X DisplayTimers(StopTimers); X SendToProgram("force\n", toFirstProgFP); X} X Xvoid XPauseProc() X{ X static previous_mode = PauseGame; X X if (gameMode != PauseGame) { X previous_mode = gameMode; X gameMode = PauseGame; X } else { X gameMode = previous_mode; X previous_mode = PauseGame; X } X DisplayTimers(StopTimers); X} X Xvoid XInitChessProgram() X{ X int pid, to_prog[2], from_prog[2]; X char *host_name, *program_name, time_control[10], moves_per_session[10]; X FILE *from_fp, *to_fp; X X switch (gameMode) { X case TwoMachinesPlay: X host_name = appData.secondHost; X program_name = appData.secondChessProgram; X break; X default: X host_name = appData.firstHost; X program_name = appData.firstChessProgram; X break; X } X X signal(SIGPIPE, EndOfGameProc); X pipe(to_prog); X pipe(from_prog); X X if ((pid = fork()) == 0) { X signal(SIGPIPE, EndOfGameProc); X dup2(to_prog[0], 0); X dup2(from_prog[1], 1); X close(to_prog[0]); X close(to_prog[1]); X close(from_prog[0]); X close(from_prog[1]); X close(2); X open("/dev/null", O_WRONLY); X sprintf(time_control, "%d", appData.timeControl); X sprintf(moves_per_session, "%d", appData.movesPerSession); X if (strcmp(host_name, "localhost") == 0) X execlp(program_name, program_name, X moves_per_session, time_control, (char *) NULL); X else X execlp("/usr/ucb/rsh", "rsh", host_name, program_name, X moves_per_session, time_control, (char *) NULL); X perror(program_name); X exit(1); X } X X close(to_prog[0]); X close(from_prog[1]); X X from_fp = fdopen(from_prog[0], "r"); X setbuf(from_fp, NULL); X to_fp = fdopen(to_prog[1], "w"); X setbuf(to_fp, NULL); X X switch (gameMode) { X case TwoMachinesPlay: X secondProgPID = pid; X fromSecondProgFP = from_fp; X toSecondProgFP = to_fp; X secondProgXID = XtAddInput(fileno(fromSecondProgFP), XtInputReadMask, X ReceiveFromProgram, fromSecondProgFP); X break; X default: X firstProgPID = pid; X fromFirstProgFP = from_fp; X toFirstProgFP = to_fp; X firstProgXID = XtAddInput(fileno(fromFirstProgFP), XtInputReadMask, X ReceiveFromProgram, fromFirstProgFP); X break; X } X} X Xvoid XSendToProgram(message, fp) X char *message; X FILE *fp; X{ X if (appData.debugMode == True) X fprintf(stderr, "Sending %s\n", message); X fputs(message, fp); X} X Xvoid XReceiveFromProgram(fp) X FILE *fp; X{ X char message[MSG_SIZ]; X X if (fgets(message, MSG_SIZ, fp) == NULL) X return; X if (appData.debugMode == True) X fprintf(stderr, "Received %s\n", message); X HandleMachineMove(message); X} X Xvoid XDisplayMessage(message) X char *message; X{ X Arg arg; X X XtSetArg(arg, XtNlabel, message); X XtSetValues(messageWidget, &arg, 1); X} X X/* X * DisplayTimers manages the game clocks. X * X * In tournament play, black starts the clock and then white makes a move. X * DisplayTimers starts black's clock when white makes the first move. X * Also, DisplayTimers doesn't account for network lag so it could get X * out of sync with GNU Chess's clock -- but then, referees are always right. X */ XXtTimerCallbackProc XDisplayTimers(clock_mode) X int clock_mode; X{ X Arg args[3]; X char buf[MSG_SIZ]; X static int white_move_flag = True, black_move_flag = True; X static time_t white_time_remaining, black_time_remaining, X white_last_time, black_last_time, current_time = 0; X static XtIntervalId white_timer_id = NULL, black_timer_id = NULL; X X current_time = time((time_t *) NULL); X X switch (clock_mode) { X case StopTimers: X if (white_timer_id != NULL) X XtRemoveTimeOut(white_timer_id); X if (black_timer_id != NULL) X XtRemoveTimeOut(black_timer_id); X white_last_time = black_last_time = current_time; X break; X case SwitchTimers: X if (currentMove % 2 == 0) { X if (white_move_flag) { X white_move_flag = False; X if (currentMove == 0 || firstMove == True) X white_time_remaining = appData.timeControl * 60; X else X white_time_remaining -= current_time - white_last_time; X } else X white_time_remaining -= current_time - white_last_time; X white_last_time = black_last_time = current_time; X if (white_time_remaining <= 0) { X white_time_remaining = 0; X DisplayMessage("White's flag dropped"); X } X sprintf(buf, "white: %s", TimeString(white_time_remaining)); X XtSetArg(args[0], XtNlabel, buf); X XtSetArg(args[1], XtNbackground, WHITE_PIXEL); X XtSetArg(args[2], XtNforeground, BLACK_PIXEL); X XtSetValues(whiteTimerWidget, args, 3); X sprintf(buf, "black: %s", TimeString(black_time_remaining)); X XtSetArg(args[0], XtNlabel, buf); X XtSetArg(args[1], XtNbackground, BLACK_PIXEL); X XtSetArg(args[2], XtNforeground, WHITE_PIXEL); X XtSetValues(blackTimerWidget, args, 3); X if (black_timer_id != NULL) X XtRemoveTimeOut(black_timer_id); X white_timer_id = XtAddTimeOut(1000, DisplayTimers, SwitchTimers); X } else { X if (black_move_flag) { X black_move_flag = False; X if (currentMove == 1) X black_time_remaining = appData.timeControl * 60; X else if (firstMove) { X firstMove = False; X white_time_remaining = appData.timeControl * 60; X } else X black_time_remaining -= current_time - black_last_time; X } else X black_time_remaining -= current_time - black_last_time; X white_last_time = black_last_time = current_time; X if (black_time_remaining <= 0) { X black_time_remaining = 0; X DisplayMessage("Black's flag dropped"); X } X sprintf(buf, "white: %s", TimeString(white_time_remaining)); X XtSetArg(args[0], XtNlabel, buf); X XtSetArg(args[1], XtNbackground, BLACK_PIXEL); X XtSetArg(args[2], XtNforeground, WHITE_PIXEL); X XtSetValues(whiteTimerWidget, args, 3); X sprintf(buf, "black: %s", TimeString(black_time_remaining)); X XtSetArg(args[0], XtNlabel, buf); X XtSetArg(args[1], XtNbackground, WHITE_PIXEL); X XtSetArg(args[2], XtNforeground, BLACK_PIXEL); X XtSetValues(blackTimerWidget, args, 3); X if (white_timer_id != NULL) X XtRemoveTimeOut(white_timer_id); X black_timer_id = XtAddTimeOut(1000, DisplayTimers, SwitchTimers); X } X /* X * reset clocks when time control is acheived X */ X if ((((int) (currentMove + 2.5) / 2) % appData.movesPerSession == 0) X && (white_time_remaining > 0) && (black_time_remaining > 0)) { X white_time_remaining = appData.timeControl * 60; X black_time_remaining = appData.timeControl * 60; X } X break; X case ResetTimers: X if (white_timer_id != NULL) { X XtRemoveTimeOut(white_timer_id); X white_timer_id = NULL; X } X white_move_flag = True; X white_time_remaining = appData.timeControl * 60; X sprintf(buf, "white: %s", TimeString(white_time_remaining)); X XtSetArg(args[0], XtNlabel, buf); X XtSetArg(args[1], XtNbackground, WHITE_PIXEL); X XtSetArg(args[2], XtNforeground, BLACK_PIXEL); X XtSetValues(whiteTimerWidget, args, 3); X X if (black_timer_id != NULL) { X XtRemoveTimeOut(black_timer_id); X black_timer_id = NULL; X } X black_move_flag = True; X black_time_remaining = appData.timeControl * 60; X sprintf(buf, "black: %s", TimeString(black_time_remaining)); X XtSetArg(args[0], XtNlabel, buf); X XtSetArg(args[1], XtNbackground, WHITE_PIXEL); X XtSetArg(args[2], XtNforeground, BLACK_PIXEL); X XtSetValues(blackTimerWidget, args, 3); X break; X } X} X Xchar * XTimeString(tm) X time_t tm; X{ X static char buf[32]; X static int i, second, minute, hour, day; X X bzero(buf, sizeof(buf)); X X if (tm >= (60 * 60 * 24)) { X day = (int) (tm / (60 * 60 * 24)); X tm -= (int) day * 60 * 60 * 24; X } else X day = 0; X X if (tm >= (60 * 60)) { X hour = (int) (tm / (60 * 60)); X tm -= (int) hour * 60 * 60; X } else X hour = 0; X X if (tm >= 60) { X minute = (int) (tm / 60); X tm -= (int) minute * 60; X } else X minute = 0; X X second = tm % 60; X X if (day > 0) X sprintf(buf, " %d:%02d:%02d:%02d ", day, hour, minute, second); X else if (hour > 0) X sprintf(buf, " %d:%02d:%02d ", hour, minute, second); X else X sprintf(buf, " %2d:%02d ", minute, second); X X return buf; X} X Xvoid XSyntax(argc, argv) X int argc; X char **argv; X{ X fprintf(stderr, "Usage %s:\n", argv[0]); X fprintf(stderr, "\tstandard Xt options\n"); X fprintf(stderr, "\t-whitePieceColor color\n"); X fprintf(stderr, "\t-blackPieceColor color\n"); X fprintf(stderr, "\t-lightSquareColor color\n"); X fprintf(stderr, "\t-darkSquareColor color\n"); X fprintf(stderr, "\t-timeDelay seconds\n"); X fprintf(stderr, "\t-timeControl minutes\n"); X fprintf(stderr, "\t-movesPerSession moves\n"); X fprintf(stderr, "\t-saveGameFile file\n"); X fprintf(stderr, "\t-readGameFile file\n"); X fprintf(stderr, "\t-initString commands\n"); X fprintf(stderr, "\t-savePositionFile file\n"); X fprintf(stderr, "\t-readPositionFile file\n"); X fprintf(stderr, "\t-firstChessProgram program\n"); X fprintf(stderr, "\t-secondChessProgram program\n"); X fprintf(stderr, "\t-firstHost host\n"); X fprintf(stderr, "\t-secondHost host\n"); X fprintf(stderr, "\t-solidPawnBitmap file\n"); X fprintf(stderr, "\t-solidRookBitmap file\n"); X fprintf(stderr, "\t-solidBishopBitmap file\n"); X fprintf(stderr, "\t-solidKnightBitmap file\n"); X fprintf(stderr, "\t-solidQueenBitmap file\n"); X fprintf(stderr, "\t-solidKingBitmap file\n"); X fprintf(stderr, "\t-outlinePawnBitmap file\n"); X fprintf(stderr, "\t-outlineRookBitmap file\n"); X fprintf(stderr, "\t-outlineBishopBitmap file\n"); X fprintf(stderr, "\t-outlineKnightBitmap file\n"); X fprintf(stderr, "\t-outlineQueenBitmap file\n"); X fprintf(stderr, "\t-outlineKingBitmap file\n"); X fprintf(stderr, "\t-matchMode (False | Init | Position | Opening)\n"); X fprintf(stderr, "\t-monoMode (False | True)\n"); X fprintf(stderr, "\t-debugMode (False | True)\n"); X exit(0); X} SHAR_EOF $TOUCH -am 1031191090 xboard.c && chmod 0644 xboard.c || echo "restore of xboard.c failed" set `wc -c xboard.c`;Wc_c=$1 if test "$Wc_c" != "61279"; then echo original size 61279, current size $Wc_c fi # ============= xboard.h ============== echo "x - extracting xboard.h (Text)" sed 's/^X//' << 'SHAR_EOF' > xboard.h && X#define BOARD_SIZE 8 /* rarely changed */ X#define SQUARE_SIZE 80 X#define LINE_GAP 3 X#define MAX_MOVES 512 X#define MSG_SIZ 256 X#define TIME_CONTROL 5 /* minutes */ X#define TIME_DELAY 1.5 /* seconds between moves */ X#define MOVES_PER_SESSION 40 /* moves per TIME_CONTROL */ X#define FIRST_CHESS_PROGRAM "gnuchessr" X#define SECOND_CHESS_PROGRAM "gnuchessr" X#define FIRST_HOST "localhost" X#define SECOND_HOST "localhost" X#define MATCH_MODE MatchFalse X#define SAVE_GAME_FILE "xboard.game.save" X#define READ_GAME_FILE "xboard.game.read" X#define INIT_STRING "new\nbeep\nrandom\neasy\n" X#define SAVE_POSITION_FILE "xboard.position.save" X#define READ_POSITION_FILE "xboard.position.read" X#define SOLID_PAWN_BITMAP "solid_pawn.bitmap" X#define SOLID_ROOK_BITMAP "solid_rook.bitmap" X#define SOLID_KNIGHT_BITMAP "solid_knight.bitmap" X#define SOLID_BISHOP_BITMAP "solid_bishop.bitmap" X#define SOLID_QUEEN_BITMAP "solid_queen.bitmap" X#define SOLID_KING_BITMAP "solid_king.bitmap" X#define OUTLINE_PAWN_BITMAP "outline_pawn.bitmap" X#define OUTLINE_ROOK_BITMAP "outline_rook.bitmap" X#define OUTLINE_KNIGHT_BITMAP "outline_knight.bitmap" X#define OUTLINE_BISHOP_BITMAP "outline_bishop.bitmap" X#define OUTLINE_QUEEN_BITMAP "outline_queen.bitmap" X#define OUTLINE_KING_BITMAP "outline_king.bitmap" X#define WHITE_PIECE_COLOR "#FFFFCC" X#define BLACK_PIECE_COLOR "#202020" X#define LIGHT_SQUARE_COLOR "#C8C365" X#define DARK_SQUARE_COLOR "#77A26D" X Xtypedef unsigned char Board[BOARD_SIZE][BOARD_SIZE]; X Xenum { X BeginningOfGame, MachinePlaysWhite, MachinePlaysBlack, TwoMachinesPlay, X ForceMoves, PlayFromGameFile, SetupPosition, PauseGame, EndOfGame X}; X Xenum { WhiteOnMove, BlackOnMove }; X Xenum { MatchFalse, MatchInit, MatchPosition, MatchOpening }; X Xenum { X WhitePawn, WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, WhiteKing, X BlackPawn, BlackRook, BlackKnight, BlackBishop, BlackQueen, BlackKing, X EmptySquare X}; X Xenum { X WhiteKingSideCastle = 1, WhiteQueenSideCastle, WhitePromotion, X BlackKingSideCastle, BlackQueenSideCastle, BlackPromotion, X WhiteCapturesEnPassant, BlackCapturesEnPassant, NormalMove, X WhiteWins, BlackWins, GameIsDrawn X}; X Xenum { /* Same order as buttonStrings */ X ButtonQuit, ButtonPlayFromFile, ButtonMachinePlaysBlack, ButtonForward, X ButtonReset, ButtonSetupFromFile, ButtonMachinePlaysWhite, ButtonBackward, X ButtonFlip, ButtonSaveGame, ButtonSwitch, ButtonForce, X ButtonHint, ButtonSavePosition, ButtonTwoMachinesPlay, ButtonPause X}; X Xenum { X ResetTimers, SwitchTimers, StopTimers X}; SHAR_EOF $TOUCH -am 1031190190 xboard.h && chmod 0644 xboard.h || echo "restore of xboard.h failed" set `wc -c xboard.h`;Wc_c=$1 if test "$Wc_c" != "2561"; then echo original size 2561, current size $Wc_c fi exit 0 dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only. -- dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only.