[comp.sources.games] v01i095: dots - multiplayer dots and boxes game

games-request@tekred.TEK.COM (07/16/87)

Submitted by: Dan Heller <island!argv@sun.com>
Comp.sources.games: Volume 1, Issue 95
Archive-name: dots

	[I compiled and ran this.  Fun game, except the computer keeps
	 beating me!	-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 shell archive."
# Contents:  Makefile dots.doc dots.h board.c comp.c comp2.c findem.c
#   main.c menu.c misc.c person.c save.c score.c sockt.c
# Wrapped by billr@tekred on Wed Jul 15 17:09:28 1987
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\" \(1912 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X#
X# Makefile for dots
X#
X#  Dots and Boxes -- the program for UNIX was programmed by Dan Heller and
X#     Don Hatch Spring, 1984 with further developments continually.
X#  Sockets Implemented by Dan Heller in May, 1985.
X#
X# This program was originally written on a PDP-11 under UNIX V7.  Since
X# then, it has been ported to 4.2BSD and won't work under any thing else
X# altho porting it shouldn't be hard -- just ifdef out the socket stuff.
X#
X# Installation is so easy that there's no need for a README or anything,
X# just edit dots.h and change some of the constants to whatever pathnames
X# you'd like them to be.  Also note DESTDIR here.
X#
X# This code is intended for public consumption and modifications are
X# enoucraged.  If you do make mods, I'd love to hear about them and
X# include in later releases (interest providing).
X#
X# Since everything includes dots.h a make depend is senseless. If you
X# make changes to defines, grep the files to note which are affected
X# and remake them.  If you change variables, use grep on .c files or use
X# "nm" on the .o files to find which files use them.
X#
X# The file "dots.doc" has more information on how to play.
X#
X# comments, etc... to:  Dan Heller
X#    island!argv@sun.com		argv@spam.istc.sri.com
X
XCFLAGS=	-O
XLDFLAGS= -s
XDESTDIR= /usr/games
XLINTFLAGS= -bxah -Dlint
XLIBES = -lcurses -ltermlib
X
XPROG=dots
X
XSRCS=main.c comp.c comp2.c board.c person.c misc.c menu.c save.c score.c \
X     sockt.c findem.c
X
XOBJS=main.o comp.o comp2.o board.o person.o misc.o menu.o save.o score.o \
X     sockt.o findem.o
X
X${PROG}: ${OBJS}
X	@echo Loading...
X	@cc ${LDFLAGS} ${OBJS} ${LIBES} -o ${PROG}
X
Xinstall: ${PROG}
X	/bin/mv ${PROG} ${DESTDIR}/${PROG}
X	chmod 711 ${DESTDIR}/${PROG}
X
Xtags:
X	ctags dots.h ${SRCS}
X
Xclean:
X	rm -f core ${OBJS} ${PROG}
X
Xlint:
X	lint ${LINTFLAGS} ${SRCS}
X
Xtar:
X	tar fcv DOTS Makefile dots.h $(SRCS) tags
X
Xshar:
X	shar Makefile dots.doc dots.h $(SRCS) > dots.shar
END_OF_Makefile
if test 1912 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f dots.doc -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"dots.doc\"
else
echo shar: Extracting \"dots.doc\" \(3304 characters\)
sed "s/^X//" >dots.doc <<'END_OF_dots.doc'
X                         . . .  D  O  T  S  . . .
X
X
X       For points, create squares like this:
X
X                                *---*
X                                | X |
X                                *---*
X
X       Whoever has more squares at the end of the game wins.
X       When a square is won, that player's initial will be
X       put inside the square as shown. 
X
X       To move the cursor, use one of three ways:
X       The "rogue/vi" keys, the number keys or the 
X       keys surrounding the 's'.
X
X       rogue:                         's':                       numbers
X        
X        y k u                        q w e                        7 8 9
X       h     l                      a  s  d                      4     6
X        b j n                        z x c                        1 2 3
X
X       The circle represents which direction you would move away from
X       where the cursor would currently be located.  The numbers are
X       good for terminals that have separate number key pads. The RETURN
X       key or the space-bar will enter a move at the current cursor position.
X
X       When a player enters a move, if he did NOT close any boxes, then
X       it is the other player's turn.  If the player DOES close a box, it
X       remains that players turn and he MUST move again even if he doesn't
X       have another scoring move.
X
X       ^L   will redraw the screen if it gets messed up (or try ^\).
X       'S'  will save your game.
X
X       If you are playing the two player game, that is, another human,
X       not the computer, use the ESCAPE key to 'talk' to the other player.
X       You can ONLY do this when it's your turn. You cannot save games when
X       playing someone else.  There is no high score file for two player games.
X
X       Command line arguments:
X
X       You can see the high-scores without playing by typing:
X
X       % dots -s
X
X       You can restart a saved game by typing:
X
X       % dots -r
X          which will read "dots.save" from your home directory or:
X
X       % dots -r saved_file_name
X	   if you've saved it as something other than "dots.save".
X	   Be sure to give the full pathname if the file is not in
X	   your current directory.
X
X       You can avoid the menu by giving the following information on
X       the command line:
X
X       % dots LENGTH WIDTH LEVEL [C]
X
X          where "length", "width", and "level" are values to use
X          for the length and width of the playing board and level
X	  is the level of difficulty to play at (0-3).
X          'C' is the initial to use if you don't want the first
X	  letter of your account name in the middle of your squares.
X
X       Example:
X
X	   % dots 5 9 0 F
X
X	   will play an easy game on a 5 X 9 board and your boxes will be
X	   initialized with 'F'.
X
X
X       There is also a way to play others on the system. In the menu,
X       choose the '7' item.  From the command line (avoiding the menu),
X       type:
X
X       % dots 2 login name [tty]
X
X       You may specify the tty if the same user is logged in more than
X       once.  You would use the same format to respond to someone else's
X       request to play you.  When you send (receive) a request, the
X       challenged will get a message every 30 seconds until that user replys 
X       or until the challenger terminates (just like talk).
X
X
END_OF_dots.doc
if test 3304 -ne `wc -c <dots.doc`; then
    echo shar: \"dots.doc\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f dots.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"dots.h\"
else
echo shar: Extracting \"dots.h\" \(2367 characters\)
sed "s/^X//" >dots.h <<'END_OF_dots.h'
X/*    dots.h    */
X
X#include <curses.h>
X#include <sys/types.h>
X#include <sys/ioctl.h>
X#ifdef lint
X#include <sys/uio.h>
X#endif lint
X#include <sys/socket.h>
X#include <ctype.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <strings.h>
X
Xextern char *sprintf();
X
X/* Most BSD systems don't have vprintf, but sun versions 3.0 and up do have it.
X * If you're system doesn't have it, comment out the define line. System-V
X * systems do have it, but until this code is ported, it doesn't matter.
X */
X/*#define VPRINTF*/
X
X#define PRIZE		"cigar"
X#define DOCFILE		"/usr/games/lib/dots/dots.doc"
X#define SAVE_FILE	"dots.save"
X#define SCOREFILE	"/usr/games/lib/dots/dots.scores" /* should be full pathname */
X#define version		"Dots version 1.0"
X
X#define when		break;case
X#define otherwise	break;default
X#define Upper(c)	(c = islower(c) ? toupper(c) : c)
X#define Lower(c)	(c = isupper(c) ? tolower(c) : c)
X#define max(a,b)	((a) > (b) ? (a) : (b))
X#define min(a,b)	((a) > (b) ? (b) : (a))
X#define erase_char	'\b'
X
X#define ESC		'\033'
X#define DEMO		0
X#define INTERACTIVE	1
X#define TWOPLAYER	2
X#define GOOD		0
X#define BAD		1
X#define DUMB		0
X#define HARD		1
X#define KILLER		2
X#define FREE		0
X#define USED		1
X#define CLOSEDEND	0  /* used for segtype for creating doublecrosses */
X#define OPENEND		1	/* ditto */
X#define MAXL		(COLS / 4)
X#define MAXW		(LINES / 2)
X#define H_MINL		10
X#define H_MINW		10
X#define MINL		4
X#define MINW		4
X#define US		0
X#define THEM		1
X#define SAVE		0
X#define LOAD		1
X#define isodd(a)	((a)%2)
X#define iseven(a)	(!isodd(a))
X#define ism4(a)		(!((a)%4))
X#define do_twice	for(twicecount=1;twicecount<=2;++twicecount)
X
Xint
X    board[120][120],
X    badboard[120][120],
X    persontally, comptally,
X    Length, Width,
X    xposit, yposit,
X    x_start, y_start,
X    mover,		/* 0 is person/US, 1 is computer/THEM */
X    twicecount,
X    no_good_moves,
X    control_already_established,
X    segtype,	/* OPENEND or CLOSEDEND ; set everytime Howbad is called */
X    dX_found,
X    segflag,
X    mode,
X    level,
X    sd,			/* socket descriptor */
X    jmpbuf_set;
X
Xstruct {
X    int x, y;
X}   Bingo;
X
Xstruct tchars tchars;
X
Xchar *opponent, prize[30], save_file[50], *getenv();
Xchar Initial[2], *username;
Xint onintr(), redraw(), oops();
X
X/* jump to the menu so there's no big stacks (supposedly) */
Xjmp_buf menu_jmp;
X
Xextern int errno;
Xextern char *sys_errlist[], *sys_siglist[];
END_OF_dots.h
if test 2367 -ne `wc -c <dots.h`; then
    echo shar: \"dots.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f board.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"board.c\"
else
echo shar: Extracting \"board.c\" \(2872 characters\)
sed "s/^X//" >board.c <<'END_OF_board.c'
X/*    board.c    routines that deal with the playing board's display or data */
X
X#include "dots.h"
X
Xsetup()
X{
X    Length = Width = 0;
X    comptally = persontally = 0;
X    xposit = 2, yposit = 1;
X
X    mvprintw(LINES - 6, 0, "Enter LENGTH of board (%d - %d).",
X	 (level == DUMB)? MINL : H_MINL, MAXL);
X    do  {
X	mvaddstr(LINES - 4, 0, "->> "), clrtoeol(), refresh();
X	x_start = COLS / 2 - (Length = get_dimensions()) * 2;
X    } while (Length > MAXL || (level == DUMB && Length < MINL) ||
X	(level != DUMB && Length < H_MINL));
X
X    mvprintw(LINES - 6, 0, "Enter WIDTH of board (%d - %d).",
X	(level==DUMB)? MINW:H_MINW, MAXW), clrtoeol();
X    do  {
X	mvaddstr(LINES - 4, 0, "->> "), clrtoeol(), refresh();
X	y_start = LINES / 2 - (Width = get_dimensions());
X    } while (Width > MAXW || (level == DUMB && Width < MINW) ||
X	(level != DUMB && Width < H_MINW));
X
X    mvprintw(LINES - 6, 0, "Length is %d, width is %d.", Length, Width);
X    clrtoeol(), refresh();
X    if (mode == INTERACTIVE)
X	mvprintw(LINES-4, 0,
X	    "Your boxes will be initialed with \"%c\"",Initial[US]), clrtoeol();
X    msg("Hit any key to continue. ");
X    getchar();
X}
X
Xfree_board()
X{
X    register int x, y;
X
X    for (x = 0; x <= Length * 2; ++x)
X	for (y = 0; y <= Width * 2; ++y)
X	    board[x][y] = FREE;
X    no_good_moves = control_already_established = 0;
X}
X
Xget_dimensions()
X{
X    char  	    string[10];
X    register char   c;
X    register int    place_on_line = 0, x = 0;
X
X    string[0] = '\0';
X
X    move(LINES - 4, 4), clrtoeol();
X    refresh();
X    while ((c = getchar()) != '\n') {
X	if (c == erase_char || c == '\027')
X	    if (place_on_line != 0) {
X		string[--x] = '\0';
X		--place_on_line;
X		addstr("\b \b"); 
X		refresh();
X	    } else
X		continue;
X	else if (isdigit(c)) {
X	    if (place_on_line == 4)
X		continue;
X	    place_on_line++;
X	    addch(string[x++] = c);
X	    refresh();
X	}
X    }
X    string[x] = '\0';
X    return atoi(string);
X}
X
Xdrawboard()
X{
X    register int x, y;
X
X    clear();
X    for (y = 1; y < 2 * Width; y++)
X	for (x = 1; x < 2 * Length; x++) {
X	    move(y_start + (y - 1), x_start + (2 * x - 2));
X	    if (iseven(x) && isodd(y) && board[x][y] == USED)
X		addstr("\b---\b\b");
X	    if (iseven(y) && isodd(x) && board[x][y] == USED)
X		addch('|');
X	    else if (iseven(x) && iseven(y) && closure(GOOD, x, y) == 4) {
X		if (board[x][y] == 1)
X		    mover = 1;
X		else
X		    mover = 0;
X		putinitial(x, y);
X	    } else if (isodd(x) && isodd(y))
X		addch('*');
X	}
X    if (mode == TWOPLAYER) {
X	mvaddstr(LINES - 3, 0, "Your Messages: ");
X	mvprintw(LINES - 2, 0, "%s's Messages: ", opponent);
X    }
X}
X
Xchlevel(c)
X{
X    if (!sure(c))
X	return;
X    level = (level + 1) % 3;
X    bottom_line();
X}
X
Xsure(c)
Xchar c;
X{
X    register int   count;
X    register char  C;
X
X    for (count = 0; count <= 3; ++count)
X	if ((C = getchar()) != c) {
X	    ungetc(C, stdin);
X	    return FALSE;
X	}
X    return TRUE;
X}
END_OF_board.c
if test 2872 -ne `wc -c <board.c`; then
    echo shar: \"board.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f comp.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"comp.c\"
else
echo shar: Extracting \"comp.c\" \(8116 characters\)
sed "s/^X//" >comp.c <<'END_OF_comp.c'
X/*    COMP.C    */
X
X#include "dots.h"
X
Xcompmove()
X{
X    bottom_line();
X    close_boxes();
X    if (!board_is_full())
X	if (!find_good_move(GOOD))
X	    force_move();
X}
X
Xclose_boxes()
X{
X    Bingo.x = Bingo.y = 0;
X    dX_found = 0;
X    if (level == DUMB || cntrl_not_established() || find_good_move(BAD))
X	close_EVERYTHING();
X    else
X	first_pass();
X}
X
Xfind_good_move(BorG)
Xint BorG;
X{
X    int x, y, xcount, ycount, x1, y1, x2, y2;
X
X    if (no_good_moves)
X	return (0);
X    if (BorG == GOOD && level == KILLER && kill_4_loops())
X	return (1);
X    for (xcount = 1, x = random() % (2 * Length - 1) + 1; xcount < Length * 2;
X	xcount++, x = x % (2 * Length - 1) + 1)
X	for (ycount = 1, y = random() % (2 * Width - 1) + 1; ycount < Width * 2;
X	    ycount++, y = y % (2 * Width - 1) + 1) {
X	    if (iseven(x + y))
X		continue;
X	    if (board[x][y] == USED)
X		continue;
X	    find_adj_squares(x, y, &x1, &y1, &x2, &y2);
X	    if (closure(GOOD, x1, y1) == 2)
X		continue;
X	    if (closure(GOOD, x2, y2) == 2)
X		continue;
X	    if (BorG == GOOD) {
X		xposit = x, yposit = y;
X		(void) entermove();
X	    }
X	    return (1);
X	}
X    no_good_moves = 1;
X    return (0);
X}
X
X/********************************************************************\
X|*   check all dots and ruins potential 4 loops.                    *|
X|*                                                                  *|
X|*      Want to prevent:      Find these:   Before they turn into:  *|
X|*         *---*---*	        *---*   *         *---*   *         *|
X|*         |       |	        |      		  |                 *|
X|*         *   *   *            *   *   *         *   *   *         *|
X|*         |       |					  |	    *|
X|*         *---*---*            *   *---*         *   *---*         *|
X|*   Because 4 loops lose points and #3 guarantees 4-loops          *|
X\********************************************************************/
X
Xkill_4_loops()
X{
X    int x, y, x1, y1, x2, y2, dx, dy, xcheck, ycheck;
X
X    for (x = 3; x <= 2 * Length - 3; x += 2)
X	for (y = 3; y <= 2 * Width - 3; y += 2) {
X	    if (closure(GOOD, x, y))
X		continue;	/* a line is connected to dot */
X	    for (dx = -1; dx <= 1; dx += 2)
X		for (dy = -1; dy <= 1; dy += 2)
X		    if (closure(GOOD, x + dx, y + dy) == 2)
X			if (closure(GOOD, x - dx, y - dy) == 1) {
X			    xcheck = x - dx, ycheck = y;
X			    do_twice
X			    {
X				find_adj_squares(xcheck, ycheck, &x1, &y1, &x2, &y2);
X				if (closure(GOOD, x1, y1) != 2 && closure(GOOD, x2, y2) != 2) {
X				    xposit = xcheck, yposit = ycheck;
X				    (void) entermove();
X				    return (1);
X				} else
X				    xcheck = x, ycheck = y - dy;
X			    }
X			}
X	}
X    return (0);
X}
X
Xforce_move()
X{
X    int x, y, xcount, ycount, x1, y1, x2, y2;
X    int Badness, bestx, besty, Bestbad = 1000, Besttype;
X
X    if (dX_found) {
X	if (comptally + persontally + segflag == OPENEND ? 2 : 4 == (Length - 1) * (Width - 1)) {
X	    Bingo.x = Bingo.y = dX_found = 0;
X	    close_EVERYTHING();
X	    return;
X	}
X	if (segflag == OPENEND) {
X	    find_adj_squares(Bingo.x, Bingo.y, &x1, &y1, &x2, &y2);
X	    if (closure(GOOD, x1, y1) == 2 && closure(GOOD, x2, y2) == 2) {
X		close_boxes();
X		if (!board_is_full())
X		    force_move();
X		return;
X	    }
X	}
X	xposit = Bingo.x;
X	yposit = Bingo.y;
X	(void) entermove();
X	return;
X    }
X    for (xcount = 1, x = random() % (2 * Length - 1) + 1; xcount < Length * 2;
X	xcount++, x = x % (2 * Length - 1) + 1)
X	for (ycount = 1, y = random() % (2 * Width - 1) + 1; ycount < Width * 2;
X	    ycount++, y = y % (2 * Width - 1) + 1)
X	    if (isodd(x + y) && board[x][y] == FREE) {
X		find_adj_squares(x, y, &x1, &y1, &x2, &y2);
X		if (closure(GOOD, x1, y1) != 3 && closure(GOOD, x2, y2) != 3)
X		    if ((Badness = Howbad(GOOD, Bestbad, x, y)) < Bestbad) {
X			Bestbad = Badness;
X			bestx = x;
X			besty = y;
X			Besttype = segtype;
X		    }
X	    }
X    if (Bestbad >= 2 && Besttype == OPENEND)
X	goto_middle_of_path(GOOD, &bestx, &besty);
X    xposit = bestx;
X    yposit = besty;
X    (void) entermove();
X}
X
Xfirst_pass()
X{
X    int x, y, x1, y1, doubleX, doubleY;
X    int Badness;
X    int start_over;
X
X    do {
X	start_over = 0;
X	for (x = 2; x <= 2 * Length - 2 && !start_over; x += 2)
X	    for (y = 2; y <= 2 * Width - 2 && !start_over; y += 2)
X		if (closure(GOOD, x, y) == 3) {
X		    x1 = x, y1 = y;
X		    goto_adj_free_line(GOOD, &x1, &y1);
X		    if (((Badness = Howbad(BAD, 1000, x1, y1)) == 2 &&
X			    segtype == OPENEND)
X			|| (Badness == 4 && segtype == CLOSEDEND)) {
X			segflag = segtype;
X			dX_found = 1;
X			doubleX = x1;
X			doubleY = y1;
X			board[x1][y1] = USED;	/* temporarily */
X			goto_next_square(GOOD, &doubleX, &doubleY);
X			goto_adj_free_line(GOOD, &doubleX, &doubleY);
X			Bingo.x = doubleX;
X			Bingo.y = doubleY;
X			board[x1][y1] = FREE;	/* SIGH */
X			close_EVERYTHING();
X			return;
X		    } else if (Badness <= 2) {
X			xposit = x1, yposit = y1;
X			entermove();
X		    } else {
X			xposit = x1, yposit = y1;
X			entermove();
X			start_over = 1;
X		    }
X		}
X    }
X    while (start_over);
X}
X
Xclose_EVERYTHING()
X{
X    int x, y, x_check, y_check, moved;
X
X    do {
X	moved = 0;
X	for (x = 2; x <= 2 * Length - 2; x += 2)
X	    for (y = 2; y <= 2 * Width - 2; y += 2)
X		if (closure(GOOD, x, y) == 3) {
X		    x_check = x, y_check = y;
X		    goto_adj_free_line(GOOD, &x_check, &y_check);
X		    /* at the end of the game, ignore this line! */
X		    if (!board_is_almost_full() && too_close(x_check, y_check))
X			continue;
X		    xposit = x_check;
X		    yposit = y_check;
X		    entermove();
X		    moved = 1;
X		}
X    }
X    while (moved);
X}
X
XHowbad(BorG, Max, xmove, ymove)
Xint BorG, Max, xmove, ymove;
X{
X    int x, y, x1, y1, x2, y2, moved, badtotal = 0;
X
X    for (x = 1; x < 2 * Length; x++)
X	for (y = isodd(x) ? 2 : 1; y < 2 * Width; y += 2)
X	    badboard[x][y] = board[x][y];
X    if (BorG == GOOD)
X	badboard[xmove][ymove] = USED;
X    segtype = OPENEND;
X
X    do_twice {
X	x = xmove;
X	y = ymove;
X	do {
X	    moved = 0;
X	    if (!goto_next_square(BAD, &x, &y))
X		break;
X	    goto_adj_free_line(BAD, &x, &y);
X	    badboard[x][y] = USED;
X	    moved = 1;
X	    find_adj_squares(x, y, &x1, &y1, &x2, &y2);
X	    if (closure(BAD, x1, y1) == 4 && closure(BAD, x2, y2) == 4)
X		badtotal++, segtype = CLOSEDEND;	/* add extra for two
X							 * sides */
X	    badtotal++;
X	    if (badtotal >= Max)
X		return (Max);
X	}
X	while (moved == 1);
X    }
X    return (badtotal);
X}
X
X/***********************************************************************\
X|*  This procedure returns true if the line passed is on either of the *|
X|*  boxes next to Bingo.                                               *|
X\***********************************************************************/
X
Xtoo_close(x, y)
Xint x, y;
X{
X    if (abs(x - Bingo.x) == 1 && abs(y - Bingo.y) == 1) {	/* REAL close */
X	if (isodd(Bingo.x)) {	/* Bingo is vertical  */
X	    if (closure(GOOD, x, Bingo.y) == 2)
X		return (1);
X	} else {	/* Bingo is horizontal */
X	    if (closure(GOOD, Bingo.x, y) == 2)
X		return (1);
X	}
X    }
X    if (isodd(Bingo.x)) {	/* Bingo is vertical  */
X	if ((abs(x - Bingo.x) == 2 && y == Bingo.y)
X	    && (closure(GOOD, (x + Bingo.x) / 2, y) == 2))
X	    return (1);
X    } else {		/* Bingo is horizontal */
X	if ((abs(y - Bingo.y) == 2 && x == Bingo.x)
X	    && (closure(GOOD, x, (y + Bingo.y) / 2) == 2))
X	    return (1);
X    }
X    return (0);
X}
X
X/***************************************************************************\
X|* This function decides if there are still more open-ended paths of       *|
X|* length two or less still on the board. If there are, it returns 1, else *|
X|* 0.                                                                      *|
X\***************************************************************************/
X
Xcntrl_not_established()
X{
X    int x, y, x1, y1, x2, y2;
X
X    if (control_already_established)
X	return (0);
X    for (x = 1; x < 2 * Length; x++)
X	for (y = isodd(x) ? 2 : 1; y < 2 * Width; y += 2)
X	    if (board[x][y] == FREE)
X		if (Howbad(GOOD, 3, x, y) <= 2 && segtype == OPENEND) {
X		    find_adj_squares(x, y, &x1, &y1, &x2, &y2);
X		    if (closure(GOOD, x1, y1) <= 2 && closure(GOOD, x2, y2) <= 2)
X			return (1);
X		}
X    control_already_established = 1;
X    return (0);
X}
END_OF_comp.c
if test 8116 -ne `wc -c <comp.c`; then
    echo shar: \"comp.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f comp2.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"comp2.c\"
else
echo shar: Extracting \"comp2.c\" \(2257 characters\)
sed "s/^X//" >comp2.c <<'END_OF_comp2.c'
X/*    COMP2.C    */
X
X#include "dots.h"
X
Xgoto_next_square(BorG, x, y)	/* returns 1 if there is one, 0 if not */
Xint BorG, *x, *y;
X{
X    int x1, y1, x2, y2;
X
X    find_adj_squares(*x, *y, &x1, &y1, &x2, &y2);
X    if (x1 != NULL && closure(BorG, x1, y1) == 3) {
X	*x = x1, *y = y1;
X	return (1);
X    }
X    if (x2 != NULL && closure(BorG, x2, y2) == 3) {
X	*x = x2, *y = y2;
X	return (1);
X    }
X    return (0);
X}
X
Xfind_adj_squares(x, y, x1, y1, x2, y2)
Xint x, y, *x1, *y1, *x2, *y2;
X{
X    if (isodd(x)) {	/* Vertical line */
X	*x1 = x - 1;
X	*y1 = y;
X	*x2 = x + 1;
X	*y2 = y;
X    } else {		/* Horizontal line */
X	*x1 = x;
X	*y1 = y - 1;
X	*x2 = x;
X	*y2 = y + 1;
X    }
X    if (!is_on_board(*x1, *y1))
X	*x1 = NULL, *y1 = NULL;
X    if (!is_on_board(*x2, *y2))
X	*x2 = NULL, *y2 = NULL;
X}
X
Xgoto_adj_free_line(BorG, x, y)
Xint BorG;
Xint *x, *y;
X{
X    int xtemp, ytemp;
X
X    for (xtemp = *x - 1; xtemp <= *x + 1; xtemp += 2)
X	if ((BorG == BAD ? badboard[xtemp][*y] : board[xtemp][*y]) == FREE) {
X	    *x = xtemp;
X	    return;
X	}
X    for (ytemp = *y - 1; ytemp <= *y + 1; ytemp += 2)
X	if (board[*x][ytemp] == FREE)
X	    if (((BorG == BAD)? badboard[*x][ytemp] : board[*x][ytemp])
X		    == FREE) {
X		*y = ytemp;
X		return;
X	    }
X    printf("You fucked up, buddy!");
X    fflush(stdout);
X    die();
X}
X
X/*****************************************************************************\
X|*  right now, this function doesn't actually go to the middle of a path,    *|
X|*  it simply goes one line away from the edge. If the length of the path is *|
X|*  two, the effect is the same.                                             *|
X\*****************************************************************************/
Xgoto_middle_of_path(BorG, x, y)
Xint BorG, *x, *y;
X{
X    int origx, origy, x1, y1, x2, y2;
X
X    find_adj_squares(*x, *y, &x1, &y1, &x2, &y2);
X    if (closure(BorG, x1, y1) == 2 && closure(BorG, x2, y2) == 2)
X	return;		/* you're sitting on it to begin with */
X    origx = *x, origy = *y;
X    if (BorG == GOOD)
X	board[origx][origy] = USED;
X    else
X	badboard[origx][origy] = USED;
X    /* Temporarily */
X    goto_next_square(BorG, x, y);
X    goto_adj_free_line(BorG, x, y);
X
X    if (BorG == GOOD)
X	board[origx][origy] = FREE;
X    else
X	badboard[origx][origy] = FREE;
X    /* SIGH! */
X}
END_OF_comp2.c
if test 2257 -ne `wc -c <comp2.c`; then
    echo shar: \"comp2.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f findem.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"findem.c\"
else
echo shar: Extracting \"findem.c\" \(1475 characters\)
sed "s/^X//" >findem.c <<'END_OF_findem.c'
X/* findem.c   find the login of the person we wanna play */
X
X#include "dots.h"
X#include <sys/stat.h>
X#include <sgtty.h>
X#include <utmp.h>
X
X#define UTMP  		"/etc/utmp"
X
Xstruct utmp utmp_buf;
Xstruct stat stat_buf;
Xstruct sgttyb sgtty_buf;
X
Xint fd;
X
Xfindem(argc, argv)
Xchar **argv;
X{
X    char *ttyname(), to_tty[13];
X    register char *login = argv[2], *where = "", *ourtty = ttyname(0) + 5;
X    register FILE *recipient;
X
X    if (argc > 3)
X	where = argv[3];
X    if (!strcmp(where, ourtty)) {
X	fprintf(stderr, "You can't play yourself.\n");
X	return 0;
X    }
X    if ((fd = open(UTMP, 0)) == -1) {
X	perror(UTMP);
X	return 0;
X    }
X
X    while (read(fd, (char *) &utmp_buf, sizeof(utmp_buf)))
X	if (!strcmp(utmp_buf.ut_name, login) &&
X	   (*where && !strcmp(utmp_buf.ut_line, where) ||
X	   (!*where && strcmp(where, ourtty))))
X		break;
X
X    (void) close(fd);
X    if (strcmp(login, utmp_buf.ut_name)) {
X	fprintf(stderr, "%s is not logged in.", login);
X	return 0;
X    }
X    if (*where && strcmp(where, utmp_buf.ut_line)) {
X	fprintf(stderr, "%s is not logged in on %s.\n", login, where);
X	return 0;
X    }
X
X    (void) sprintf(to_tty, "/dev/%s", utmp_buf.ut_line);
X    if (!(recipient = fopen(to_tty, "w"))) {
X	perror(to_tty);
X	fprintf(stderr, "%s: Can't ask %s to play.\n", argv[0], argv[2]);
X	return 0;
X    }
X    setuid(getuid());	/* turns off set-uid attribute once tty is opened */
X    setgid(getgid());	/* probably isn't necessary most of the time */
X
X    return invite(recipient);
X}
END_OF_findem.c
if test 1475 -ne `wc -c <findem.c`; then
    echo shar: \"findem.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\" \(5156 characters\)
sed "s/^X//" >main.c <<'END_OF_main.c'
X/*    MAIN.C	*/
X
X#include "dots.h"
X
Xchar *error_msg[] = {
X    "usages:\n",
X    "%s -s		gives top scores.\n",
X    "%s -d		reads the directions\n",
X    "%s -r [file]	restart saved game (from file if given).\n",
X    "%s L W D [C]	plays a game using integer arguments as\n",
X    "			Length, Width and Difficulty levels, respectively.\n",
X    "			'C' is inital for boxes.\n",
X    "%s 2 user [tty]	send request/reply to play someone else (2-user).\n",
X    "\nsetenv DOTSOPTS \"name=whoareyou,savefile=path,initial=X,prize=whatever\"\n",
X    0
X};
X
Xchar *getusername();
X
Xbus_n_seg(sig)
X{
X    if (sig == SIGBUS)
X	fprintf(stderr, "Bus error.\n");
X    else
X	fprintf(stderr, "Segmentation Fault.\n");
X    die();
X}
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X    register char *p;
X    extern char *UP;
X
X    setbuf(stdout, (char *)NULL);
X    setbuf(stderr, (char *)NULL);
X
X    username = getusername();
X
X    savetty();
X    initscr();
X
X    (void) signal(SIGBUS,  bus_n_seg);
X    (void) signal(SIGSEGV, bus_n_seg);
X    (void) signal(SIGINT,  onintr);
X    (void) signal(SIGPIPE, onintr);
X    (void) signal(SIGCHLD, SIG_IGN); /* to return from shell esc */
X    (void) signal(SIGQUIT, redraw);
X
X    if (argc > 1 && argv[1][0] == '-' && argv[1][1] != 'r')
X	if (argv[1][1] == 'd')
X	    readinst(1), exit(0);
X	else if (argv[1][1] == 's')
X	    high_score(TRUE, FALSE), die();
X	else if (argv[1][1] == 'x')
X	    high_score(TRUE, TRUE), die();
X	else
X	    do_error(argv[0]), die();
X
X    if (COLS < 4 * H_MINL || LINES < 2 * H_MINW) {
X	printf("Window must be at least %d by %d.\n", 4 * H_MINL, 2 * H_MINW);
X	die();
X    }
X    if (!*UP) {
X	printf("You need cursor movement capability on your terminal.\n");
X	die();
X    }
X
X    srandom(getpid());
X    mover = US, Initial[THEM] = '$';
X    getopts();
X    noecho(), crmode();
X
X    if (argc > 1)
X	parse_command(argc, argv);
X    else
X	menu();
X}
X
Xdo_error(arg)
Xchar *arg;
X{
X    int count = 0;
X
X    while (error_msg[count])
X	fprintf(stderr, error_msg[count++], arg);
X    die();
X}
X
XDots(which)	/* which? recovered game, start from command line, or menu */
Xint which;	/* 0 = start from beginning, 1 = recovered game */
X{
X    Upper(Initial[US]);
X    Lower(Initial[THEM]);
X
X    if (mode == TWOPLAYER) {
X	mvprintw(LINES-5,0, "Your label is '%c' and %s's is '%c'.",
X					Initial[US], opponent, Initial[THEM]);
X	mvprintw(LINES-4,0, "%s will go first.", (mover==US)? "You" : opponent);
X	mvaddstr(LINES-3,0, "^Z stops game for you only. \"fg\" resumes game.");
X	mvaddstr(LINES-2,0, "ESC to talk to other player. ^L to redraw board.");
X	msg("--hit any key to continue-- ");
X	getchar();
X	set_redraw_signal_key_to('\014');	/* change to ^L */
X	free_board();
X    }
X    if (!which)		/* could be a restart of a saved game  or  a new game */
X	setup(), free_board();
X    drawboard();
X    while (!board_is_full())
X	if (mode != DEMO && (mode == TWOPLAYER || mover == US))
X	    mover = (personmove()) ? mover : !mover; /* switch if we got some */
X	else if (mode != TWOPLAYER && (mode == DEMO || mover == THEM))
X	    if (!board_is_full())
X		compmove(), mover = !mover;
X    end_of_game();
X}
X
Xgetopts()
X{
X    char *p, *opts, temp[BUFSIZ], *length, *index();
X
X    (void) strcpy(prize, PRIZE);
X    (void) strcpy(save_file, SAVE_FILE);
X    if (opts = getenv("DOTSOPTS")) {
X	length = opts + strlen(opts);
X	while (opts < length) {
X	    (void) sscanf(opts, "%[^,]", temp);
X	    if (p = index(temp, '='))
X		if (!strncmp(temp, "name", 4))
X		    username = ++p;
X		else if (!(strncmp(temp, "savefile", 8)))
X		    (void) strcpy(save_file, ++p);
X		else if (!(strncmp(temp, "prize", 5)))
X		    (void) strcpy(prize, ++p);
X		else if (!(strncmp(temp, "initial", 7)))
X		    Initial[US] = *++p;
X	    opts += 1 + strlen(temp);
X	}
X    }
X    if (!Initial[US])
X	Initial[US] = *username;
X}
X
Xparse_command(argc, argv)
Xint argc;
Xchar **argv;
X{
X    if (!strcmp(argv[1], "2")) {
X	if (argc < 3)
X	    printf(error_msg, argv[0]);
X	else
X	    mode = TWOPLAYER, sockit(argc, argv);
X	die();
X    }
X
X    mode = INTERACTIVE;
X
X    if (!strcmp(argv[1], "-r")) {
X	if (argc == 3)
X	    (void) strcpy(save_file, argv[2]);
X	if (recover(1))
X	    Dots(1);
X	else
X	    die();
X	menu();
X    }
X
X    if (argc < 4)
X	do_error(argv[0]);
X
X    if ((level = atoi(argv[3])) < DUMB || level > KILLER) {
X	printf("%s: Invalid Difficulty Level (0,1, or 2)\n", argv[0]);
X	die();
X    }
X    if ((Length = atoi(argv[1])) > MAXL || Length < (level? H_MINL : MINL)) {
X	printf("%s: (%d) Invalid Length.\n", argv[0], Length);
X	die();
X    }
X    if ((Width = atoi(argv[2])) > MAXW || Width < (level? H_MINW : MINW)) {
X	printf("%s: (%d) Invalid Width.\n", argv[0], Width);
X	die();
X    }
X
X    if (argc > 4)
X	Initial[US] = *argv[4];
X    comptally = persontally = 0;
X    xposit = 2, yposit = 1;
X    y_start = 1 + LINES / 2 - Width;
X    x_start = 1 + COLS / 2 - Length * 2;
X    Dots(2);
X}
X
X#include <pwd.h>
Xchar *
Xgetusername()
X{
X    struct passwd *entry;
X    extern char *getlogin();
X    register char *p;
X
X    if ((p = getenv("NAME"))
X	|| (p = getenv("SIGNATURE"))
X	|| (p = getenv("USER"))
X	|| (p = getlogin()))
X	return p;
X    if (!(entry = getpwuid(getuid())))
X	puts("Who the hell are you?"), die();
X    endpwent();
X    return entry->pw_name;
X}
END_OF_main.c
if test 5156 -ne `wc -c <main.c`; then
    echo shar: \"main.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f menu.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"menu.c\"
