games-request@tekred.TEK.COM (11/25/87)
Submitted by: (Tom Anderson) toma@tc.fluke.com Comp.sources.games: Volume 2, Issue 95 Archive-name: nchess/Part03a #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 3 (of 4)." # Contents: Icons/bishopStencil.icon Icons/knightStencil.icon # Icons/queenStencil.icon Icons/rookStencil.icon chessprocess.c # controlsw.c daemon.c decls.h ipc.c main.c msgsw.c tool.c # Wrapped by billr@tekred on Thu Nov 19 10:49:22 1987 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f Icons/bishopStencil.icon -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Icons/bishopStencil.icon\" else echo shar: Extracting \"Icons/bishopStencil.icon\" \(1933 characters\) sed "s/^X//" >Icons/bishopStencil.icon <<'END_OF_Icons/bishopStencil.icon' X/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16 X */ X 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, X 0x0000,0x0000,0x0000,0x0000,0x0000,0x000C,0x3000,0x0000, X 0x0000,0x001E,0x7800,0x0000,0x0000,0x001E,0x7800,0x0000, X 0x0000,0x003F,0xFC00,0x0000,0x0000,0x007F,0xFE00,0x0000, X 0x0000,0x007F,0xFE00,0x0000,0x0000,0x00FF,0xFF00,0x0000, X 0x0000,0x00FF,0xFF00,0x0000,0x0000,0x01FF,0xFF80,0x0000, X 0x0000,0x03FF,0xFFC0,0x0000,0x0000,0x03FF,0xFFC0,0x0000, X 0x0000,0x07FF,0xFFE0,0x0000,0x0000,0x07FF,0xFFE0,0x0000, X 0x0000,0x0FFF,0xFFF0,0x0000,0x0000,0x0FFF,0xFFF0,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x3FFF,0xFFFC,0x0000,0x0000,0x3FFF,0xFFFC,0x0000, X 0x0000,0x3FFF,0xFFFC,0x0000,0x0000,0x3FFF,0xFFFC,0x0000, X 0x0000,0x7FFF,0xFFFE,0x0000,0x0000,0x7FFF,0xFFFE,0x0000, X 0x0000,0x7FFF,0xFFFE,0x0000,0x0000,0x7FFF,0xFFFE,0x0000, X 0x0000,0x7FFF,0xFFFE,0x0000,0x0000,0x7FFF,0xFFFE,0x0000, X 0x0000,0x7FFF,0xFFFE,0x0000,0x0000,0x7FFF,0xFFFE,0x0000, X 0x0000,0x7FFF,0xFFFE,0x0000,0x0000,0x7FFF,0xFFFE,0x0000, X 0x0000,0x7FFF,0xFFFE,0x0000,0x0000,0x3FFF,0xFFFC,0x0000, X 0x0000,0x3FFF,0xFFFC,0x0000,0x0000,0x3FFF,0xFFFC,0x0000, X 0x0000,0x3FFF,0xFFFC,0x0000,0x0000,0x3FFF,0xFFFC,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x0FFF,0xFFF0,0x0000, X 0x0000,0x0FFF,0xFFF0,0x0000,0x0000,0x0FFF,0xFFF0,0x0000, X 0x0000,0x07FF,0xFFE0,0x0000,0x0000,0x07FF,0xFFE0,0x0000, X 0x0000,0x07FF,0xFFE0,0x0000,0x0000,0x07FF,0xFFE0,0x0000, X 0x0000,0x07FF,0xFFE0,0x0000,0x0000,0xFFFF,0xFFFF,0x0000, X 0x0001,0xFFFF,0xFFFF,0x8000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0003,0xFFFF,0xFFFF,0xC000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0003,0xFFFF,0xFFFF,0xC000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0003,0xFFFF,0xFFFF,0xC000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0001,0xFFFF,0xFFFF,0x8000,0x0000,0xFFFF,0xFFFF,0x0000, X 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 END_OF_Icons/bishopStencil.icon if test 1933 -ne `wc -c <Icons/bishopStencil.icon`; then echo shar: \"Icons/bishopStencil.icon\" unpacked with wrong size! fi # end of overwriting check fi if test -f Icons/knightStencil.icon -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Icons/knightStencil.icon\" else echo shar: Extracting \"Icons/knightStencil.icon\" \(1933 characters\) sed "s/^X//" >Icons/knightStencil.icon <<'END_OF_Icons/knightStencil.icon' X/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16 X */ X 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, X 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, X 0x0000,0x0DB6,0xC000,0x0000,0x0000,0x1FFF,0xE01C,0x0000, X 0x0001,0x7FFF,0xF8FC,0x0000,0x0001,0xFFFF,0xFBFC,0x0000, X 0x0002,0xFFFF,0xFFF8,0x0000,0x0005,0xFFFF,0xFFF0,0x0000, X 0x000F,0xFFFF,0xFFE0,0x0000,0x0017,0xFFFF,0xFFC0,0x0000, X 0x000F,0xFFFF,0xFFE0,0x0000,0x002F,0xFFFF,0xFFF0,0x0000, X 0x005F,0xFFFF,0xFFF8,0x0000,0x00BF,0xFFFF,0xFFFC,0x0000, X 0x00FF,0xFFFF,0xFFFE,0x0000,0x007F,0xFFFF,0xFFFF,0x0000, X 0x00FF,0xFFFF,0xFFFE,0x0000,0x007F,0xFFFF,0xFFFE,0x0000, X 0x00FF,0xFFFF,0xFFFE,0x0000,0x017F,0xFFFF,0xFFFF,0x0000, X 0x00FF,0xFFFF,0xFFFF,0x8000,0x01FF,0xFFFF,0xFFFF,0xC000, X 0x007F,0xFFFF,0xFFFF,0xE000,0x01FF,0xFFFF,0xFFFF,0xF000, X 0x00FF,0xFFFF,0xFFFF,0xF800,0x01FF,0xFFFF,0xFFFF,0xF800, X 0x01FF,0xFFFF,0xFFFF,0xFC00,0x00FF,0xFFFF,0x7FFF,0xFC00, X 0x01FF,0xFFFF,0x9FFF,0xFC00,0x01FF,0xFFFF,0xC07F,0xFC00, X 0x00FF,0xFFFF,0xC01F,0xF800,0x01FF,0xFFFF,0xE00F,0xF000, X 0x01FF,0xFFFF,0xE007,0xC000,0x00FF,0xFFFF,0xF003,0x8000, X 0x01FF,0xFFFF,0xF800,0x0000,0x01FF,0xFFFF,0xFC00,0x0000, X 0x00FF,0xFFFF,0xFE00,0x0000,0x01FF,0xFFFF,0xFE00,0x0000, X 0x01FF,0xFFFF,0xFF00,0x0000,0x00FF,0xFFFF,0xFF80,0x0000, X 0x00BF,0xFFFF,0xFF80,0x0000,0x007F,0xFFFF,0xFFC0,0x0000, X 0x003F,0xFFFF,0xFFC0,0x0000,0x002F,0xFFFF,0xFFE0,0x0000, X 0x003F,0xFFFF,0xFFF0,0x0000,0x000F,0xFFFF,0xFFF8,0x0000, X 0x001F,0xFFFF,0xFFF8,0x0000,0x001F,0xFFFF,0xFFFC,0x0000, X 0x0007,0xFFFF,0xFFFE,0x0000,0x0000,0xFFFF,0xFFFF,0x0000, X 0x0001,0xFFFF,0xFFFF,0x8000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0003,0xFFFF,0xFFFF,0xC000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0003,0xFFFF,0xFFFF,0xC000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0003,0xFFFF,0xFFFF,0xC000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0001,0xFFFF,0xFFFF,0x8000,0x0000,0xFFFF,0xFFFF,0x0000, X 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 END_OF_Icons/knightStencil.icon if test 1933 -ne `wc -c <Icons/knightStencil.icon`; then echo shar: \"Icons/knightStencil.icon\" unpacked with wrong size! fi # end of overwriting check fi if test -f Icons/queenStencil.icon -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Icons/queenStencil.icon\" else echo shar: Extracting \"Icons/queenStencil.icon\" \(1933 characters\) sed "s/^X//" >Icons/queenStencil.icon <<'END_OF_Icons/queenStencil.icon' X/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16 X */ X 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, X 0x0000,0x0000,0x0000,0x0000,0x0000,0x0001,0x8000,0x0000, X 0x0000,0x0003,0xC000,0x0000,0x0000,0x0003,0xC000,0x0000, X 0x0000,0x0007,0xE000,0x0000,0x0000,0x0007,0xE000,0x0000, X 0x0000,0x000F,0xF000,0x0000,0x0000,0x000F,0xF000,0x0000, X 0x0000,0x001F,0xF800,0x0000,0x0000,0x001F,0xF800,0x0000, X 0x0000,0x003F,0xFC00,0x0000,0x0000,0x003F,0xFC00,0x0000, X 0x0000,0x007F,0xFE00,0x0000,0x0000,0x007F,0xFE00,0x0000, X 0x0000,0x00FF,0xFF00,0x0000,0x0040,0x00FF,0xFF00,0x0200, X 0x0060,0x01FF,0xFF80,0x0600,0x0070,0x01FF,0xFF80,0x0E00, X 0x0078,0x03FF,0xFFC0,0x1E00,0x007C,0x03FF,0xFFC0,0x3E00, X 0x007E,0x07FF,0xFFE0,0x7E00,0x007E,0x07FF,0xFFE0,0x7E00, X 0x003F,0x0FFF,0xFFF0,0xFC00,0x003F,0x8FFF,0xFFF1,0xFC00, X 0x003F,0xDFFF,0xFFFB,0xFC00,0x003F,0xDFFF,0xFFFB,0xFC00, X 0x001F,0xFFFF,0xFFFF,0xF800,0x001F,0xFFFF,0xFFFF,0xF800, X 0x001F,0xFFFF,0xFFFF,0xF800,0x001F,0xFFFF,0xFFFF,0xF800, X 0x000F,0xFFFF,0xFFFF,0xF000,0x000F,0xFFFF,0xFFFF,0xF000, X 0x000F,0xFFFF,0xFFFF,0xF000,0x000F,0xFFFF,0xFFFF,0xF000, X 0x000F,0xFFFF,0xFFFF,0xF000,0x0007,0xFFFF,0xFFFF,0xE000, X 0x0007,0xFFFF,0xFFFF,0xE000,0x0007,0xFFFF,0xFFFF,0xE000, X 0x0007,0xFFFF,0xFFFF,0xE000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0003,0xFFFF,0xFFFF,0xC000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0003,0xFFFF,0xFFFF,0xC000,0x0001,0xFFFF,0xFFFF,0x8000, X 0x0001,0xFFFF,0xFFFF,0x8000,0x0001,0xFFFF,0xFFFF,0x8000, X 0x0001,0xFFFF,0xFFFF,0x8000,0x0000,0xFFFF,0xFFFF,0x0000, X 0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0xFFFF,0xFFFF,0x0000, X 0x0001,0xFFFF,0xFFFF,0x8000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0003,0xFFFF,0xFFFF,0xC000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0003,0xFFFF,0xFFFF,0xC000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0003,0xFFFF,0xFFFF,0xC000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0001,0xFFFF,0xFFFF,0x8000,0x0000,0xFFFF,0xFFFF,0x0000, X 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 END_OF_Icons/queenStencil.icon if test 1933 -ne `wc -c <Icons/queenStencil.icon`; then echo shar: \"Icons/queenStencil.icon\" unpacked with wrong size! fi # end of overwriting check fi if test -f Icons/rookStencil.icon -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Icons/rookStencil.icon\" else echo shar: Extracting \"Icons/rookStencil.icon\" \(1933 characters\) sed "s/^X//" >Icons/rookStencil.icon <<'END_OF_Icons/rookStencil.icon' X/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16 X */ X 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, X 0x0000,0x0000,0x0000,0x0000,0x0000,0x001F,0xF800,0x0000, X 0x0000,0x003F,0xFC00,0x0000,0x0000,0x787F,0xFE1E,0x0000, X 0x0001,0xFC7F,0xFE3F,0x8000,0x0003,0xFC7F,0xFE3F,0xC000, X 0x0007,0xFC7F,0xFE3F,0xE000,0x000F,0xFC7F,0xFE3F,0xF000, X 0x000F,0xFC7F,0xFE3F,0xF000,0x000F,0xFDFF,0xFFBF,0xF000, X 0x000F,0xFFFF,0xFFFF,0xF000,0x000F,0xFFFF,0xFFFF,0xF000, X 0x000F,0xFFFF,0xFFFF,0xF000,0x000F,0xFFFF,0xFFFF,0xF000, X 0x000F,0xFFFF,0xFFFF,0xF000,0x000F,0xFFFF,0xFFFF,0xF000, X 0x0007,0xFFFF,0xFFFF,0xE000,0x0001,0xFFFF,0xFFFF,0x8000, X 0x0000,0x7FFF,0xFFFE,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x1FFF,0xFFF8,0x0000, X 0x0000,0x1FFF,0xFFF8,0x0000,0x0000,0x3FFF,0xFFFC,0x0000, X 0x0000,0x7FFF,0xFFFE,0x0000,0x0000,0xFFFF,0xFFFF,0x0000, X 0x0001,0xFFFF,0xFFFF,0x8000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0003,0xFFFF,0xFFFF,0xC000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0003,0xFFFF,0xFFFF,0xC000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0003,0xFFFF,0xFFFF,0xC000,0x0003,0xFFFF,0xFFFF,0xC000, X 0x0001,0xFFFF,0xFFFF,0x8000,0x0000,0xFFFF,0xFFFF,0x0000, X 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 END_OF_Icons/rookStencil.icon if test 1933 -ne `wc -c <Icons/rookStencil.icon`; then echo shar: \"Icons/rookStencil.icon\" unpacked with wrong size! fi # end of overwriting check fi if test -f chessprocess.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"chessprocess.c\" else echo shar: Extracting \"chessprocess.c\" \(9812 characters\) sed "s/^X//" >chessprocess.c <<'END_OF_chessprocess.c' X/* X * Copyright 1987 Tom Anderson; 20831 Frank Waters Road; X * Stanwood, WA 98282. All rights reserved. X */ X X/* X * manage one or two chess game processes X */ X X#include <sys/types.h> X#include <sys/socket.h> X#include <sys/wait.h> X#include <sys/stat.h> X#include <sys/time.h> X#include <sys/resource.h> X#include <signal.h> X#include <stdio.h> X#include <strings.h> X#include <ctype.h> X X#include "nchess.h" X Xextern char * gets(); X Xint ChessPid[2], X ChessProcessFDs[2]; XFILE * ReadChessProcess[2], * WriteChessProcess[2]; XBOOL SigChildInterceptOn = FALSE; XBOOL MachineDebug = FALSE; Xchar * colorStrings[] = { "black", "white" }; X X/* X * intercept SIGCHLD X * X * print a message for the first chess process that dies and abort the X * game. (note: any change in child status is interpreted as death). X */ XhandleSigChild() X{ X int pid; X union wait status; X X while(1) { X pid = wait3(&status, WNOHANG, (struct rusage *) 0); X if (pid <= 0) X return; X if ( ! GameOver && (pid == ChessPid[BLACK] || pid == ChessPid[WHITE])) { X Message (pid == ChessPid[WHITE] ? X "White's process died" : X "Black's process died" ); X KillMouseActivity(); X GameOver = TRUE; X Mouse = LOCKED; X } X } X} X X/* X * have a chess process make the first move. X * X * note: with the wonderful unix chess program, "first" also implies X * playing the white pieces. nonetheless, color is an argument to this X * function in case we ever find out how to get around this problem. X */ Xvoid XMachineFirst(color) X int color; X{ X fputs("first\n", WriteChessProcess[color]); X fflush(WriteChessProcess[color]); X if (MachineDebug) X fprintf(stderr, "sent to %s: first\n", colorStrings[color]); X} X X/* X * open a pipe to a chess game process X * X * startIt indicates whether the process should be sent the "first" X * command. X */ Xvoid XInitChessProcess(cp, color, startIt) X char ** cp; X int color; X BOOL startIt; X{ X int sv[2]; X char c[128]; X X if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) { X fputs("socketpair failed\n", stderr); X exit(1); X } X if ((ChessPid[color] = fork()) == 0) { X dup2(sv[0], 0); X dup2(sv[0], 1); X chdir("/tmp"); /* so that "chess.out" can always be written */ X execvp(cp[0], cp); X puts("exec"); X fflush(stdout); X _exit(1); X } X/* dup2(sv[1], 0); X dup2(sv[1], 1); */ X /* want to intercept SIGCHLD */ X if ( ! SigChildInterceptOn) { X SigChildInterceptOn = TRUE; X signal(SIGCHLD, handleSigChild); X } X ChessProcessFDs[color] = (1 << sv[1]); X ReadChessProcess[color] = fdopen(sv[1], "r"); X WriteChessProcess[color] = fdopen(sv[1], "w"); X setbuf(ReadChessProcess[color], (char *) 0); X /* X * eat the "Chess" prompt X * note: if the child's exec failed, X * catch the "exec" prompt and give up X */ X fgets(c, sizeof(c), ReadChessProcess[color]); X if (strcmp(c, "exec\n") == 0) { X KillChessProcesses(); X fprintf(stderr, "exec of %s failed\n", cp[0]); X exit(1); X } X /* set algebraic notation mode */ X fputs("alg\n", WriteChessProcess[color]); X fflush(WriteChessProcess[color]); X if (MachineDebug) X fprintf(stderr, "sent to %s: alg\n", colorStrings[color]); X if (startIt) X MachineFirst(color); X} X X X/* X * reap one or more chess process X */ Xvoid XReapChessProcesses() X{ X union wait status; X X while (wait3(&status, WNOHANG, (struct rusage *) 0) >= 0) X ; X} X X/* X * kill any and all chess processes X */ Xvoid XKillChessProcesses() X{ X signal(SIGCHLD, SIG_IGN); X if (ChessPid[BLACK]) X kill(ChessPid[BLACK], SIGKILL); X if (ChessPid[WHITE]) X kill(ChessPid[WHITE], SIGKILL); X ReapChessProcesses(); X} X X/* X * get a move from a chess process X * X * return 1 if a move was successfully obtained, 0 if not. X */ Xint XGetMachineMove(move, color) X Move * move; X int color; X{ X char c[256], c2[256]; X char file1, file2; X int rank1, rank2; X X if (fgets(c, sizeof(c), ReadChessProcess[color]) == (char *) 0) X return(0); X if (MachineDebug) X fprintf(stderr, "rec'd from %s: %s", colorStrings[color], c); X /* look for special announcements */ X if (strcmp(c, "Forced mate\n") == 0) { X Message(color == WHITE ? X "White announces forced mate" : X "Black announces forced mate"); X return(0); X } X if (strcmp(c, "Resign\n") == 0) { X Message(color == WHITE ? "White resigns" : "Black resigns"); X DoResignation(color); X Mouse = LOCKED; X return(0); X } X if (strcmp(c, "Illegal move\n") == 0) { X Message("Internal botch - illegal move detected"); X return(0); X } X if (strncmp(c, "done", 4) == 0) { X return(0); X } X if (strncmp(c, "White wins", 10) == 0 X || strncmp(c, "Black wins", 10) == 0) { X c[10] = '\0'; X Message(c); X GameOver = TRUE; X Mouse = LOCKED; X return(0); X } X /* e.g., 1. d2d4 */ X if (sscanf(c, "%*d. %c%d%c%d", &file1, &rank1, &file2, &rank2) == 4 X /* e.g., 1. ... d2d4 */ X || sscanf(c, "%*d. ... %c%d%c%d", &file1, &rank1, &file2, &rank2) == 4) { X move->x1 = file1 - (isupper(file1) ? 'A' : 'a'); X move->y1 = 8 - rank1; X move->x2 = file2 - (isupper(file2) ? 'A' : 'a'); X move->y2 = 8 - rank2; X /* TBD: possible non-queen pawn promotion X * (the existing chess program doesn't implement this) */ X move->newPieceType = (int) QUEEN; X return(1); X } else { X strcpy(c2, color == WHITE ? "White announces: " : "Black announces: "); X Message(strncat(c2, c, sizeof(c2) - strlen(c2) - 2)); X if (strncmp(c, "Draw", 4) == 0) { X GameOver = TRUE; X Mouse = LOCKED; X } X return(0); X } X} X X/* X * send a move to a chess process X * X * note: if the process responds with a move too quickly, we won't X * get another select() trigger to get its move. thus, we need to X * check for the availability of a move when the echo is received. X */ Xvoid XSendMachineMove(move, color) X Move * move; X int color; X{ X char c[128]; X X if (move->x1 != move->x2 X && GetSquare(move->x1, move->y1)->type == PAWN X && GetSquare(move->x2, move->y2)->type == NULLPC) { X /* re-encode en passant captures as horizontal moves */ X fprintf(WriteChessProcess[color], "%c%d%c%d\n", X move->x1 + 'a', 8 - move->y1, X move->x2 + 'a', 8 - move->y1); X if (MachineDebug) X fprintf(stderr, "sent move to %s: %c%d%c%d\n", X colorStrings[color], X move->x1 + 'a', 8 - move->y1, X move->x2 + 'a', 8 - move->y1); X } else { X fprintf(WriteChessProcess[color], "%c%d%c%d\n", X move->x1 + 'a', 8 - move->y1, X move->x2 + 'a', 8 - move->y2); X if (MachineDebug) X fprintf(stderr, "sent move to %s: %c%d%c%d\n", X colorStrings[color], X move->x1 + 'a', 8 - move->y1, X move->x2 + 'a', 8 - move->y2); X } X fflush(WriteChessProcess[color]); X fgets(c, sizeof(c), ReadChessProcess[color]); /* eat the move echo */ X if (MachineDebug) X fprintf(stderr, "rec'd from %s: %s", colorStrings[color], c); X} X X/* X * undo the last machine move and our move X */ Xvoid XMachineUndo(color) X{ X fputs("remove\n", WriteChessProcess[color]); X fflush(WriteChessProcess[color]); X if (MachineDebug) X fprintf(stderr, "sent to %s: remove\n", colorStrings[color]); X UnDoMove(); X UnDoMove(); X} X X/* X * set up the board X * (as noted above: with the existing unix chess program, there is no X * apparent way (short of deciphering the chess.out format, which is X * totally un-fun) to inform the chess program whose turn it is and X * which color it is supposed to play - it assumes that white always X * is the first to move. X */ X Xchar whitePieceChars[] = { 'p', 'n', 'b', 'r', 'q', 'k', ' ' }; Xchar blackPieceChars[] = { 'P', 'N', 'B', 'R', 'Q', 'K', ' ' }; X X/* X * set up a board state against the machine. X * returns TRUE if successful, FALSE otherwise X */ XBOOL XMachineSetup(color) X int color; X{ X register int x, y; X Square * sqp; X char c[128]; X X fputs("setup\n", WriteChessProcess[color]); X if (MachineDebug) X fprintf(stderr, "sent to %s:\nsetup\n", colorStrings[color]); X for (y = 0 ; y < 8 ; y++) { X for (x = 0 ; x < 8 ; x++) { X sqp = GetSquare(x, y); X putc(sqp->color == WHITE ? X whitePieceChars[(int) sqp->type] : X blackPieceChars[(int) sqp->type], X WriteChessProcess[color]); X if (MachineDebug) X fputc(sqp->color == WHITE ? X whitePieceChars[(int) sqp->type] : X blackPieceChars[(int) sqp->type], X stderr); X } X putc('\n', WriteChessProcess[color]); X if (MachineDebug) X fputc('\n', stderr); X } X fflush(WriteChessProcess[color]); X fgets(c, sizeof(c), ReadChessProcess[color]); X if (MachineDebug) X fprintf(stderr, "rec'd from %s: %s", colorStrings[color], c); X return(strcmp(c, "Setup successful\n") == 0); X} X X/* X * have a chess process save the game as "/tmp/chess.out". X * return the size of chess.out. X */ Xint XMachineSave(color) X int color; X{ X FILE * saveFile; X struct stat saveFileStatus; X int saveFileSize; X int retryCount = 0; X X fputs("save\n", WriteChessProcess[color]); X fflush(WriteChessProcess[color]); X if (MachineDebug) X fprintf(stderr, "sent to %s: save\n", colorStrings[color]); X sleep((unsigned) 1); X /* wait for the chess process to create chess.out */ X do { X if ((saveFile = fopen("/tmp/chess.out", "r")) == (FILE *) 0) X sleep((unsigned) 2); X } while(saveFile == (FILE *) 0 && ++retryCount < 10); X if (saveFile == (FILE *) 0) { X Message("Can't open chess.out!"); X return(-1); X } X saveFileStatus.st_size = -1; X /* wait until chess.out stops growing */ X do { X sleep((unsigned) 1); X saveFileSize = saveFileStatus.st_size; X fstat(fileno(saveFile), &saveFileStatus); X } while (saveFileSize != saveFileStatus.st_size); X fclose(saveFile); X return(saveFileSize); X} X X/* X * restore the game X */ Xvoid XMachineRestore(color) X int color; X{ X fputs("restore\n", WriteChessProcess[color]); X fflush(WriteChessProcess[color]); X if (MachineDebug) X fprintf(stderr, "sent to %s: restore\n", colorStrings[color]); X} X END_OF_chessprocess.c if test 9812 -ne `wc -c <chessprocess.c`; then echo shar: \"chessprocess.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f controlsw.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"controlsw.c\" else echo shar: Extracting \"controlsw.c\" \(3122 characters\) sed "s/^X//" >controlsw.c <<'END_OF_controlsw.c' X/* X * Copyright 1987 Tom Anderson; 20831 Frank Waters Road; X * Stanwood, WA 98282. All rights reserved. X */ X X/* X * control panel subwindow handling X */ X X#include <stdio.h> X#include <suntool/tool_hs.h> X#include <suntool/panel.h> X#include <suntool/menu.h> X X#include "nchess.h" X XBOOL SaveWanted = FALSE; /* machine opponent and game save deferred */ X Xstruct toolsw * ControlPanelSW; XPanel ControlPanel; X X/* button items */ XPanel_item UndoButton; XPanel_item LastPlayButton; XPanel_item ResignButton; XPanel_item TranscriptButton; XPanel_item SaveButton; X X/* X * undo move button event handler X */ X/*ARGSUSED*/ XundoProc(item, event) X Panel_item item; X struct inputevent * event; X{ X if ( ! IHaveMoved()) { X Message("You haven't moved yet!"); X } else if (Mouse == IDLE) { X UndoWanted = TRUE; X Mouse = LOCKED; /* lock the mouse until the reply arrives */ X SendUndoRequest(PeerColor); X } X} X X/* X * last play button event handler X */ X/*ARGSUSED*/ XlastPlayProc(item, event) X Panel_item item; X struct inputevent * event; X{ X ShowLastPlay(); X} X X/* X * resign button event handler X */ X/*ARGSUSED*/ XresignProc(item, event) X Panel_item item; X struct inputevent * event; X{ X /* make sure this is what the user wants to do */ X if (Mouse == IDLE) { X ConfirmResignation(); X } X} X X/* X * write a transcript X */ X/*ARGSUSED*/ XtranscriptProc(item, event) X Panel_item item; X struct inputevent * event; X{ X WriteTranscript(TranscriptFileName, TranscriptType); X} X X/* X * save the game X */ X/*ARGSUSED*/ XsaveProc(item, event) X Panel_item item; X struct inputevent * event; X{ X /* X * caveats: can't save games while we're still setting them up, X * and cannot save a game involving machines after the game is over. X */ X if (SetupMode X || GameOver && (IsMachine[WHITE] || IsMachine[BLACK])) X return; X if (IsMachine[WHITE] && IsMachine[BLACK] X || IsMachine[PeerColor] && Turn != MyColor) { X Message("Will save game when machine finishes move..."); X SaveWanted = TRUE; X } else { X SaveGame(SaveFileName); X } X} X X/* X * set up the control subwindow X */ Xvoid XInitControlSW() X{ X if ((ControlPanelSW = panel_create(NchessTool, 0)) == NULL) { X fprintf(stderr, "Can't create control panel\n"); X exit(1); X } X ControlPanel = ControlPanelSW->ts_data; X /* set up the buttons */ X if ( ! IsMachine[WHITE] || ! IsMachine[BLACK]) { X ResignButton = panel_create_item(ControlPanel, PANEL_BUTTON, X PANEL_LABEL_STRING, "(Resign)", X PANEL_NOTIFY_PROC, resignProc, X 0); X UndoButton = panel_create_item(ControlPanel, PANEL_BUTTON, X PANEL_LABEL_STRING, "(Undo)", X PANEL_NOTIFY_PROC, undoProc, X 0); X } X LastPlayButton = panel_create_item(ControlPanel, PANEL_BUTTON, X PANEL_LABEL_STRING, "(Last Play)", X PANEL_NOTIFY_PROC, lastPlayProc, X 0); X TranscriptButton = panel_create_item(ControlPanel, PANEL_BUTTON, X PANEL_LABEL_STRING, "(Transcript)", X PANEL_NOTIFY_PROC, transcriptProc, X 0); X SaveButton = panel_create_item(ControlPanel, PANEL_BUTTON, X PANEL_LABEL_STRING, "(Save)", X PANEL_NOTIFY_PROC, saveProc, X 0); X panel_fit_height(ControlPanel); X} END_OF_controlsw.c if test 3122 -ne `wc -c <controlsw.c`; then echo shar: \"controlsw.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f daemon.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"daemon.c\" else echo shar: Extracting \"daemon.c\" \(4613 characters\) sed "s/^X//" >daemon.c <<'END_OF_daemon.c' X/* X * Copyright 1987 Tom Anderson; 20831 Frank Waters Road; X * Stanwood, WA 98282. All rights reserved. X */ X X/* X * chess invitation rendezvous server X * X * there are three entry points: X * - request a game X * - reply to a request X * - cancel a request X */ X X#include <stdio.h> X#include <rpc/rpc.h> X#include <sys/time.h> X#include <strings.h> X X#include "nchess.h" X Xchar LocalHostName[256]; /* local host name string */ X X#define MAXINVITES 32 Xtypedef struct { /* registered invitations with call-back information */ X GameRequest gr; /* call-back information */ X BOOL active; /* is this slot active? */ X unsigned long time; /* time invitation was registered */ X} Invitation; X XInvitation Invitations[MAXINVITES]; X X/* X * register a game invitation and print a message on the console. X */ Xvoid XgameRequest(gameReq) X GameRequest * gameReq; X{ X struct timeval tv; X struct tm * timep; X register int i, oldSlot, oldTime; X register Invitation * invp; X int avail = -1; X FILE * console; X X X (void) gettimeofday(&tv, (struct timezone *) 0); X timep = localtime((long *) &tv.tv_sec); X oldTime = tv.tv_sec; X /* find an empty invitation slot, keeping track of the oldest active one */ X for (i = 0 ; i < MAXINVITES ; i++) { X invp = &Invitations[i]; X if ( ! invp->active) { X avail = i; X break; X } else if (invp->time < oldTime) { X oldSlot = i; X oldTime = invp->time; X } X } X /* if no slots are empty, re-use the oldest one */ X if (avail < 0) X avail = oldSlot; X /* fill out the invitation slot */ X invp = &Invitations[avail]; X invp->active = TRUE; X invp->time = tv.tv_sec; X invp->gr.progNum = gameReq->progNum; X invp->gr.color = gameReq->color; X invp->gr.resumeGame = gameReq->resumeGame; X strncpy(invp->gr.hostName, gameReq->hostName, sizeof(gameReq->hostName)); X strncpy(invp->gr.userName, gameReq->userName, sizeof(gameReq->userName)); X /* X * print the invitation message on the local console X */ X if ((console = fopen("/dev/console", "w")) != (FILE *) 0) { X fprintf(console, "\n\007\007\007Message from Chess Daemon@%s at %d:%02d ...\n", X LocalHostName, timep->tm_hour, timep->tm_min); X if (gameReq->resumeGame) X fprintf(console, "%s wants to resume a game of chess.\n", X gameReq->userName); X else X fprintf(console, "%s wants to play a game of chess.\n", X gameReq->userName); X fprintf(console, "reply with: nchess %s@%s\n", X gameReq->userName, gameReq->hostName); X fflush (console); X fclose(console); X } X} X X/* X * attempt to respond to a game invitation X */ XGameRequest * XgameAcknowledge(gameAck) X GameRequest * gameAck; X{ X static GameRequest gr; X register int i, newestTime = 0, newestIndex = -1; X X /* X * look for the most recently registered invitation X * if one exists, return the prog. number and the color, X * then remove the entry. X * else return an entry with a program number of zero. X */ X gr.progNum = 0; X for (i = 0 ; i < MAXINVITES && Invitations[i].active ; i++) { X if (strcmp(Invitations[i].gr.hostName, gameAck->hostName) == 0 X && strcmp(Invitations[i].gr.userName, gameAck->userName) == 0 X && Invitations[i].time > newestTime) { X newestIndex = i; X newestTime = Invitations[i].time; X } X } X if (newestIndex >= 0) { X gr.progNum = Invitations[newestIndex].gr.progNum; X gr.color = Invitations[newestIndex].gr.color; X gr.resumeGame = Invitations[newestIndex].gr.resumeGame; X Invitations[newestIndex].active = FALSE; X } X return(&gr); X} X X/* X * cancel a game invitation X */ Xvoid XcancelRequest(gr) X GameRequest * gr; X{ X register int i; X X for (i = 0 ; i < MAXINVITES && Invitations[i].active ; i++) { X if (strcmp(Invitations[i].gr.hostName, gr->hostName) == 0 X && strcmp(Invitations[i].gr.userName, gr->userName) == 0 X && Invitations[i].gr.progNum == gr->progNum) { X Invitations[i].active = FALSE; X break; X } X } X} X X/*ARGSUSED*/ Xmain(argc, argv) X int argc; X char ** argv; X{ X if (gethostname(LocalHostName, sizeof(LocalHostName)) != 0) { X fprintf(stderr, "%s: can't determine the local host name\n", argv[0]); X exit(1); X } X pmap_unset(SERVERPROGNUM, VERSNUM); X /* register the entry points */ X registerrpc(SERVERPROGNUM, VERSNUM, REQPROCNUM, X gameRequest, XdrGameReq, xdr_void); X registerrpc(SERVERPROGNUM, VERSNUM, ACKPROCNUM, X gameAcknowledge, XdrGameReq, XdrGameReq); X registerrpc(SERVERPROGNUM, VERSNUM, CANCELPROCNUM, X cancelRequest, XdrGameReq, xdr_void); X svc_run(); X fprintf(stderr, "%s: exiting - svc_run returned\n", argv[0]); X exit(1); X} X END_OF_daemon.c if test 4613 -ne `wc -c <daemon.c`; then echo shar: \"daemon.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f decls.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"decls.h\" else echo shar: Extracting \"decls.h\" \(2262 characters\) sed "s/^X//" >decls.h <<'END_OF_decls.h' X/* X * Copyright 1987 Tom Anderson; 20831 Frank Waters Road; X * Stanwood, WA 98282. All rights reserved. X */ X X/* X * global declarations X */ X X/* board.c */ X Xextern void InitBoard(), DoMove(), UnDoMove(), ShowLastPlay(), X SaveGame(), WriteTranscript(), RestoreGame(), DoSetupChange(), X DoResignation(); Xextern BOOL InitialTurn, IsOurPieceAt(), IsSrcPieceAt(), X IsMoveLegal(), IHaveMoved(), InCheck(), GameOver; Xextern Square * GetSquare(), * GetSrcSquare(); Xextern int PromotePawn(), Turn; X X/* boardsw.c */ X Xextern void InitBoardSW(), DrawBoard(), DrawSquare(), AddVictim(), X DeleteVictim(), KillMouseActivity(), RequestUndo(); Xextern MouseState Mouse; Xextern BOOL Flashing; X X/* chessprocess.c */ X Xextern void InitChessProcess(), ReapChessProcesses(), KillChessProcesses(), X SendMachineMove(), MachineUndo(), MachineRestore(), MachineFirst(); Xextern BOOL MachineSetup(), MachineDebug; Xextern int GetMachineMove(), MachineSave(), ChessProcessFDs[]; X X/* controlsw.c */ X Xextern void InitControlSW(); Xextern BOOL SaveWanted; X X/* ipc.c */ X Xextern int MyColor, PeerColor; Xextern unsigned long PeerProgNum; Xextern void InitRPC(), SendResignation(), SendUndoRequest(), SendTalkMsg(), X SendRestoreMove(), SendEndRestore(), SendSetupChange(), X SendUndoAcknowledgement(); Xextern BOOL UndoWanted, SendMove(), RestoringGame; Xextern char * PeerUserName; X X/* main.c */ X X#ifdef FILE Xextern FILE * RestoreFile; X#endif Xextern int errno, TranscriptType; Xextern char * TranscriptFileName, * SaveFileName, * PlayerName[]; Xextern BOOL SetupMode, IsMachine[2]; Xextern struct passwd * UserPWEntry; X X/* msgsw.c */ X Xextern void InitMsgSW(), Message(), ClearMessage(), WhoseMoveMessage(); X X/* rpcsw.c */ X Xextern void AddRPCSubwindow(), DeleteRPCSubwindow(); X X/* select.c */ X Xextern void SelectAll(); X X/* talksw.c */ X Xextern void RecvTalkMsg(), InitTalkSW(); X X/* tool.c */ X X/* the following is a kludge, but hides enormous organizational problems X * with Sun's headers */ X#ifdef TOOL_NULL Xextern Tool * NchessTool; X#endif Xextern void RunTool(), InitTool(), ParseToolArgs(); X X/* xdr.c */ X Xextern int XdrGameReq(), XdrMove(), XdrString(), XdrSetup(); X X/* undeclared system calls and library fxns */ X Xextern int getpid(); Xextern long random(); Xextern char * malloc(); END_OF_decls.h if test 2262 -ne `wc -c <decls.h`; then echo shar: \"decls.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f ipc.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"ipc.c\" else echo shar: Extracting \"ipc.c\" \(15504 characters\) sed "s/^X//" >ipc.c <<'END_OF_ipc.c' X/* X * Copyright 1987 Tom Anderson; 20831 Frank Waters Road; X * Stanwood, WA 98282. All rights reserved. X */ X X/* X * manage communication with the peer chess tool, if one exists. X * some communication functions with a background chess process are X * relayed by functions in this file. X */ X X#include <stdio.h> X#include <rpc/rpc.h> X#include <strings.h> X#include <errno.h> X#include <sys/time.h> X#include <sys/socket.h> X#include <pwd.h> X#include <signal.h> X X#include "nchess.h" X Xunsigned long MyProgNum = (u_long) 0; /* my program number */ Xunsigned long PeerProgNum; /* program number of peer */ Xchar * PeerHostName; /* host name of peer */ Xchar * PeerUserName; /* user name of peer */ XBOOL peerDead = FALSE; /* peer connection lost or chess program died */ X XBOOL UndoWanted = FALSE; /* undo was requested locally */ XBOOL RestoringGame = FALSE; /* restoring a saved game via the peer */ XSVCXPRT * Xprt; /* RPC service transport handle */ X X/* X * get a transient program number X */ Xunsigned long XgetTransient(vers, sockp) X unsigned long vers; X int * sockp; X{ X unsigned long progNum = 0x52000000L; X int s, len; X struct sockaddr_in addr; X X /* create a socket */ X if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { X fprintf(stderr, "can't create a socket\n"); X exit(1); X } X * sockp = s; X addr.sin_addr.s_addr = 0; X addr.sin_family = AF_INET; X addr.sin_port = 0; X len = sizeof(addr); X bind(s, (struct sockaddr *) &addr, len); X if (getsockname(s, (caddr_t) &addr, &len) < 0) { X fprintf(stderr, "getsockname failed\n"); X exit(1); X } X /* now find and reserve an available transient program number */ X while ( ! pmap_set(progNum++, vers, IPPROTO_UDP, addr.sin_port)) X continue; X return(progNum - 1); X} X X/* X * timed out the peer X */ Xvoid XpeerDied() X{ X Message("Lost connection to your opponent"); X peerDead = GameOver = TRUE; X Mouse = LOCKED; X} X X/* X * RPC procedure dispatch routine X */ Xvoid Xdispatch(request, xprt) X struct svc_req * request; X SVCXPRT * xprt; X{ X Move move; X SetupChange setup; X GameRequest gr; X char ans[80]; X int isUndoOK; X X switch (request->rq_proc) { X /* X * are you there? X */ X case NULLPROC: X if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) { X fprintf(stderr, "can't reply to remote peer\n"); X exit(1); X } X break; X /* X * game invitation accepted X */ X case ACCEPTPROCNUM: X if ( ! svc_getargs(xprt, XdrGameReq, &gr)) { X svcerr_decode(xprt); X exit(1); X } X if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) { X fprintf(stderr, "can't reply to remote peer\n"); X exit(1); X } X PeerProgNum = gr.progNum; X PeerColor = gr.color; X if (MyColor + PeerColor != WANTSWHITE + WANTSBLACK) { X switch(MyColor) { X /* I don't care - pick a color based on what the peer wants */ X case EITHERCOLOR: X switch(PeerColor) { X case WANTSBLACK: X MyColor = WANTSWHITE; X break; X case WANTSWHITE: X MyColor = WANTSBLACK; X break; X default: X fprintf(stderr, "color arbitration botch\n"); X exit(1); X } X break; X case WANTSBLACK: X if (PeerColor == WANTSBLACK) { X printf("Your opponent insists on playing black - is that OK? "); X scanf("%s", ans); X if (ans[0] == 'y' || ans[0] == 'Y') X MyColor = WANTSWHITE; X else { X fprintf(stderr, "couldn't agree on colors - bye\n"); X (void) callrpc(PeerHostName, PeerProgNum, VERSNUM, COLORFAILPROCNUM, X xdr_void, (caddr_t) 0, X xdr_void, (caddr_t) 0); X exit(1); X } X } X break; X case WANTSWHITE: X if (PeerColor == WANTSWHITE) { X printf("Your opponent insists on playing white - is that OK? "); X scanf("%s", ans); X if (ans[0] == 'y' || ans[0] == 'Y') X MyColor = WANTSBLACK; X else { X fprintf(stderr, "couldn't agree on colors - bye\n"); X (void) callrpc(PeerHostName, PeerProgNum, VERSNUM, COLORFAILPROCNUM, X xdr_void, (caddr_t) 0, X xdr_void, (caddr_t) 0); X exit(1); X } X } X break; X } X } X break; X /* X * the other player didn't ameliorate our insistence on color X */ X case COLORFAILPROCNUM: X fprintf(stderr, "couldn't agree on colors - bye\n"); X (void) svc_sendreply(xprt, xdr_void, (caddr_t) 0); X exit(1); X /* X * receive a move from the other player X */ X case MOVEPROCNUM: X if ( ! svc_getargs(xprt, XdrMove, &move)) { X fprintf(stderr, "can't get RPC args\n"); X exit(1); X } X if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) { X peerDied(); X } else { X DoMove(&move, TRUE); X Turn = MyColor; X Flashing = TRUE; X if (Mouse != CONFIRMING) X WhoseMoveMessage((char *) 0); X } X break; X /* X * receive a setup change from the other player X */ X case SETUPPROCNUM: X if ( ! svc_getargs(xprt, XdrSetup, &setup)) { X fprintf(stderr, "can't get RPC args\n"); X exit(1); X } X if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) { X peerDied(); X } else { X DoSetupChange(&setup); X } X break; X /* X * receive a restoration move from the other player's process X */ X case RESTOREMOVEPROCNUM: X if ( ! svc_getargs(xprt, XdrMove, &move)) { X fprintf(stderr, "can't get RPC args\n"); X exit(1); X } X if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) { X peerDied(); X } else { X DoMove(&move, TRUE); X Turn = OTHERCOLOR(Turn); X } X break; X /* X * restoration complete X */ X case ENDRESTOREPROCNUM: X if ( ! svc_getargs(xprt, xdr_int, &Turn)) { X fprintf(stderr, "can't get RPC args\n"); X exit(1); X } X if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) { X peerDied(); X } else { X WhoseMoveMessage((char *) 0); X RestoringGame = FALSE; X Mouse = IDLE; /* unlock the mouse */ X Flashing = (Turn == MyColor); X } X break; X /* X * other player wants to undo his previous move X */ X case UNDOPROCNUM: X if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) { X peerDied(); X } else { X RequestUndo(); X Flashing = TRUE; X } X break; X /* X * the other player blew away his tool. X */ X case GOODBYEPROCNUM: X svc_sendreply(xprt, xdr_void, (caddr_t) 0); X KillMouseActivity(); X peerDead = GameOver = TRUE; X Mouse = LOCKED; X Message("Your opponent killed his tool process"); X break; X /* X * other player is acknowledging our request to undo. X */ X case UNDOACKPROCNUM: X if ( ! svc_getargs(xprt, xdr_int, &isUndoOK)) { X fprintf(stderr, "can't get RPC args\n"); X exit(1); X } X if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) { X peerDied(); X } else { X if (isUndoOK) { X UnDoMove(); X if (Turn == MyColor) X UnDoMove(); X else X Turn = MyColor; X WhoseMoveMessage("Undo accepted"); X } else { X WhoseMoveMessage("Undo refused"); X } X UndoWanted = FALSE; X Mouse = IDLE; X Flashing = TRUE; X } X break; X /* X * other player resigned X */ X case RESIGNPROCNUM: X if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) X peerDead = TRUE; X Message(PeerColor == BLACK ? "Black resigns" : "White resigns"); X KillMouseActivity(); X Mouse = LOCKED; /* game is over */ X DoResignation(OTHERCOLOR(MyColor)); X Flashing = TRUE; X break; X case MSGPROCNUM: X if ( ! svc_getargs(xprt, XdrString, ans)) { X fprintf(stderr, "can't get RPC args\n"); X exit(1); X } X if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) { X peerDied(); X } else { X RecvTalkMsg(ans); X Flashing = TRUE; X } X break; X } X} X X X/* X * outstanding invitation - shared by InitRPC() and quitEarly(). X */ XGameRequest gr; X X/* X * cancel our invitation with the remote daemon if we receive a signal X * before the invitee responds. X */ XquitEarly() X{ X callrpc(PeerHostName, SERVERPROGNUM, VERSNUM, CANCELPROCNUM, X XdrGameReq, (caddr_t) &gr, X xdr_void, (caddr_t) 0); X exit(1); X} X X/* X * initialize the RPC connection, using the user's "user@host" arg. X */ Xvoid XInitRPC(cp, progName) X char * cp, * progName; X{ X GameRequest gr2; X int sock, rfds; X char localHostName[256], ans[80]; X BOOL resumeGame = FALSE; X X /* X * decipher the remote host and user strings X */ X if (cp == (char *) 0 || (PeerHostName = index(cp, '@')) == (char *) 0) { X fprintf(stderr, "%s: illegal/non-existent user@host arg\n", progName); X exit(1); X } X *PeerHostName++ = '\0'; X PeerUserName = cp; X /* X * determine the local host and user names X */ X if (gethostname(localHostName, sizeof(localHostName)) != 0) { X fprintf(stderr, "%s: can't determine local host name\n", progName); X exit(1); X } X /* X * generate the transient RPC program number used by this player. X */ X MyProgNum = getTransient(VERSNUM, &sock); X if ((Xprt = svcudp_create(sock)) == (SVCXPRT *) 0) { X fprintf(stderr, "svcudp_create failed\n"); X exit(1); X } X /* X * register the peer-to-peer RPC dispatch procedure X */ X (void) svc_register(Xprt, MyProgNum, VERSNUM, dispatch, 0L); X /* X * check for an invitation registered with the local chess X * daemon, indicating that we are responding to an invitation. X */ X (void) strcpy(gr.userName, PeerUserName); X (void) strcpy(gr.hostName, PeerHostName); X if (callrpc(localHostName, SERVERPROGNUM, VERSNUM, ACKPROCNUM, X XdrGameReq, (caddr_t) &gr, X XdrGameReq, (caddr_t) &gr2) != 0) X { X fprintf(stderr, "error: callrpc of local daemon (%s)\n", localHostName); X exit(1); X } X PeerProgNum = gr2.progNum; X PeerColor = gr2.color; X resumeGame = gr2.resumeGame; X do { X /* X * if no invitation was registered or the remote program X * is no longer running, X * then register an invitation with the remote daemon. X */ X if (PeerProgNum == 0L X || callrpc(PeerHostName, PeerProgNum, VERSNUM, NULLPROC, X xdr_void, (caddr_t) 0, X xdr_void, (caddr_t) 0) != 0) X { X gr.progNum = MyProgNum; X gr.color = MyColor; X gr.resumeGame = (RestoreFile != (FILE *) 0 || SetupMode); X (void) strcpy(gr.userName, UserPWEntry->pw_name); X (void) strcpy(gr.hostName, localHostName); X signal(SIGINT, quitEarly); X signal(SIGQUIT, quitEarly); X signal(SIGHUP, quitEarly); X if (callrpc(PeerHostName, SERVERPROGNUM, VERSNUM, REQPROCNUM, X XdrGameReq, (caddr_t) &gr, X xdr_void, (caddr_t) 0) != 0) X { X fprintf(stderr, "error: callrpc of remote daemon\n"); X exit(1); X } X printf("waiting for %s to respond...\n", PeerUserName); X /* X * wait for the remote peer to send us his program number and color X */ X do { X rfds = svc_fds; X switch(select(32, &rfds, (int *) 0, (int *) 0, (struct timeval *) 0)) { X case -1: X if (errno == EINTR) X continue; X fprintf(stderr, "RPC select botch\n"); X exit(1); X case 0: X break; X default: X svc_getreq(rfds); X break; X } X } while(PeerProgNum == 0L); X signal(SIGINT, SIG_DFL); X signal(SIGQUIT, SIG_DFL); X signal(SIGHUP, SIG_DFL); X } X /* X * else accept the invitation, sending the remote program X * our program number and color. X */ X else { X if (resumeGame) { X MyColor = EITHERCOLOR; X RestoringGame = TRUE; X SetupMode = FALSE; X } X /* try to pre-arrange colors */ X if (MyColor + PeerColor != WANTSWHITE + WANTSBLACK) { X switch(MyColor) { X /* I don't care - pick a color based on what the peer wants */ X case EITHERCOLOR: X switch(PeerColor) { X case EITHERCOLOR: X MyColor = (random() & 0x01) ? WANTSBLACK : WANTSWHITE; X break; X case WANTSBLACK: X MyColor = WANTSWHITE; X break; X case WANTSWHITE: X MyColor = WANTSBLACK; X break; X } X break; X case WANTSBLACK: X if (PeerColor == WANTSBLACK) { X printf("%s also wants to play black - is that OK? ", PeerUserName); X scanf("%s", ans); X if (ans[0] == 'y' || ans[0] == 'Y') X MyColor = WANTSWHITE; X } X break; X case WANTSWHITE: X if (PeerColor == WANTSWHITE) { X printf("%s also wants to play white - is that OK? ", PeerUserName); X scanf("%s", ans); X if (ans[0] == 'y' || ans[0] == 'Y') X MyColor = WANTSBLACK; X } X break; X } X } X gr.progNum = MyProgNum; X gr.color = MyColor; X if (callrpc(PeerHostName, PeerProgNum, VERSNUM, ACCEPTPROCNUM, X XdrGameReq, (caddr_t) &gr, X xdr_void, (caddr_t) 0) != 0) X { X PeerProgNum = 0L; X } X } X } while(PeerProgNum == 0L); X PeerColor = OTHERCOLOR(MyColor); X PlayerName[MyColor] = UserPWEntry->pw_name; X PlayerName[PeerColor] = PeerUserName; X /* X * if the other player is shipping us the game state, lock the X * mouse in the meantime. X */ X if (RestoringGame) X Mouse = LOCKED; X} X X/* X * send a move to the 'color' player X */ XBOOL XSendMove(move, color) X Move * move; X int color; X{ X if ( ! peerDead) { X if (IsMachine[color]) { X SendMachineMove(move, color); X } else if (callrpc(PeerHostName, PeerProgNum, VERSNUM, MOVEPROCNUM, X XdrMove, (caddr_t) move, X xdr_void, (caddr_t) 0) != 0) X { X peerDied(); X } X } X return( ! peerDead); X} X Xvoid XSendRestoreMove(move, color) X Move * move; X int color; X{ X if ( ! IsMachine[color] X && ! peerDead X && callrpc(PeerHostName, PeerProgNum, VERSNUM, RESTOREMOVEPROCNUM, X XdrMove, (caddr_t) move, X xdr_void, (caddr_t) 0) != 0) X { X peerDied(); X } X} X Xvoid XSendEndRestore() X{ X if ( ! peerDead X && callrpc(PeerHostName, PeerProgNum, VERSNUM, ENDRESTOREPROCNUM, X xdr_int, (caddr_t) &Turn, X xdr_void, (caddr_t) 0) != 0) X { X peerDied(); X } X} X Xvoid XSendUndoRequest(color) X int color; X{ X if ( ! peerDead) { X if (IsMachine[color]) { X if (Turn != MyColor) { X Message("Will undo after machine moves..."); X } else { X MachineUndo(color); X UndoWanted = FALSE; X Mouse = IDLE; X } X } else { X Message("Sending undo request to your opponent (please wait)..."); X if (callrpc(PeerHostName, PeerProgNum, VERSNUM, UNDOPROCNUM, X xdr_void, (caddr_t) 0, X xdr_void, (caddr_t) 0) != 0) X { X peerDied(); X } X } X } X} X Xvoid XSendResignation(color) X int color; X{ X if ( ! peerDead) { X if (IsMachine[color]) { X KillChessProcesses(); X } else if (callrpc(PeerHostName, PeerProgNum, VERSNUM, RESIGNPROCNUM, X xdr_void, (caddr_t) 0, X xdr_void, (caddr_t) 0) != 0) X { X peerDied(); X } X } X} X Xvoid XSendTalkMsg(cp) X char * cp; X{ X if ( ! peerDead X && callrpc(PeerHostName, PeerProgNum, VERSNUM, MSGPROCNUM, X XdrString, (caddr_t) cp, X xdr_void, (caddr_t) 0) != 0) X { X peerDied(); X } X} X Xvoid XSendSetupChange(setup, color) X SetupChange * setup; X int color; X{ X if ( ! IsMachine[color] X && ! peerDead X && callrpc(PeerHostName, PeerProgNum, VERSNUM, SETUPPROCNUM, X XdrSetup, (caddr_t) setup, X xdr_void, (caddr_t) 0) != 0) X { X peerDied(); X } X} X Xvoid XSendUndoAcknowledgement(isUndoOK) X int isUndoOK; X{ X if (callrpc(PeerHostName, PeerProgNum, VERSNUM, UNDOACKPROCNUM, X xdr_int, (caddr_t) &isUndoOK, X xdr_void, (caddr_t) 0) != 0) X { X peerDied(); X } else if (isUndoOK) { X UnDoMove(); X if (Turn == MyColor) X Turn = OTHERCOLOR(MyColor); X else X UnDoMove(); X Message(MyColor == WHITE ? X "Waiting for black to re-play..." : X "Waiting for white to re-play..."); X } else X WhoseMoveMessage((char *) 0); X} X Xvoid XSendGoodbye() X{ X if ( ! IsMachine[PeerColor] && ! peerDead) { X callrpc(PeerHostName, PeerProgNum, VERSNUM, GOODBYEPROCNUM, X xdr_void, (caddr_t) 0, X xdr_void, (caddr_t) 0); X } X if (MyProgNum != 0) { X /* unregister the RPC transport handle */ X xprt_unregister(Xprt); X /* release my program number for re-use */ X pmap_unset(MyProgNum, VERSNUM); X } X} END_OF_ipc.c if test 15504 -ne `wc -c <ipc.c`; then echo shar: \"ipc.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f main.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"main.c\" else echo shar: Extracting \"main.c\" \(6364 characters\) sed "s/^X//" >main.c <<'END_OF_main.c' X/* X * Copyright 1987 Tom Anderson; 20831 Frank Waters Road; X * Stanwood, WA 98282. All rights reserved. X */ X X/* X * main client part of network chess. X */ X X#include <stdio.h> X#include <strings.h> X#include <errno.h> X#include <suntool/tool_hs.h> X#include <pwd.h> X X#include "nchess.h" X Xint errno; /* global error number */ X Xchar * TranscriptFileName = "nchess.transcript"; Xint TranscriptType = TR_MIN_NORMAL; Xchar * SaveFileName = "nchess.save"; Xchar * PlayerName[2]; XBOOL SetupMode = FALSE; XBOOL IsMachine[2] = { FALSE, FALSE }; XFILE * RestoreFile; /* restoration file */ Xstruct passwd * UserPWEntry; X X#define MAXCHESSPROCARGS 16 Xchar * ChessProcessArgs[2][MAXCHESSPROCARGS]; X X/* X * walk away from the game in the middle on receipt of an appropriate X * signal X */ XbobbyFischer() X{ X /* kill any and all chess processes */ X KillChessProcesses(); X /* send a goodbye to the peer */ X SendGoodbye(); X exit(1); X} X Xmain(argc, argv) X int argc; X char ** argv; X{ X register int i, j; X char * cp = (char *) 0, * iconDirectory = (char *) 0; X int chessArgIndex[2]; X BOOL useRetained = TRUE; X X if ((UserPWEntry = getpwuid(getuid())) == (struct passwd *) 0) { X fputs("Can't determine who you are\n", stderr); X exit(1); X } X chessArgIndex[BLACK] = chessArgIndex[WHITE] = 0; X /* randomize things a bit */ X (void) srandom((long) getpid()); X /* parse and strip out the tool-related arguments */ X ParseToolArgs(&argc, argv); X /* scan the remaining argument list */ X for (i = 1 ; i < argc ; i++) { X if (argv[i][0] == '-') { X switch (argv[i][1]) { X case 'c': X useRetained = FALSE; /* use a retained pixrect for the board */ X break; X case 'v': X MachineDebug = TRUE; /* turn on chess program i/f debugging */ X break; X case 'd': /* custom piece icon directory name */ X if (argv[i][j=2] == '\0' && (j = 0 , ++i >= argc)) { X fprintf(stderr, "%s: bad piece icon directory name arg\n", argv[0]); X exit(1); X } X iconDirectory = &argv[i][j]; X break; X case 'b': /* wants to play the black pieces */ X MyColor = WANTSBLACK; X break; X case 'w': /* wants to play the white pieces */ X MyColor = WANTSWHITE; X break; X case 'x': /* specify transcript notation type */ X if (argv[i][j=2] == '\0' && (j = 0 , ++i >= argc) X || sscanf(&argv[i][j], "%d", &TranscriptType) != 1 X || TranscriptType < TR_MIN_TYPE X || TranscriptType > TR_MAX_TYPE) { X fprintf(stderr, "%s: bad transcript mode arg\n", argv[0]); X exit(1); X } X break; X case 't': /* specify transcript file name */ X if (argv[i][j=2] == '\0' && (j = 0 , ++i >= argc)) { X fprintf(stderr, "%s: bad transcript filename arg\n", argv[0]); X exit(1); X } X TranscriptFileName = &argv[i][j]; X break; X case 's': /* specify save file name */ X if (argv[i][j=2] == '\0' && (j = 0 , ++i >= argc)) { X fprintf(stderr, "%s: bad save filename arg\n", argv[0]); X exit(1); X } X SaveFileName = &argv[i][j]; X break; X case 'r': X if (argv[i][j=2] == '\0' && (j = 0 , ++i >= argc) X || ((RestoreFile = fopen(&argv[i][j], "r")) == (FILE *) 0)) { X fprintf(stderr, "%s: bad restore file arg\n", argv[0]); X exit(1); X } X if (fread((caddr_t) &MyColor, sizeof(MyColor), 1, RestoreFile) != 1) { X fputs("Bad save file\n", stderr); X exit(1); X } X break; X case 'e': X SetupMode = TRUE; X Mouse = SETUP; X break; X case 'm': X IsMachine[WHITE] = TRUE; X if (argv[i][j=2] == '\0' && (j = 0 , ++i >= argc)) { X fprintf(stderr, "%s: bad chess program arg\n", argv[0]); X exit(1); X } X if (chessArgIndex[WHITE] >= MAXCHESSPROCARGS - 1) { X fprintf(stderr, "%s: too many chess program args\n", argv[0]); X exit(1); X } X ChessProcessArgs[WHITE][chessArgIndex[WHITE]++] = &argv[i][j]; X ChessProcessArgs[WHITE][chessArgIndex[WHITE]] = (char *) 0; X break; X case 'n': X IsMachine[BLACK] = TRUE; X if (argv[i][j=2] == '\0' && (j = 0 , ++i >= argc)) { X fprintf(stderr, "%s: bad chess program arg\n", argv[0]); X exit(1); X } X if (chessArgIndex[BLACK] >= MAXCHESSPROCARGS - 1) { X fprintf(stderr, "%s: too many chess program args\n", argv[0]); X exit(1); X } X ChessProcessArgs[BLACK][chessArgIndex[BLACK]++] = &argv[i][j]; X ChessProcessArgs[BLACK][chessArgIndex[BLACK]] = (char *) 0; X break; X } X } else X cp = argv[i]; X } X if (SetupMode && RestoreFile != (FILE *) 0) { X fprintf(stderr, "%s: can only specify one of -r and -s\n", argv[0]); X exit(1); X } X /* X * if white is a machine, start up the white chess process and X * force us to play the black pieces (if we get to play at all) X */ X if (IsMachine[WHITE]) { X InitChessProcess(ChessProcessArgs[WHITE], WHITE, X ! SetupMode && RestoreFile == (FILE *) 0); X PlayerName[WHITE] = ChessProcessArgs[WHITE][0]; X MyColor = BLACK; X } X /* X * if black is a machine, start up the black chess process and X * force us to play the white pieces (if we get to play at all) X */ X if (IsMachine[BLACK]) { X InitChessProcess(ChessProcessArgs[BLACK], BLACK, FALSE); X PlayerName[BLACK] = ChessProcessArgs[BLACK][0]; X MyColor = WHITE; X } X /* X * if both players are human, initialize the peer-to-peer RPC X * "connection" X */ X if ( ! IsMachine[WHITE] && ! IsMachine[BLACK]) { X InitRPC(cp, argv[0]); X /* X * else if both players are machines, lock the mouse to avoid X * spectator interference (unless the spectator is going to set X * up the cannon fodder first) X */ X } else if (IsMachine[WHITE] && IsMachine[BLACK]) { X if ( ! SetupMode) X Mouse = LOCKED; /* lock out the mouse */ X /* X * else the user is playing a machine X */ X } else { X PlayerName[MyColor] = UserPWEntry->pw_name; X PeerColor = OTHERCOLOR(MyColor); X } X signal(SIGINT, bobbyFischer); X signal(SIGQUIT, bobbyFischer); X signal(SIGHUP, bobbyFischer); X /* initialize the board state */ X InitBoard(); X /* X * if we want to restore the game and our opponent hasn't beaten X * us to it, try to do it now X */ X if (RestoreFile != (FILE *) 0 && ! RestoringGame) X RestoreGame(); X /* initialize and install the tool */ X InitTool(useRetained, iconDirectory); X tool_install(NchessTool); X /* now play the game */ X RunTool(); X /* post-game cleanup */ X KillChessProcesses(); X SendGoodbye(); X} X END_OF_main.c if test 6364 -ne `wc -c <main.c`; then echo shar: \"main.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f msgsw.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"msgsw.c\" else echo shar: Extracting \"msgsw.c\" \(1793 characters\) sed "s/^X//" >msgsw.c <<'END_OF_msgsw.c' X/* X * Copyright 1987 Tom Anderson; 20831 Frank Waters Road; X * Stanwood, WA 98282. All rights reserved. X */ X X/* X * message subwindow handling X */ X X#include <stdio.h> X#include <ctype.h> X#include <suntool/tool_hs.h> X#include <suntool/panel.h> X#include <strings.h> X X#include "nchess.h" X Xstruct toolsw * MessageSW; XPanel MessagePanel; X XPanel_item MessageItem; X X/* X * set up the message subwindow X */ Xvoid XInitMsgSW() X{ X if ((MessageSW = panel_create(NchessTool, 0)) == NULL) { X fprintf(stderr, "Can't create message panel\n"); X exit(1); X } X MessagePanel = MessageSW->ts_data; X /* create the message panel item */ X MessageItem = panel_create_item(MessagePanel, PANEL_MESSAGE, X PANEL_LABEL_STRING, X RestoringGame ? "Please wait..." : X SetupMode ? "Setup: left - source, middle - delete, right - end" : X IsMachine[Turn] || Turn != MyColor ? X (Turn == WHITE ? X "Waiting for white to play..." : X "Waiting for black to play...") : X "Your move" , X PANEL_SHOW_ITEM, TRUE, X 0); X panel_fit_height(MessagePanel); X} X Xvoid XMessage(cp) X char * cp; X{ X panel_set(MessageItem, X PANEL_LABEL_STRING, cp, X PANEL_SHOW_ITEM, TRUE, X 0); X} X X/* X * write the standard "your move", "waiting ..." message X * pre-pended with the passed string (if non-null) X */ Xvoid XWhoseMoveMessage(cp) X char * cp; X{ X char c1[256], c2[256]; X X if (GameOver) X strcpy(c2, "Game over"); X else if (IsMachine[Turn] || Turn != MyColor) X strcpy(c2, Turn == WHITE ? X "Waiting for white to play..." : X "Waiting for black to play..."); X else if (InCheck()) X strcpy(c2, "Your move (check)"); X else X strcpy(c2, "Your move"); X X if (cp != (char *) 0) { X c2[0] = tolower(c2[0]); X strcpy(c1, cp); X strcat(c1, " - "); X Message(strcat(c1, c2)); X } else X Message(c2); X} X END_OF_msgsw.c if test 1793 -ne `wc -c <msgsw.c`; then echo shar: \"msgsw.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f tool.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"tool.c\" else echo shar: Extracting \"tool.c\" \(3131 characters\) sed "s/^X//" >tool.c <<'END_OF_tool.c' X/* X * Copyright 1987 Tom Anderson; 20831 Frank Waters Road; X * Stanwood, WA 98282. All rights reserved. X */ X X/* X * handle the tool environment X */ X X#include <stdio.h> X#include <suntool/tool_hs.h> X#include <suntool/panel.h> X#include <suntool/gfxsw.h> X#include <sys/resource.h> X#include <sys/ioctl.h> X#include <strings.h> X X#include "nchess.h" X XTool * NchessTool; Xchar ** ToolAttrs = (char **) NULL; Xchar * ToolName; X X/* X * iconic form of window X */ Xunsigned short IconImage[] = { X#include "Icons/nchess.icon" X}; X XDEFINE_ICON_FROM_IMAGE(WindowIcon, IconImage); X Xsigwinched() X{ X tool_sigwinch(NchessTool); X} X X/* X * parse the tool args. X */ Xvoid XParseToolArgs(argc, argv) X int *argc; X char **argv; X{ X ToolName = argv[0]; X (*argc)--; X argv++; X if (tool_parse_all(argc, argv, &ToolAttrs, ToolName) == -1) { X tool_usage(ToolName); X exit(1); X } X (*argc)++; X} X X/* X * set up the tool environment X */ Xvoid XInitTool(useRetained, iconDirectory) X BOOL useRetained; /* use a retained pixrect for the board */ X char * iconDirectory; /* custom piece icon directory */ X{ X register unsigned int height; X register Toolsw * twsp; X char c[256]; X X /* create the tool marquee */ X strcpy(c, " "); X strcat(c, PlayerName[WHITE]); X strcat(c, " vs. "); X strcat(c, PlayerName[BLACK]); X if ((NchessTool = tool_make( X WIN_LABEL, c, X WIN_ICON, &WindowIcon, X WIN_ATTR_LIST, ToolAttrs, X WIN_WIDTH, 8 * (SQUARE_WIDTH-1) + 2 * tool_borderwidth(NchessTool) - 1, X /* X * NOTE: The following line was unnecessary in Sun release 2.2, X * but is necessary in release 3.0. For some unknown reason, the X * call to tool_set_attributes following the call to InitBoardSW X * now fails to uncover the board area that was obscured by the X * default tool height being too small (note that the tool has not X * been installed yet). X */ X WIN_HEIGHT, 2000, X 0)) == (Tool *) NULL) X { X fputs("Can't make tool\n", stderr); X exit(1); X } X tool_free_attribute_list(ToolAttrs); X /* initialize the subwindows */ X InitTalkSW(); X InitMsgSW(); X InitControlSW(); X InitBoardSW(useRetained, iconDirectory); X /* X * add up subwindow heights and force the tool to the resulting size X */ X height = tool_stripeheight(NchessTool) + tool_borderwidth(NchessTool) - tool_subwindowspacing(NchessTool); X for (twsp = NchessTool->tl_sw ; twsp != (Toolsw *) 0 ; twsp = twsp->ts_next) X height += twsp->ts_height + tool_subwindowspacing(NchessTool); X /* X * NOTE: under 2.2, the above calculation yielded the correct height. X * under 3.0, we need to add a few pixels to make it come out right (the X * reason is not yet known). X */ X height += 2; X tool_set_attributes(NchessTool, WIN_HEIGHT, height, 0); X signal(SIGWINCH, sigwinched); X} X Xvoid XRunTool() X{ X /* X * NOTE: this is another difference between release 2.2 and 3.0: X * in release 2.2, the SIGWINCH handler would get called once at the X * outset to draw the board area; in release 3.0, this doesn't happen. X */ X DrawBoard(); X tool_select(NchessTool, 0); X tool_destroy(NchessTool); X} X END_OF_tool.c if test 3131 -ne `wc -c <tool.c`; then echo shar: \"tool.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 3 \(of 4\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 4 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 4 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archivelor;; Xcp