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