else
echo shar: Extracting \"menu.c\" \(4094 characters\)
sed "s/^X//" >menu.c <<'END_OF_menu.c'
X/*    MENU.C    */
X
X#include "dots.h"
X#include <utmp.h>
X#include <sys/stat.h>
X
X#define ever (;;)
X
Xmenu()
X{
X    int c, command = 1;
X
X    jmpbuf_set = 1;
X    (void) setjmp(menu_jmp);
X    disp_menu();
X    for ever {
X	while ((c = getchar()) != '\n')
X	    if (c > '0' && c < '9')
X		putchar(c), putchar('\b'), command = c;
X	switch (command - '0') {
X	    case 1: readinst(0), disp_menu();
X	    when 2: level = DUMB, mode = INTERACTIVE, Dots(0);
X	    when 3: level = HARD, mode = INTERACTIVE, Dots(0);
X	    when 4: level = KILLER, mode = INTERACTIVE, Dots(0);
X	    when 5: level = DUMB, mode = DEMO, Dots(0);
X	    when 6: if (recover(0)) Dots(1);
X	    when 7: challenge();
X	    when 8: goodbye(1);
X	}
X    }
X}
X
Xdisp_menu()
X{
X    int partition = LINES / 10, lines;
X
X    clear();
X    mvaddstr((lines = partition + LINES - 10 * partition), COLS / 2 - 10, ". . . D O T S . . .");
X    mvaddstr((lines += partition), COLS / 6, "1. Read instructions.");
X    mvaddstr((lines += partition), COLS / 6, "2. Easy game.");
X    mvaddstr((lines += partition), COLS / 6, "3. Hard game.");
X    mvaddstr((lines += partition), COLS / 6, "4. Killer game.");
X    mvaddstr((lines = partition + LINES - 9 * partition), 4 * COLS / 6, "5. Demo game.");
X    mvaddstr((lines += partition), 4 * COLS / 6, "6. Recover saved game.");
X    mvaddstr((lines += partition), 4 * COLS / 6, "7. Play someone else.");
X    mvaddstr((lines += partition), 4 * COLS / 6, "8. Leave game.");
X    mvaddstr((lines += partition), COLS / 2 - 9, "Enter command. [ ]\b\b");
X    refresh();
X}
X
Xreadinst(before)
Xbool before;		/* before or after curses mode has been set */
X{
X    int c, line_count = 0;
X    FILE *fp2;
X
X    if (!before)
X	clear(), refresh();
X    else
X	noecho(), crmode();
X    if ((fp2 = fopen(DOCFILE, "r")) == NULL)
X	perror(DOCFILE);
X    else {
X	while ((c = getc(fp2)) != EOF) {
X	    putchar(c);
X	    if (c == '\n')
X		line_count++;
X	    if (line_count == LINES - 1) {
X		printf("--more--(or 'q' to return)");
X		if (getchar() == 'q') {
X		    fclose(fp2);
X		    if (before)
X			echo(), nocrmode();
X		    return;
X		}
X		printf("\015                          \015");
X		line_count = 0;
X	    }
X	}
X	fclose(fp2);
X    }
X    if (!before) {
X	printf("Hit return to continue [ ]\b\b");
X	while (getchar() != '\n');
X    } else
X	echo(), nocrmode();
X}
X
Xwritable(line)
Xchar *line;
X{
X    char ttyno[20];
X
X    sprintf(ttyno, "/dev/%s", line);
X    return !access(ttyno, 02);
X}
X
Xchallenge()
X{
X    struct utmp buf;
X    int count = 0, col = LINES / 3, l_len = 0;
X    char *p, *index(), *victim[4], string[20], *ttyname(), *tty = ttyname(0)+5;
X    FILE *file;
X
X    victim[0] = "Dots";
X    victim[1] = "2";
X    clear();
X    mvaddstr(col, 0, "Here are your potential opponents: ");
X    move(++col, 0);
X
X    if ((file = fopen("/etc/utmp", "r")) == NULL) {
X	disp_menu();
X	msg("/etc/utmp: %s", sys_errlist[errno]);
X	return;
X    }
X    while (fread((char *)&buf, sizeof(struct utmp), 1, file) > 0)
X	if (buf.ut_name[0] && writable(buf.ut_line)) {
X	    if (!strncmp(buf.ut_name, username, 8) && !strcmp(buf.ut_line, tty))
X		continue;
X	    if (count++)
X		addstr(", ");
X	    if ((l_len + 10 + min(strlen(buf.ut_name), 8)) > COLS - 1)
X		clrtoeol(), move(++col, 0), l_len = 0;
X	    l_len += 10 + min(strlen(buf.ut_name), 8);
X	    printw("%-.8s (%s)", buf.ut_name, buf.ut_line);
X	}
X    (void) fclose(file);
X    if (!count) {
X	disp_menu();
X	msg("There doesn't seem to be anyone who can play.");
X	return;
X    }
X    mvaddstr(col += 2, 0, "RETURN for menu.");
X    mvaddstr(++col, 0, "Whom would you like to play (user [ttyxx])? ");
X    refresh();
X    count = 2;
X    Getstr(string, min(20, COLS - 1));
X    if (string[0] == NULL) {
X	disp_menu();
X	return;
X    }
X    move(++col, 0);
X    refresh();
X    victim[count++] = string;
X    if ((p = index(string, ' ')) != NULL) {
X	*(p++) = '\0';
X	victim[count - 1] = string;
X	victim[count++] = p;
X    }
X    mode = TWOPLAYER;
X    sockit(count, victim); /* shouldn't return. If so, there was an error */
X    mode = DEMO;
X    putchar('\n'); /* don't overwrite any error messages */
X    msg("Hit any key to continue.");
X    getchar();
X    disp_menu();
X}
END_OF_menu.c
if test 4094 -ne `wc -c <menu.c`; then
    echo shar: \"menu.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f misc.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"misc.c\"
