[comp.sources.games] v04i020: bridge - multiplayer networked bridge game, Part02/02

games@tekred.TEK.COM (05/31/88)

Submitted by: Jiang-Hsing Chu <jchu@mimsy.umd.edu>
Comp.sources.games: Volume 4, Issue 20
Archive-name: bridge/Part02

	[Oops! Forgot to mention in Part01 that this does look BSD specific.
	 I don't know what it would take to get it running on SysV. -br]

#! /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 2 (of 2)."
# Contents:  Makefile ctl.c ctl.h get_addrs.c get_names.c
#   invitebridge.README slave_talk.c talk.h talk_ctl.h
# Wrapped by billr@saab on Tue May 31 09:13:31 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(478 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X# Makefile for multi-player bridge
X
XOBJ1 = master_talk.o  bridge.o get_names.o master_io.o msgs.o ctl.o init_disp.o get_addrs.o ctl_transact.o invite.o look_up.o
X
XOBJ2 = slave_talk.o get_names.o slave_io.o msgs.o ctl.o init_disp.o get_addrs.o ctl_transact.o invite.o look_up.o
X
Xall:	invitebridge bridge
X
Xinvitebridge: $(OBJ1)
X	cc -O -o invitebridge  $(OBJ1) -lcurses -ltermlib 
X
Xbridge: $(OBJ2)
X	cc -O -o bridge  $(OBJ2) -lcurses -ltermlib 
X
Xclean:
X	-rm *.o bridge invitebridge
END_OF_Makefile
if test 478 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f ctl.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"ctl.c\"
else
echo shar: Extracting \"ctl.c\" \(1868 characters\)
sed "s/^X//" >ctl.c <<'END_OF_ctl.c'
X#ifndef lint
Xstatic	char sccsid[] = "@(#)ctl.c 1.1 86/02/05 SMI"; /* from UCB 1.4 83/06/09 */
X#endif
X
X/* This file handles haggling with the various talk daemons to
X   get a socket to talk to. sockt is opened and connected in
X   the progress
X */
X
X#include "talk_ctl.h"
X
Xstruct sockaddr_in daemon_addr = { AF_INET };
Xstruct sockaddr_in ctl_addr = { AF_INET };
Xstruct sockaddr_in my_addr = { AF_INET };
X
X    /* inet addresses of the two machines */
Xstruct in_addr my_machine_addr;
Xstruct in_addr his_machine_addr;
X
Xu_short daemon_port;	/* port number of the talk daemon */
X
Xint ctl_sockt;
Xint sockt;
Xint invitation_waiting = 0;
X
XCTL_MSG msg;
X
Xopen_sockt()
X{
X    int length;
X
X    my_addr.sin_addr = my_machine_addr;
X    my_addr.sin_port = 0;
X
X    sockt = socket(AF_INET, SOCK_STREAM, 0, 0);
X
X    if (sockt <= 0) {
X	p_error("Bad socket");
X    }
X
X    if ( bind(sockt, &my_addr, sizeof(my_addr)) != 0) {
X	p_error("Binding local socket");
X    }
X
X    length = sizeof(my_addr);
X
X    if (getsockname(sockt, &my_addr, &length) == -1) {
X	p_error("Bad address for socket");
X    }
X}
X
X    /* open the ctl socket */
X
Xopen_ctl() 
X{
X    int length;
X
X    ctl_addr.sin_port = 0;
X    ctl_addr.sin_addr = my_machine_addr;
X
X    ctl_sockt = socket(AF_INET, SOCK_DGRAM, 0, 0);
X
X    if (ctl_sockt <= 0) {
X	p_error("Bad socket");
X    }
X
X    if (bind(ctl_sockt, &ctl_addr, sizeof(ctl_addr), 0) != 0) {
X	p_error("Couldn't bind to control socket");
X    }
X
X    length = sizeof(ctl_addr);
X    if (getsockname(ctl_sockt, &ctl_addr, &length) == -1) {
X	p_error("Bad address for ctl socket");
X    }
X}
X
X/* print_addr is a debug print routine */
X
Xprint_addr(addr)
Xstruct sockaddr_in addr;
X{
X    int i;
X
X    printf("addr = %x, port = %o, family = %o zero = ",
X	    addr.sin_addr, addr.sin_port, addr.sin_family);
X
X    for (i = 0; i<8;i++) {
X	printf("%o ", (int)addr.sin_zero[i]);
X    }
X    putchar('\n');
X}
END_OF_ctl.c
if test 1868 -ne `wc -c <ctl.c`; then
    echo shar: \"ctl.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f ctl.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"ctl.h\"
else
echo shar: Extracting \"ctl.h\" \(1170 characters\)
sed "s/^X//" >ctl.h <<'END_OF_ctl.h'
X/*	@(#)ctl.h 1.1 86/02/05 SMI; from UCB 1.4 83/03/28	*/
X
X/* ctl.h describes the structure that talk and talkd pass back
X   and forth
X */
X
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <netdb.h>
X
X#define NAME_SIZE 9
X#define TTY_SIZE 16
X#define HOST_NAME_LENGTH 256
X
X#define MAX_LIFE 60 /* maximum time an invitation is saved by the
X			 talk daemons */
X#define RING_WAIT 30  /* time to wait before refreshing invitation 
X			 should be 10's of seconds less than MAX_LIFE */
X
X    /* the values for type */
X
X#define LEAVE_INVITE 0
X#define LOOK_UP 1
X#define DELETE 2
X#define ANNOUNCE 3
X
X    /* the values for answer */
X
X#define SUCCESS 0
X#define NOT_HERE 1
X#define FAILED 2
X#define MACHINE_UNKNOWN 3
X#define PERMISSION_DENIED 4
X#define UNKNOWN_REQUEST 5
X
Xtypedef struct ctl_response CTL_RESPONSE;
X
Xstruct ctl_response {
X    char type;
X    char answer;
X    int id_num;
X    struct sockaddr_in addr;
X};
X
Xtypedef struct ctl_msg CTL_MSG;
X
Xstruct ctl_msg {
X    char type;
X    char l_name[NAME_SIZE];
X    char r_name[NAME_SIZE];
X    int id_num;
X    int pid;
X    char r_tty[TTY_SIZE];
X    struct sockaddr_in addr;
X    struct sockaddr_in ctl_addr;
X};
END_OF_ctl.h
if test 1170 -ne `wc -c <ctl.h`; then
    echo shar: \"ctl.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f get_addrs.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"get_addrs.c\"
else
echo shar: Extracting \"get_addrs.c\" \(1678 characters\)
sed "s/^X//" >get_addrs.c <<'END_OF_get_addrs.c'
X#ifndef lint
Xstatic	char sccsid[] = "@(#)get_addrs.c 1.1 86/02/05 SMI"; /* from UCB 1.5 83/04/01 */
X#endif
X
X#include "talk_ctl.h"
X
Xstruct hostent *gethostbyname();
Xstruct servent *getservbyname();
X
Xget_addrs(my_machine_name, his_machine_name)
Xchar *my_machine_name;
Xchar *his_machine_name;
X{
X    struct hostent *hp;
X    struct servent *sp;
X
X    msg.pid = getpid();
X
X	/* look up the address of the local host */
X
X    hp = gethostbyname(my_machine_name);
X
X    if (hp == (struct hostent *) 0) {
X	printf("This machine doesn't exist. Boy, am I confused!\n");
X	exit(-1);
X    }
X
X    if (hp->h_addrtype != AF_INET) {
X	printf("Protocal mix up with local machine address\n");
X	exit(-1);
X    }
X
X    bcopy(hp->h_addr, (char *)&my_machine_addr, hp->h_length);
X
X	/* if he is on the same machine, then simply copy */
X
X    if ( bcmp((char *)&his_machine_name, (char *)&my_machine_name,
X		sizeof(his_machine_name)) == 0) {
X	bcopy((char *)&my_machine_addr, (char *)&his_machine_addr,
X		sizeof(his_machine_name));
X    } else {
X
X	/* look up the address of the recipient's machine */
X
X	hp = gethostbyname(his_machine_name);
X
X	if (hp == (struct hostent *) 0 ) {
X	    printf("%s is an unknown host\n", his_machine_name);
X	    exit(-1);
X	}
X
X	if (hp->h_addrtype != AF_INET) {
X	    printf("Protocol mix up with remote machine address\n");
X	    exit(-1);
X	}
X
X	bcopy(hp->h_addr, (char *) &his_machine_addr, hp->h_length);
X    }
X
X	/* find the daemon portal */
X
X#ifdef NTALK
X    sp = getservbyname("ntalk", "udp");
X#else
X    sp = getservbyname("talk", "udp");
X#endif
X
X    if (strcmp(sp->s_proto, "udp") != 0) {
X	printf("Protocol mix up with talk daemon\n");
X	exit(-1);
X    }
X
X    daemon_port = sp->s_port;
X}
END_OF_get_addrs.c
if test 1678 -ne `wc -c <get_addrs.c`; then
    echo shar: \"get_addrs.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f get_names.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"get_names.c\"
else
echo shar: Extracting \"get_names.c\" \(2077 characters\)
sed "s/^X//" >get_names.c <<'END_OF_get_names.c'
X#ifndef lint
Xstatic	char sccsid[] = "@(#)get_names.c 1.1 86/02/05 SMI"; /* from UCB 1.2 83/03/26 */
X#endif
X
X#include "talk.h"
X#include "ctl.h"
X
Xchar *getlogin(), *ttyname(), *rindex();
X
Xextern CTL_MSG msg;
X
X/*
X * Determine the local and remote user, tty, and machines
X */
X
Xstruct hostent *gethostbyname();
X
Xget_names(argc, argv)
Xint argc;
Xchar *argv[];
X{
X    char hostname[HOST_NAME_LENGTH];
X    char *his_name;
X    char *my_name;
X    char *my_machine_name;
X    char *his_machine_name;
X    char *my_tty;
X    char *his_tty;
X    char *ptr;
X    int name_length;
X
X    if (argc < 2 ) {
X	printf("Usage:  talk user [ttyname]\n");
X	exit(-1);
X    }
X    if ( !isatty(0) ) {
X	printf("Standard input must be a tty, not a pipe or a file\n");
X	exit(-1);
X    }
X
X    my_name = getlogin();
X    if (my_name == NULL) {
X	printf("You don't exist. Go away.\n");
X	exit(-1);
X    }
X
X    name_length = HOST_NAME_LENGTH;
X    gethostname(hostname, &name_length);
X    my_machine_name = hostname;
X
X    my_tty = rindex(ttyname(0), '/') + 1;
X
X	/* check for, and strip out, the machine name 
X	    of the target */
X
X    for (ptr = argv[1]; *ptr != '\0' &&
X			 *ptr != '@' &&
X			 *ptr != ':' &&
X			 *ptr != '!' &&
X			 *ptr != '.'     ; ptr++) {
X    }
X
X    if (*ptr == '\0') {
X
X	    /* this is a local to local talk */
X
X	his_name = argv[1];
X	his_machine_name = my_machine_name;
X
X    } else {
X
X	if (*ptr == '@') {
X		/* user@host */
X	    his_name = argv[1];
X	    his_machine_name = ptr + 1;
X	} else {
X		/* host.user or host!user or host:user */
X	    his_name = ptr + 1;
X	    his_machine_name = argv[1];
X	}
X	*ptr = '\0';
X    }
X
X
X    if (argc > 2) {
X	his_tty = argv[2];	/* tty name is arg 2 */
X    } else {
X	his_tty = "";
X    }
X
X    get_addrs(my_machine_name, his_machine_name);
X
X	/* Load these useful values into the standard message header */
X
X    msg.id_num = 0;
X
X    strncpy(msg.l_name, my_name, NAME_SIZE);
X    msg.l_name[NAME_SIZE - 1] = '\0';
X
X    strncpy(msg.r_name, his_name, NAME_SIZE);
X    msg.r_name[NAME_SIZE - 1] = '\0';
X
X    strncpy(msg.r_tty, his_tty, TTY_SIZE);
X    msg.r_tty[TTY_SIZE - 1] = '\0';
X}
END_OF_get_names.c
if test 2077 -ne `wc -c <get_names.c`; then
    echo shar: \"get_names.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f invitebridge.README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"invitebridge.README\"
else
echo shar: Extracting \"invitebridge.README\" \(1688 characters\)
sed "s/^X//" >invitebridge.README <<'END_OF_invitebridge.README'
X"invitebridge" is the brain of the whole system.  The system looks like this:
X
X                             ----------
X                             |player1@|
X                             |machine1|
X                             ----------
X                                 | bridge@
X                                 | machine1
X                                 |
X         ----------------------------------------
X         |                       |              |
X         |   ----------          |              |   bridge@  ----------
X         |   |player4@|     invitebridge@       |   machine2 |player2@|
X         |   |machine4|----    machine4  -------|------------|machine2|
X         |   ----------          |              |            ---------
X         ----------------------------------------
X                                 | bridge@
X                                 | machine3
X                                 |               
X                             ----------
X                             |player3@|
X                             |machine3|
X                             ----------
X
XTo play the bridge game via compute communication, the central site needs
Xthe "invitebridge" program and the remote sites need "bridge" program.
XThe game is started by issuing the following command:
X   invitebridge player1@machine1 player2@machine2 player@machine3
X
XIn the given example, the player1 will be the North, the player2 will be
Xthe East, and the player3 will be the South.  You, player4, are always 
Xthe West.
X
XThe game record will be stored in "bridge.log" in your working directory.
XThe guide of bidding, playing,.. can be found in "bridge.README" which
Xis part of this package.
END_OF_invitebridge.README
if test 1688 -ne `wc -c <invitebridge.README`; then
    echo shar: \"invitebridge.README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f slave_talk.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"slave_talk.c\"
else
echo shar: Extracting \"slave_talk.c\" \(264 characters\)
sed "s/^X//" >slave_talk.c <<'END_OF_slave_talk.c'
X
X#include "talk.h"
X
X
Xxwin_t comwin[19];
Xchar *current_state;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	get_names(argc, argv);
X
X	open_ctl();
X	open_sockt();
X	start_msgs();
X
X	if ( !check_local() ) {
X	    invite_remote();
X	}
X	end_msgs();
X
X	init_disp();
X
X	talk();
X}
END_OF_slave_talk.c
if test 264 -ne `wc -c <slave_talk.c`; then
    echo shar: \"slave_talk.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f talk.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"talk.h\"
