#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	README
#	Makefile
#	go.6
#	backup.c
#	changes.c
#	connect.c
#	curse.c
#	board.c
#	doloop.c
#	doother.c
#	file.c
#	go.c
#	handicap.c
#	help.c
#	life.c
#	loop.c
#	mesg.c
#	opts.c
#	putpiece.c
#	score.c
#	strength.c
#	tick.c
#	traps.c
#	var.c
#	go.h
#	std.disclaimer
# This archive created: Fri Nov 15 23:50:54 1991
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
cat << \SHAR_EOF > 'README'
        Copyright 1990      Greg Hale
        Portions Copyright 1990, Fred Hansen

Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting
documentation.  No representations are made about the
suitability of this software for any purpose.  It is
provided "as is" without express or implied warranty.

-----------

To make the Internet GO board type:

    make

If you get re-defined errors from connect.c, remove the lines near the top
between and including the #ifndef.

By default, the program will install at   .    
To change this, modify the BINDIR variable in the Makefile.
It will install the manual page in MANDIR (default:   . ).

If you want the long help option to work, you will need to change
the HELP_CMD in go.h to reference the correct directory.


Have fun and please report all bugs to: 
            Greg Hale (hale@scam.berkeley.edu)
         or Adrian Mariano (adrian@milton.u.washington.edu)

P.S.  Be sure to add yourself to the internet go players list by sending 
      mail to adrian@milton.u.washington.edu.

-----------
Changes:

11/15/87 (v 1.2)
	Add command line arguements, variable board size, handicapping.
	Select the port available to the user in case
	several games are running at once to avoid collisions.

11/23/87 (v 1.5)
	-c option for command line welcome message.  Show last move
	command (key is '/').  Beeps when a message is sent.  Nomove.c
	modified; some compilers thought the expression was too complicated.

11/27/87 (v 1.6)
	Keep track of stregth and wins in a default file in user's home
	directory.  Use this to determine sides and handicapping.
	I/O problems (when selecting socket and stdin) fixed.

1/30/88 (v 2.0)
	Add demo mode and optional beeping. 

2/10/88 (v 2.1)
	Change in arguments, modification to strength and scoring
	algorithm.  A bug in declining that had led to lock up was fixed.
	Among other options, KOMI was added to scoring.

4/13/88 (v 4.2)
        Fixed scoring and option bug

1/30/90 (v 5.0)
	Add coordinates to the side of the board.  Show captured stones.
	At the end of the game, clear the screen using
	carriage returns instead of Clear() BEFORE the score info is printed.

2/15/90
	Interface is cleaned up, synchonization for load games,
	Exit the message section by ^D,
	and restore saved game.

7/17/90 (v 7.0)
        Added move by move game logging to Smart-Go, and restore from 
	   Smart-Go files.  
	Added inverse video and made it easy to redefine black stone character.
	Added number keys for movement
	Handicap information is only used if the -E option is specified
	Cleaned up options.

11/10/90 (v 7.1)
	Fixed so ^D from message will invent a newline if none given
	Added automatic timekeeping
		Byoyomi allows for a sequence of periods in each of
		which the player must make some given number of moves.
		If the opponent's version of inetgo doesn't have timing,
		then he is sent a time message after each move.
	Added * as HANDICAP mode command to set standard handicaps
	Added T as HANDICAP mode command to set time limit parameters
	Reformatted the indenting in DoOther()
	Changed so S prints a message only if game really saved
	Revised help message to differ for the three principle modes
	Fixed homemes() to put next message at top of message area

        Fixed Smart-Go load to not print the file, and to correctly handle
            captured stones.
SHAR_EOF
fi
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
# Makefile for Go version 7.20
# by Greg Hale
# Monday, June 8, 1987
# Modified by Jeff Boscole ( aesop@blake.acs.washington.edu )  8/31/89
# Modified by Adrian Mariano ( adrian@u.washington.edu ) 7/13/90
# Modified by Fred Hansen ( wjh+@andrew.cmu.edu ) 8 Nov 1990

CFLAGS= -w -DINVERSE=${INVERSE} -DBLACK=${BLACK} -DVERSION='"Go 7.20"'

# Video options.  Set INVERSE to 128 to set default to inverse video
# or set it to 0 to get normal video as default.  Set BLACK to the
# default character for black stones.

INVERSE = 128 

#INVERSE = 0

#This line gets black # for black stones
#BLACK = 35

BLACK = "'*'"

# destination manual pages
MANSRC=go.6
MAN=go.doc

# destination directory vvvvvvv ---  put your directory here  vvvvvvvvvvvv |
MANDIR= .
BINDIR= .

# PROGRAM NAMES        ^^^^^^^^ ---  put your directory here  ^^^^^^^^^^^^ |
GO=go
SHAR=shar
SHARCHIVE=inetgo.sh

FORMATTER=format

# files which make up the shell archive along with sources
FILES = README Makefile $(MANSRC) 

MOBJECTS = curse.o \
           board.o \
        doloop.o \
        go.o \
        loop.o \
        mesg.o \
        tick.o \
        traps.o 

SHARED = changes.o \
        connect.o \
        backup.o \
        doother.o \
        file.o \
        handicap.o \
        life.o \
        strength.o \
        help.o \
        opts.o \
        putpiece.o \
        score.o \
        var.o 

SRCS =  backup.c changes.c \
        connect.c curse.c \
        board.c \
        doloop.c doother.c \
         file.c   \
        go.c  handicap.c  help.c \
        life.c  loop.c \
           mesg.c \
        opts.c \
        putpiece.c \
        score.c \
        strength.c \
         tick.c \
        traps.c \
        var.c

HDRS =	go.h \
	std.disclaimer

all: $(GO) $(MAN)

$(GO): $(MOBJECTS) $(SHARED)
	@echo "loading $(GO)..."
	@cc $(MOBJECTS) $(SHARED) -lcurses -ltermlib -o $(BINDIR)/$(GO);
	@echo "done."

$(MAN): $(MANSRC)
	@echo -n "typesetting manual..."
	@nroff -man $(MANSRC) > $(MANDIR)/$(MAN)
	@echo "done."

tags:
	ctags *.c *.h

clean:
	@echo -n "removing extra files..."
	@-rm -f *.o $(GO) $(SHARCHIVE) $(SHARCHIVE).Z
	@echo "done."

make:
	mkmf -d

archive:
	shar $(FILES) $(SRCS) $(HDRS)  > igo.sh

# alternate for new archive program
archive1:
	shar -m 100000 -f $(SHARCHIVE) $(FILES) $(SRCS) $(HDRS)

$(MOBJECTS): go.h
$(SHARED): go.h

checkout:
	co -l $(SRCS) go.h
checkin:
	ci $(SRCS) go.h
SHAR_EOF
fi
if test -f 'go.6'
then
	echo shar: "will not over-write existing file 'go.6'"