else
echo shar: Extracting \"misc.c\" \(6276 characters\)
sed "s/^X//" >misc.c <<'END_OF_misc.c'
X/*    MISC.C    */
X
X#include "dots.h"
X
X/* has to be a function instead of define because signal calls this */
Xredraw()
X{
X    clearok(curscr, TRUE), wrefresh(curscr);
X}
X
X/* returns the number of boxes closed, if any */
Xentermove()
X{
X    Cursor(xposit, yposit);
X    addstr(iseven(yposit) ? "|\b" : "\b---\b\b");
X    board[xposit][yposit] = USED;
X    return he_got_some();
X}
X
Xclosure(BorG, x, y)
Xregister int BorG, x, y;
X{
X    if (!is_on_board(x, y))
X	return (-1);
X    if (BorG == GOOD)
X	return (board[x][y - 1]
X	    + board[x][y + 1]
X	    + board[x - 1][y]
X	    + board[x + 1][y]);
X    else
X	return (badboard[x][y - 1]
X	    + badboard[x][y + 1]
X	    + badboard[x - 1][y]
X	    + badboard[x + 1][y]);
X}
X
Xhe_got_some()
X{
X    int total = 0, x1, y1, x2, y2;
X
X    find_adj_squares(xposit, yposit, &x1, &y1, &x2, &y2);
X    if (closure(GOOD, x1, y1) == 4) {
X	putinitial(x1, y1);
X	total++;
X    }
X    if (closure(GOOD, x2, y2) == 4) {
X	putinitial(x2, y2);
X	total++;
X    }
X    if (mover == THEM)
X	comptally += total;
X    else
X	persontally += total;
X    bottom_line();
X
X    return total;
X}
X
Xset_redraw_signal_key_to(c)
Xchar c;
X{
X    static char oldquit = 0;
X
X    if (!oldquit)
X	if (ioctl(0, TIOCGETC, &tchars) == -1)
X	    oops("ioctl get call");
X	else
X	    oldquit = tchars.t_quitc;
X    tchars.t_quitc = (c) ? c : oldquit;	/* redraw screen anytime by signal */
X    if (ioctl(0, TIOCSETC, &tchars) == -1)
X	oops("ioctl set call");
X}
X
Xbottom_line()
X{
X    char line[128], Opponent[12];
X    register char *p = line;
X
X    (void) sprintf(Opponent, "%s's", opponent);
X    if (mode != DEMO)
X	p += strlen(sprintf(p, "%8s turn.    ",
X	    (mover == US) ? "Your" : (mode == TWOPLAYER) ? Opponent : "My"));
X    p += strlen(sprintf(p, "%s: %3d    %s: %3d     ",
X	(mode == DEMO) ? "Player 1" : "You",
X	persontally, (mode == TWOPLAYER) ? opponent :
X	(mode == DEMO) ? "Player 2" : "Me", comptally));
X    if (mode != TWOPLAYER && mode != DEMO && strlen(line) + 13 < COLS - 1)
X	p += strlen(sprintf(p, "Level: %s ",
X	    (level == DUMB) ? "EASY" : (level == HARD) ? "HARD" : "KILLER"));
X    if (p - line + 14 < COLS - 1 && mode != DEMO)
X	p += strlen(sprintf(p, "   '?' for help."));
X    if (mode == DEMO)
X	p += strlen(sprintf(p, "            Demo Game."));
X    if (mode == TWOPLAYER && p - line + 29 < COLS - 1)
X	(void) sprintf(p, "  '^L' to redraw.  ESC to talk.");
X    msg(line);
X    Cursor(xposit, yposit);
X}
X
Xboard_is_almost_full()
X{
X    return (persontally + comptally >= (Length - 1) * (Width - 1) - 4);
X}
X
Xboard_is_full()
X{
X    return (persontally + comptally == (Length - 1) * (Width - 1));
X}
X
Xend_of_game()
X{
X    char line[80], c;
X    register char *p = line;
X
X    move(LINES - 1, 0);
X    if (board_is_full()) {
X	p += strlen(sprintf(p, "Score: %d to %d.  ", comptally, persontally));
X	if (comptally == persontally)
X	    p += strlen(sprintf(p, "No one won.  "));
X	else if (mode == DEMO)
X	    p += strlen(sprintf(p, "%s won.  ", (comptally > persontally)
X		? "Player 2" : "Player 1"));
X	else
X	    p += strlen(sprintf(p, "%s won.  ",
X		(comptally > persontally) ? (mode == TWOPLAYER) ?
X		"They" : "I" : "You"));
X	addstr(line);
X	if (mode != DEMO)
X	    if (comptally - persontally < 0) {
X		printw("You get a %s. ", prize);
X		if (mode != TWOPLAYER)
X		    high_score(0, 0);
X	    } else if (comptally != persontally)
X		printw("You lose a %s. ", prize);
X    } else
X	addstr("No score, you quit.");
X    if (mode == TWOPLAYER)
X	goodbye(1);
X    addstr("--more--"), clrtoeol();
X    refresh();
X    getchar();
X    msg("RETURN for menu; 'Q' to exit. ");
X    if ((c = getchar()) == 'q' || c == 'Q')
X	goodbye(1);
X    disp_menu();
X}
X
Xgoodbye(When)
Xbool When;
X{
X    if (When)
X	msg("");
X    if (When && mode != TWOPLAYER)
X	high_score(TRUE, FALSE);
X    printf("\nThanx, %s.\n", username);
X    die();
X}
X
X/*VARARGS1*/
Xmsg(fmt, args)
Xchar *fmt;
X{
X    char string[BUFSIZ];
X#ifdef VPRINTF
X    vsprintf(string, fmt, &args);
X#else
X    FILE foo;
X    foo._cnt = BUFSIZ;
X    foo._base = foo._ptr = string; /* may have to be cast(unsigned char *) */
X    foo._flag = _IOWRT+_IOSTRG;
X    _doprnt(fmt, &args, &foo);
X    (void) fputc(0, &foo);
X#endif VPRINTF
X    mvaddstr(LINES-1, 0, string), clrtoeol(), refresh();
X}
X
X/*VARARGS1*/
Xoops(fmt, args)
Xchar *fmt;
X{
X#ifdef VPRINTF
X    vprintf(fmt, &args);
X#else
X    _doprnt(fmt, &args, stdout);
X#endif VPRINTF
X    perror("");
X}
X
Xdie()
X{
X    set_redraw_signal_key_to(0);	/* reset to original, whatever it was */
X    if (mode == TWOPLAYER)
X	destroysocket();
X    nocrmode(), echo(), endwin();
X    exit(0);
X}
X
Xonintr(sig)
X{
X    int x, y;
X
X    (void) signal(sig, onintr);
X    (void) alarm(0);
X    if (sig != SIGPIPE) {
X	getyx(stdscr, y, x);
X	msg("Really quit? ");
X	if (getchar() != 'y') {
X	    move(y, x);
X	    if (Length && Width)
X		bottom_line();
X	    else
X		refresh();
X	    return;
X	}
X    }
X    msg("");
X    if (sig != SIGINT && sig != SIGQUIT) {
X	if (sig == SIGPIPE)
X	    destroysocket(), fprintf(stderr, "Your opponent terminated.\n");
X	else
X	    printw("I got signal #%d: %s", sig, sys_siglist[sig]);
X	clrtoeol();
X	refresh();
X    }
X    if (jmpbuf_set && sig != SIGINT && sig != SIGQUIT)
X	longjmp(menu_jmp, 1);
X    die();
X}
X
XCursor(a, b)
Xint a, b;
X{
X    move(y_start + b - 1, x_start + a * 2 - 2), refresh();
X}
X
Xis_on_board(x, y)
Xregister int x, y;
X{
X    return (x > 0 && y > 0 && x < 2 * Length && y < 2 * Width);
X}
X
Xputinitial(x, y)
Xregister int x, y;
X{
X    Cursor(x, y);
X    addch(Initial[mover]);
X    refresh();
X    board[x][y] = mover;
X}
X
Xshell()
X{
X    register char 	*SHELL;
X    register int	pid, w;
X    int 		status, (*oq)(), (*oi)();
X
X    clear(), refresh();
X    printf("Which Shell, (sh / csh (s/c))? ");
X    SHELL = (getchar() == 'c') ? "/bin/csh" : "/bin/sh";
X    echo(), nocrmode();
X
X    oi = signal(SIGINT, SIG_IGN);  /* old interrupt (oi) and old quit (oq) */
X    oq = signal(SIGQUIT, SIG_IGN); /* signals saved on return of signal() */
X
X    if ((pid = fork()) == 0) {
X	setuid(getuid());
X	setgid(getgid());
X	execl(SHELL, SHELL, 0);
X	oops("Couldn't execl(%s)", SHELL);
X	_exit(127);
X    }
X    while ((w = wait(&status)) != pid && w != -1)
X	;
X    printf("[Hit return to continue]");
X    while (getchar() != '\n')
X	;
X
X    (void) signal(SIGINT, oi);	/* reset old signals */
X    (void) signal(SIGQUIT, oq);
X    noecho(), crmode();
X    drawboard(), bottom_line();
X    return (status);
X}
END_OF_misc.c
if test 6276 -ne `wc -c <misc.c`; then
    echo shar: \"misc.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f person.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"person.c\"