else
echo shar: Extracting \"talk.h\" \(656 characters\)
sed "s/^X//" >talk.h <<'END_OF_talk.h'
X/*	@(#)talk.h 1.1 86/02/05 SMI; from UCB 1.2 83/04/23	*/
X
X#include <curses.h>
X#include <utmp.h>
X
X#define	forever		for(;;)
X
X#define	BUF_SIZE	512
X#define PUT		1
X#define GET		2
X#define TYPE		buf.type
X#define	WN		buf.wn
X#define ROW		buf.row
X#define COL		buf.col
X#define STR		buf.string
X
XFILE *popen();
Xint quit(), sleeper();
X
Xextern int sockt;
Xextern int curses_initialized;
Xextern int invitation_waiting;
X
Xextern char *current_state;
Xextern int current_line;
X
Xtypedef struct xwin {
X	WINDOW *x_win;
X	int x_nlines;
X	int x_ncols;
X	int x_line;
X	int x_col;
X} xwin_t;
X
Xextern xwin_t comwin[19];
X
Xtypedef struct {
X	char	type, wn, row, col;
X	char	string[40];
X} BMSG;
END_OF_talk.h
if test 656 -ne `wc -c <talk.h`; then
    echo shar: \"talk.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f talk_ctl.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"talk_ctl.h\"
else
echo shar: Extracting \"talk_ctl.h\" \(395 characters\)
sed "s/^X//" >talk_ctl.h <<'END_OF_talk_ctl.h'
X/*	@(#)talk_ctl.h 1.1 86/02/05 SMI; from UCB 1.1 83/03/26	*/
X
X#include "ctl.h"
X#include "talk.h"
X#include <errno.h>
X
Xextern int errno;
X
Xextern struct sockaddr_in daemon_addr;
Xextern struct sockaddr_in ctl_addr;
Xextern struct sockaddr_in my_addr;
Xextern struct in_addr my_machine_addr;
Xextern struct in_addr his_machine_addr;
Xextern u_short daemon_port;
Xextern int ctl_sockt;
Xextern CTL_MSG msg;
END_OF_talk_ctl.h
if test 395 -ne `wc -c <talk_ctl.h`; then
    echo shar: \"talk_ctl.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 2 \(of 2\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0