else
cat << \SHAR_EOF > 'go.6'
.TH GO 6  "6 September 1991"
.SH NAME
go \- the oriental game of go
.SH SYNOPSIS
.B go
[option switches] user[@host]
.SH DESCRIPTION
.I Go
is an ancient oriental strategy game based on the capturing of territory.  
The players alternate putting stones on the board, 
trying to surround as many empty intersections as possible.  
Although go rules are very similar everywhere, there are variations in the 
details of scoring;  in general this program corresponds 
to the Japanese method of scoring.
If you do not know how to play,
it may help to find someone who does (look at the file 
.B goplayers
) and have him or her explain.
.SH WHAT TO DO
The standard rogue keys
.B [hjklyubn]
are used for cursor movement and the space bar selects a point.
If rogue keys are not one's "cup of tea" then the numeric keypad 
.B [12346789] 
may be used:
.B [?]
will give a short help list for further commands.
When a command is inappropriate at the given time, 
the game will beep when the action is attempted.
.LP
[CTRL-C] will exit the game at any time.
.LP
A [>] indicates which player one is by
appearing next to the player status at the bottom of the screen.
Either player can switch which player he is by selecting the switch command.
(Use the panic command if both players are the same color.  The panic command
only switches one side.)
.LP
When the game begins,
both players have the option of setting up the handicap until play begins.
Selecting a point on the board puts a black piece down or
takes it away if there is already one there.
After setting up the handicap,
either player can select the play option to begin the game.
.LP
NOTE- the program keeps track of respective player strengths
in a file in the home directory called '.go_strength'.
It contains two values separated by a space and followed
by a carriage return.
.LP
The first value is the player strength,
starting at 35 kyu = value -5,
and working down to 1 kyu = value 29.
Higher values represent dan level players.
The second value is the number of games won (if positive),
or the number of games lost (if negative).
.LP
Versions of Inet GO prior to 7.0 take the difference in
player strengths from the info in '.go_strength' to determine handicap stones.
For each point difference,
one handicap stone is given
to the weaker player on a 19x19 board.
Smaller boards reduce this handicap proportionally.
After the player wins or looses several games
in a row,
his rank changes accordingly.
Inet GO version 7.0 and future versions do not set handicapping 
automatically in the initial display window unless players specify the -E
option on the run-time command line. 
.LP
Note: One may set rank with command line options.
.LP
If any player does not like the rank assigned automatically by computer,
the handicap stones may be changed manually,
as well as player rank.
.LP
Play begins with black if no handicap stones are put down,
otherwise play begins with white.
Afterwards,
play alternates until the end of the game.
The most recent move can be shown by selecting the Last command.
.LP
When a player thinks the game is over,
he may select the score option.
This will enable scoring and both players
can remove the dead groups from the board.
If either player disagrees with the scoring and/or wishes to resume play,
the cancel option returns the game to the state just before scoring
and play resumes as before.
The player whose turn it was when scoring began resumes his turn.
If both players agree to scoring,
the quit option should be selected by either player.
The other player will be queried to make sure he agrees with the scoring,
the the program will print the resulting score.
.LP
Another way to leave the game is via the resign option.
When a player resigns,
the other player is automatically declared a winner and the score
files are updated.
.LP
The game also terminates when either player runs out of time.  
The other player is automatically declared a winner and the score
files are updated.  The time limits and byoyomi options are set 
during game setup by by 'T' command.
.LP
There are several byoyomi schemes, most of which are supported by this 
program.  The program implements three parameters for byoyomi:
.IP
.B Seconds -
The number of seconds per byoyomi period.   Default 400 for 20 seconds per stone.
.IP
.B Stones -
The number of stones to play in a period.   Default 20 stones.
.IP
.B Extends -
The number of occasions when time can run out without losing.  Default zero.
Use for Japanese professional byoyomi.
.LP
It is a good idea to give a little extra time per stone in byoyomi because the 
mechanics of making a move are harder.
.LP
In most North American tournaments the value of Extends is zero.  
This means that the player may have as many byoyomi periods as desired
and must use the number of stones given by the Stones parameter during
each period.  Typically this is using 20 stones in 5 minutes 
or 30 stones in 10 minutes.  If the Stones are used before time runs out, the 
player is given another set of stones and the timer is set back to Seconds.
.LP
In European play the Extends value is also zero but the player is given a 
certain number of seconds to play each stone.  In this case the Stones parameter 
is 1 and the number of Seconds is whatever is allowed.
.LP
In Japanese professional play, Stones is 1, seconds are 60, and Extends are 4.
At the beginning of byoyomi the player is shown as having 5 minutes for 
the current byoyomi period and the 4 extends.  If the player completes a move 
in under one minute, the time for the next move is again 5 minutes.  Each extend is 
an extra minute that can be used for a move during byoyomi.  After it is used, 
the total time alloted is one minute less.  Thus if a player has five minutes 
and uses 121 seconds for one stone only three minutes will be shown for 
subsequent plays.
.LP
Please note that the timing version of inetgo will operate with
prior versions.  If the opponent does not have a clock, the side with the
clock keeps him informed by sending message notes with the clock values.
.LP
When both players are using 7.1 or better, each keeps his or her own clock.  But
while the opponent is moving, the local inetgo is keeping a shadow
version of the  opponent's clock.  Since there can be network delays,
the opponents clock can appear to move backward when his or her turn
ends;  the amount of the jump reflects the network delay.  Consequence:
you will never run out of time due to something on your opponents
machine or due to network delay (even though it may temporarily appear
to your opponent as though you have run out of time when you haven't.)
.LP
If this version is used with an old version (or possibly due to a bug), 
the program may start up incorrectly, with both sides proclaiming "Your turn"
or "Waiting for opponent."  In this case, use the panic key, ctrl-P to switch 
the state on your end only to allow the game to proceed.
.SH OPTIONS
.TP 8
.B none
Print out the options and a short explanation of each.
.LP
.TP 8
.B -h
Print out this help file.
.LP
.TP 8
.B -p
Set the port to the specified port number.
This is so the connection can be forced to a
free port if several programs are running at once.
.LP
.TP 8
.B -q
Quiet -- don't issue any beeps. 
.LP
.TP 8
.B -s
Set the size of the board to a value from 7 to 19.
If both players select a size,
the smaller board will be used.
.LP
.TP 8
.B -n
Set the number of times to blink a piece.
This is useful for various screen-display speeds.
.LP
.TP 8 
.B -E
Use the handicapping info from the respective .go_strength files.
If both players specify -E then the .go_strength file info is used
to calculate a correct handicapping on the display at initialization.
If one of the players is using a former version of Inet GO previous
to release version 7.0, then the .go_strength files will be used.
If both players are using Inet GO release version 7.0, or subsequent
releases, then the the initial display will, by default, show -no-
handicapping stones.   To provide for an initial handicap setting -other-
than a value calculated from the respective .go_strength files, do not
specify -E, but use the -H option or the '*' command during setup.
.LP
.TP 8
.B -c 
Gives an opening message and credits. 
.LP
.TP 8
.B -H
Set the number of handicap stones to the value specified.
If the two players select different numbers,
the larger value will be used.
.LP
.TP 8
.B -r
Give the program's approximation of player rank and wins.
.LP
.TP 8
.B -R
Modify current player rank.  
``go -R 5 k'' would set player rank to 5 kyu (amateur).
``go -R 5 d'' would set player rank to 5 dan (middle ranks).
``go -R 5 p'' would set player rank to 5 professional dan (highest ranks).
``go -R +'' would increase player rank by one.
``go -R -'' would decrease player rank by one.
The lowest rank is 35 kyu,
climbing to 1 kyu.
Then one may become 1 dan (Shodan),
increasing to 7 dan.
Lastly,
the professional ranks go from 1 to 9 professional dan.
These 51 rankings are linked to 51 states of Buddha consciousness.
.LP
.TP 8
.B -l
Load a file.
``-l filename'' will load a saved file.
The format is as follows:
all numbers are separated by spaces.
The first value is the board size (7-19).
The next is the current player (0-1=b/w).
Then a `#' delimits the board info on a line by itself.
Following are rows of the board with a newline at the end of each.
At the end of the rows is another `#' on a new line.
Then the captured black, captured white, cursor x and y positions follow.
You will be prompted for a filename.
.LP
.TP 8
.B -L
Initiate game-logging to the 'Smart-GO' file format.
``-L sgfile'' will output the game-record as the game is played.
If the specified file already exists, it will be loaded as 
a 'Smart-GO' file.   This
option is intended to restore logged games, rather than to read Smart-Go
files in general.  Only the AddBlack, AddWhite, AddEmpty, White, and Black
Smart-Go commands are supported.  Variations will be superimposed. 
This takes precedence over the -l option
for restoring a game.
.LP
.TP 8
.B -a
Do not include the player messages from the
discussion windows in the 'Smart-GO' game record.
.LP
.TP 8
.B -V
Flip (invert) the video orientation opposite to
whatever the default compile options were.
.LP
.TP 8
.B -B
Use ascii code number, or char for displaying the Black stones.
(e.g.  -B 42, or -B \\* gives the '*' character).
.LP
.LP
.B Setting/unsetting 
.B stones
.B during play:
The 'z' and 'x' keys set/unset stones on the board.
.LP
.SH ABOUT THE GAME
In the rest of this document,
[O] refers to white or player two,
and [@] refers to black or player one.
.LP
Some general rules are common.
First of all, liberties are the
free points horizontally or vertically adjacent to a group.
In the following examples,
white has 0,1,2,3,4,5, and 6 liberties
respectively:
.sp
.nf
     (l = liberty, normally a [.])
     (# = out of bounds)

     #. @ .      #. @ .     #. @ .     #. @ .     #. l .
     #@ O @      #@ O l     #l O l     #l O l     #l O l
     #. @ .      #. @ .     #. @ .     #. l .     #. l .
     ######      ######     ######     ######     ######

     #. l @ .    #. l l .
     #l O O l    #l O O l
     #. l l .    #. l l .
     ########    ########
.fi
.LP
During play,
the players are not allowed to play a point when the 
corresponding group will have no liberties at the end of
the turn.  This is the "no suicide" rule.
.LP
When the last liberty of a group is taken away,
it is captured.
These captured stones count one point at the end of the game.
.sp
.nf
     (@ plays at 1)
     #. . . . .                #. . . . .
     #. @ @ @ .                #. @ @ @ .
     #@ O O O 1   --->         #@ . . . @
     #. @ @ @ .                #. @ @ @ .
     #. . . . .                #. . . . .
     ##########                ##########
.fi
.LP
A territory which can not be saved does not have to be removed
from the board before the end of the game.
The surrounding player can remove the stones during scoring mode at the end of
the game without having to play it out.
.LP
In these examples,
white owns the territory surrounded unconditionally.
Black can not fill in the last point
of either hole since he will not capture any stones
in the process.
Some of the points may be filled,
but white will eventually capture the black stones no matter
what black does.
If black does try this,
white will simply wait and gain points by passing.
.sp
.nf
     #. . . . . . . . .    #. . . . . . . . .
     #. . . . . . . . .    #. . . . . . . . .
     #@ @ @ @ @ @ @ @ .    #. . . . . . . . .
     #O O O O O O O @ .    #@ @ @ @ . . . . .
     #. . * O . . O @ .    #O O O @ . . . . .
     #. . O O . . O @ .    #O . O @ . . . . .
     #. . . O . . O @ .    #. O O @ . . . . .
     ##################    ##################
.fi
.LP
In these examples,
white does
.B not
own the territory because
black can fill in the remaining points and kill white.
It is important to understand that black will lose one or two
pieces in the second example,
but will succeed in the end.
.sp
.nf
     #. . . . . .           #. . . . . .
     #. . . . . .           #. . . . . .
     #@ @ @ @ . .           #@ @ @ @ @ .
     #O O O @ . .           #O O O O @ .
     #. . O @ . .           #. @ . O @ .
     ############           ############
.fi
.LP
In this example,
if white goes first and plays the center point,
he will have what is known as a cats eye and will be safe.
If black goes first and plays this point,
white is dead.
.sp
.nf
     #. . . . . .
     #. . . . . .
     #@ @ @ @ @ .
     #O O O O @ .
     #. . . O @ .
     ############
.fi
.LP
In all cases where a group like these can be considered dead,
they can be removed from the board at the end
of the game without further play.
This of course excludes cases where the external
group will die before it has
a chance to kill the internal group.
.LP
Another common situation is as follows:
.sp
.nf
     . . . . . .
     . . . . . .
     . O O @ @ .
     . O . O @ .
     . O O @ @ .
     . . . . . .
.fi
.LP
If black plays the empty space capturing white,
white can then capture black,
etc.
This can go on forever.
This situation is a
.B KO,
and white is not allowed to take black immediately.
White
.B MUST
play somewhere else,
then if black does not fill the KO,
white can then try to take it,
then black must play somewhere else.
Sooner or later,
someone should fill it before scoring is done.
.LP
If there is any debate whether territory is owned by a player,
just play further and the winner will prevail.
.LP
A good strategy in the beginning is to try to build stable
structures.
When something is stable,
one may attach appendages
to it and expand safely.
For beginners,
one big strong group is better than
several spread out vulnerable groups.
.LP
Later,
try to spread out:
place one or two pieces in open territory to obtain
influence over that section of the board.
Good Go players need only to put one piece near a
corner to know that they have a good chance of owning it
later.
.LP
At the end of the game, when scoring,
each captured stone is worth one point,
and each point owned as territory is one point.
The player with the most points wins.
The procedure is to erase all groups both players
agree have no chance of surviving.
If at any time a disagreement occurs,
either player can cancel scoring and continue the
game at the point before scoring occurred.
.LP
When all scoring is complete,
both players must agree to quit and the game
with print out the score.
.LP
As a final note, I highly recommend a 
purchase of go literature if one intends to enjoy
the game to its fullest.
To pass through the lower levels swiftly and correctly,
I STRONGLY recommend the _Graded Go Problems for Beginners_
series by the Ishi Press.
Almost any game store should be able to supply it.
.SH FILES
go.doc     	this file
.sp
$(HOME)/.go_strength	a file kept in the player's home directory keeping track of ranks and wins.
.sp
go.players	a file set up by users to tell other players who they are.
.sp
.SH BUGS
.nf
A SiZe[xx] statement in a Smart-Go file will be ignored.
.LP
When loading a Smart-Go file, the program may not correctly 
identify the player whose turn it is.
.LP
Smart-Go files must not contain variations
.LP
If both players specify -L on files that contain game data, 
the two games will be superimposed.
.LP
There is no way to save or load game timing information.
.LP
Send further bug reports to "adrian@u.washington.edu",
"...!ucbvax!scam!hale" or "hale@scam.Berkeley.EDU"
.fi
.sp
.SH AUTHORS
Greg Hale (hale@scam.berkeley.edu)
.LP
Jeff Boscole
.LP
Adrian Mariano (adrian@u.washington.edu)
.LP
Fred Hansen (wjh+@andrew.cmu.edu)
.sp
.SH "SEE ALSO"
rn rec.games.go \- a newsgroup on the game
.br
_Graded go problems for beginners,
vol 1-3._, Ishi Press.
(Highly recommended.)
.br
_In the Beginning_,
Ishi Press.
.br
_The Treasure Chest Enigma_,
Ishi Press.
.br
go.players \- an optional file with players and ranks
SHAR_EOF
fi
if test -f 'backup.c'
then
	echo shar: "will not over-write existing file 'backup.c'"
else
cat << \SHAR_EOF > 'backup.c'
#include "std.disclaimer"
#include "go.h"

int ohama[2] =
{
   0, 0
};
static int ocur;
static BOARD lastboard;
int lhama[2] =
{
   0, 0
};


saveboard()
{
   int i, j;
   ocur = curplr;
   ohama[0] = hama[0];
   ohama[1] = hama[1];

   for (i = 0; i < MAXX; i++)
      for (j = 0; j < MAXY; j++)
	 backup.d[i][j] = board.d[i][j];
}

saveboard0()
{
   int i, j;
   for (i = 0; i < MAXX; i++)
      for (j = 0; j < MAXY; j++)
	 backup.d[i][j] = lastboard.d[i][j];
}

savelast()
{
   int i, j;
   lhama[0] = hama[0];
   lhama[1] = hama[1];
   for (i = 0; i < MAXX; i++)
      for (j = 0; j < MAXY; j++)
	 lastboard.d[i][j] = board.d[i][j];
}

restlast()
{
   int i, j;
   hama[0] = lhama[0];
   hama[1] = lhama[1];
   for (i = 0; i < MAXX; i++)
      for (j = 0; j < MAXY; j++) {
	 if (board.d[i][j] != lastboard.d[i][j]) {
	    Plt(&lastboard, i, j);
	 }
	 board.d[i][j] = lastboard.d[i][j];
      }
}

restboard()
{
   int i, j;
   hama[0] = ohama[0];
   hama[1] = ohama[1];
   curplr = ocur;
   for (i = 0; i < MAXX; i++)
      for (j = 0; j < MAXY; j++)
	 board.d[i][j] = backup.d[i][j];
}

int compboard()
{
   int i, j;
   for (i = 0; i < MAXX; i++)
      for (j = 0; j < MAXY; j++)
	 if (board.d[i][j] != backup.d[i][j])
	    return (-1);
   return (0);
}
SHAR_EOF
fi
if test -f 'changes.c'
then
	echo shar: "will not over-write existing file 'changes.c'"
else
cat << \SHAR_EOF > 'changes.c'
#include "std.disclaimer"

changes()
{
   printf("\
----------------------------------------------------------------------\n\
\n\
  			        %s\n\
		             By Greg Hale\n\
                    Enhancements by Adrian Mariano, Jeff Boscole, and Fred Hansen\n\
\n\
Welcome to the oriental game of Go.  If you do not know how to play,\n\
I recommend that you read the documentation or find someone who knows\n\
how to play.\n\
\n\
This program was developed at the Experimental Computing Facility at the\n\
University of California, Berkeley, by Greg Hale and enhanced by Adrian\n\
Mariano at the University of Washington and Fred Hansen.  Thanks to all the\n\
other members for their input, support, and test playing.\n\
\n\
----------------------------------------------------------------------\n \
[Hit return to continue]\n\n", VERSION);
   getchar();
}
SHAR_EOF
fi
if test -f 'connect.c'
then
	echo shar: "will not over-write existing file 'connect.c'"
else
cat << \SHAR_EOF > 'connect.c'
#include "std.disclaimer"
#include "go.h"
#include <sys/param.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pwd.h>
#include <errno.h>

/* Some systems do not have these defined in the include files. */
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
typedef short uid_t;
#endif

char *opponent;
char myhostname[MAXHOSTNAMELEN + 1];
extern char *myname;

extern int errno;

FILE *inp, *out;

connectport(oppon, port)
    char *oppon;
    u_short port;
{
   struct sockaddr_in addr;
   struct hostent *host;
   struct passwd *mypasswd, *getpwuid();
   char *hishostname, *index(), *getpw(), *malloc();
   char *hisaddr, *myaddr;
   int hislen, mylen;
   u_long iaddr;
   uid_t getuid();
   u_short hashport(), hashaddr();
   char *copyhost();
   int s, i;

   opponent = oppon;
   if (gethostname(myhostname, MAXHOSTNAMELEN) < 0)
      error("gethostname in connectport");
   host = gethostbyname(myhostname);
   if (host == NULL) {
      errno = 0;
      error("don't know my own name.");
   }
   mylen = host->h_length;
   myaddr = copyhost(host);
   if (hishostname = index(oppon, '@')) {
      *hishostname++ = '\0';	/* separate user and host */
      if (hishostname[0] >= '0' && hishostname[0] <= '9') {
	 iaddr = inet_addr(hishostname);
	 hisaddr = (char *) &iaddr;
	 hislen = sizeof iaddr;
      } else {
	 host = gethostbyname(hishostname);
	 if (host == NULL) {
	    errno = 0;
	    error("Unknown host");
	 }
	 hislen = host->h_length;
	 hisaddr = copyhost(host);
	 hishostname = host->h_name;
      }
   } else {
      hislen = mylen;
      hisaddr = myaddr;
      hishostname = myhostname;
   }
   mypasswd = getpwuid((int) getuid());
   myname = mypasswd->pw_name;

   if (iamserver == UNSET)
      if (i = strcmp(myname, oppon))
	 iamserver = (i < 0);
      else if (i = comparehost(myaddr, hisaddr))
	 iamserver = (i < 0);
   if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
      error("socket in connectport");
   bzero((char *) &addr, sizeof(addr));
   if (port != 0) {
      if (port > 1000) {
	 errno = 0;
	 error("bad port number");
      }
   } else if (iamserver) {
      port = hashaddr(myaddr, port, mylen);
      port = hashaddr(hisaddr, port, hislen);
      port = hashport(myname, port);
      port = hashport(oppon, port);
   } else {
      port = hashaddr(hisaddr, port, hislen);
      port = hashaddr(myaddr, port, mylen);
      port = hashport(oppon, port);
      port = hashport(myname, port);
   }
   port += 3000;
   addr.sin_family = AF_INET;
   addr.sin_port = htons(port);

   connectmes(hishostname);

   if (iamserver) {
      s = sock;
      if (bind(s, /* (char *) */ &addr, sizeof(addr)) < 0)
	 if (errno == EADDRINUSE && iamserver == UNSET) {
	    /* hope other player is server */
	    iamserver = FALSE;
	    close(s);
	    if ((sock = socket(AF_INET, SOCK_STREAM, 0))
		< 0)
	       error("socket in connectport");
	 } else
	    error("bind in connectport");
      if (iamserver) {
	 if (listen(s, 1) < 0)
	    error("listen in connectport");
	 while ((sock = accept(s, (struct sockaddr_in *) NULL,
			       (int *) NULL)) < 0)
	    if (errno != EINTR)
	       error("accept in connectport");
	 close(s);
      }
   }
   if (!iamserver) {
      bcopy(hisaddr, (char *) &addr.sin_addr, hislen);
      while (connect(sock, /* (char *) */ &addr, sizeof(addr)) < 0)
	 if (errno == EINTR || errno == ECONNREFUSED) {
	    close(sock);
	    sleep(2);
	    if ((sock = socket(AF_INET, SOCK_STREAM, 0))
		< 0)
	       error("socket in connectport");
	 } else
	    error("connect in connectport");
   }
   if ((s = dup(sock)) < 0)
      error("dup");
   if ((inp = fdopen(sock, "r")) == NULL)
      error("fdopen");
   if ((out = fdopen(s, "w")) == NULL)
      error("fdopen");
   setlinebuf(out);

   sockmask[1] = 1 << sock;
}

u_short hashport(s, port)
    char *s;
    u_short port;
{
   while (*s)
      port = (port << 1) + *s++;
   return (port & 0x7fff);
}

/* addr is in network byte order. */
u_short hashaddr(addr, port, len)
    u_short port;
    char *addr;
{

   while (len--)
      port = (port << 1) + *addr++;
   return (port & 0x7fff);
}

char *copyhost(host)
    struct hostent *host;
{
   char *ret;

   ret = malloc(host->h_length);
   if (ret == NULL)
      error("malloc");
   bcopy(host->h_addr, ret, host->h_length);

   return ret;
}

comparehost(h1, h2)
    char *h1, *h2;
{
   auto unsigned long l1, l2;

   bcopy(h1, &l1, sizeof l1);
   bcopy(h2, &l2, sizeof l2);

   if (l1 < l2)
      return -1;
   else if (l1 > l2)
      return 1;
   return 0;
}


RECV(mes)
    char *mes;
{
   char num[4];
   int u;
   num[3] = '\0';
   if (read(sock, num, 3) != 3) {
      error("\n\nError- bad transmission\n");
      getchar();
   }
   u = read(sock, mes, atoi(num));
   mes[u] = '\0';
   if (u != atoi(num)) {
      error("\n\nRECEIVE: length does not match.\n");
   }
}


SEND(mes)
    char *mes;
{
   char tbuf[MAXBUF];
   sprintf(tbuf, "%03d%s", strlen(mes), mes);
   write(sock, tbuf, strlen(tbuf));
}

readint(i)
    int *i;
{
   RECV(buf);
   *i = atoi(buf);
}

sendint(i)
    int i;
{
   sprintf(buf, "%d", i);
   SEND(buf);
}
SHAR_EOF
fi
if test -f 'curse.c'
then
	echo shar: "will not over-write existing file 'curse.c'"
else
cat << \SHAR_EOF > 'curse.c'
#include "std.disclaimer"
#include "go.h"
#include <ctype.h>
#include <curses.h>

#define DEBUG_CURSE 0

extern int mesflg;


int curpos = 0;
#define OFFX (2*MAXX+2)
#define MAXL 23

connectmes(hname)
    char *hname;
{
   extern char *myname, myhostname[];
   extern char *hisname;
   move(0, 0);
   printw("Waiting for %s@%s to type 'go user@host.net' ", hisname, hname);
   refresh();
}

doneconnectmes()
{
   clear();
   refresh();
}

REFRESH()
{
   refresh();
}
CLEAR()
{
   clear();
   refresh();
}

DoQuit()
{
   char c;
   homemes();
   addmes("- Opponent wants to score and quit.   Do you accept? (y/n)");
   Beep();
   do
      c = GetAKey0();
   while (c != 'y' && c != 'n');
   if (c == 'y') {
      SEND(MACCEPT);
      Score();
   } else {
      dodecline();
      SEND(MDECLINE);
   }
   move(0, 0);
   clrtoeol();
   refresh();
}


#define mesgy 1
#define mesgy2 5
#define mesgx 42

homemes()
{
   int y;
   for (y = mesgy; y < mesgy2; y++) {
      move(y, mesgx);
      clrtoeol();
   }
   curpos = 0;
}

addmes(mes)
    char *mes;
{
   do {
      move(curpos + mesgy, mesgx);
      printw("%.35s", mes);
      curpos = (curpos + 1) % (mesgy2 - mesgy + 1);
      move(curpos + mesgy, mesgx);
      clrtoeol();
      if (strlen(mes) <= 35)
	 break;
      else
	 mes += 35;
   }
   while (1);
   refresh();
}


GetAKey0()
{
   char c;
   if (read(FD_INPUT, &c, 1) <= 0) {
      SEND(MEXIT);
      error("Aborting- End of File read.\n");
   }
   return (c);
}

movecur(x, y)
    int x, y;
{
   cx = (cx + x + MAXX) % MAXX;
   cy = (cy + y + MAXX) % MAXY;
}

chkmve(c)
    char c;
{
   switch (c) {
    WHEN '4':
   case 'h':
      movecur(-1, 0);
      return (1);
    WHEN '2':
   case 'j':
      movecur(0, 1);
      return (1);
    WHEN '8':
   case 'k':
      movecur(0, -1);
      return (1);
    WHEN '6':
   case 'l':
      movecur(1, 0);
      return (1);
    WHEN '7':
   case 'y':
      movecur(-1, -1);
      return (1);
    WHEN '9':
   case 'u':
      movecur(1, -1);
      return (1);
    WHEN '1':
   case 'b':
      movecur(-1, 1);
      return (1);
    WHEN '3':
   case 'n':
      movecur(1, 1);
      return (1);
    WHEN 'H':
      movecur(-FASTMOVE, 0);
      return (1);
    WHEN 'J':
      movecur(0, FASTMOVE);
      return (1);
    WHEN 'K':
      movecur(0, -FASTMOVE);
      return (1);
    WHEN 'L':
      movecur(FASTMOVE, 0);
      return (1);
    WHEN 'Y':
      movecur(-FASTMOVE, -FASTMOVE);
      return (1);
    WHEN 'U':
      movecur(FASTMOVE, -FASTMOVE);
      return (1);
    WHEN 'B':
      movecur(-FASTMOVE, FASTMOVE);
      return (1);
    WHEN 'N':
      movecur(FASTMOVE, FASTMOVE);
      return (1);
    OTHERWISE:
      return (0);
   }
}

getcmd()
{
   char c;
   int ret;

   c = GetAKey0();

#if DEBUG_CURSE
   {
      char buf[100];

      sprintf(buf, "char hit '%c'", c);
      addmes(buf);
   }
#endif

   if (mesflg) {
       /*-->*/ return c;
   }
   /* move the cursor */
   if (chkmve(c))
       /*-->*/ return C_NOTHING;

   switch (c) {
   case 'T':
      ret = C_SETTIME;
      break;
   case '*':
      ret = C_SETHAND;
      break;
   case REDRAW:
      ret = C_REDRAW;
      break;
   case 'V':			/* inverse */
      /* hadle here. */
      ret = C_INVERSE;
      break;
   case 'S':			/* save */
      ret = C_SAVE;
      break;
   case '#':			/* load */
      ret = C_LOAD;
      break;
   case 'q':			/* quit */
      ret = C_QUIT;
      break;
   case 't':			/* tally */
      ret = C_TALLY;
      break;
   case 'c':			/* cancel */
      ret = C_CANCEL;
      break;
   case 'C':			/* clear */
      ret = C_CLEAR;
      break;
   case 'm':			/* message */
      ret = C_MESSAGE;
      break;
   case 'R':			/* resign */
      ret = C_RESIGN;
      break;
   case 's':			/* switch */
      ret = C_SWITCH;
      break;
   case '/':			/* play */
      /* bad name for this command.  show last would be better. */
      ret = C_LAST;
      break;
   case 'P':
      ret = C_PAUSE;
      break;
   case 'p':			/* pass */
      ret = C_PASS;
      break;
   case '?':			/* help */
      /* hadle here. */
      ret = C_HELP;
      break;
   case 'z':			/* dohand with '0' */
      ret = C_SETBLACK;
      break;
   case 'x':			/* dohand with '0' */
      ret = C_SETWHITE;
      break;
   case '0':
   case ' ':			/* put priece, remove group */
      ret = C_PLAY;
      break;
   case 'P'&31:
      ret = C_PANIC;
      break;
   default:
      ret = C_NOTHING;
   }

   return ret;
}


moveto(x, y)
{
   move(y + 1, (x * 2) + 1);
}


setmode()
{
   /* cbreak(); */
   noecho();
   crmode();
}

unsetmode()
{
   /* nocbreak(); */
   echo();
   nocrmode();
}

DoRefresh()
{
   clearok(stdscr, 1);
   refresh();
   clearok(stdscr, 0);
}


int getLine(query, dst, maxLen)	/* char *, char *, int */
    char *query, *dst;
    int maxLen;
{
   int qLen, dLen;
   int c;
   move(0, 1);
   for (c = 0; c < maxLen; c++)
      addch(' ');
   mvaddstr(0, 1, query);
   dLen = 0;
   qLen = strlen(query);
   do {
      move(0, qLen + 1 + dLen);
      refresh();
      c = getchar();
      if (isprint(c) && dLen < maxLen) {
	 mvaddch(0, qLen + dLen + 1, c);
	 dst[dLen++] = c;
      } else if (dLen && (c == '\b' || c == '\177')) {
	 dLen--;
	 mvaddch(0, qLen + dLen + 1, ' ');
      }
   }
   while (c != '\n' && c != '\r');
   dst[dLen] = 0;
   move(0, 1);
   for (c = 0; c < maxLen; c++)
      addch(' ');
   return dLen;
}

DoRedraw()
{
   touchwin(stdscr);
   clear();
   PrintBoard(&board);
}
SHAR_EOF
fi
if test -f 'board.c'
then
	echo shar: "will not over-write existing file 'board.c'"
else
cat << \SHAR_EOF > 'board.c'
#include "std.disclaimer"
#include "go.h"
#include <curses.h>

PrintBoard(br)
    BOARD *br;
{
   extern int handin, dimensions, inverse;
   int x, y;
   touchwin(stdscr);
   handin = (dimensions > 12) ? 3 : 2;
   for (y = 1; y < MAXY + 1; y++)
      for (x = 0; x < MAXX * 2; x++)
	 mvaddch(y, x, 32 + inverse);
   for (y = 0; y < MAXY; y++) {
      for (x = 0; x < MAXX; x++) {
	 Plt(br, x, y);
      }
      mvprintw(y + 1, MAXX * 2, "|%d", MAXY - y);
   }
   for (x = MAXX; x--;) {
      char c;
      c = 'A' + x;
      c = (c >= 'I') ? c + 1 : c;
      mvaddch(MAXY + 1, x * 2 + 1, c);
   }
   initmesg();
   printscore();
   printtimes();
   refresh();
}

printscore()
{  char lin[80];
   /* mvaddstr(MAXY+1,0,"Go - By Greg Hale"); */
   move(21, 0);
   addch(player ? '>' : ' ');

/* This next bit gets around a bug on ES/OS in the printw function */

   sprintf(lin,"Player one [%c] (captured O): %4d", pieces[1]&127, hama[0]);
   printw(lin);

   move(22, 0);
   addch(!player ? '>' : ' ');
   
   sprintf(lin,"Player two [O] (captured %c): %4d", pieces[1]&127, hama[1]);
   printw(lin);
}


InitBoard(br)
    BOARD *br;
{
   int x, y;
   for (y = 0; y < MAXY; y++)
      for (x = 0; x < MAXX; x++)
	 br->d[x][y] = NONE;
}


Plt(br, x, y)
    BOARD *br;
    int x, y;
{
   char c;
   moveto(x, y);
   c = (pieces[br->d[x][y]]);
   if (c == pieces[0])
      c = cp(x, y);
   addch(c);
}

cp(x, y)
    int x, y;
{
   extern int handin;

   if ((x == handin || x == MAXX - 1 - handin || x == (MAXX - 1) / 2) &&
       (y == handin || y == MAXY - 1 - handin || y == (MAXY - 1) / 2)) {
      return (pieces[4]);
   } else {
      return (pieces[0]);
   }
}


setboard(x, y, p)
    int x, y;
    char p;
{
   if ((p < 1 || p > 2) && b(x, y) == 1 || b(x, y) == 2) {
      hama[!(b(x, y) - 1)]++;
   }
   board.d[x][y] = p;
   Plt(&board, x, y);
}


deletes(x, y)
    int x, y;
{
   InitBoard(&marks);
   killit(x, y, b(x, y));
}



Kill(x, y, type)
    int x, y, type;
{
   int t;
   InitBoard(&marks);
   t = !(type - 1) + 1;
   if (!IsSafe(x - 1, y))
      killit(x - 1, y, t);
   if (!IsSafe(x + 1, y))
      killit(x + 1, y, t);
   if (!IsSafe(x, y - 1))
      killit(x, y - 1, t);
   if (!IsSafe(x, y + 1))
      killit(x, y + 1, t);
}


killit(x, y, t)
    int x, y, t;
{
   if (ir(x, y) && b(x, y) == t && t != NONE) {
      setboard(x, y, NONE);
      Plt(&board, x, y);
      killit(x - 1, y, t);
      killit(x + 1, y, t);
      killit(x, y - 1, t);
      killit(x, y + 1, t);
   }
}


DoHand(x, y, c)
    int x, y, c;
{

   sethand(x, y, (b(x, y) == c + 1 ? 0 : c + 1));
   printscore();
}

sethand(x, y, v)
    int x, y, v;
{
   extern int handicaps;
   if (b(x, y) != v) {
      if (AreWe(HANDICAP)) {
	 if (v)
	    handicaps++;
	 else
	    handicaps--;
      }
      b(x, y) = v;
      dolog(x, y, v);
      Plt(&board, x, y);
      SEND(MHANDICAP);
      SendCoord(x, y);
      sendint(v);
   }
}



NoMove(x, y, c, d)
    int x, y, c, d;
{
   return (!IsSafe(x, y) &&
	   nmv0(x - 1, y, c, d) &&
	   nmv0(x + 1, y, c, d) &&
	   nmv0(x, y - 1, c, d) &&
	   nmv0(x, y + 1, c, d));
}

nmv0(x, y, c, d)
    int x, y, c, d;
{
   return (!ir(x, y) ||
	   (b(x, y) == c && IsSafe(x, y)) ||
	   (b(x, y) == d && !IsSafe(x, y)));
}
SHAR_EOF
fi
if test -f 'doloop.c'
then
	echo shar: "will not over-write existing file 'doloop.c'"
else
cat << \SHAR_EOF > 'doloop.c'
#include "std.disclaimer"
#include "go.h"
#include <ctype.h>

extern int mesflg, loadflg, inverse, handicaps;

DEBUG(extern FILE * debug;
)
    bool getint(prompt, dest)
    char *prompt;
    int *dest;
{
   char buffer[5], *bx;
   int v;

   getLine(prompt, buffer, sizeof(buffer) - 1);
   bx = buffer;
   while (*bx && !isdigit(*bx))
      bx++;
   if (!*bx)
      return FALSE;
   v = 0;
   while (*bx && isdigit(*bx))
      v = v * 10 + (*bx++ - '0');
   *dest = v;
   return TRUE;
}

DoLoop()
{
   char c;
   char buf[20];

   c = getcmd();

   if (mesflg)
      domesg(c);
   else if (!disable)
      switch (c) {
	 WHEN C_REDRAW:
	    DoRefresh();
	 WHEN C_INVERSE:
	 if (inverse) {
	    for (c = 0; c < 6; c++)
	       pieces[c] -= 128;
	    inverse = 0;
	 } else {
	    for (c = 0; c < 6; c++)
	       pieces[c] += 128;
	    inverse = 128;
	 }
	 DoRedraw();
	 WHEN C_SAVE:
	    dosave();
	 WHEN C_SETTIME:
	 if (AreWe(HANDICAP)) {
	    dosettiming();
	 } else
	       Beep();
	 WHEN C_SETHAND:
	 if (AreWe(HANDICAP) && getint("Handicap: ", &handicaps)) {
	    SEND(MCLEAR);
	    doclear();
	    sethandi();
	 } else
	       Beep();
	 WHEN C_LOAD:
	 if (!AreWe(PAUSED))
	       doload();
	 WHEN C_QUIT:
	 if (AreWe(SCORE)) {
	    SEND(MQUIT);
	    disable = 1;
	 } else
	       Beep();
	 WHEN C_TALLY:
	 if (AreWe(SCORE)) {
	    savelast();
	    Tally();
	    PrintBoard(&board);
	    GetAKey();
	    restlast();
	 } else
	       Beep();

	 WHEN C_CANCEL:
	 if (AreWe(SCORE)) {
	    docancel();
	    SEND(MCANCEL);
	 } else
	       Beep();

	 WHEN C_CLEAR:
	 if ((!AreWe(PAUSED)) && verify("Clear the board (y/n)?")) {
	    SEND(MCLEAR);
	    doclear();
	 }
	 WHEN C_MESSAGE:
	 /* addmes("control-D to finish message"); */
	    mesflg++;

	 WHEN C_RESIGN:
	 if ((!AreWe(PAUSED)) && verify("Resign (y/n)?")) {
	    SEND(MRESIGN);
	    dodecided(FALSE,
		      "You resigned.",
		      "\nYou lost by resignation.\n");
	 }
         WHEN C_PANIC:
            doswitch();
            addmes("Switched game state ON THIS END");
	 WHEN C_SWITCH:
	 if (AreWe(HANDICAP)) {
	    SEND(MSWITCH);
	    doswitch();
	 } else if (AreWe(PLAY)) {
	    SEND(MSCORE);
	    doscore();
	 } else
	    Beep();

	 WHEN C_LAST:
	 if (AreWe(PLAY)) {
	    ShowLast();
	 } else
	       Beep();
	 WHEN C_PASS:
	 if (AreWe(PLAY) && myturn) {
	    stoptick(TRUE);
	    curplr = !curplr;
	    SEND(MPASS);
	    if (timedgame) {
	       if (opphastiming) {
		  SEND(MTIME);
		  sprintf(buf, "%d",
			  mytime.left.tv_sec);
		  SEND(buf);
	       } else
		     sendtimemesg();
	    }
	    starttick(FALSE);
	 } else if (AreWe(HANDICAP)) {
	    SEND(MPLAY);
	    doplay();
	    printscore();
	 } else
	    Beep();
	 WHEN C_HELP:
	    help();
	 PrintBoard(&board);

	 WHEN C_SETBLACK:
	 if (AreWe(PLAY))
	       DoHand(cx, cy, 0);
	 else
	    Beep();
	 WHEN C_SETWHITE:
	 if (AreWe(PLAY))
	       DoHand(cx, cy, 1);
	 else
	    Beep();
	 WHEN C_PAUSE:
	 if (AreWe(PAUSED))
	       unpausegame(TRUE);
	 else if (AreWe(PLAY))
	    pausegame(TRUE);
	 WHEN C_PLAY:
	 if (AreWe(HANDICAP)) {
	    sethand(cx, cy, !b(cx, cy));
	 } else if (AreWe(SCORE))
	       doscorehit(cx, cy);
	 else if (AreWe(PLAY) && myturn) {
	    stoptick(TRUE);
	    putpiece(cx, cy, curplr, TRUE, TRUE);
	    if (timedgame) {
	       if (opphastiming) {
		  SEND(MTIME);
		  sprintf(buf, "%d",
			  mytime.left.tv_sec);
		  SEND(buf);
	       } else
		  sendtimemesg();
	    }
	    starttick(FALSE);
	 } else
	    Beep();
	 printscore();
	 WHEN C_NOTHING:;
       OTHERWISE:
	 Beep();
      }
}



int verify(s)
    char *s;
{
   char buf[2];
   do {
      getLine(s, buf, 1);
   }
   while (buf[0] != 'y' && buf[0] != 'n');

   return buf[0] == 'y';
}
SHAR_EOF
fi
if test -f 'doother.c'
then
	echo shar: "will not over-write existing file 'doother.c'"
else
cat << \SHAR_EOF > 'doother.c'
#include "std.disclaimer"
#include "go.h"

extern int loadflg;
extern char loadname[];
extern bool savegame();
extern int handicaps;
int turn;
bool done;

DEBUG(extern FILE * debug;
)
/* this table should match the one in go.h and the numeric sequence must match
 * the entries in DoOther() */
    char messages[][15] =
    {
       "SCORE",			/* 0 */
       "QUIT",			/* 1 */
       "ACCEPT",		/* 2 */
       "EXIT",			/* 3 */
       "DECLINE",		/* 4 */
       "CANCEL",		/* 5 */
       "PLAY",			/* 6 */
       "MOVE",			/* 7 */
       "LOAD",			/* 8 */
       "DELETE",		/* 9 */
       "CLEAR",			/* 10 */
       "PASS",			/* 11 */
       "MESSAGE",		/* 12 */
       "HANDICAP",		/* 13 */
       "SWITCH",		/* 14 */
       "RESIGN",		/* 15 */
       "TIME",			/* 16 */
       "SETTIME",		/* 17 */
       "SETBYO",		/* 18 */
       "TIMELOSE",		/* 19 */
       "PAUSE",			/* 20 */
       ""
    };

DoOther()
{
   extern int lastx, lasty;
   int x, y, cur;
   int i;

   RECV(buf);
   for (i = 0; *messages[i]; i++)
      if (!strcmp(messages[i], buf))
	 break;

   DEBUG(fprintf(debug, "%d %s\n", i, buf);
   fflush(debug);
   )
      switch (i) {
    WHEN 0:			/* MSCORE */
      doscore();
    WHEN 1:			/* MQUIT */
      DoQuit();
    WHEN 2:			/* MACCEPT */
      Score();
    WHEN 3:			/* MEXIT */
      homemes();
      addmes("- your opponent has departed");
      SetStat(EXIT);
    WHEN 4:			/* MDECLINE */
      homemes();
      addmes("- Other player has declined.");
      addmes("-	Please resume play.");
      Beep();
      disable = 0;
      dodecline();
    WHEN 5:			/* MCANCEL */
      docancel();
    WHEN 6:			/* MPLAY */
      doplay();
      printscore();
    WHEN 7:			/* MMOVE */
      if (!opphastiming && timedgame) {
	 /* he has no clock. tell him what we he's got left */
	 stoptick(FALSE);
	 sendtimemesg();
      } else if (timedgame)
	 opptime.stones--;
      if (!(AreWe(HANDICAP)))
{
	 Beep();
Beep();Beep();
}
      savelast();
      GetCoord(&x, &y);
      readint(&cur);

      lastx = x;
      lasty = y;
      setboard(x, y, cur + 1);
      Kill(x, y, cur + 1);
      Plt(&board, x, y);
      REFRESH();
      dolog(x, y, cur + 1);
      printscore();
      blink(x, y, cur + 1);
      NextPlr();
      saveboard0();
      starttick(TRUE);
    WHEN 8:			/* MLOAD */
      doReceiveLoad();
    WHEN 9:			/* MDELETE */
      GetCoord(&x, &y);
      deletes(x, y);
    WHEN 10:			/* MCLEAR */
      doclear();
    WHEN 11:			/* MPASS */
      if (!opphastiming && timedgame) {
	 /* he has no clock. tell him what he's got left */
	 stoptick(FALSE);
	 sendtimemesg();
      } else if (timedgame)
	 opptime.stones--;
      homemes();
      addmes("- Other player passed.");
      NextPlr();
      starttick(TRUE);
    WHEN 12:			/* MMESSAGE */
      RECV(buf);
      /* if (beepflg) Beep(); */
      addtalk(buf);
    WHEN 13:			/* MHANDICAP */
      GetCoord(&x, &y);
      readint(&cur);
      if (cur != b(x, y)) {
	 if (AreWe(HANDICAP)) {
	    if (cur)
	       handicaps++;
	    else
	       handicaps--;
	 }
	 b(x, y) = cur;
	 Plt(&board, x, y);
	 dolog(x, y, cur);
      }
      printscore();
    WHEN 14:			/* MSWITCH */
      doswitch();
    WHEN 15:			/* MRESIGN */
      dodecided(FALSE,
		"The other player resigned.",
		"\nYou won by resignation.\n");
    WHEN 16:			/* MTIME */
      readint(&cur);
      opptime.left.tv_sec = cur;
      opptime.left.tv_usec = 0;
      showtime(FALSE, &opptime);
      opphastiming = TRUE;
      starttick(FALSE);		/* this is solely to set the time left */
    WHEN 17:			/* MSETTIME */
      opphastiming = TRUE;
      readint(&totalmin);
      timedgame = (totalmin > 0);
      inittick();
      SEND(MTIME);		/* to set his opphastiming */
      sendint(mytime.left.tv_sec);
    WHEN 18:			/* MSETBYO */
      readint(&byosec);
      readint(&byostones);
      readint(&byoextends);
      showbyo();
    WHEN 19:			/* MTIMELOSE */
      dodecided(FALSE,
		"Your opponent's clock ran out.",
		"\nYou won by time out.\n");
    WHEN 20:			/* MPAUSE */
      myturn = !myturn;
      if (ticking)
	 pausegame(FALSE);
      else
	 unpausegame(FALSE);
      myturn = !myturn;
   }
}

pausegame(needsend)
    char needsend;
{
   if (!timedgame)
      return;
   if (needsend) {
      if (opphastiming)
	 SEND(MPAUSE);
      else {
	 SEND(MMESSAGE);
	 SEND("Clock paused.");
      }
   }
   Beep();
   Beep();
   Beep();
   addmes("- Game paused.  Hit P to resume.");
   pausetick(myturn);
   SetStat(PAUSED);
   ClrStat(PLAY);
}

unpausegame(needsend)
    char needsend;
{
   if (needsend) {
      if (opphastiming)
	 SEND(MPAUSE);
      else {
	 SEND(MMESSAGE);
	 SEND("Clock restarted.");
      }
   }
   Beep();
   Beep();
   Beep();
   addmes("- Game resumed.");
   resumetick(myturn);
   SetStat(PLAY);
   ClrStat(PAUSED);
}



dodecided(isme, msg1, msg2)
    int isme;
    char *msg1, *msg2;
{
   iwon = !isme;
   savestr();
   homemes();
   Beep();
   addmes(msg1);
   testsave();
   CLEAR();
   printf(msg2);
   Exit();
}

setcurplr()
{
   int x, y;
   for (x = 0; x < MAXX; x++)
      for (y = 0; y < MAXY; y++)
	 if (b(x, y)) {
	    curplr = 1;
	    return (0);
	 }
}

/* print out the messages to start scoring */
scoremes()
{
   homemes();
   addmes("- Please score now.");
   addmes("   - Cancel returns to play.");
   addmes("   - Select dead groups.");
   addmes("   - Quit determines winner.");
   Beep();
}

dosave()
{
   if (savegame())
      addmes("Game saved.");
   else
      addmes("Not saved");
   homemes();
}

doplay()
{
   extern int loadflg;
   homemes();
   addmes("- Please begin play.");
   Beep();
   ClrStat(HANDICAP);
   SetStat(PLAY);
   if (!loadflg) {
      /*hama[0] = hama[1] = 0;
      setcurplr();*/
if (handicaps) curplr = !curplr;
   }
   DEBUG(
	 fprintf(debug, "doplay - player: %d    curplr: %d    start for %d\n",
		 player, curplr, (!player && curplr) || (player && !curplr));
   fflush(debug);
   )
      starttick((!player && curplr) || (player && !curplr));
}

doscorehit(x, y)
    int x, y;
{
   if (b(x, y)) {
      deletes(x, y);
      SEND(MDELETE);
      SendCoord(x, y);
   } else
      Beep();
}


doswitch()
{
   player = !player;
   printscore();
   /* initmesg() ; */
}

dodecline()
{
   extern int mesflg, curx, cury, tcury;
   int curxbak, curybak, mesgbak, tcurybak;
   curxbak = curx;
   curybak = cury;
   mesgbak = mesflg;
   tcurybak = tcury;
   restboard();
   ClrStat(SCORE);
   SetStat(PLAY);
   PrintBoard(&board);
   mesflg = mesgbak;
   tcury = tcurybak;

   curx = curxbak;
   cury = curybak;
}

docancel()
{
   extern int mesflg, curx, cury, tcury;
   int curxbak, curybak, mesgbak, tcurybak;
   curxbak = curx;
   curybak = cury;
   mesgbak = mesflg;
   tcurybak = tcury;
   restboard();
   ClrStat(SCORE);
   SetStat(PLAY);
   PrintBoard(&board);

   REFRESH();
   homemes();
   addmes("- Scoring is cancelled.");
   addmes("-     Resume play.");
   mesflg = mesgbak;
   tcury = tcurybak;

   curx = curxbak;
   cury = curybak;
   resumetick(myturn);
}

doscore()
{
   pausetick(myturn);
   SetStat(SCORE);
   ClrStat(PLAY);
   scoremes();
   saveboard();
}



doclear()
{
   int x, y;
   char token[12];

   strcpy(token, ";\nAddEmpty");
   for (y = 0; y < dimensions; y++)
      for (x = 0; x < dimensions; x++)
	 if (b(x, y)) {
	    b(x, y) = 0;
	    Plt(&board, x, y);


	    loglist(x, y, token);
	    strcpy(token, "");


	 }
   logendlist();
   curplr = 0;
   hama[0] = hama[1] = 0;


}




GetAKey()
{
   addmes(HITAKEYMES);
   return (GetAKey0());
}


Beep()
{
   extern int beepflg;
   if (beepflg)
      putchar(07);
}


NextPlr()
{
   curplr = !curplr;
   turn++;
   if (done)
      done--;
}
SHAR_EOF
fi
if test -f 'file.c'
then
	echo shar: "will not over-write existing file 'file.c'"
else
cat << \SHAR_EOF > 'file.c'
#include "std.disclaimer"
#include "go.h"
#include <strings.h>
#include <sys/file.h>


/* save file */

FILE *sf;
int initload;
int commenting = 0;

char input_buffer[MAXBUF];

extern int beepflg, status;
extern int handicaps;
extern int dimensions, myport;
extern char *arg0;
extern int logflg;
extern FILE *logfile;

/* file format:
 * 
 * #<board dimension> #<curplr: 0/1> #<black's prisoners> #<white's prisoners>
 * #<cursor x> #<cursor y> <options= Rxx -> right justify with x being width
 * Bxx -> bottom justify with xx being height of data > '(' xoooxoxox..x
 * ..x..x...... ...x..x..xxx ')' %comments to be printed. %in the message
 * window
 * 
 */

static char *cont = ".@O.....";

bool
savegame()
{
   extern char *opponent;
   int x, y;

   getLine("Save as <ret exits>:", input_buffer, 44);
   if (input_buffer[0]) {
      sf = fopen(input_buffer, "w");
      if (!sf)
	 badload("Can't create file.");
      fprintf(sf, "%d %d %d %d %d %d %d\n",
	      dimensions, curplr, hama[0], hama[1], cx, cy, player);
      fprintf(sf, "(\n");
      for (y = 0; y < MAXY; y++) {
	 for (x = 0; x < MAXX; x++)
	    fprintf(sf, "%c ", cont[b(x, y)]);
	 fprintf(sf, "\n");
      }
      fprintf(sf, ")\n\n");
      fclose(sf);
      return TRUE;
   }
   return FALSE;
}

testsave()
{
   char buf[2];
   getLine("Save Game (y/n)? ", buf, 1);
   if (buf[0] == 'y')
      savegame();
   printf("\n");
}

doReceiveLoad()
{
   extern int loadflg;
   extern char loadname[];
   loadflg = TRUE;
   loadname[0] = 0;
   readint(&hama[0]);
   readint(&hama[1]);
   readint(&curplr);
   readint(&dimensions);
   readint(&player);
   MAXX = MAXY = dimensions;
   DoRedraw();
}

restgame(f)
    char *f;
{
   char *cp;
   int x, y, done;
   int lj, bj;


   sf = fopen(f, "r");

   getbuf(1);
   sscanf(input_buffer, "%d %d %d %d %d %d %d",
	  &dimensions, &curplr, &hama[0], &hama[1], &cx, &cy, &player);



   MAXX = MAXY = lj = bj = dimensions;
   if (!initload) {
      initload = 1;
      PrintBoard(&board);
   } else {
      SEND(MCLEAR);
      doclear();
   }


   homemes();
   if (!curplr)
      addmes("== Black to play.");
   else
      addmes("== White to play.");

   done = 0;
   do {
      getbuf(1);
      if (input_buffer[0] == 'R' || input_buffer[0] == 'r') {
	 lj = atoi(input_buffer + 1);
	 if (lj < 1 || lj > dimensions)
	    lj = dimensions;
      } else if (input_buffer[0] == 'B' || input_buffer[0] == 'b') {
	 bj = atoi(input_buffer + 1);
	 if (bj < 1 || bj > dimensions)
	    bj = dimensions;
      } else
	 done++;
   }
   while (!done);

   SEND(MLOAD);
   sendint(hama[0]);
   sendint(hama[1]);
   sendint(curplr);
   sendint(dimensions);
   sendint(!player);

   while (input_buffer[0] != '(')
      getbuf(1);

   getbuf(1);
   done = 0;
   x = dimensions - lj;
   y = dimensions - bj;
   cp = input_buffer;

   while (!done) {
      switch (*cp) {
      case '.':
      case '0':
	 cp++;
	 sethand(x++, y, 0);
	 break;

      case 'O':
      case 'o':
      case 'w':
      case '2':
	 cp++;
	 sethand(x++, y, 2);
	 break;

      case 'X':
      case '*':
      case 'x':
      case '@':
      case 'b':
      case '1':
	 cp++;
	 sethand(x++, y, 1);
	 break;

      case '\n':
      case ';':
      case '\0':
	 getbuf(1);
	 cp = input_buffer;
	 x = dimensions - lj;
	 y++;
	 break;

      case ')':
	 done++;
	 break;
      default:
	 cp++;
	 break;
      }

      if (x >= dimensions) {
	 getbuf(1);
	 x = dimensions - lj;
	 y++;
	 cp = input_buffer;
      }
      if (y >= dimensions)
	 done++;
   }
   /* Read in and display comments */
   while (fgets(input_buffer, MAXBUF, sf) != NULL && input_buffer[0] == '%') {
      if (input_buffer[0] == '%') {
	 char *cc;
	 cc = index(input_buffer, '\n');
	 if (cc != NULL)
	    *cc = '\0';
	 addmes(input_buffer + 1);	/* display the message */
      }
      input_buffer[0] = '\0';	/* is this neccessary? */
   }

   fclose(sf);
}

getbuf(err)
    int err;
{
   do {
      if (fgets(input_buffer, MAXBUF, sf) == NULL)
	 if (err)
	    badload("Bad Data/End of file reached early.");
   }
   while (input_buffer[0] == '\n' || input_buffer[0] == '\0' || input_buffer[0] == ';' || input_buffer[0] == '#');
}

badload(s)
    char *s;
{
   homemes();
   addmes(s);
   Beep();
   GetAKey();
   SEND(MEXIT);
   Exit();
}

doload()
{
   extern char loadname[];
   extern int loadflg;

   if (!loadname[0])
      getLine("Load which file?", loadname, 40);
   loadflg = loadname[0];
   if (loadflg)
      restgame(loadname);
   return 1;
}

int lastpiecex=  -1,lastpiecey= -1,lastpiecec= -1;

addapiece(str, c)
    char *str;
    int c;
{
   int x, y;

   while (str[0] == '[' && str[3] == ']' && str[1] >= 'a' && str[1] <= 's' &&
	  str[2] >= 'a' && str[2] <= 's') {
      x = str[1] - 'a';
      y = str[2] - 'a';
      if (c == 2) {
	 if (b(x, y) == 1)
	    DoHand(x, y, 0);
	 else if (b(x, y) == 2)
	    DoHand(x, y, 1);
      } else {
	 lastpiecex=x;
	 lastpiecey=y;
	 lastpiecec=c;
	 setboard(x, y, c + 1);
	 Kill(x, y, c + 1);
	 Plt(&board, x, y);
	 SEND(MMOVE);
	 curplr=!curplr;
	 SendCoord(x, y);
	 sendint(c);
      }
      str += 4;
   }
}


loadlog()
{
   char instr[1024];
   extern int logflg;

   logflg = 0;
   fseek(logfile, 0, 0);
   while (!feof(logfile)) {
      fgets(instr, 1023, logfile);
      if (!strncmp(instr, "Black[", 6))
	 addapiece(instr + 5, 0);
      else if (!strncmp(instr, "AddBlack[", 9))
	 addapiece(instr + 8, 0);
      else if (!strncmp(instr, "White[", 6))
	 addapiece(instr + 5, 1);
      else if (!strncmp(instr, "AddWhite[", 9))
	 addapiece(instr + 8, 1);
      else if (!strncmp(instr, "AddEmpty[", 9))
	 addapiece(instr + 8, 2);
   }
   logflg++;
   PrintBoard(&board);
   if (lastpiecec != -1) {
      sprintf(instr,"Last move %s %c%d",lastpiecec?"White":"Black",
          lastpiecex+'A',19-lastpiecey);
      addmes(instr);
   }      
}


int openlogfile()
{
   extern char logname[];
   extern int logflg;
   int d;
   char c;

   if (logfile = fopen(logname, "r+")) {
      loadlog();
      fseek(logfile, 0, 2);
      if (ftell(logfile)) {
	 d = (-1);
	 fseek(logfile, d, 2);
	 do {
	    d--;
	    c = fgetc(logfile);
	 }
	 while ((!fseek(logfile, d, 2)) && ((c != ')') && (c != ']')));
	 if (c == ')')
	    d++;
	 else
	    d = 0;
      }
      fseek(logfile, d, 2);
      logflg = 2;
      return 1;
   } else if (logfile = fopen(logname, "a+")) {
      fprintf(logfile, "(\n;\nGaMe[1]\nVieW[]\nSiZe[%d]\n", dimensions);
      logflg = 2;
      return 0;
   } else {
      SEND(MEXIT);
      logflg = 0;
      fprintf(stderr, "Error opening logfile\n\n");
      Exit();
   }
}


logendlist()
{
   if (logflg)
      fprintf(logfile, "\n");
}


loglist(x, y, text)
    int x, y;
    char *text;
{
   if (logflg) {
      if (commenting) {
	 commenting = 0;
	 fprintf(logfile, "]\n");
      }
      fprintf(logfile, "%s[%c%c]", text, x + 'a', y + 'a');
      fflush(logfile);
   }
}


char *Player[] =
{
   "AddEmpty", "Black", "White"};

dolog(x, y, color)
    int x, y, color;
{
   if (logflg) {
      if (commenting) {
	 commenting = 0;
	 fprintf(logfile, "]\n");
      }
      fprintf(logfile, ";\n%s[%c%c]\n", Player[color], x + 'a', y + 'a');
      fflush(logfile);
   }
}


closelogfile()
{
   if (logflg == 2) {
      if (commenting)
	 fprintf(logfile, "]\n");
      fprintf(logfile, ")\n");
      fclose(logfile);
   }
}


logcomment(comm, player)
    char *comm;
    int player;

{
   extern char *myname, *hisname;
   extern int usemess;

   if ((logflg) && (usemess) && (*comm) && (*comm != '\\')) {
      if (!commenting)
	 fputs("Comment[", logfile);
      if ((player == 1) && (commenting != 1))
	 fprintf(logfile, "\n %s:", myname);
      else if ((player == 2) && (commenting != 2))
	 fprintf(logfile, "\n %s:", hisname);
      commenting = player;
      fputc(' ', logfile);
      for (; *comm; comm++) {
	 if ((*comm == ')') || (*comm == '(') || (*comm == '[') || (*comm == ']'))
	    fputc('\\', logfile);
	 fputc(*comm, logfile);
      }
   }
}
SHAR_EOF
fi
if test -f 'go.c'
then
	echo shar: "will not over-write existing file 'go.c'"
else
cat << \SHAR_EOF > 'go.c'
/* Go written by Greg Hale (April 20 1987) */

#include "std.disclaimer"
#include "go.h"
#include <ctype.h>
#include <signal.h>
#include <strings.h>

bool iamserver = UNSET;
long random();
long time();

DEBUG(FILE * debug = NULL;
)
main(argc, argv)
    int argc;
    char **argv;
{
   extern int loadflg, logflg, myport;
   extern char loadname[], *hisname, waiting;
   int port, trap_cdump(), trap_sigint(), tstp(), ts_tp();
   char *p, *malloc();

   if (argc <= 1)
      helpstart(argv);
   parseline(argc, argv);

   sockmask[0] = 1;

   port = myport;

   signal(SIGINT, SIG_IGN);
   signal(SIGPIPE, SIG_IGN);
   srandom(time((long *) NULL));

   Init();

   signal(SIGINT, trap_sigint);
   setcore(trap_cdump);		/* set up the core dump trap */

   p = hisname;			/* used to be argv[argc-1] */
   connectport(p, port);
   doneconnectmes();
   waiting = 0;

   player = iamserver;
   DEBUG(debug = fopen((player) ? "/tmp/deb1" : "/tmp/deb0", "w");
   )
      printscore();
   initmesg();
   DEBUG(fprintf(debug, "Ready to Synchronize\n");
   fflush(debug);
   )
      Synchronize();
   if (timedgame)
      sendtimestart();
   if (!((logflg && openlogfile()) || (loadflg && doload()))) {
      PrintBoard(&board);
      sethandi();
   }
   DEBUG(fprintf(debug, "Ready to Loop\n");
   fflush(debug);
   )
      Loop();

   testsave();
   CLEAR();

   Exit();
}


/* Make sure all game parameters match in programs */
Synchronize()
{
   extern int strength, opponstr, handin, handicaps;
   int temp;
   extern char *myname;


   swap(MSTR, strength, &opponstr,
	"Incompatable version: strength not sent from other program.\n");

   swap(MMODE, 1, &temp, "Incompatable version: demoflag not sent from other program.\n");


   swap(MSIZE, dimensions, &temp,
	"Incompatable verison: size not sent from other program.\n");
   if (temp < dimensions)
      dimensions = temp;
   /* dimensions = dimensions / 2 * 2 + 1; */
   MAXX = MAXY = dimensions;
   handin = (dimensions > 12) ? 3 : 2;

   swap(MHAND, handicaps, &temp,
	"Incompatable verison: # of handicaps not sent from other program.\n");
   if (temp >= 0 || handicaps >= 0) {
      handicaps = (temp > handicaps ? temp : handicaps);
   } else {
      temp = opponstr - strength;
      handicaps = (temp > 0 ? temp : -temp);
      handicaps = (handicaps * dimensions * dimensions) / (19 * 19);
      if (temp)
	 player = temp > 0;
   }

}


swap(mesg, s, r, err)
    char *mesg, *err;
    int *r, s;
{
   char line[100];

   SEND(mesg);
   RECV(line);
   if (strcmp(line, mesg)) {
      error(err);
   }
   sprintf(line, "%d", s);
   SEND(line);

   RECV(line);
   *r = atoi(line);
}


Exit()
{
   unsetmode();
   endwin();
   closelogfile();
   exit(0);
}


Init()
{
   extern int tstp();
   int myts_tp(), myts_cont();

   MAXX = dimensions;
   MAXY = dimensions;

   initscr();
   /* signal (SIGTSTP, myts_tp); signal (SIGCONT, myts_cont); */
   setmode();

   CLEAR();
   InitBoard(&board);
   SetStat(HANDICAP);
}
SHAR_EOF
fi
if test -f 'handicap.c'
then
	echo shar: "will not over-write existing file 'handicap.c'"
else
cat << \SHAR_EOF > 'handicap.c'
#include "std.disclaimer"
#include "go.h"

#define MAXHANDICAPS 9

hcap(x, y, log)
    int x, y, log;
{
   extern FILE *logfile;
   cx = x;
   cy = y;
   Handicap(!b(x, y));
   if (log)
      fprintf(logfile, "[%c%c]", x + 'a', y + 'a');
}

sethandi()
{
   extern int handicaps, handin;
   int savelog;
   extern int logflg;
   extern FILE *logfile;

   int h;
   h = handicaps;
   if (h > MAXHANDICAPS)
      h = MAXHANDICAPS;
   SetStat(HANDICAP);
   if (h < 2)
      return;
   if (savelog = logflg) {
      logflg = 0;
      fprintf(logfile, "AddBlack");
   }
   switch (h) {
   case 5:
      hcap(MAXX / 2, MAXY / 2, savelog);
   case 4:
      hcap(handin, MAXY - 1 - handin, savelog);
   case 3:
      hcap(MAXX - 1 - handin, handin, savelog);
   case 2:
      hcap(MAXX - 1 - handin, MAXY - 1 - handin, savelog);
      hcap(handin, handin, savelog);
      break;
   case 7:
      hcap(MAXX / 2, MAXY / 2, savelog);
   case 6:
      hcap(handin, handin, savelog);
      hcap(MAXX - 1 - handin, MAXY - 1 - handin, savelog);
      hcap(MAXX - 1 - handin, handin, savelog);
      hcap(handin, MAXY - 1 - handin, savelog);
      hcap(handin, MAXY / 2, savelog);
      hcap(MAXX - 1 - handin, MAXY / 2, savelog);
      break;
   case 9:
      hcap(MAXX / 2, MAXY / 2, savelog);
   case 8:
      hcap(handin, handin, savelog);
      hcap(MAXX - 1 - handin, MAXY - 1 - handin, savelog);
      hcap(MAXX - 1 - handin, handin, savelog);
      hcap(handin, MAXY - 1 - handin, savelog);
      hcap(handin, MAXY / 2, savelog);
      hcap(MAXX - 1 - handin, MAXY / 2, savelog);
      hcap(MAXX / 2, handin, savelog);
      hcap(MAXX / 2, MAXY - 1 - handin, savelog);
      break;
   }
   if (logflg = savelog)
      fprintf(logfile, "\n");

}



Handicap(i)
    int i;
{
   int savehand;
   extern int handicaps;
   savehand = handicaps;
   if (AreWe(HANDICAP))
      sethand(cx, cy, i);
   handicaps = savehand;
}
SHAR_EOF
fi
if test -f 'help.c'
then
	echo shar: "will not over-write existing file 'help.c'"
else
cat << \SHAR_EOF > 'help.c'
#include "std.disclaimer"
#include "go.h"
#include <curses.h>

help()
{
   CLEAR();

   /* first five lines */
   printf("\
    %s: by Greg Hale, Jeff Boscole, Adrian Mariano, and Fred Hansen\n\
    \n\
    ^c:       leave the game\n\
    ?:        help\n\
    [12346789hjklyubnHJKLYUBN]:  move cursor\n\
    \n",
	  VERSION);

   /* middle eight lines */
   if (AreWe(HANDICAP)) {

      printf("\
    MODE - Setting game parameters\n\
    \n\
            <space>,0: place or remove handicap stone at current point\n\
            p:        start play\n\
            s:        switch which player you are (black/white)\n\
            *:        set standard handicap stones\n\
            T:        set time limit and byoyomi\n\
    \n"
	 );

   } else if (AreWe(PLAY)) {

      printf("\
    MODE - Playing the game\n\
            <space>, 0:  play at current point\n\
            /:        show the last move\n\
            p:        pass your turn\n\
            s:        turn on scoring mode\n\
            R:        resign and give the win to the other player\n\
            z,x:      set and unset moves for demonstrations\n\
            P:        Pause/unpause the clock\n\
	    ^P:       PANIC - press only if game is not synchronized"
	 );

   } else if (AreWe(SCORE)) {

      printf("\
    MODE - computing the score\n\
    \n\
            <space>, 0: declare that group at current point is dead\n\
            t:        tally--show how territory is defined\n\
            c:        cancel scoring mode and restore game\n\
            q:        print score and quit\n\
            R:        resign and give the win to the other player\n\
    \n"
	 );

   }
   /* last eleven lines */
   printf("\
    \n\
    m:        send a message to the other player\n\
                press control-D to resume playing\n\
    C:        clear the board\n\
    ^l:       redraw the screen\n\
    V:        toggle inverse <-> normal video\n\
    S:        save the current board, turn, and score\n\
    #:        load a saved game\n\
    \n\
    <hit any key to continue>"
      );

   refresh();
   GetAKey0();
   clear();
}


longhelp()
{
   system(HELP_CMD);
   exit(0);
}
SHAR_EOF
fi
if test -f 'life.c'
then
	echo shar: "will not over-write existing file 'life.c'"
else
cat << \SHAR_EOF > 'life.c'
#include "std.disclaimer"
#include "go.h"

IsSafe(x, y)
    int x, y;
{
   int t;
   if (!ir(x, y) || (t = b(x, y)) == NONE)
      return (FALSE);
   InitBoard(&marks);
   return (esc(x, y, t));
}

esc(x, y, t)
    int x, y, t;
{
   if (!ir(x, y))
      return (FALSE);
   if (b(x, y) == NONE)
      return (TRUE);
   if (!m(x, y) && b(x, y) == t) {
      m(x, y) = MARK;
      return (esc(x - 1, y, t) ||
	      esc(x + 1, y, t) ||
	      esc(x, y - 1, t) ||
	      esc(x, y + 1, t));
   }
   return (FALSE);
}


Owner(x, y)
    int x, y;
{
   int o;
   InitBoard(&marks);
   o = Owner0(x, y);
   return (o == -1 ? 3 : o);
}

Owner0(x, y)
    int x, y;
{
   if (m(x, y) || !ir(x, y))
      return 3;
   m(x, y) = 1;
   if (b(x, y) != NONE)
      return (b(x, y) + 3);
   return (New(New(New(New(3, x - 1, y), x + 1, y), x, y - 1), x, y + 1));

}

New(o, x2, y2)			/* 3= undetermined, 4=p1, 5=p2, -1=shared */
    register int o;
    int x2, y2;
{
   register int n;		/* old, new */
   n = Owner0(x2, y2);
   if (o == 3)
      return n;
   if (n == 3)
      return o;
   if (o < 0)
      return o;
   return (n == o ? o : -1);
}

int ir(x, y)
    int x, y;
{
   return ((x >= 0) && (x < MAXX) && (y >= 0) && (y < MAXY));
}
SHAR_EOF
fi
if test -f 'loop.c'
then
	echo shar: "will not over-write existing file 'loop.c'"
else
cat << \SHAR_EOF > 'loop.c'
#include "std.disclaimer"
#include "go.h"
#include <strings.h>
#include <curses.h>

extern int errno;
extern int mesflg, curx, cury;


Loop()
{
   int mask;
   struct timeval waittime;
   int result;

/*   homemes();*/
   /* strcpy(message,"- "); strcat(message,VERSION); strcat(message," By Greg
    * Hale"); addmes(message); */
   addmes("- Set up handicap.");
   addmes("- Press 'p' to play");

   inittick();

   do {
      myturn = (!player && curplr) || (player && !curplr);
      if (AreWe(PAUSED))
	 notify(" Paused...");
      else if (AreWe(PLAY)) {
	 if (myturn) {
	    notify(" Your turn");
	 } else
	    notify(" Waiting for opponent");
      } else if (AreWe(HANDICAP)) {
	 notify(" Set Handicap");
      } else if (AreWe(SCORE)) {
	 notify(" Scoring");
      } else {
	 notify(" What are we doing??");
      }

      do {
	 if (mesflg)
	    move(cury, curx);
	 else
	    moveto(cx, cy);

	 REFRESH();

	 mask = sockmask[0] | sockmask[1];
	 if (timedgame && AreWe(PLAY)) {
	    waittime.tv_sec = 1;
	    waittime.tv_usec = 0;
	    result = select(32, &mask, 0, 0, &waittime);
	 } else
	    result = select(32, &mask, 0, 0, 0);
	 if (result == -1) {
	    if (errno == EINTR)
	       continue;
	    else
	       error(" Error- Select failed\n");
	 } else if (result == 0) {
	    if (AreWe(PLAY))
	       tick(myturn);
	 }
      } while (result == 0);

      if (mask & sockmask[0]) {
	 DoLoop();
      } else if (mask == sockmask[1]) {
	 myturn = !myturn;
	 DoOther();
      } else
	 error(" Error - bad select\n");

   }
   while (!AreWe(EXIT));
}
SHAR_EOF
fi
if test -f 'mesg.c'
then
	echo shar: "will not over-write existing file 'mesg.c'"
else
cat << \SHAR_EOF > 'mesg.c'
#include "std.disclaimer"
#include "go.h"
#include <curses.h>
#include <ctype.h>

extern char *opponent;

int mesgx = 42;
int mesgy = 7;
int mesgx2 = 78;
int mesgy2 = 14;


int talkx = 42;
int talky = 16;
int talkx2 = 78;
int talky2 = 23;

int timex = 55;

static char mesgbuf[1000];
int cur;
int curx;
int cury;
int mesflg;

int tcury;

notify(s)
    char *s;
{
   mvaddstr(0, 0, "                                ");
   mvaddstr(0, 0, s);
}

initmesg()
{
   mesflg = 0;
   cur = -1;
   curx = mesgx;
   cury = mesgy;

   tcury = talky;


   mvaddstr(0, mesgx, "   -- Internet ");
   mvaddstr(0, mesgx + 15, VERSION);
   mvaddstr(0, mesgx + 16 + strlen(VERSION), "--");
   /* mvaddstr (mesgy - 1, mesgx, "   -- your messages ^D end   --"); mvaddstr
    * (talky - 1, talkx, "   -- opponent      ^D end   --"); */
   mvaddstr(mesgy - 1, mesgx, "   -- you -- ^D ends");
   mvaddstr(talky - 1, talkx, "   -- opp --");
}

addtalk(s)
    char *s;
{
   logcomment(s, 2);
   mvaddstr(tcury, talkx, s);
   if (tcury++ == talky2)
      tcury = talky;
   move(tcury, talkx);
   clrtoeol();
}

domesg(c)
    char c;
{
   if (c == '\b' || c == '\177')
      delchar();
   else if (c == '\n')
      mesgnl();
   else if (c == 004) {		/* ^D returns to board now */
      if (curx != mesgx)
	 mesgnl();
      mesflg = 0;
      return (0);
   } else {
      if (isprint(c) || c == 007)
	 addchar(c);
   }
   move(cury, curx);
}

mesgnl()
{
   sendbuf();
   curx = mesgx;
   if (cury++ == mesgy2)
      cury = mesgy;
   move(cury, curx);
   clrtoeol();
}

addchar(c)
    char c;
{
   mesgbuf[++cur] = c;
   mvaddch(cury, curx, c);
   if (curx++ == mesgx2) {
      mesgnl();
   }
}

delchar()
{
   if (cur >= 0 && curx > mesgx) {
      curx--;
      cur--;
      mvaddch(cury, curx, ' ');
   }
}

sendbuf()
{
   mesgbuf[++cur] = '\0';
   SEND(MMESSAGE);
   SEND(mesgbuf);
   cur = -1;
   logcomment(mesgbuf, 1);
}

/* show time at y,timex, where y is talky-1 for you==0 or mesgy-1 iff you==1 t
 * is seconds remaining.  s is number of stones left in byomi */

showtime(myturn, t)
    bool myturn;
    struct timing *t;
{
   int y;
   char buf[25];
   long secs = t->left.tv_sec;
   if (!timedgame) return 0;
/*      strcpy(buf, "                     ");*/
   else if (secs < 1800 || t->byoyomi
	    DEBUG(||TRUE)
      )
      sprintf(buf, "%d:%02d:%02d", secs / 3600, (secs % 3600) / 60, secs % 60);
   else
      sprintf(buf, "%d:%02d", secs / 3600, (secs % 3600) / 60);
   if (t->byoyomi)
      sprintf(buf + strlen(buf), "  %d stones", t->stones);
   y = ((myturn) ? mesgy : talky) - 1;
   mvaddstr(y, timex, buf);
}
SHAR_EOF
fi
if test -f 'opts.c'
then
	echo shar: "will not over-write existing file 'opts.c'"
else
cat << \SHAR_EOF > 'opts.c'
#include "std.disclaimer"
#include "go.h"
#include <strings.h>
#include <sys/file.h>

#define ISARG(s) (!strncmp(*argv,s,strlen(s)))

int numberblink;

parseline(argc, argv)
    int argc;
    char **argv;
{
   char **argval;
   extern char loadname[], logname[], *hisname, *myname;
   extern int beepflg, strength, myport, handicaps;
   extern int loadflg;
   extern int inverse;
   extern int usemess;
   extern int logflg;
   extern float wins;
   extern FILE *logfile;

   GetStr();
   inverse = INVERSE;
   numberblink = 4;
   handicaps = 0;
   argval = argv;
   dimensions = MAXDIM;
   myport = DEFAULTPORT;
   beepflg = 1;
   usemess = 1;
   hisname = NULL;

   while (++argv, --argc > 0) {
      if (ISARG("-h")) {
	 longhelp();
      } else if (ISARG("-s")) {
	 if (--argc > 0) {
	    dimensions = atoi(*++argv);
	    if (dimensions < 7)
	       dimensions = 7;
	    if (dimensions > 19)
	       dimensions = 19;
	 } else
	    helpstart(argval);
      } else if (ISARG("-p")) {
	 if (--argc > 0)
	    myport = atoi(*++argv);
	 else
	    helpstart(argval);
      } else if (ISARG("-a")) {
	 usemess = 0;
      } else if (ISARG("-H")) {
	 if (--argc > 0)
	    handicaps = atoi(*++argv);
	 else
	    helpstart(argval);
      } else if (ISARG("-c")) {
	 changes();
      } else if (ISARG("-r")) {
	 showstr();
	 exit(0);
      } else if (ISARG("-B")) {
	 if (--argc > 0) {
	    char black;
	    black = atoi(*++argv);
	    if ((black) && (black < 127))
	       pieces[1] = black + inverse;
	    else
	       pieces[1] = (**argv) + inverse;
	 } else
	    helpstart(argval);
      } else if (ISARG("-E")) {
	 handicaps = -2;
      } else if (ISARG("-V")) {
	 char c;
	 if (inverse) {
	    for (c = 0; c < 6; c++)
	       pieces[c] -= 128;
	    inverse = 0;
	 } else {
	    for (c = 0; c < 6; c++)
	       pieces[c] += 128;
	    inverse = 128;
	 }
      } else if (ISARG("-q")) {
	 beepflg = 0;
      } else if (ISARG("-n")) {
	 if (--argc > 0) {
	    numberblink = atoi(*++argv);
	    if (numberblink < 0)
	       numberblink = 4;
	 } else
	    helpstart(argval);

      } else if (ISARG("-l")) {
	 if (--argc > 0) {
	    loadflg++;
	    strcpy(loadname, *++argv);
	 } else
	    helpstart(argval);
      } else if (ISARG("-L")) {
	 if (--argc > 0) {
	    logflg = 1;
	    strcpy(logname, *++argv);
	 } else
	    helpstart(argval);
      } else if (ISARG("-t")) {
	 if (--argc > 3) {
	    totalmin = atoi(*++argv);
	    byosec = atoi(*++argv);
	    byostones = atoi(*++argv);
	    byoextends = atoi(*++argv);
	    timedgame = TRUE;
	    argc -= 3;

	 } else
	    helpstart(argval);
      } else if (ISARG("-R")) {
	 wins = 0.0;
	 if (--argc) {
	    if (*argv[1] == '+') {
	       strength++;
	       argv++;
	    } else if (*argv[1] == '-') {
	       strength--;
	       argv++;

	    } else if (--argc) {
	       switch (*argv[2]) {
		WHEN 'k':
		  strength = 31 - atoi(argv[1]);
		WHEN 'd':
		  strength = 30 + atoi(argv[1]);
		WHEN 'p':
		  strength = 39 + atoi(argv[1]);
		OTHERWISE:
		  helpstart(argval);
	       }
	       argv += 2;
	    } else
	       helpstart(argval);

	    if (strength < 1)
	       strength = 1;
	    else if (strength > MAXSTR)
	       strength = MAXSTR;

	    savestr0();
	    exit(0);
	 } else
	    helpstart(argval);
      } else {
	 hisname = *argv++;
      }
   }
   if (hisname == NULL)
      helpstart(argval);
}


helpstart(argv)
    char *argv[];
{




   fprintf(stderr, "                      %s\n", VERSION);
   fprintf(stderr, "\nUsage:\n");
   fprintf(stderr, "%s {opts} user[@host]\n", argv[0]);

   fprintf(stderr, "{opts} is any of :\n");
   fprintf(stderr, "-p port#               which address to meet at.\n");
   fprintf(stderr, "-q                     quiet -- don't beep.\n");
   fprintf(stderr, "-s size                set the board size [7-19].\n");
   fprintf(stderr, "-n blink               set the number of times to blink a piece.\n");
   fprintf(stderr, "-H #handicaps          set the number of handicap stones.\n");
   fprintf(stderr, "-c                     give the opening message and credits.\n");
   fprintf(stderr, "-l <filename>          load a saved/sample game from diagram file.\n");
   fprintf(stderr, "-L <filename>          load or create a move by move log of game.\n");
   fprintf(stderr, "-a                     abridged log -- don't include player messages.\n");
   fprintf(stderr, "-t time byo stones ex  where time is time in minutes, byo and stones are\n");
   fprintf(stderr, "                       the time in seconds and number of stones for\n");
   fprintf(stderr, "                       byoyomi, and ex is the number of extends.\n");
#if (INVERSE==0)
   fprintf(stderr, "-V                     use inverse video.\n");
#else
   fprintf(stderr, "-V                     use normal video instead of inverse.\n");
#endif
   fprintf(stderr, "-B {number|char}       Use ascii code number, or char for black stones.\n");
   fprintf(stderr, "-E                     use handicap info from go_strength.\n");
   fprintf(stderr, "OR:\n");
   fprintf(stderr, "\"%s -r\" for your current rank.\n", argv[0]);
   fprintf(stderr, "\"%s -h\" for help.\n", argv[0]);
   fprintf(stderr, "\"%s -R # {k|d|p} to set your rank to # kyu/dan/pro dan respectively\n", argv[0]);
   fprintf(stderr, "\"%s -R {+|-} to increase/decrease your rank respectively\n", argv[0]);
   exit(0);
}
SHAR_EOF
fi
if test -f 'putpiece.c'
then
	echo shar: "will not over-write existing file 'putpiece.c'"
else
cat << \SHAR_EOF > 'putpiece.c'
#include "std.disclaimer"
#include "go.h"
#define DELAY 30000

int lastx, lasty;

extern int logflg;

putpiece(cx, cy, cur, blinkflg, switchB)
    int cx, cy;
    int cur;
    int blinkflg;
    int switchB;
{
   if (blinkflg)
      /*Beep()*/;
   if (b(cx, cy) == NONE) {
      int c, d;
      savelast();
      c = !cur + 1;
      d = cur + 1;
      setboard(cx, cy, d);
      if (NoMove(cx, cy, c, d)) {
	 b(cx, cy) = 0;
	 Plt(&board, cx, cy);
      } else {
	 Kill(cx, cy, d);

	 if (!compboard()) {
	    homemes();
	    addmes("- That's a KO. You can't");
	    addmes("  go there.");
	    restlast();
	 } else {
	    lastx = cx;
	    lasty = cy;
	    if (switchB) {
	       SEND(MMOVE);
	       SendCoord(cx, cy);
	       sprintf(buf, "%d", cur);
	       SEND(buf);
	    }
	    Plt(&board, cx, cy);
	    REFRESH();
	    if (blinkflg)
	       blink(cx, cy, d);
	    if (logflg)
	       dolog(cx, cy, d);
	    if (switchB)
	       NextPlr();
	    saveboard0();
	 }
      }
   }
}

ShowLast()
{
   blink(lastx, lasty, b(lastx, lasty));
}

blink(x, y, d)
    int x, y, d;
{
   extern int numberblink;
   int blinks;
   int mask;
   struct timeval tv;
   if (!AreWe(HANDICAP)) {
      for (blinks = numberblink; blinks--;) {
	 mask = sockmask[0];
	 tv.tv_sec = 0;
	 tv.tv_usec = 200000;
	 if (select(sizeof(mask), &mask, 0, 0, &tv))
	    break;
	 b(x, y) = b(x, y) ? 0 : d;
	 Plt(&board, x, y);
	 REFRESH();
      }
      b(x, y) = d;
      Plt(&board, x, y);
      REFRESH();
   }
}


GetCoord(x, y)
    int *x, *y;
{
   RECV(buf);
   *x = atoi(buf);
   RECV(buf);
   *y = atoi(buf);
}

SendCoord(x, y)
    int x, y;
{
   sprintf(buf, "%d", x);
   SEND(buf);
   sprintf(buf, "%d", y);
   SEND(buf);
}
SHAR_EOF
fi
if test -f 'score.c'
then
	echo shar: "will not over-write existing file 'score.c'"
else
cat << \SHAR_EOF > 'score.c'
#include "std.disclaimer"
#include "go.h"
#include <curses.h>

Score()
{
   extern int handicaps;
   char temp[100];
   float komi, s1, s2, s1space, s2space;
   int i, j;

   s1 = s2 = 0.0;
   Tally();
   for (i = 0; i < MAXX; i++) {
      for (j = 0; j < MAXY; j++) {
	 if (b(i, j) == 4) {
	    s1++;
	 } else if (b(i, j) == 5) {
	    s2++;
	 }
      }
   }
   komi = (handicaps > 0 || dimensions != 19) ? 0.0 : KOMI;
   s1space = s1;
   s2space = s2;
   s2 += hama[1];
   s1 += hama[0];
   s2 = s2 + komi;
   if (s1 > s2)
      sprintf(temp, "Black has won by %g points!", s1 - s2);
   else if (s2 > s1)
      sprintf(temp, "White has won by %g points!", s2 - s1);
   else
      sprintf(temp, "It was a tie game!");

   homemes();
   addmes("Final Results:");
   addmes(temp);

   if (s1 != s2) {
      iwon = (player && (s1 > s2)) || (!player && (s1 < s2));
      savestr();
   }
   GetAKey();
   clear();
   move(1, 0);
   printw("------------------------------------------------\n");
   printw("-       Final Results (Japanese counting)      -\n");
   printw("------------------------------------------------\n");
   printw("-     Territory + Captured + Komi = Final Score\n");
   printw("-Black:  %3.1f       %3.1f        0         %3.1f\n",
	  s1space, (float) hama[0], s1);
   printw("-White:  %3.1f       %3.1f        %1.1f         %3.1f\n",
	  s2space, (float) hama[1], komi, s2);
   printw("-------------------------------------------------\n");
   printw("\n%s\n", temp);
   refresh();
   testsave();
   move(20, 0);
   refresh();
   Exit();
}





Tally()
{
   int i, j;
   for (i = 0; i < MAXX; i++)
      for (j = 0; j < MAXY; j++)
	 if (b(i, j) == NONE)
	    fill(i, j, Owner(i, j));
}



static int fillwith;

fill(x, y, type)
    int x, y, type;
{
   fillwith = type;
   InitBoard(&marks);
   fill0(x, y);
}

fill0(x, y)
    int x, y;
{
   if (ir(x, y) && b(x, y) == NONE && m(x, y) == NONE) {
      m(x, y) = MARK;
      b(x, y) = fillwith;
      fill0(x - 1, y);
      fill0(x + 1, y);
      fill0(x, y - 1);
      fill0(x, y + 1);
   }
}
SHAR_EOF
fi
if test -f 'strength.c'
then
	echo shar: "will not over-write existing file 'strength.c'"
else
cat << \SHAR_EOF > 'strength.c'
#include "std.disclaimer"
#include "go.h"
#include <pwd.h>

FILE *strfile;
char filename[500];
extern int strength, opponstr;
extern float wins;

GetStr()
{
   int id;
   struct passwd *pw;
   char *dir;
   id = geteuid();
   pw = getpwuid(id);
   dir = pw->pw_dir;
   strcpy(filename, dir);
   strcat(filename, GOFILE);
   /* fprintf(stderr,"FILENAME:%s\n",filename); */
   if ((strfile = fopen(filename, "r")) != NULL) {
      fscanf(strfile, "%d", &strength);
      fscanf(strfile, "%f", &wins);
      fclose(strfile);
   } else {
      strength = 0;
      wins = 0.0;
   }

}




savestr()
{
   float getdelta(), newwins;
   newwins = getdelta();
   if (newwins * wins < 0.0)
      wins = newwins;
   else
      wins += newwins;
   savestr0();
}

savestr0()
{
   if ((strfile = fopen(filename, "w")) != NULL) {
      if ((wins >= WINSUP && strength < MAXSTR)) {
	 fprintf(strfile, "%d 0.0\n", strength + 1);
      } else if ((wins <= -WINSUP && strength > 1)) {
	 fprintf(strfile, "%d 0.0\n", strength - 1);
      } else {
	 fprintf(strfile, "%d %f\n", strength, wins);
      }
      fclose(strfile);
   }
}


float getdelta()
{
   if (iwon) {			/* i won */
      if (strength < opponstr)	/* i'm weaker */
	 return ((opponstr - strength) / 10.0 + 1.0);
      else
	 return (((strength - opponstr) > 20) ? 2.0 : 1.0);
   } else {
      if (strength < opponstr)
	 return (-1.0);
      else
	 return (-((strength - opponstr) / 20.0 + 1.0));
   }
}

showstr()
{
   GetStr();
   if (strength < 31) {
      printf("Your strength is about: %d kyu.\n", 31 - strength);
   } else if (strength < 40) {
      printf("Your strength is about: %d dan.\n", strength - 30);
   } else if (strength < MAXSTR + 1) {
      printf("Your strength is about: %d professional dan.\n", strength - 39);
   } else {
      printf("Your are at maximum strength.\n");
   }
   if (wins >= 0)
      printf("You have also won %d games in a row.\n", (int) (wins / 2.0));
   else
      printf("You have also lost %d games in a row.\n", -(int) (wins));
}
SHAR_EOF
fi
if test -f 'tick.c'
then
	echo shar: "will not over-write existing file 'tick.c'"
else
cat << \SHAR_EOF > 'tick.c'
#include "std.disclaimer"
#include "go.h"

DEBUG(extern FILE * debug;
)
printtimes()
{
   showtime(TRUE, &mytime);
   showtime(FALSE, &opptime);
}

showbyo()
{
   char buf[40];
   sprintf(buf, "Byoyomi: %d stones in %d sec", byostones, byosec);
   addmes(buf);
   if (byoextends > 0) {
      sprintf(buf, "Byoyomi may be extended %d times", byoextends);
      addmes(buf);
   }
}

inittick()
{
   mytime.left.tv_sec = opptime.left.tv_sec = totalmin * 60;
   mytime.left.tv_usec = opptime.left.tv_usec = 0;
   mytime.byoyomi = opptime.byoyomi = FALSE;
   printtimes();
}

/* compute t -= d */
static timediff(t, d)
    register struct timeval *t, *d;
{
   while (d->tv_usec > t->tv_usec) {
      t->tv_usec += 1000000;
      t->tv_sec--;
   }
   t->tv_sec -= d->tv_sec;
   t->tv_usec -= d->tv_usec;
   while (t->tv_usec > 1000000) {
      t->tv_usec -= 1000000;
      t->tv_sec++;
   }
}

starttick(myturn)
    bool myturn;
{
   struct timing *t = (myturn) ? &mytime : &opptime;
   struct timeval now;
   gettimeofday(&now, NULL);
   t->start = now;

   DEBUG(fprintf(debug, "StartTick for %d.   Remaining %d\n",
		 myturn, t->left.tv_sec);
   fflush(debug);
   )
}

stoptick(myturn)
    bool myturn;
{
   struct timing *t = (myturn) ? &mytime : &opptime;
   struct timeval now;
   long left;

   if (!timedgame)
      return;
   t->stones--;
   if (t->byoyomi && t->stones <= 0) {
      /* get another packet of byoyomi stones */
      /* set time to the next larger multiple of byosec */
      for (left = 0; left <= t->left.tv_sec; left += byosec) {
      }
      t->left.tv_sec = left;
      t->left.tv_usec = 0;
      t->stones = byostones;
   } else {
      gettimeofday(&now, NULL);
      /* left -=  (now - start) */
      timediff(&now, &t->start);
      timediff(&t->left, &now);
   }

   showtime(myturn, t);

   DEBUG(fprintf(debug, "StopTick for %d.   Remaining %d\n",
		 myturn, t->left.tv_sec);
   fflush(debug);
   )
}



tick(myturn)
    bool myturn;
{
   struct timing *t = (myturn) ? &mytime : &opptime;
   struct timeval now, temp;

   if (!ticking)
      return;
   gettimeofday(&now, NULL);

   temp = now;
   /* left -=  (now - start) */
   timediff(&now, &t->start);
   timediff(&t->left, &now);
   t->start = temp;

   if (t->left.tv_sec < 0) {
      /* OOPS out of time */
      if (t->byoyomi) {
	 if (myturn) {
	    /* SIGH.  lost by running out of time */
	    SEND(MTIMELOSE);
	    dodecided(TRUE,
		      "Your clock ran out.",
		      "\nYou lost by exceeding time limit\n");
	 }
      } else {
	 t->byoyomi = TRUE;
	 Beep();
	 homemes();
	 addmes("- You are in byoyomi.");
	 t->extends = byoextends;
	 t->left.tv_sec = byosec * (t->extends + 1);
	 t->left.tv_usec = 0;
	 t->stones = byostones;
      }
   }
   showtime(myturn, t);
}


dosettiming()
{
   if (!getint("Minutes per player [untimed]: ", &totalmin) || totalmin == 0) {
      timedgame = FALSE;
      SEND(MSETTIME);
      sendint(0);
      printtimes();
      return;
   }
   timedgame = TRUE;
   if (!getint("Stones / byoyomi period [20]: ", &byostones))
      byostones = 20;
   if (!getint("Seconds / byoyomi period [400]: ", &byosec))
      byosec = 400;
   if (!getint("Byoyomi timeouts allowed [0]: ", &byoextends))
      byoextends = 0;
   sendtimestart();
}

sendtimestart()
{
   SEND(MSETTIME);
   sendint(totalmin);
   SEND(MSETBYO);
   sendint(byosec);
   sendint(byostones);
   sendint(byoextends);
   showbyo();
   inittick();
}



static void tmesg(who, t)
    char *who;
    struct timing *t;
{
   long secs;
   char buf[50];
   secs = t->left.tv_sec;
   if (t->byoyomi)
      sprintf(buf, "%s clock %d:%02d:%02d for %d stones",
	      who, secs / 3600, (secs % 3600) / 60, secs % 60, t->stones);
   else
      sprintf(buf, "%s clock %d:%02d:%02d",
	      who, secs / 3600, (secs % 3600) / 60, secs % 60);
   SEND(MMESSAGE);
   SEND(buf);
}

sendtimemesg()
{
   long secs, y;
   char buf[50];
   y = opptime.left.tv_sec;
   secs = mytime.left.tv_sec;
   if (opptime.byoyomi || mytime.byoyomi) {
      tmesg("Your", &opptime);
      tmesg("My", &mytime);
   } else {
      sprintf(buf, "Your clock %d:%02d:%02d   Mine %d:%02d:%02d",
	      y / 3600, (y % 3600) / 60, y % 60,
	      secs / 3600, (secs % 3600) / 60, secs % 60);
      SEND(MMESSAGE);
      SEND(buf);
   }
}


/* To really provide a pause-clock option we need to provide it as primitives
 * in tick.c.  After the changes listed below, the clock is paused with
 * pausetick(myturn) and restarted with resumetick(myturn) (Probably need to
 * add SEND messages so the opponent can be synchronized.) */


pausetick(myturn)
    bool myturn;
{
   struct timing *t = (myturn) ? &mytime : &opptime;
   struct timeval now;
   gettimeofday(&now, NULL);

   /* left -=  (now - start) */
   timediff(&now, &t->start);
   timediff(&t->left, &now);
   ticking = FALSE;
}


resumetick(myturn)
    bool myturn;
{
   struct timing *t = (myturn) ? &mytime : &opptime;
   struct timeval now;
   gettimeofday(&now, NULL);
   t->start = now;
   ticking = TRUE;
}
SHAR_EOF
fi
if test -f 'traps.c'
then
	echo shar: "will not over-write existing file 'traps.c'"
else
cat << \SHAR_EOF > 'traps.c'
#include "std.disclaimer"
#include "go.h"
#include <signal.h>
#include <curses.h>

trap_sigint()
{
   char c;
   extern char waiting;

   signal(SIGINT, SIG_IGN);
   if (waiting) {
      CLEAR();
      Exit();
   }
   clear();
   mvaddstr(22, 1, "Quit (y/n)?");
   refresh();
   c = GetAKey0();
   while (c != 'n' && c != 'N' && c != 'y' && c != 'Y') {
      if (c == '\f')
	 refresh();
      c = GetAKey();
   }
   if (c == 'y') {
      SEND(MEXIT);
      CLEAR();
      Exit();
   }
   touchwin(stdscr);
   PrintBoard(&board);

   signal(SIGINT, trap_sigint);
}


/* set up all the core dump signal vectors to the signal handler given */

setcore(f)
    int (*f) ();
{
   signal(SIGQUIT, f);
   signal(SIGILL, f);
   signal(SIGTRAP, f);
   signal(SIGIOT, f);
   signal(SIGEMT, f);
   signal(SIGFPE, f);
   signal(SIGBUS, f);
   signal(SIGSEGV, f);
   signal(SIGSYS, f);
}

/* very fatal error occured twice.  Time to die. We have been surrounded :) */

trap_cdumpII()
{
   setcore(SIG_IGN);
   fprintf(stderr, "Save failed! Fatal error! Committing processide...\n");
   exit(666);
}

/* The first core dump signal goes here, then to cdumpII The first signal
 * attempts to save the game and leave cleanly. the second version just dies :( */

trap_cdump()
{
   int trap_cdumpII();
   setcore(trap_cdumpII);
   fprintf(stderr, "core dump attempted- attempting save...\n");
   savegame();
   fprintf(stderr, "save successful.\n\n");
   Exit();
}
SHAR_EOF
fi
if test -f 'var.c'
then
	echo shar: "will not over-write existing file 'var.c'"
else
cat << \SHAR_EOF > 'var.c'
#include "std.disclaimer"
#include <sys/file.h>
#include "go.h"

BOARD backup, board, marks;

int handin, handicaps = 0,	/* handicap indentation */
   dimensions, myport, cx = 0, cy = 0, curplr = 0, hama[2] =
{0, 0}, MAXX, MAXY, beepflg, disable = 0, status, sock, sockmask[2], myturn,
   player, iwon, opponstr, strength, loadflg, logflg, usemess, inverse, totalmin = 60,
   byosec = 400, byostones = 20, byoextends = 0;

float wins;

char loadname[128], logname[128], *myname, *hisname, ticking = TRUE, opphastiming = FALSE,
   timedgame = FALSE, buf[MAXBUF], pieces[] =
{
   '.' + INVERSE,
   BLACK + INVERSE,
   'O' + INVERSE,
   '=' + INVERSE,
   '+' + INVERSE,
   '-' + INVERSE
};

FILE *logfile;

struct timing mytime =
{
   {3600, 0}, FALSE, 0, 0}, opptime =
{
   {3600, 0}, FALSE, 0, 0};


char waiting=1;
SHAR_EOF
fi
if test -f 'go.h'
then
	echo shar: "will not over-write existing file 'go.h'"
else
cat << \SHAR_EOF > 'go.h'
#include "std.disclaimer"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <errno.h>
#include <stdio.h>


#define bool char

#define TRUE (1)
#define FALSE (0)


/* keep the following in synch with table in doother.c */

#define MSCORE		"SCORE"
#define MQUIT		"QUIT"
#define MACCEPT		"ACCEPT"
#define MEXIT		"EXIT"
#define MDECLINE		"DECLINE"
#define MCANCEL		"CANCEL"
#define MPLAY		"PLAY"
#define MMOVE		"MOVE"
#define MLOAD		"LOAD"
#define MDELETE		"DELETE"
#define MCLEAR		"CLEAR"
#define MPASS		"PASS"
#define MMESSAGE	"MESSAGE"
#define MHANDICAP	"HANDICAP"
#define MSWITCH		"SWITCH"
#define MRESIGN		"RESIGN"
#define MTIME		"TIME"
#define MSETTIME		"SETTIME"
#define MSETBYO		"SETBYO"
#define MTIMELOSE	"TIMELOSE"
#define MPAUSE	"PAUSE"

#define MSIZE		"SIZE"
#define MHAND		"HANDI"
#define MSTR		"STREN"
#define MMODE		"MODE"

#define AreWe(s) (status & s)
#define SetStat(s) status=status | s;
#define ClrStat(s) status=status & ~s;
#define	HELP_CMD "/usr/ucb/more /usr/public/go.doc"

#define MAXDIM 19		/* maximum dimension */
#define MINDIM 9		/* minimum board dimension */
#define DEFAULTPORT 525		/* default port to connect with */

#define GOFILE "/.go_strength"	/* information on player's strength */
#define DEFAULTSTR 1		/* default strength if never played */
#define MAXSTR 48		/* count from 1... maxstr */
#define WINSUP 6		/* how many wins (losses) in a row are needed to
* go up a rank if you are weaker than
* the other player. */
#define KOMI	5.5		/* standard komi- add to white at end of game */


#define FD_INPUT   0
#define C_NOTHING  0
#define C_REDRAW   1
#define C_INVERSE  2
#define C_SAVE     3
#define C_LOAD     4
#define C_QUIT     5
#define C_TALLY    6
#define C_CANCEL   7
#define C_CLEAR    8
#define C_MESSAGE  9
#define C_RESIGN   10
#define C_SWITCH   11
#define C_LAST     12
#define C_PASS     13
#define C_HELP     14
#define C_SETBLACK 15
#define C_SETWHITE 16
#define C_PLAY   17
#define C_SETTIME  18
#define C_SETHAND  19
#define C_PAUSE    20
#define C_PANIC    21

#define P1 1			/* board types - player 1 pieces */
#define P2 2			/* player 2 pieces */
#define NONE 0			/* nothing */
#define MARK 3			/* neutral/marks for searches */


#define FASTMOVE 3		/* speed with <shift><dir> */
#define REDRAW '\014'		/* ^l */
#define MAXBUF 200		/* maximum line buffer */

#define DEBUG(m)

#define WHEN break; case
#define OTHERWISE break; default

#define UNSET 2


#define error(x) { fprintf(stderr,x); testsave(); Exit(); }

typedef struct { 
	char d[MAXDIM][MAXDIM]; 
} 
BOARD;
#define b(x1,y1) board.d[x1][y1]	/* JOE CODE- lazy hack. */
#define m(x2,y2) marks.d[x2][y2]	/* my apologies */

#define HITAKEYMES "[Hit any key]"

#define SCORE		0x01		/* state values */
#define EXIT		0x02
#define PLAY		0x04
#define HANDICAP	0x08
#define PAUSED	0x10

extern int parm;
extern bool haveparm;

extern struct timing {
	struct timeval start;
	struct timeval left;
	bool byoyomi;
	int stones;
	int extends;
} mytime, opptime;

extern int totalmin, byosec, byostones, byoextends;
extern bool opphastiming, timedgame;
extern BOARD backup,board,marks;
extern int curplr,hama[],MAXX,MAXY,cx,cy;
extern int disable,myturn,sock,sockmask[],status,player,dimensions;
extern char *blanks;
extern char pieces[], buf[], ticking;
extern bool iamserver;
extern int iwon;


SHAR_EOF
fi
if test -f 'std.disclaimer'
then
	echo shar: "will not over-write existing file 'std.disclaimer'"
else
cat << \SHAR_EOF > 'std.disclaimer'

SHAR_EOF
fi
exit 0
#	End of shell archive