else
echo shar: Extracting \"person.c\" \(3768 characters\)
sed "s/^X//" >person.c <<'END_OF_person.c'
X/*    PERSON.C    */
X
X#include "dots.h"
X
X#define ever (;;)
X
Xpersonmove()
X{
X    char c;
X    int fd = ((mover == US) ? 0 : sd);
X
X    Cursor(xposit, yposit);	/* do this so raw mode won't destroy screen */
X    raw();
X    noraw();		/* flush type-ahead */
X    bottom_line();
X    do  {
X	for ever {
X	    if (read(fd, &c, 1) <= 0)
X		onintr(SIGPIPE);	/* someone terminated */
X	    if (mode == TWOPLAYER)
X		if (c == '!' || c == 'S' || c == '.' || c == '/' || c == 'Q')
X		    continue;
X		else if (c != 'r' && fd != sd)
X		    (void) write(sd, &c, 1);	/* send info to other player */
X	    if (c == '\n' || c == ' ')
X		break;
X	    Cursor(xposit, yposit);
X	    switch (c) {
X		case ESC:
X		    if (mode == TWOPLAYER)
X		        talk();
X
X		when '?':
X		    if (mover == US)
X			readinst(0), drawboard();
X		    if (mode == TWOPLAYER)
X			if (mover == THEM) {
X			    msg("%s is reading the instructions.", opponent);
X			    if (read(fd, &c, 1) <= 0)	/* wait for a char */
X				onintr(SIGPIPE);
X			} else
X			    (void) write(sd, &c, sizeof(c));
X		    bottom_line();
X		when '!':
X		    if (shell() == -1)
X			perror("shell");
X		when 'Q':
X		    if (mode != TWOPLAYER)
X			end_of_game();
X		    else
X			onintr(SIGPIPE);
X		when 'S': Save_game();
X		when 'r': redraw();
X	        when '7': case 'q': case 'y':
X		    if (is_on_board(xposit - 1, yposit - 1))
X		        xposit -= 1, yposit -= 1;
X	        when '8': case 'w': case 'k':
X		    if (is_on_board(xposit, yposit - 2))
X		        yposit -= 2;
X	        when '9': case 'e': case 'u':
X		    if (is_on_board(xposit + 1, yposit - 1))
X		        xposit += 1, yposit -= 1;
X	        when '4': case 'a': case 'h':
X		    if (is_on_board(xposit - 2, yposit))
X		        xposit -= 2;
X	        when '6': case 'd': case 'l':
X		    if (is_on_board(xposit + 2, yposit))
X		        xposit += 2;
X	        when '1': case 'z': case 'b':
X		    if (is_on_board(xposit - 1, yposit + 1))
X		        xposit -= 1, yposit += 1;
X	        when '2': case 'x': case 'j':
X		    if (is_on_board(xposit, yposit + 2))
X		        yposit += 2;
X	        when '3': case 'c': case 'n':
X		    if (is_on_board(xposit + 1, yposit + 1))
X		        xposit += 1, yposit += 1;
X		when '.': chlevel(c);
X	    }
X	    Cursor(xposit, yposit);
X	}
X	if (board[xposit][yposit] == USED && mover == US) {
X	    mvaddstr(LINES - 1, 0, "It's taken.   ");
X	    Cursor(xposit, yposit);
X	}
X    }
X    while (board[xposit][yposit] == USED);
X    return entermove();
X}
X
X#define Addch(c)    addch(c); if (mode == TWOPLAYER) (void) write(sd, &c, 1)
X#define backspace() Addch(back_char); Addch(space); Addch(back_char); refresh()
X
XGetstr(String, length)
Xchar *String;
Xint length;
X{
X    char garbage, space = ' ', back_char = erase_char;
X    int count = 0;
X
X    while ((garbage = getchar()) != '\n' && garbage != 4 && garbage != ESC)
X	if (garbage == _tty.sg_erase && count) {
X	    backspace();
X	    String[count--] = 0;
X	} else if (garbage == _tty.sg_kill && count)
X	    do {
X		backspace();
X	    } while (--count);
X	else if (garbage == '\027' && count)	/* ^W */
X	    do  {
X		backspace();
X		String[count--] = 0;
X		if (!count || (String[count-1]==' ' && !isspace(String[count])))
X		    break;
X	    } while (count);
X	else if (count == length)
X	    fputc('\007', stderr);
X	else if (garbage > 31 && garbage != 127) {
X	    String[count++] = garbage;
X	    Addch(garbage);
X	    refresh();
X	}
X    String[count] = 0;
X}
X
Xtalk()
X{
X    char c, dummy[128], cr = '\n';
X    int nread = 0;
X
X    if (mover == US) {
X	move(LINES - 3, 15);
X	clrtoeol(), refresh();
X	Getstr(dummy, COLS - 16);
X	(void) write(sd, &cr, 1);
X    } else {
X	move(LINES - 2, strlen(opponent) + 3 + strlen("Messages: "));
X	clrtoeol();
X	refresh();
X	while ((nread = read(sd, &c, 1)) > 0 && c != cr)
X	    addch(c), refresh();
X	if (nread == -1)
X	    oops("bad socket read");
X    }
X}
END_OF_person.c
if test 3768 -ne `wc -c <person.c`; then
    echo shar: \"person.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f save.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"save.c\"
