Article View: net.sources.games
Article #763network chess (4 of 5)
From: Tom Anderson
Date: Thu, 08 Jan 1987 23:51
Date: Thu, 08 Jan 1987 23:51
940 lines
23927 bytes
23927 bytes
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by spock!toma on Thu Jan 8 14:33:58 PST 1987
# Contents: ipc.c tool.c controlsw.c
echo x - ipc.c
sed 's/^@//' > "ipc.c" <<'@//E*O*F ipc.c//'
/*
* manage communication with the peer chess tool, if one exists.
* some communication functions with a background chess process are
* relayed by functions in this file.
*/
#include <stdio.h>
#include <rpc/rpc.h>
#include <strings.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <pwd.h>
#include <signal.h>
#include "nchess.h"
unsigned long MyProgNum = (u_long) 0; /* my program number */
unsigned long PeerProgNum; /* program number of peer */
char * PeerHostName; /* host name of peer */
char * PeerUserName; /* user name of peer */
BOOL peerDead = FALSE; /* peer connection lost or chess program died */
BOOL UndoWanted = FALSE; /* undo was requested locally */
BOOL RestoringGame = FALSE; /* restoring a saved game via the peer */
SVCXPRT * Xprt; /* RPC service transport handle */
/*
* get a transient program number
*/
unsigned long
getTransient(vers, sockp)
unsigned long vers;
int * sockp;
{
unsigned long progNum = 0x52000000L;
int s, len;
struct sockaddr_in addr;
/* create a socket */
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
fprintf(stderr, "can't create a socket\n");
exit(1);
}
* sockp = s;
addr.sin_addr.s_addr = 0;
addr.sin_family = AF_INET;
addr.sin_port = 0;
len = sizeof(addr);
bind(s, (struct sockaddr *) &addr, len);
if (getsockname(s, (caddr_t) &addr, &len) < 0) {
fprintf(stderr, "getsockname failed\n");
exit(1);
}
/* now find and reserve an available transient program number */
while ( ! pmap_set(progNum++, vers, IPPROTO_UDP, addr.sin_port))
continue;
return(progNum - 1);
}
/*
* timed out the peer
*/
void
peerDied()
{
Message("Lost connection to your opponent");
peerDead = GameOver = TRUE;
Mouse = LOCKED;
}
/*
* RPC procedure dispatch routine
*/
void
dispatch(request, xprt)
struct svc_req * request;
SVCXPRT * xprt;
{
Move move;
SetupChange setup;
GameRequest gr;
char ans[80];
int isUndoOK;
switch (request->rq_proc) {
/*
* are you there?
*/
case NULLPROC:
if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) {
fprintf(stderr, "can't reply to remote peer\n");
exit(1);
}
break;
/*
* game invitation accepted
*/
case ACCEPTPROCNUM:
if ( ! svc_getargs(xprt, XdrGameReq, &gr)) {
svcerr_decode(xprt);
exit(1);
}
if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) {
fprintf(stderr, "can't reply to remote peer\n");
exit(1);
}
PeerProgNum = gr.progNum;
PeerColor = gr.color;
if (MyColor + PeerColor != WANTSWHITE + WANTSBLACK) {
switch(MyColor) {
/* I don't care - pick a color based on what the peer wants */
case EITHERCOLOR:
switch(PeerColor) {
case WANTSBLACK:
MyColor = WANTSWHITE;
break;
case WANTSWHITE:
MyColor = WANTSBLACK;
break;
default:
fprintf(stderr, "color arbitration botch\n");
exit(1);
}
break;
case WANTSBLACK:
if (PeerColor == WANTSBLACK) {
printf("Your opponent insists on playing black - is that OK? ");
scanf("%s", ans);
if (ans[0] == 'y' || ans[0] == 'Y')
MyColor = WANTSWHITE;
else {
fprintf(stderr, "couldn't agree on colors - bye\n");
(void) callrpc(PeerHostName, PeerProgNum, VERSNUM, COLORFAILPROCNUM,
xdr_void, (caddr_t) 0,
xdr_void, (caddr_t) 0);
exit(1);
}
}
break;
case WANTSWHITE:
if (PeerColor == WANTSWHITE) {
printf("Your opponent insists on playing white - is that OK? ");
scanf("%s", ans);
if (ans[0] == 'y' || ans[0] == 'Y')
MyColor = WANTSBLACK;
else {
fprintf(stderr, "couldn't agree on colors - bye\n");
(void) callrpc(PeerHostName, PeerProgNum, VERSNUM, COLORFAILPROCNUM,
xdr_void, (caddr_t) 0,
xdr_void, (caddr_t) 0);
exit(1);
}
}
break;
}
}
break;
/*
* the other player didn't ameliorate our insistence on color
*/
case COLORFAILPROCNUM:
fprintf(stderr, "couldn't agree on colors - bye\n");
(void) svc_sendreply(xprt, xdr_void, (caddr_t) 0);
exit(1);
/*
* receive a move from the other player
*/
case MOVEPROCNUM:
if ( ! svc_getargs(xprt, XdrMove, &move)) {
fprintf(stderr, "can't get RPC args\n");
exit(1);
}
if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) {
peerDied();
} else {
DoMove(&move, TRUE);
Turn = MyColor;
Flashing = TRUE;
if (Mouse != CONFIRMING)
WhoseMoveMessage((char *) 0);
}
break;
/*
* receive a setup change from the other player
*/
case SETUPPROCNUM:
if ( ! svc_getargs(xprt, XdrSetup, &setup)) {
fprintf(stderr, "can't get RPC args\n");
exit(1);
}
if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) {
peerDied();
} else {
DoSetupChange(&setup);
}
break;
/*
* receive a restoration move from the other player's process
*/
case RESTOREMOVEPROCNUM:
if ( ! svc_getargs(xprt, XdrMove, &move)) {
fprintf(stderr, "can't get RPC args\n");
exit(1);
}
if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) {
peerDied();
} else {
DoMove(&move, TRUE);
Turn = OTHERCOLOR(Turn);
}
break;
/*
* restoration complete
*/
case ENDRESTOREPROCNUM:
if ( ! svc_getargs(xprt, xdr_int, &Turn)) {
fprintf(stderr, "can't get RPC args\n");
exit(1);
}
if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) {
peerDied();
} else {
WhoseMoveMessage((char *) 0);
RestoringGame = FALSE;
Mouse = IDLE; /* unlock the mouse */
Flashing = (Turn == MyColor);
}
break;
/*
* other player wants to undo his previous move
*/
case UNDOPROCNUM:
if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) {
peerDied();
} else {
RequestUndo();
Flashing = TRUE;
}
break;
/*
* the other player blew away his tool.
*/
case GOODBYEPROCNUM:
svc_sendreply(xprt, xdr_void, (caddr_t) 0);
KillMouseActivity();
peerDead = GameOver = TRUE;
Mouse = LOCKED;
Message("Your opponent killed his tool process");
break;
/*
* other player is acknowledging our request to undo.
*/
case UNDOACKPROCNUM:
if ( ! svc_getargs(xprt, xdr_int, &isUndoOK)) {
fprintf(stderr, "can't get RPC args\n");
exit(1);
}
if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) {
peerDied();
} else {
if (isUndoOK) {
UnDoMove();
if (Turn == MyColor)
UnDoMove();
else
Turn = MyColor;
WhoseMoveMessage("Undo accepted");
} else {
WhoseMoveMessage("Undo refused");
}
UndoWanted = FALSE;
Mouse = IDLE;
Flashing = TRUE;
}
break;
/*
* other player resigned
*/
case RESIGNPROCNUM:
if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0))
peerDead = TRUE;
Message(PeerColor == BLACK ? "Black resigns" : "White resigns");
KillMouseActivity();
Mouse = LOCKED; /* game is over */
DoResignation(OTHERCOLOR(MyColor));
Flashing = TRUE;
break;
case MSGPROCNUM:
if ( ! svc_getargs(xprt, XdrString, ans)) {
fprintf(stderr, "can't get RPC args\n");
exit(1);
}
if ( ! svc_sendreply(xprt, xdr_void, (caddr_t) 0)) {
peerDied();
} else {
RecvTalkMsg(ans);
Flashing = TRUE;
}
break;
}
}
/*
* outstanding invitation - shared by InitRPC() and quitEarly().
*/
GameRequest gr;
/*
* cancel our invitation with the remote daemon if we receive a signal
* before the invitee responds.
*/
quitEarly()
{
callrpc(PeerHostName, SERVERPROGNUM, VERSNUM, CANCELPROCNUM,
XdrGameReq, (caddr_t) &gr,
xdr_void, (caddr_t) 0);
exit(1);
}
/*
* initialize the RPC connection, using the user's "user@host" arg.
*/
void
InitRPC(cp, progName)
char * cp, * progName;
{
GameRequest gr2;
int sock, rfds;
char localHostName[256], ans[80];
BOOL resumeGame = FALSE;
/*
* decipher the remote host and user strings
*/
if (cp == (char *) 0 || (PeerHostName = index(cp, '@')) == (char *) 0) {
fprintf(stderr, "%s: illegal/non-existent user@host arg\n", progName);
exit(1);
}
*PeerHostName++ = '\0';
PeerUserName = cp;
/*
* determine the local host and user names
*/
if (gethostname(localHostName, sizeof(localHostName)) != 0) {
fprintf(stderr, "%s: can't determine local host name\n", progName);
exit(1);
}
/*
* generate the transient RPC program number used by this player.
*/
MyProgNum = getTransient(VERSNUM, &sock);
if ((Xprt = svcudp_create(sock)) == (SVCXPRT *) 0) {
fprintf(stderr, "svcudp_create failed\n");
exit(1);
}
/*
* register the peer-to-peer RPC dispatch procedure
*/
(void) svc_register(Xprt, MyProgNum, VERSNUM, dispatch, 0L);
/*
* check for an invitation registered with the local chess
* daemon, indicating that we are responding to an invitation.
*/
(void) strcpy(gr.userName, PeerUserName);
(void) strcpy(gr.hostName, PeerHostName);
if (callrpc(localHostName, SERVERPROGNUM, VERSNUM, ACKPROCNUM,
XdrGameReq, (caddr_t) &gr,
XdrGameReq, (caddr_t) &gr2) != 0)
{
fprintf(stderr, "error: callrpc of local daemon (%s)\n", localHostName);
exit(1);
}
PeerProgNum = gr2.progNum;
PeerColor = gr2.color;
resumeGame = gr2.resumeGame;
do {
/*
* if no invitation was registered or the remote program
* is no longer running,
* then register an invitation with the remote daemon.
*/
if (PeerProgNum == 0L
|| callrpc(PeerHostName, PeerProgNum, VERSNUM, NULLPROC,
xdr_void, (caddr_t) 0,
xdr_void, (caddr_t) 0) != 0)
{
gr.progNum = MyProgNum;
gr.color = MyColor;
gr.resumeGame = (RestoreFile != (FILE *) 0 || SetupMode);
(void) strcpy(gr.userName, UserPWEntry->pw_name);
(void) strcpy(gr.hostName, localHostName);
signal(SIGINT, quitEarly);
signal(SIGQUIT, quitEarly);
signal(SIGHUP, quitEarly);
if (callrpc(PeerHostName, SERVERPROGNUM, VERSNUM, REQPROCNUM,
XdrGameReq, (caddr_t) &gr,
xdr_void, (caddr_t) 0) != 0)
{
fprintf(stderr, "error: callrpc of remote daemon\n");
exit(1);
}
printf("waiting for %s to respond...\n", PeerUserName);
/*
* wait for the remote peer to send us his program number and color
*/
do {
rfds = svc_fds;
switch(select(32, &rfds, (int *) 0, (int *) 0, (struct timeval *) 0)) {
case -1:
if (errno == EINTR)
continue;
fprintf(stderr, "RPC select botch\n");
exit(1);
case 0:
break;
default:
svc_getreq(rfds);
break;
}
} while(PeerProgNum == 0L);
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGHUP, SIG_DFL);
}
/*
* else accept the invitation, sending the remote program
* our program number and color.
*/
else {
if (resumeGame) {
MyColor = EITHERCOLOR;
RestoringGame = TRUE;
SetupMode = FALSE;
}
/* try to pre-arrange colors */
if (MyColor + PeerColor != WANTSWHITE + WANTSBLACK) {
switch(MyColor) {
/* I don't care - pick a color based on what the peer wants */
case EITHERCOLOR:
switch(PeerColor) {
case EITHERCOLOR:
MyColor = (random() & 0x01) ? WANTSBLACK : WANTSWHITE;
break;
case WANTSBLACK:
MyColor = WANTSWHITE;
break;
case WANTSWHITE:
MyColor = WANTSBLACK;
break;
}
break;
case WANTSBLACK:
if (PeerColor == WANTSBLACK) {
printf("%s also wants to play black - is that OK? ", PeerUserName);
scanf("%s", ans);
if (ans[0] == 'y' || ans[0] == 'Y')
MyColor = WANTSWHITE;
}
break;
case WANTSWHITE:
if (PeerColor == WANTSWHITE) {
printf("%s also wants to play white - is that OK? ", PeerUserName);
scanf("%s", ans);
if (ans[0] == 'y' || ans[0] == 'Y')
MyColor = WANTSBLACK;
}
break;
}
}
gr.progNum = MyProgNum;
gr.color = MyColor;
if (callrpc(PeerHostName, PeerProgNum, VERSNUM, ACCEPTPROCNUM,
XdrGameReq, (caddr_t) &gr,
xdr_void, (caddr_t) 0) != 0)
{
PeerProgNum = 0L;
}
}
} while(PeerProgNum == 0L);
PeerColor = OTHERCOLOR(MyColor);
PlayerName[MyColor] = UserPWEntry->pw_name;
PlayerName[PeerColor] = PeerUserName;
/*
* if the other player is shipping us the game state, lock the
* mouse in the meantime.
*/
if (RestoringGame)
Mouse = LOCKED;
}
/*
* send a move to the 'color' player
*/
BOOL
SendMove(move, color)
Move * move;
int color;
{
if ( ! peerDead) {
if (IsMachine[color]) {
SendMachineMove(move, color);
} else if (callrpc(PeerHostName, PeerProgNum, VERSNUM, MOVEPROCNUM,
XdrMove, (caddr_t) move,
xdr_void, (caddr_t) 0) != 0)
{
peerDied();
}
}
return( ! peerDead);
}
void
SendRestoreMove(move, color)
Move * move;
int color;
{
if ( ! IsMachine[color]
&& ! peerDead
&& callrpc(PeerHostName, PeerProgNum, VERSNUM, RESTOREMOVEPROCNUM,
XdrMove, (caddr_t) move,
xdr_void, (caddr_t) 0) != 0)
{
peerDied();
}
}
void
SendEndRestore()
{
if ( ! peerDead
&& callrpc(PeerHostName, PeerProgNum, VERSNUM, ENDRESTOREPROCNUM,
xdr_int, (caddr_t) &Turn,
xdr_void, (caddr_t) 0) != 0)
{
peerDied();
}
}
void
SendUndoRequest(color)
int color;
{
if ( ! peerDead) {
if (IsMachine[color]) {
if (Turn != MyColor) {
Message("Will undo after machine moves...");
} else {
MachineUndo(color);
UndoWanted = FALSE;
Mouse = IDLE;
}
} else {
Message("Sending undo request to your opponent (please wait)...");
if (callrpc(PeerHostName, PeerProgNum, VERSNUM, UNDOPROCNUM,
xdr_void, (caddr_t) 0,
xdr_void, (caddr_t) 0) != 0)
{
peerDied();
}
}
}
}
void
SendResignation(color)
int color;
{
if ( ! peerDead) {
if (IsMachine[color]) {
KillChessProcesses();
} else if (callrpc(PeerHostName, PeerProgNum, VERSNUM, RESIGNPROCNUM,
xdr_void, (caddr_t) 0,
xdr_void, (caddr_t) 0) != 0)
{
peerDied();
}
}
}
void
SendTalkMsg(cp)
char * cp;
{
if ( ! peerDead
&& callrpc(PeerHostName, PeerProgNum, VERSNUM, MSGPROCNUM,
XdrString, (caddr_t) cp,
xdr_void, (caddr_t) 0) != 0)
{
peerDied();
}
}
void
SendSetupChange(setup, color)
SetupChange * setup;
int color;
{
if ( ! IsMachine[color]
&& ! peerDead
&& callrpc(PeerHostName, PeerProgNum, VERSNUM, SETUPPROCNUM,
XdrSetup, (caddr_t) setup,
xdr_void, (caddr_t) 0) != 0)
{
peerDied();
}
}
void
SendUndoAcknowledgement(isUndoOK)
int isUndoOK;
{
if (callrpc(PeerHostName, PeerProgNum, VERSNUM, UNDOACKPROCNUM,
xdr_int, (caddr_t) &isUndoOK,
xdr_void, (caddr_t) 0) != 0)
{
peerDied();
} else if (isUndoOK) {
UnDoMove();
if (Turn == MyColor)
Turn = OTHERCOLOR(MyColor);
else
UnDoMove();
Message(MyColor == WHITE ?
"Waiting for black to re-play..." :
"Waiting for white to re-play...");
} else
WhoseMoveMessage((char *) 0);
}
void
SendGoodbye()
{
if ( ! IsMachine[PeerColor] && ! peerDead) {
callrpc(PeerHostName, PeerProgNum, VERSNUM, GOODBYEPROCNUM,
xdr_void, (caddr_t) 0,
xdr_void, (caddr_t) 0);
}
if (MyProgNum != 0) {
/* unregister the RPC transport handle */
xprt_unregister(Xprt);
/* release my program number for re-use */
pmap_unset(MyProgNum, VERSNUM);
}
}
@//E*O*F ipc.c//
chmod u=r,g=r,o=r ipc.c
echo x - tool.c
sed 's/^@//' > "tool.c" <<'@//E*O*F tool.c//'
/*
* handle the tool environment
*/
#include <stdio.h>
#include <suntool/tool_hs.h>
#include <suntool/panel.h>
#include <suntool/gfxsw.h>
#include <sys/resource.h>
#include <sys/ioctl.h>
#include <strings.h>
#include "nchess.h"
Tool * NchessTool;
char ** ToolAttrs = (char **) NULL;
char * ToolName;
/*
* iconic form of window
*/
unsigned short IconImage[] = {
#include "Icons/nchess.icon"
};
DEFINE_ICON_FROM_IMAGE(WindowIcon, IconImage);
sigwinched()
{
tool_sigwinch(NchessTool);
}
/*
* parse the tool args.
*/
void
ParseToolArgs(argc, argv)
int *argc;
char **argv;
{
ToolName = argv[0];
(*argc)--;
argv++;
if (tool_parse_all(argc, argv, &ToolAttrs, ToolName) == -1) {
tool_usage(ToolName);
exit(1);
}
(*argc)++;
}
/*
* set up the tool environment
*/
void
InitTool(useRetained, iconDirectory)
BOOL useRetained; /* use a retained pixrect for the board */
char * iconDirectory; /* custom piece icon directory */
{
register unsigned int height;
register Toolsw * twsp;
char c[256];
/* create the tool marquee */
strcpy(c, " ");
strcat(c, PlayerName[WHITE]);
strcat(c, " vs. ");
strcat(c, PlayerName[BLACK]);
if ((NchessTool = tool_make(
WIN_LABEL, c,
WIN_ICON, &WindowIcon,
WIN_ATTR_LIST, ToolAttrs,
WIN_WIDTH, 8 * (SQUARE_WIDTH-1) + 2 * tool_borderwidth(NchessTool) - 1,
/*
* NOTE: The following line was unnecessary in Sun release 2.2,
* but is necessary in release 3.0. For some unknown reason, the
* call to tool_set_attributes following the call to InitBoardSW
* now fails to uncover the board area that was obscured by the
* default tool height being too small (note that the tool has not
* been installed yet).
*/
WIN_HEIGHT, 2000,
0)) == (Tool *) NULL)
{
fputs("Can't make tool\n", stderr);
exit(1);
}
tool_free_attribute_list(ToolAttrs);
/* initialize the subwindows */
InitTalkSW();
InitMsgSW();
InitControlSW();
InitBoardSW(useRetained, iconDirectory);
/*
* add up subwindow heights and force the tool to the resulting size
*/
height = tool_stripeheight(NchessTool) + tool_borderwidth(NchessTool) - tool_subwindowspacing(NchessTool);
for (twsp = NchessTool->tl_sw ; twsp != (Toolsw *) 0 ; twsp = twsp->ts_next)
height += twsp->ts_height + tool_subwindowspacing(NchessTool);
/*
* NOTE: under 2.2, the above calculation yielded the correct height.
* under 3.0, we need to add a few pixels to make it come out right (the
* reason is not yet known).
*/
height += 2;
tool_set_attributes(NchessTool, WIN_HEIGHT, height, 0);
signal(SIGWINCH, sigwinched);
}
void
RunTool()
{
/*
* NOTE: this is another difference between release 2.2 and 3.0:
* in release 2.2, the SIGWINCH handler would get called once at the
* outset to draw the board area; in release 3.0, this doesn't happen.
*/
DrawBoard();
tool_select(NchessTool, 0);
tool_destroy(NchessTool);
}
@//E*O*F tool.c//
chmod u=r,g=r,o=r tool.c
echo x - controlsw.c
sed 's/^@//' > "controlsw.c" <<'@//E*O*F controlsw.c//'
/*
* control panel subwindow handling
*/
#include <stdio.h>
#include <suntool/tool_hs.h>
#include <suntool/panel.h>
#include <suntool/menu.h>
#include "nchess.h"
BOOL SaveWanted = FALSE; /* machine opponent and game save deferred */
struct toolsw * ControlPanelSW;
Panel ControlPanel;
/* button items */
Panel_item UndoButton;
Panel_item LastPlayButton;
Panel_item ResignButton;
Panel_item TranscriptButton;
Panel_item SaveButton;
/*
* undo move button event handler
*/
/*ARGSUSED*/
undoProc(item, event)
Panel_item item;
struct inputevent * event;
{
if ( ! IHaveMoved()) {
Message("You haven't moved yet!");
} else if (Mouse == IDLE) {
UndoWanted = TRUE;
Mouse = LOCKED; /* lock the mouse until the reply arrives */
SendUndoRequest(PeerColor);
}
}
/*
* last play button event handler
*/
/*ARGSUSED*/
lastPlayProc(item, event)
Panel_item item;
struct inputevent * event;
{
ShowLastPlay();
}
/*
* resign button event handler
*/
/*ARGSUSED*/
resignProc(item, event)
Panel_item item;
struct inputevent * event;
{
/* make sure this is what the user wants to do */
if (Mouse == IDLE) {
ConfirmResignation();
}
}
/*
* write a transcript
*/
/*ARGSUSED*/
transcriptProc(item, event)
Panel_item item;
struct inputevent * event;
{
WriteTranscript(TranscriptFileName, TranscriptType);
}
/*
* save the game
*/
/*ARGSUSED*/
saveProc(item, event)
Panel_item item;
struct inputevent * event;
{
/*
* caveats: can't save games while we're still setting them up,
* and cannot save a game involving machines after the game is over.
*/
if (SetupMode
|| GameOver && (IsMachine[WHITE] || IsMachine[BLACK]))
return;
if (IsMachine[WHITE] && IsMachine[BLACK]
|| IsMachine[PeerColor] && Turn != MyColor) {
Message("Will save game when machine finishes move...");
SaveWanted = TRUE;
} else {
SaveGame(SaveFileName);
}
}
/*
* set up the control subwindow
*/
void
InitControlSW()
{
if ((ControlPanelSW = panel_create(NchessTool, 0)) == NULL) {
fprintf(stderr, "Can't create control panel\n");
exit(1);
}
ControlPanel = ControlPanelSW->ts_data;
/* set up the buttons */
if ( ! IsMachine[WHITE] || ! IsMachine[BLACK]) {
ResignButton = panel_create_item(ControlPanel, PANEL_BUTTON,
PANEL_LABEL_STRING, "(Resign)",
PANEL_NOTIFY_PROC, resignProc,
0);
UndoButton = panel_create_item(ControlPanel, PANEL_BUTTON,
PANEL_LABEL_STRING, "(Undo)",
PANEL_NOTIFY_PROC, undoProc,
0);
}
LastPlayButton = panel_create_item(ControlPanel, PANEL_BUTTON,
PANEL_LABEL_STRING, "(Last Play)",
PANEL_NOTIFY_PROC, lastPlayProc,
0);
TranscriptButton = panel_create_item(ControlPanel, PANEL_BUTTON,
PANEL_LABEL_STRING, "(Transcript)",
PANEL_NOTIFY_PROC, transcriptProc,
0);
SaveButton = panel_create_item(ControlPanel, PANEL_BUTTON,
PANEL_LABEL_STRING, "(Save)",
PANEL_NOTIFY_PROC, saveProc,
0);
panel_fit_height(ControlPanel);
}
@//E*O*F controlsw.c//
chmod u=r,g=r,o=r controlsw.c
echo Inspecting for damage in transit...
temp=/tmp/shar$$; dtemp=/tmp/.shar$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
646 1975 15392 ipc.c
121 392 3019 tool.c
136 347 3010 controlsw.c
903 2714 21421 total
!!!
wc ipc.c tool.c controlsw.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if [ -s $dtemp ]
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
fi
exit 0
Technical Details
Message-ID:
<259@spock.tc.fluke.COM>Path:
arc1-ca.pugleaf.net!utzoo!mnetor!seismo!lll-lcc!mordor!sri-spam!sri-unix!hplabs!pesnta!amd!intelca!mipos3!omepd!psu-cs!reed!tektronix!uw-beaver!fluke!tomaShow Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: arc1-ca.pugleaf.net!utzoo!mnetor!seismo!lll-lcc!mordor!sri-spam!sri-unix!hplabs!pesnta!amd!intelca!mipos3!omepd!psu-cs!reed!tektronix!uw-beaver!fluke!toma From: toma@tc.fluke.COM (Tom Anderson) Newsgroups: net.sources.games Subject: network chess (4 of 5) Message-ID: <259@spock.tc.fluke.COM> Date: Thu, 8-Jan-87 18:51:44 EST Article-I.D.: spock.259 Posted: Thu Jan 8 18:51:44 1987 Date-Received: Thu, 15-Jan-87 19:49:46 EST Organization: John Fluke Mfg. Co., Inc., Everett, WA Lines: 940