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