else
echo shar: Extracting \"save.c\" \(5455 characters\)
sed "s/^X//" >save.c <<'END_OF_save.c'
X/*  SAVE.C  */
X
X#include "dots.h"
X
XSave_game()
X{
X    int c;
X    FILE *fp;
X    char buf[40];
X
X    buf[0] = 0;
X
X    msg("File: %s? ", save_file);
X    if ((c = getchar()) != 'Y' && c != 'y') {
X	if (c != ESC) {
X	    msg("File: ");
X	    Getstr(buf, min(40, COLS - 8));
X	    if (strlen(buf) > 1)
X		(void) strcpy(save_file, buf);
X	}
X    } else
X	(void) strcpy(buf, save_file);
X    if (*buf)
X	if (!(fp = fopen(buf, "w"))) {
X	    msg("Couldn't open %s: %s --more--", save_file, sys_errlist[errno]);
X	    while (getchar() != ' ')
X		fputc(7, stderr);
X	} else {
X	    c = save(fp, SAVE);
X	    (void) fclose(fp);
X	    if (c)
X		fputc('\n', stdout), die();
X	}
X    bottom_line();
X}
X
Xrecover(before)
Xbool before;
X{
X    int c, xspot, yspot;
X    FILE *fp;
X
X    if (!before) {
X	getyx(stdscr, yspot, xspot);
X	msg("File: %s? ", save_file);
X	if ((c = getchar()) != 'Y' && c != 'y')
X	    if (c != ESC) {
X		char buf[40];
X		msg("Input Filename: ");
X		Getstr(buf, min(40, COLS - 17));
X		move(LINES - 1, 0);
X		refresh();
X		if (strlen(buf) < 2) {
X		    move(yspot, xspot);
X		    refresh();
X		    return 0;
X		} else
X		    (void) strcpy(save_file, buf);
X	    } else
X		return 0;
X    }
X    if (!(fp = fopen(save_file, "r")))
X	if (before)
X	    perror(save_file);
X	else
X	    msg("Couldn't open %s: %s", save_file, sys_errlist[errno]);
X    else if (save(fp, LOAD)) {
X	(void) fclose(fp);
X	if (unlink(save_file) < 0)
X	    oops("Couldn't unlink savefile"), puts("Are you trying to cheat?");
X	return 1;
X    } else {
X	(void) fclose(fp);
X	if (before)
X	    putchar('\n'), die();
X    }
X    if (!before)
X	move(yspot, xspot), refresh();
X    return 0;
X}
X
Xsave(fp, funct)
XFILE *fp;
X{
X    register int x, y;
X    int i;
X
X    if (funct == LOAD) {
X	char V[80], *p;
X
X	if (fgets(V, 80, fp) && (p = index(V, '\n')))
X	    *p = 0;
X	if (strcmp(V, version)) {
X	    printf("Sorry, file is wrong version.");
X	    return FALSE;
X	}
X        if (fscanf (fp, "persontally = %d\n", &persontally) < 1 ||
X	    fscanf (fp, "comptally = %d\n", &comptally) < 1 ||
X	    fscanf (fp, "Length = %d\n", &Length) < 1 ||
X	    fscanf (fp, "Width = %d\n", &Width) < 1)
X		goto bad;
X	for (x = 0; x < Length * 2; ++x)
X	    for (y = 0; y < Width * 2; ++y) {
X		if (fscanf (fp, "board[%*d][%*d] = %d\n", &i) < 1)
X		    goto bad;
X		board[x][y] = i;
X	    }
X        if (fscanf (fp, "xposit = %d\n", &xposit) < 1 ||
X	    fscanf (fp, "yposit = %d\n", &yposit) < 1 ||
X	    fscanf (fp, "x_start = %d\n", &x_start) < 1 ||
X	    fscanf (fp, "y_start = %d\n", &y_start) < 1 ||
X	    fscanf (fp, "no_good_moves = %d\n", &no_good_moves) < 1 ||
X	    fscanf (fp, "control_already_established = %d\n",
X			&control_already_established) < 1 ||
X	    fscanf (fp, "segtype = %d\n", &segtype) < 1 ||
X	    fscanf (fp, "dX_found = %d\n", &dX_found) < 1 ||
X	    fscanf (fp, "segflag = %d\n", &segflag) < 1 ||
X	    fscanf (fp, "mode = %d\n", &mode) < 1 ||
X	    fscanf (fp, "level = %d\n", &level) < 1 ||
X	    fscanf (fp, "Bingo.x = %d, Bingo.y = %d\n",
X		&Bingo.x, &Bingo.y) < 2 ||
X	    fscanf (fp, "Initial = %2s\n", Initial) < 1 ||
X	    fscanf (fp, "mover = %d\n", &mover) < 1)
X		goto bad;
X	if (Length < 4 || Width < 4) {
Xbad:
X	    msg("File has been corrupted.");
X	    return FALSE;
X	}
X    } else {
X	(void) fprintf(fp, "%s\n", version);
X        fprintf (fp, "persontally = %d\n", persontally);
X        fprintf (fp, "comptally = %d\n", comptally);
X        fprintf (fp, "Length = %d\n", Length);
X        fprintf (fp, "Width = %d\n", Width);
X	for (x = 0; x < Length * 2; ++x)
X	    for (y = 0; y < Width * 2; ++y)
X		fprintf (fp, "board[%d][%d] = %d\n", x, y, board[x][y]);
X        fprintf (fp, "xposit = %d\n", xposit);
X        fprintf (fp, "yposit = %d\n", yposit);
X        fprintf (fp, "x_start = %d\n", x_start);
X        fprintf (fp, "y_start = %d\n", y_start);
X        fprintf (fp, "no_good_moves = %d\n", no_good_moves);
X        fprintf (fp, "control_already_established = %d\n",
X		      control_already_established);
X        fprintf (fp, "segtype = %d\n", segtype);
X        fprintf (fp, "dX_found = %d\n", dX_found);
X        fprintf (fp, "segflag = %d\n", segflag);
X        fprintf (fp, "mode = %d\n", mode);
X        fprintf (fp, "level = %d\n", level);
X        fprintf (fp, "Bingo.x = %d, Bingo.y = %d\n", Bingo.x, Bingo.y);
X        fprintf (fp, "Initial = %2s\n", Initial);
X        fprintf (fp, "mover = %d\n", mover);
X    }
X    return TRUE;
X}
X#if 0
X    (*funct) (&persontally, sizeof(persontally), 1, fp);
X    (*funct) (&comptally, sizeof(comptally), 1, fp);
X    (*funct) (&Length, sizeof(Length), 1, fp);
X    (*funct) (&Width, sizeof(Width), 1, fp);
X    for (x = 0; x < 120; ++x)
X	for (y = 0; y < 120; ++y) {
X	    if (funct == SAVE)
X		i = board[x][y];
X	    (*funct) (&i, sizeof(int), 1, fp);
X	    if (funct == SAVE)
X		board[x][y] = i;
X	}
X    (*funct) (&xposit, sizeof(xposit), 1, fp);
X    (*funct) (&yposit, sizeof(yposit), 1, fp);
X    (*funct) (&x_start, sizeof(x_start), 1, fp);
X    (*funct) (&y_start, sizeof(y_start), 1, fp);
X    (*funct) (&no_good_moves, sizeof(no_good_moves), 1, fp);
X    (*funct) (&control_already_established, sizeof(control_already_established), 1, fp);
X    (*funct) (&segtype, sizeof(segtype), 1, fp);
X    (*funct) (&dX_found, sizeof(dX_found), 1, fp);
X    (*funct) (&segflag, sizeof(segflag), 1, fp);
X    (*funct) (&mode, sizeof(mode), 1, fp);
X    (*funct) (&level, sizeof(level), 1, fp);
X    (*funct) (&Bingo, sizeof(Bingo), 1, fp);
X    (*funct) (Initial, sizeof(Initial), 1, fp);
X    (*funct) (&mover, sizeof(mover), 1, fp);
X#endif
END_OF_save.c
if test 5455 -ne `wc -c <save.c`; then
    echo shar: \"save.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f score.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"score.c\"
else
echo shar: Extracting \"score.c\" \(2371 characters\)
sed "s/^X//" >score.c <<'END_OF_score.c'
X/*  SCORE.C  */
X
X#include 		"dots.h"
X
X#define NAMELEN		30
X
Xstruct scores {
X    int sc_person;
X    int sc_comp;
X    char sc_name[NAMELEN];
X    int sc_level;
X    int sc_width;
X    int sc_length;
X    char sc_login[9];
X}   top_ten[10];
X
Xhigh_score(Read, names)
Xbool Read, names;
X{
X    struct scores *scp, *temp;
X    int fd;
X
X    for (scp = top_ten; scp < &top_ten[10]; scp++) {
X	scp->sc_name[0] = 0;
X	scp->sc_login[0] = 0;
X	scp->sc_length = 0;
X	scp->sc_width = 0;
X	scp->sc_person = 0;
X	scp->sc_comp = 0;
X	scp->sc_level = 0;
X    }
X
X    /* read the top ten file into the array and close the file */
X    if ((fd = open(SCOREFILE, 2)) < 0) {
X	printf("no score file\n");
X	return;
X    }
X    (void) read(fd, (char *) top_ten, sizeof(top_ten));
X
X    /* Print the list */
X    if (Read) {
X	printf("Top Players:\n");
X	printf("Level\tDimensions   Computer   Human\tName\n");
X	for (scp = top_ten; scp < &top_ten[10]; scp++)
X	    if (scp->sc_person) {
X		printf("%s\t  %2d X %2d      %3d       %3d\t%s",
X		    (scp->sc_level == DUMB) ?
X		    "Easy" : (scp->sc_level == HARD ?
X			"Hard" : "Killer"),
X		    scp->sc_width,
X		    scp->sc_length, scp->sc_comp, scp->sc_person, scp->sc_name);
X		if (names)
X		    printf("(%s)", scp->sc_login);
X		putchar('\n');
X	    } else
X		break;
X    }
X    /* check to see if current score made it */
X    else {
X	for (scp = top_ten; scp < &top_ten[10]; scp++)
X	    if (value_cmp(scp))
X		break;
X	if (scp < &top_ten[10]) {
X	    char *getlogin(), *login = getlogin();
X
X	    for (temp = &top_ten[9]; temp > scp; temp--)
X		*temp = *(temp - 1);
X	    scp->sc_width = Width;
X	    scp->sc_length = Length;
X	    scp->sc_person = persontally;
X	    scp->sc_comp = comptally;
X	    scp->sc_level = level;
X	    (void) strcpy(scp->sc_login, login);
X	    addstr("--more--"), clrtoeol();
X	    refresh();
X	    raw(), noraw();
X	    while (getchar() != ' ')
X		fputc(7, stderr);
X	    msg("You made the top ten! Enter a name: ");
X	    Getstr(scp->sc_name, NAMELEN - 1);
X	    if (strlen(scp->sc_name) > 1) {
X		(void) lseek(fd, (long)0, 0);
X		(void) write(fd, (char *)top_ten, sizeof top_ten);
X	    } else
X		msg("Nothing entered.");
X	}
X	(void) close(fd);
X    }
X}
X
Xvalue_cmp(entry)
Xstruct scores *entry;
X{
X    int value;
X
X    value = (level - entry->sc_level) * 500;
X    value += persontally + Length * Width;
X    return (value > entry->sc_length * entry->sc_width + entry->sc_person);
X}
END_OF_score.c
if test 2371 -ne `wc -c <score.c`; then
    echo shar: \"score.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f sockt.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"sockt.c\"
else
echo shar: Extracting \"sockt.c\" \(4229 characters\)
sed "s/^X//" >sockt.c <<'END_OF_sockt.c'
X/* sockt.c */
X/* All the stuff that deals with sockets is here */
X
X#include "dots.h"
X#include <sys/un.h>	/* unix domain sockets */
X#include <errno.h>
X
X#define SOCKNAME  "/tmp/dots"
X
X#define namelen(sockt) (sizeof (sockt.sun_family) + strlen(sockt.sun_path))
X
Xint len;
Xstatic int (*oldint)(), (*oldquit)();
Xstruct sockaddr_un sockt;
X
Xsockit(argc, argv)
Xchar **argv;
X{
X    setbuf(stdout, (char *)NULL);
X
X    mover = THEM;
X    opponent = argv[2];
X    Initial[THEM] = *opponent;
X
X    (void) strcpy(sockt.sun_path, SOCKNAME);
X    len = namelen(sockt);
X
X    if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {	/* create a socket */
X	oops("Socket error");
X	return;
X    }
X
X    /* try to respond to a possible connection already established */
X    while (connect(sd, (struct sockaddr *)&sockt, namelen(sockt)) == -1)
X	/*
X	 * check to see if we can't connect because of "correct" errors 
X	 */
X	if (errno != ENOENT) {	/* no such file or directory */
X	    perror("connect on socket");
X	    puts("Trying again...");
X	    (void) close(sd);
X	    sockit(argc, argv);
X	} else {
X	    mover = US;	/* challenger goes first */
X	    if (!findem(argc, argv))
X		return;
X	    else
X		break;
X	}
X    getsizes();		/* get the window sizes of both players */
X    Dots(2);		/* we are connected and won't return */
X}
X
X/* send an invitation */
X
X#include <sys/time.h>
Xstruct itimerval waittime;
Xjmp_buf jmpbuf;
X
Xreinvite(sig)
X{
X    if (sig == SIGALRM) {
X	printf("\nre");
X	longjmp(jmpbuf, 1);
X    }
X    timerclear(&waittime.it_interval);
X    timerclear(&waittime.it_value);
X    (void) setitimer(ITIMER_REAL, &waittime, (struct itimerval *) 0);
X    destroysocket();
X    (void) signal(SIGINT, oldint);
X    (void) signal(SIGQUIT, oldquit);
X    longjmp(jmpbuf, 2);
X}
X
Xinvite(recipient)
XFILE *recipient;
X{
X    int newsok;
X
X    waittime.it_value.tv_sec = 30;
X    waittime.it_value.tv_usec = 0;
X    waittime.it_interval = waittime.it_value;
X
X    /*
X     * we're a server, so we give a name to the socket to the client knows
X     * what to connect with. bind() is used to give a name to a socket. 
X     */
X    if (bind(sd, (struct sockaddr *)&sockt, len) == -1) {
X	oops("Can't bind %s", SOCKNAME);
X	return 0;
X    }
X    if (listen(sd, 5) == -1) {
X	oops("Can't listen %s", SOCKNAME);
X	return 0;
X    }
X
X    setbuf(recipient, (char *)NULL);
X
X    /*
X     * accept() will hang around and do nothing unless someone requests a
X     * connection.  So, we wait..  signal again every 30 secs with setitmer 
X     */
X    (void) signal(SIGALRM, reinvite);
X    oldint = signal(SIGINT, reinvite);
X    oldquit = signal(SIGQUIT, reinvite);
X    (void) setitimer(ITIMER_REAL, &waittime, (struct itimerval *) 0);
X    if (setjmp(jmpbuf) == 2)
X	return 0;
X    printf("sending challenge...");
X    fprintf(recipient, "Message from the \"dots\" game...\007\007\007\n");
X    fprintf(recipient, "%s would like to play \"dots.\"\n", username);
X    fprintf(recipient, "respond with \"dots 2 %s\"\n", username);
X
X    while ((newsok = accept(sd, (struct sockaddr *)0, (int *)0)) == -1)
X	if (errno != EINTR) {
X	    oops("Can't accept %s", SOCKNAME);
X	    return 0;
X	} else
X	    continue;
X
X    timerclear(&waittime.it_interval);
X    timerclear(&waittime.it_value);
X    (void) setitimer(ITIMER_REAL, &waittime, (struct itimerval *) 0);
X    (void) close(sd);
X    sd = newsok;
X    return 1;
X}
X
X /* find lines and cols of the other guy */
Xgetsizes()
X{
X    int their_lines, their_cols;
X
X    do_twice {
X	if (mover == US) {
X	    (void) write(sd, (char *)&COLS, sizeof(int));
X	    (void) write(sd, (char *)&LINES, sizeof(int));
X	} else {
X	    (void) read(sd, (char *)&their_cols, sizeof(int));
X	    (void) read(sd, (char *)&their_lines, sizeof(int));
X	}
X	mover = !mover;
X    }
X    Length = min(COLS, their_cols) / 4;
X    Width = min(LINES, their_lines) / 2 - 2;
X    comptally = persontally = 0;
X    xposit = 2, yposit = 1;
X    y_start = 1 + (LINES - 2) / 2 - Width;
X    x_start = 1 + COLS / 2 - Length * 2;
X
X    (void) signal(SIGINT, oldint);
X    (void) signal(SIGQUIT, oldquit);
X}
X
Xdestroysocket()
X{
X    if (!access(SOCKNAME, 0)) {
X	if (shutdown(sd, 2) == -1)  /* dissallow further sends and recieves */
X	    oops("shutdown failed cuz");
X	if (unlink(SOCKNAME) == -1)
X	    oops("Can't unlink %s", SOCKNAME);
X    }
X}
END_OF_sockt.c
if test 4229 -ne `wc -c <sockt.c`; then
    echo shar: \"sockt.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0