[net.sources] Sail

yee@ucbvax.ARPA (Peter E. Yee) (01/24/85)

This is the distribution of the game SAIL.  It is based on a game by Avalon
Hill. This game is the creation of David Riggle and also reflects the work of
Edward Wang and Craig Leres, along with countless others.  Permission is
granted to use (or abuse) this game, as long is as it is not done for profit.
Please send bug reports to ucbvax!yee.

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
-----cut here-----cut here-----cut here-----cut here-----
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	sail/driver.h
#	sail/driver1.c
#	sail/driver2.c
#	sail/driver3.c
# This archive created: Wed Jan 23 19:46:37 1985
cat << \SHAR_EOF > sail/driver.h
/*
 * sccsid = "@(#)driver.h	2.1 10/31/83";
 */
#include "externs.h"

int dtab[];
SHAR_EOF
if test 82 -ne "`wc -c sail/driver.h`"
then
echo shar: error transmitting sail/driver.h '(should have been 82 characters)'
fi
cat << \SHAR_EOF > sail/driver1.c
#ifndef lint
static	char *sccsid = "@(#)driver1.c	2.10 84/03/08";
#endif

#include "driver.h"

main(argc, argv)
int argc;
char **argv;
{
	register int n;
	register struct ship *sp;
	int nat[NNATION];

	if (argc != 2)
		exit(1);
	(void) signal(SIGINT, SIG_IGN);
	(void) signal(SIGQUIT, SIG_IGN);
	(void) signal(SIGTSTP, SIG_IGN);
	(void) srand(getpid());
	(void) setruid(geteuid());
	/* ;;; add code here to check the game number. */
	game = atoi(argv[1]);
	cc = &scene[game];
	ls = SHIP(cc->vessels);
	if (sync_open() < 0) {
		perror("driver: syncfile");
		exit(1);
	}
	for (n = 0; n < NNATION; n++)
		nat[n] = 0;
	foreachship(sp) {
		sp->file = (struct File *) calloc(1, sizeof (struct File));
		if (sp == NULL) {
			(void) printf("driver: OUT OF MEMORY\n");
			exit(1);
		}
		sp->file->index = sp - SHIP(0);
		sp->file->loadL = L_ROUND;
		sp->file->loadR = L_ROUND;
		sp->file->readyR = R_LOADED|R_INITIAL;
		sp->file->readyL = R_LOADED|R_INITIAL;
		sp->file->stern = nat[sp->nationality]++;
		sp->file->dir = sp->shipdir;
		sp->file->row = sp->shiprow;
		sp->file->col = sp->shipcol;
	}
	windspeed = cc->windspeed;
	winddir = cc->winddir;
	for (;;) {
		sleep(7);
		if (Sync() < 0) {
			sync_close(1);
			exit(1);
		}
		next();
		unfoul();
		checkup();
		prizecheck();
		moveall();
		thinkofgrapples();
		boardcomp();
		compcombat();
		resolve();
		reload();
		checksails();
		if (Sync() < 0) {
			sync_close(1);
			exit(1);
		}
	}
}

unfoul()
{
	register struct ship *sp;
	struct ship *to;
	register int nat;
	register i;

	foreachship(sp) {
		if (sp->file->captain[0])
			continue;
		nat = capship(sp)->nationality;
		foreachship(to) {
			if (nat != capship(to)->nationality
			    && !toughmelee(sp, to, 0, 0))
				continue;
			for (i = fouled2(sp, to); --i >= 0;)
				if (die() <= 2)
					cleanfoul(sp, to, 0);
		}
	}
}

boardcomp()
{
	int crew[3];
	register struct ship *sp, *sq;

	foreachship(sp) {
		if (*sp->file->captain)
			continue;
		if (sp->file->dir == 0)
			continue;
		if (sp->file->struck || sp->file->captured != 0)
			continue;
		if (!snagged(sp))
			continue;
		crew[0] = sp->specs->crew1 != 0;
		crew[1] = sp->specs->crew2 != 0;
		crew[2] = sp->specs->crew3 != 0;
		foreachship(sq) {
			if (!Xsnagged2(sp, sq))
				continue;
			if (meleeing(sp, sq))
				continue;
			if (!sq->file->dir
				|| sp->nationality == capship(sq)->nationality)
				continue;
			switch (sp->specs->class - sq->specs->class) {
			case -3: case -4: case -5:
				if (crew[0]) {
					/* OBP */
					sendbp(sp, sq, crew[0]*100, 0);
					crew[0] = 0;
				} else if (crew[1]){
					/* OBP */
					sendbp(sp, sq, crew[1]*10, 0);
					crew[1] = 0;
				}
				break;
			case -2:
				if (crew[0] || crew[1]) {
					/* OBP */
					sendbp(sp, sq, crew[0]*100+crew[1]*10,
						0);
					crew[0] = crew[1] = 0;
				}
				break;
			case -1: case 0: case 1:
				if (crew[0]) {
					/* OBP */
					sendbp(sp, sq, crew[0]*100+crew[1]*10,
						0);
					crew[0] = crew[1] = 0;
				}
				break;
			case 2: case 3: case 4: case 5:
				/* OBP */
				sendbp(sp, sq, crew[0]*100+crew[1]*10+crew[2],
					0);
				crew[0] = crew[1] = crew[2] = 0;
				break;
			}
		}
	}
}

fightitout(from, to, key)
struct ship *from, *to;
int key;
{
	struct ship *fromcap, *tocap;
	int crewfrom[3], crewto[3], menfrom, mento;
	int pcto, pcfrom, fromstrength, strengthto, frominjured, toinjured;
	int topoints;
	int index, totalfrom = 0, totalto = 0;
	int count;
	char message[60];

	menfrom = mensent(from, to, crewfrom, &fromcap, &pcfrom, key);
	mento = mensent(to, from, crewto, &tocap, &pcto, 0);
	if (fromcap == 0)
		fromcap = from;
	if (tocap == 0)
		tocap = to;
	if (key) {
		if (!menfrom) {		 /* if crew surprised */
			if (fromcap == from)
				menfrom = from->specs->crew1
					+ from->specs->crew2
					+ from->specs->crew3;
			else
				menfrom = from->file->pcrew;
		} else {
			menfrom *= 2;	/* DBP's fight at an advantage */
		}
	}
	fromstrength = menfrom * fromcap->specs->qual;
	strengthto = mento * tocap->specs->qual;
	for (count = 0;
	     (fromstrength < strengthto * 3 && strengthto < fromstrength * 3
	      || fromstrength == -1) && count < 4;
	     count++) {
		index = fromstrength/10;
		if (index > 8)
			index = 8;
		toinjured = MT[index][2 - die() / 3];
		totalto += toinjured;
		index = strengthto/10;
		if (index > 8)
			index = 8;
		frominjured = MT[index][2 - die() / 3];
		totalfrom += frominjured;
		menfrom -= frominjured;
		mento -= toinjured;
		fromstrength = menfrom * fromcap->specs->qual;
		strengthto = mento * tocap->specs->qual;
	}
	if (fromstrength >= strengthto * 3 || count == 4) {
		unboard(to, from, 0);
		subtract(from, totalfrom, crewfrom, fromcap, pcfrom);
		subtract(to, totalto, crewto, tocap, pcto);
		makesignal(from, "boarders from %s repelled", to);
		(void) sprintf(message, "killed in melee: %d.  %s: %d",
			totalto, from->shipname, totalfrom);
		Write(W_SIGNAL, to, 1, (int) message, 0, 0, 0);
		if (key)
			return 1;
	} else if (strengthto >= fromstrength * 3) {
		unboard(from, to, 0);
		subtract(from, totalfrom, crewfrom, fromcap, pcfrom);
		subtract(to, totalto, crewto, tocap, pcto);
		if (key) {
			if (fromcap != from)
				Write(W_POINTS, fromcap, 0,
					fromcap->file->points -
						from->file->struck
						? from->specs->pts
						: 2 * from->specs->pts,
					0, 0, 0);

/* ptr1 points to the shipspec for the ship that was just unboarded.
   I guess that what is going on here is that the pointer is multiplied
   or something. */

			Write(W_CAPTURED, from, 0, to->file->index, 0, 0, 0);
			topoints = 2 * from->specs->pts + to->file->points;
			if (from->file->struck)
				topoints -= from->specs->pts;
			Write(W_POINTS, to, 0, topoints, 0, 0, 0);
			mento = crewto[0] ? crewto[0] : crewto[1];
			if (mento) {
				subtract(to, mento, crewto, tocap, pcto);
				subtract(from, - mento, crewfrom, to, 0);
			}
			(void) sprintf(message, "captured by the %s!",
				to->shipname);
			Write(W_SIGNAL, from, 1, (int) message, 0, 0, 0);
			(void) sprintf(message, "killed in melee: %d.  %s: %d",
				totalto, from->shipname, totalfrom);
			Write(W_SIGNAL, to, 1, (int) message, 0, 0, 0);
			mento = 0;
			return 0;
		}
	}
	return 0;
}

resolve()
{
	int thwart;
	register struct ship *sp, *sq;

	foreachship(sp) {
		if (sp->file->dir == 0)
			continue;
		for (sq = sp + 1; sq < ls; sq++)
			if (sq->file->dir && meleeing(sp, sq) && meleeing(sq, sp))
				(void) fightitout(sp, sq, 0);
		thwart = 2;
		foreachship(sq) {
			if (sq->file->dir && meleeing(sq, sp))
				thwart = fightitout(sp, sq, 1);
			if (!thwart)
				break;
		}
		if (!thwart) {
			foreachship(sq) {
				if (sq->file->dir && meleeing(sq, sp))
					unboard(sq, sp, 0);
				unboard(sp, sq, 0);
			}
			unboard(sp, sp, 1);
		} else if (thwart == 2)
			unboard(sp, sp, 1);
	}
}

compcombat()
{
	register n;
	register struct ship *sp;
	struct ship *closest;
	int crew[3], men = 0, target, temp;
	int r, guns, ready, load, car;
	int index, rakehim, sternrake;
	int shootat, hit;

	foreachship(sp) {
		if (sp->file->captain[0] || sp->file->dir == 0)
			continue;
		crew[0] = sp->specs->crew1;
		crew[1] = sp->specs->crew2;
		crew[2] = sp->specs->crew3;
		for (n = 0; n < 3; n++) {
			if (sp->file->OBP[n].turnsent)
				men += sp->file->OBP[n].mensent;
		}
		for (n = 0; n < 3; n++) {
			if (sp->file->DBP[n].turnsent)
				men += sp->file->DBP[n].mensent;
		}
		if (men){
			crew[0] = men/100 ? 0 : crew[0] != 0;
			crew[1] = (men%100)/10 ? 0 : crew[1] != 0;
			crew[2] = men%10 ? 0 : crew[2] != 0;
		}
		for (r = 0; r < 2; r++) {
			if (!crew[2])
				continue;
			if (sp->file->struck)
				continue;
			if (r) {
				ready = sp->file->readyR;
				guns = sp->specs->gunR;
				car = sp->specs->carR;
			} else {
				ready = sp->file->readyL;
				guns = sp->specs->gunL;
				car = sp->specs->carL;
			}
			if (!guns && !car)
				continue;
			if ((ready & R_LOADED) == 0)
				continue;
			closest = closestenemy(sp, r ? 'r' : 'l', 0);
			if (closest == 0)
				continue;
			if (range(closest, sp) > range(sp, closestenemy(sp, r ? 'r' : 'l', 1)))
				continue;
			if (closest->file->struck)
				continue;
			target = range(sp, closest);
			if (target > 10)
				continue;
			if (!guns && target >= 3)
				continue;
			load = L_ROUND;
			if (target == 1 && sp->file->loadwith == L_GRAPE)
				load = L_GRAPE;
			if (target <= 3 && closest->file->FS)
				load = L_CHAIN;
			if (target == 1 && load != L_GRAPE)
				load = L_DOUBLE;
			if (load > L_CHAIN && target < 6)
				shootat = HULL;
			else
				shootat = RIGGING;
			rakehim = gunsbear(sp, closest)
				&& !gunsbear(closest, sp);
			temp = portside(closest, sp, 1)
				- closest->file->dir + 1;
			if (temp < 1)
				temp += 8;
			if (temp > 8)
				temp -= 8;
			sternrake = temp > 4 && temp < 6;
			index = guns;
			if (target < 3)
				index += car;
			index = (index - 1) / 3;
			index = index > 8 ? 8 : index;
			if (!rakehim)
				hit = HDT[index][target-1];
			else
				hit = HDTrake[index][target-1];
			if (rakehim && sternrake)
				hit++;
			hit += QUAL[index][capship(sp)->specs->qual - 1];
			for (n = 0; n < 3 && sp->file->captured == 0; n++)
				if (!crew[n])
					if (index <= 5)
						hit--;
					else
						hit -= 2;
			if (ready & R_INITIAL) {
				if (!r)
					sp->file->readyL &= ~R_INITIAL;
				else
					sp->file->readyR &= ~R_INITIAL;
				if (index <= 3)
					hit++;
				else
					hit += 2;
			}
			if (sp->file->captured != 0)
				if (index <= 1)
					hit--;
				else
					hit -= 2;
			hit += AMMO[index][load - 1];
			temp = sp->specs->class;
			if ((temp >= 5 || temp == 1) && windspeed == 5)
				hit--;
			if (windspeed == 6 && temp == 4)
				hit -= 2;
			if (windspeed == 6 && temp <= 3)
				hit--;
			if (hit >= 0) {
				if (load != L_GRAPE)
					hit = hit > 10 ? 10 : hit;
				table(shootat, load, hit, closest, sp, die());
			}
		}
	}
}

next()
{
	if (++turn % 55 == 0)
		if (alive)
			alive = 0;
		else
			people = 0;
	if (people <= 0 || windspeed == 7) {
		register struct ship *s;
		struct ship *bestship;
		float net, best = 0.0;
		foreachship(s) {
			if (*s->file->captain)
				continue;
			net = (float)s->file->points / s->specs->pts;
			if (net > best) {
				best = net;
				bestship = s;
			}
		}
		if (best > 0.0) {
			char *p = getenv("WOTD");
			if (p == 0)
				p = "Driver";
			if (islower(*p))
				*p = toupper(*p);
			strncpy(bestship->file->captain, p,
				sizeof bestship->file->captain);
			bestship->file->captain
				[sizeof bestship->file->captain - 1] = 0;
			log(bestship);
		}
		sync_close(1);
		exit(0);
	}
	Write(W_TURN, SHIP(0), 0, turn, 0, 0, 0);
	if (turn % 7 == 0) {
		if (die() >= cc->windchange || !windspeed) {
			switch (die()) {
			case 1:
				winddir = 1;
				break;
			case 2:
				break;
			case 3:
				winddir++;
				break;
			case 4:
				winddir--;
				break;
			case 5:
				winddir += 2;
				break;
			case 6:
				winddir -= 2;
				break;
			}
			if (winddir > 8)
				winddir -= 8;
			if (winddir < 1)
				winddir += 8;
			if (windspeed)
				switch (die()) {
				case 1:
				case 2:
					windspeed--;
					break;
				case 5:
				case 6:
					windspeed++;
					break;
				}
			else
				windspeed++;
			Write(W_WIND, SHIP(0), 0, winddir, windspeed, 0, 0);
		}
	}
}

/*ARGSUSED*/
/*VARARGS2*/
Signal(fmt, ship, a, b, c)
char *fmt;
struct ship *ship;
{
}
SHAR_EOF
if test 11241 -ne "`wc -c sail/driver1.c`"
then
echo shar: error transmitting sail/driver1.c '(should have been 11241 characters)'
fi
cat << \SHAR_EOF > sail/driver2.c
#ifndef lint
static	char *sccsid = "@(#)driver2.c	2.6 84/04/28";
#endif

#include "driver.h"

#define couldwin(f,t) (f->specs->crew2 > t->specs->crew2 * 1.5)

thinkofgrapples()
{
	register struct ship *sp, *sq;
	char friendly;

	foreachship(sp) {
		if (sp->file->captain[0] || sp->file->dir == 0)
			continue;
		foreachship(sq) {
			friendly = sp->nationality == capship(sq)->nationality;
			if (!friendly) {
				if (sp->file->struck || sp->file->captured != 0)
					continue;
				if (range(sp, sq) != 1)
					continue;
				if (grappled2(sp, sq))
					if (toughmelee(sp, sq, 0, 0))
						ungrap(sp, sq);
					else
						grap(sp, sq);
				else if (couldwin(sp, sq)) {
					grap(sp, sq);
					sp->file->loadwith = L_GRAPE;
				}
			} else
				ungrap(sp, sq);
		}
	}
}

checkup()
{
	register struct ship *sp, *sq;
	register char explode, sink;

	foreachship(sp) {
		if (sp->file->dir == 0)
			continue;
		explode = sp->file->explode;
		sink = sp->file->sink;
		if (explode != 1 && sink != 1)
			continue;
		if (die() < 5)
			continue;
		Write(sink == 1 ? W_SINK : W_EXPLODE, sp, 0, 2, 0, 0, 0);
		Write(W_DIR, sp, 0, 0, 0, 0, 0);
		if (snagged(sp))
			foreachship(sq)
				cleansnag(sp, sq, 1);
		if (sink != 1) {
			makesignal(sp, "exploding!", (struct ship *)0);
			foreachship(sq) {
				if (sp != sq && sq->file->dir && range(sp, sq) < 4)
					table(RIGGING, L_EXPLODE, sp->specs->guns/13, sq, sp, 6);
			}
		} else
			makesignal(sp, "sinking!", (struct ship *)0);
	}
}

prizecheck()
{
	register struct ship *sp;

	foreachship(sp) {
		if (sp->file->captured == 0)
			continue;
		if (sp->file->struck || sp->file->dir == 0)
			continue;
		if (sp->specs->crew1 + sp->specs->crew2 + sp->specs->crew3 > sp->file->pcrew * 6) {
			Write(W_SIGNAL, sp, 1,
				(int)"prize crew overthrown", 0, 0, 0);
			Write(W_POINTS, sp->file->captured, 0, sp->file->captured->file->points - 2 * sp->specs->pts, 0, 0, 0);
			Write(W_CAPTURED, sp, 0, -1, 0, 0, 0);
		}
	}
}

strend(str)
char *str;
{
	register char *p;

	for (p = str; *p; p++)
		;
	return p == str ? 0 : p[-1];
}

closeon(from, to, command, ta, ma, af)
register struct ship *from, *to;
char command[];
int ma, ta, af;
{
	int high;
	char temp[10];

	temp[0] = command[0] = '\0';
	high = -30000;
	try(command, temp, ma, ta, af, ma, from->file->dir, from, to, &high, 0);
}

int dtab[] = {0,1,1,2,3,4,4,5};		/* diagonal distances in x==y */

score(movement, ship, to, onlytemp)
char movement[];
register struct ship *ship, *to;
char onlytemp;
{
	char drift;
	int row, col, dir, total, ran;
	register struct File *fp = ship->file;

	if ((dir = fp->dir) == 0)
		return 0;
	row = fp->row;
	col = fp->col;
	drift = fp->drift;
	move(movement, ship, &fp->dir, &fp->row, &fp->col, &drift);
	if (!*movement)
		(void) strcpy(movement, "d");

	ran = range(ship, to);
	total = -50 * ran;
	if (ran < 4 && gunsbear(ship, to))
		total += 60;
	if ((ran = portside(ship, to, 1) - fp->dir) == 4 || ran == -4)
		total = -30000;

	if (!onlytemp) {
		fp->row = row;
		fp->col = col;
		fp->dir = dir;
	}
	return total;
}

move(p, ship, dir, row, col, drift)
register char *p;
register struct ship *ship;
register char *dir;
register short *row, *col;
register char *drift;
{
	int dist;
	char moved = 0;

	for (; *p; p++) {
		switch (*p) {
		case 'r':
			if (++*dir == 9)
				*dir = 1;
			break;
		case 'l':
			if (--*dir == 0)
				*dir = 8;
			break;
		case '1': case '2': case '3': case '4':
		case '5': case '6': case '7':
			moved++;
			if (*dir % 2 == 0)
				dist = dtab[*p - '0'];
			else
				dist = *p - '0';
			*row -= dr[*dir] * dist;
			*col -= dc[*dir] * dist;
			break;
		}
	}
	if (!moved) {
		if (windspeed != 0 && ++*drift > 2) {
			if (ship->specs->class >= 3 && !snagged(ship)
			    || (turn & 1) == 0) {
				*row -= dr[winddir];
				*col -= dc[winddir];
			}
		}
	} else
		*drift = 0;
}

try(command, temp, ma, ta, af, vma, dir, f, t, high, rakeme)
register struct ship *f, *t;
int ma, ta, af, *high, rakeme;
char command[], temp[];
{
	register int new, n;
	char st[4];
#define rakeyou (gunsbear(f, t) && !gunsbear(t, f))

	if ((n = strend(temp)) < '1' || n > '9')
		for (n = 1; vma - n >= 0; n++) {
			(void) sprintf(st, "%d", n);
			(void) strcat(temp, st);
			new = score(temp, f, t, rakeme);
			if (new > *high && (!rakeme || rakeyou)) {
				*high = new;
				(void) strcpy(command, temp);
			}
			try(command, temp, ma-n, ta, af, vma-n,
				dir, f, t, high, rakeme);
			rmend(temp);
		}
	if (ma > 0 && ta > 0 && (n = strend(temp)) != 'l' && n != 'r' || !strlen(temp)) {
		(void) strcat(temp, "r");
		new = score(temp, f, t, rakeme);
		if (new > *high && (!rakeme || gunsbear(f, t) && !gunsbear(t, f))) {
			*high = new;
			(void) strcpy(command, temp);
		}
		try(command, temp, ma-1, ta-1, af, min(ma-1, maxmove(f, (dir == 8 ? 1 : dir+1), 0)), (dir == 8 ? 1 : dir+1),f,t,high,rakeme);
		rmend(temp);
	}
	if ((ma > 0 && ta > 0 && (n = strend(temp)) != 'l' && n != 'r') || !strlen(temp)){
		(void) strcat(temp, "l");
		new = score(temp, f, t, rakeme);
		if (new > *high && (!rakeme || (gunsbear(f, t) && !gunsbear(t, f)))){
			*high = new;
			(void) strcpy(command, temp);
		}
		try(command, temp, ma-1, ta-1, af, (min(ma-1,maxmove(f, (dir-1 ? dir-1 : 8), 0))), (dir-1 ? dir -1 : 8), f, t, high, rakeme);
		rmend(temp);
	}
}

rmend(str)
char *str;
{
	register char *p;

	for (p = str; *p; p++)
		;
	if (p != str)
		*--p = 0;
}
SHAR_EOF
if test 5363 -ne "`wc -c sail/driver2.c`"
then
echo shar: error transmitting sail/driver2.c '(should have been 5363 characters)'
fi
cat << \SHAR_EOF > sail/driver3.c
#ifndef lint
static	char *sccsid = "@(#)driver3.c	2.6 84/04/28";
#endif

#include "driver.h"

moveall()		/* move all comp ships */
{
	register struct ship *sp, *sq;		/* r11, r10 */
	register int n;				/* r9 */
	register int k, l;			/* r8, r7 */
	int row[NSHIP], col[NSHIP], dir[NSHIP], drift[NSHIP];
	char moved[NSHIP];

	/*
	 * first try to create moves for OUR ships
	 */
	foreachship(sp) {
		struct ship *closest;
		int ma, ta;
		char af;

		if (sp->file->captain[0] || sp->file->dir == 0)
			continue;
		if (!sp->file->struck && windspeed && !snagged(sp)
		    && sp->specs->crew3) {
			ta = maxturns(sp, &af);
			ma = maxmove(sp, sp->file->dir, 0);
			closest = closestenemy(sp, 0, 0);
			if (closest == 0)
				*sp->file->movebuf = '\0';
			else
				closeon(sp, closest, sp->file->movebuf,
					ta, ma, af);
		} else
			*sp->file->movebuf = '\0';
	}
	/*
	 * Then execute the moves for ALL ships (dead ones too),
	 * checking for collisions and snags at each step.
	 * The old positions are saved in row[], col[], dir[].
	 * At the end, we compare and write out the changes.
	 */
	n = 0;
	foreachship(sp) {
		if (snagged(sp))
			(void) strcpy(sp->file->movebuf, "d");
		else
			if (*sp->file->movebuf != 'd')
				(void) strcat(sp->file->movebuf, "d");
		row[n] = sp->file->row;
		col[n] = sp->file->col;
		dir[n] = sp->file->dir;
		drift[n] = sp->file->drift;
		moved[n] = 0;
		n++;
	}
	/*
	 * Now resolve collisions.
	 * This is the tough part.
	 */
	for (k = 0; stillmoving(k); k++) {
		/*
		 * Step once.
		 * And propagate the nulls at the end of sp->file->movebuf.
		 */
		n = 0;
		foreachship(sp) {
			if (!sp->file->movebuf[k])
				sp->file->movebuf[k+1] = '\0';
			else if (sp->file->dir)
				step(sp->file->movebuf[k], sp, &moved[n]);
			n++;
		}
		/*
		 * The real stuff.
		 */
		n = 0;
		foreachship(sp) {
			if (sp->file->dir == 0 || isolated(sp))
				goto cont1;
			l = 0;
			foreachship(sq) {
				char snap = 0;

				if (sp == sq)
					goto cont2;
				if (sq->file->dir == 0)
					goto cont2;
				if (!push(sp, sq))
					goto cont2;
				if (snagged2(sp, sq) && range(sp, sq) > 1)
					snap++;
				if (!range(sp, sq) && !fouled2(sp, sq)) {
					makesignal(sp,
						"collision with %s (%c%c)", sq);
					if (die() < 4) {
						makesignal(sp,
							"fouled with %s (%c%c)",
							sq);
						Write(W_FOUL, sp, 0, l, 0, 0, 0);
						Write(W_FOUL, sq, 0, n, 0, 0, 0);
					}
					snap++;
				}
				if (snap) {
					sp->file->movebuf[k + 1] = 0;
					sq->file->movebuf[k + 1] = 0;
					sq->file->row = sp->file->row - 1;
					if (sp->file->dir == 1
					    || sp->file->dir == 5)
						sq->file->col =
							sp->file->col - 1;
					else
						sq->file->col = sp->file->col;
					sq->file->dir = sp->file->dir;
				}
			cont2:
				l++;
			}
		cont1:
			n++;
		}
	}
	/*
	 * Clear old moves.  And write out new pos.
	 */
	n = 0;
	foreachship(sp) {
		if (sp->file->dir != 0) {
			*sp->file->movebuf = 0;
			if (row[n] != sp->file->row)
				Write(W_ROW, sp, 0, sp->file->row, 0, 0, 0);
			if (col[n] != sp->file->col)
				Write(W_COL, sp, 0, sp->file->col, 0, 0, 0);
			if (dir[n] != sp->file->dir)
				Write(W_DIR, sp, 0, sp->file->dir, 0, 0, 0);
			if (drift[n] != sp->file->drift)
				Write(W_DRIFT, sp, 0, sp->file->drift, 0, 0, 0);
		}
		n++;
	}
}

stillmoving(k)
register int k;
{
	register struct ship *sp;

	foreachship(sp)
		if (sp->file->movebuf[k])
			return 1;
	return 0;
}

isolated(ship)
register struct ship *ship;
{
	register struct ship *sp;

	foreachship(sp) {
		if (ship != sp && range(ship, sp) <= 10)
			return 0;
	}
	return 1;
}

push(from, to)
register struct ship *from, *to;
{
	register int bs, sb;

	sb = to->specs->guns;
	bs = from->specs->guns;
	if (sb > bs)
		return 1;
	if (sb < bs)
		return 0;
	return from < to;
}

step(com, sp, moved)
char com;
register struct ship *sp;
char *moved;
{
	register int dist;

	switch (com) {
	case 'r':
		if (++sp->file->dir == 9)
			sp->file->dir = 1;
		break;
	case 'l':
		if (--sp->file->dir == 0)
			sp->file->dir = 8;
		break;
		case '0': case '1': case '2': case '3':
		case '4': case '5': case '6': case '7':
		if (sp->file->dir % 2 == 0)
			dist = dtab[com - '0'];
		else
			dist = com - '0';
		sp->file->row -= dr[sp->file->dir] * dist;
		sp->file->col -= dc[sp->file->dir] * dist;
		*moved = 1;
		break;
	case 'b':
		break;
	case 'd':
		if (!*moved) {
			if (windspeed != 0 && ++sp->file->drift > 2 &&
			    (sp->specs->class >= 3 && !snagged(sp)
			     || (turn & 1) == 0)) {
				sp->file->row -= dr[winddir];
				sp->file->col -= dc[winddir];
			}
		} else
			sp->file->drift = 0;
		break;
	}
}

sendbp(from, to, sections, isdefense)
register struct ship *from, *to;
int sections;
char isdefense;
{
	int n;
	register struct BP *bp;

	bp = isdefense ? from->file->DBP : from->file->OBP;
	for (n = 0; n < NBP && bp[n].turnsent; n++)
		;
	if (n < NBP && sections) {
		Write(isdefense ? W_DBP : W_OBP, from, 0,
			n, turn, to->file->index, sections);
		if (isdefense)
			makesignal(from, "repelling boarders",
				(struct ship *)0);
		else
			makesignal(from, "boarding the %s (%c%c)", to);
	}
}

toughmelee(ship, to, isdefense, count)
register struct ship *ship, *to;
int isdefense, count;
{
	register struct BP *bp;
	register obp = 0;
	int n, OBP = 0, DBP = 0, dbp = 0;
	int qual;

	qual = ship->specs->qual;
	bp = isdefense ? ship->file->DBP : ship->file->OBP;
	for (n = 0; n < NBP; n++, bp++) {
		if (bp->turnsent && (to == bp->toship || isdefense)) {
			obp += bp->mensent / 100
				? ship->specs->crew1 * qual : 0;
			obp += (bp->mensent % 100)/10
				? ship->specs->crew2 * qual : 0;
			obp += bp->mensent % 10
				? ship->specs->crew3 * qual : 0;
		}
	}
	if (count || isdefense)
		return obp;
	OBP = toughmelee(to, ship, 0, count + 1);
	dbp = toughmelee(ship, to, 1, count + 1);
	DBP = toughmelee(to, ship, 1, count + 1);
	if (OBP > obp + 10 || OBP + DBP >= obp + dbp + 10)
		return 1;
	else
		return 0;
}

reload()
{
	register struct ship *sp;

	foreachship(sp) {
		sp->file->loadwith = 0;
	}
}

checksails()
{
	register struct ship *sp;
	register int rig, full; 
	struct ship *close;

	foreachship(sp) {
		if (sp->file->captain[0] != 0)
			continue;
		rig = sp->specs->rig1;
		if (windspeed == 6 || windspeed == 5 && sp->specs->class > 4)
			rig = 0;
		if (rig && sp->specs->crew3) {
			close = closestenemy(sp, 0, 0);
			if (close != 0) {
				if (range(sp, close) > 9)
					full = 1;
				else
					full = 0;
			} else 
				full = 0;
		} else
			full = 0;
		if ((sp->file->FS != 0) != full)
			Write(W_FS, sp, 0, full, 0, 0, 0);
	}
}
SHAR_EOF
if test 6529 -ne "`wc -c sail/driver3.c`"
then
echo shar: error transmitting sail/driver3.c '(should have been 6529 characters)'
fi
#	End of shell archive
exit 0

yee@ucbvax.ARPA (Peter E. Yee) (01/24/85)

This is part 2 of the SAIL distribution.

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
-----cut here-----cut here-----cut here-----cut here-----
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	sail/player.h
#	sail/player1.c
#	sail/player2.c
#	sail/player3.c
#	sail/player4.c
#	sail/player5.c
#	sail/player6.c
#	sail/player7.c
# This archive created: Wed Jan 23 19:46:49 1985
cat << \SHAR_EOF > sail/player.h
/*
 * sccsid = "@(#)player.h	2.7 2/23/84";
 */
#include <curses.h>
#include "externs.h"

/* sizes and coordinates for the screen */

#define LINE_T		0
#define LINE_L		0
#define LINE_X		COLS
#define LINE_Y		1
#define LINE_B		(LINE_T+LINE_Y-1)
#define LINE_R		(LINE_L+LINE_X-1)

#define BOX_T		1
#define BOX_L		0
#define BOX_X		65
#define BOX_Y		16
#define BOX_B		(BOX_T+BOX_Y-1)
#define BOX_R		(BOX_L+BOX_X-1)

#define TURN_T		BOX_B
#define TURN_Y		1
#define TURN_L		((BOX_L+BOX_R-TURN_X)/2)
#define TURN_X		9
#define TURN_B		(TURN_T+TURN_Y+1)
#define TURN_R		(TURN_L+TURN_X+1)

#define STAT_T		0
#define STAT_B		BOX_B
#define STAT_L		(BOX_R+2)
#define STAT_X		14
#define STAT_Y		(STAT_B-STAT_T+1)
#define STAT_R		(STAT_L+STAT_X-1)
#define STAT_1		0
#define STAT_2          (STAT_1+4)
#define STAT_3          (STAT_2+7)

#define SCROLL_T	(BOX_B+1)
#define SCROLL_L	0
#define SCROLL_B	(LINES-1)
#define SCROLL_R	(COLS-1)
#define SCROLL_X	(SCROLL_R-SCROLL_L+1)
#define SCROLL_Y	(SCROLL_B-SCROLL_T+1)

#define VIEW_T		(BOX_T+1)
#define VIEW_L		(BOX_L+1)
#define VIEW_X		(BOX_X-5)
#define VIEW_Y		(BOX_Y-2)
#define VIEW_B		(VIEW_T+VIEW_Y-1)
#define VIEW_R		(VIEW_L+VIEW_X-1)

#define SLOT_T		VIEW_T
#define SLOT_L		(VIEW_R+1)
#define SLOT_X		3
#define SLOT_Y		VIEW_Y
#define SLOT_B		VIEW_B
#define SLOT_R		(SLOT_L+SLOT_X-1)

#ifdef SIGTSTP
#define SCREENTEST()	(initscr() != ERR && signal(SIGTSTP, SIG_DFL) != BADSIG && STAT_R < COLS && SCROLL_Y > 0)
#else
#define SCREENTEST()	(initscr() != ERR && STAT_R < COLS && SCROLL_Y > 0)
#endif

WINDOW *view_w;
WINDOW *slot_w;
WINDOW *scroll_w;
WINDOW *stat_w;
WINDOW *turn_w;

char done_curses;
char loaded, fired, changed, repaired;
char dont_adjust;
int viewrow, viewcol;
char movebuf[sizeof SHIP(0)->file->movebuf];
char version[];
int player;
struct ship *ms;		/* memorial structure, &cc->ship[player] */
struct File *mf;		/* ms->file */
struct shipspecs *mc;		/* ms->specs */

/* condition codes for leave() */
#define LEAVE_QUIT	0
#define LEAVE_CAPTURED	1
#define LEAVE_HURRICAN	2
#define LEAVE_DRIVER	3
#define LEAVE_FORK	4
#define LEAVE_SYNC	5
SHAR_EOF
if test 2091 -ne "`wc -c sail/player.h`"
then
echo shar: error transmitting sail/player.h '(should have been 2091 characters)'
fi
cat << \SHAR_EOF > sail/player1.c
#ifndef lint
static	char *sccsid = "@(#)player1.c	2.8 84/12/12";
#endif

#include "player.h"
#include <sys/types.h>
#include <sys/wait.h>

int choke(), child();

/*ARGSUSED*/
main(argc, argv)
int argc;
char **argv;
{
	char nodrive = 0, randomize = 0, debug = 0;
	extern char _sobuf[];

	setbuf(stdout, _sobuf);
	isplayer = 1;

	while (*++argv && **argv == '-')
		switch (*++*argv) {
		case 'd':
			nodrive = 1;
			break;
		case 'D':
			debug++;
			break;
		case 'x':
			randomize = 1;
			break;
		default:
			printf("Unknown flag '%s'\n",*argv);
			break;
		}
	if (*argv)
		game = atoi(*argv);
	else
		game = -1;
	initialize(nodrive, randomize, debug);
	Signal("Aye aye, Sir", (struct ship *)0);
	play();
}

initialize(nodriver, randomize, debug)
char randomize, nodriver, debug;
{
	register struct File *fp;
	register struct ship *sp;
	char captain[80];
	char message[60];
	int load;
	register int n;
	char *nameptr;
	int nat[NNATION];

	if (!SCREENTEST()) {
		printf("Can't sail on this terminal.\n");
		exit(1);
	}

	(void) srand(getpid());

	if (game < 0) {
		(void) puts("Choose a scenario:\n");
		(void) puts("\n\tNUMBER\tSHIPS\tIN PLAY\tTITLE");
		for (n = 0; n < NSCENE; n++) {
			/* ( */
			printf("\t%d):\t%d\t%s\t%s\n", n, scene[n].vessels,
				sync_exists(n) ? "YES" : "no",
				scene[n].name);
		}
reprint:
		printf("\nScenario number? ");
		(void) fflush(stdout);
		(void) scanf("%d", &game);
		while (getchar() != '\n')
			;
	}
	if (game < 0 || game >= NSCENE) {
		(void) puts("Very funny.");
		exit(1);
	}
	cc = &scene[game];
	ls = SHIP(cc->vessels);

	for (n = 0; n < NNATION; n++)
		nat[n] = 0;
	foreachship(sp) {
		sp->file = (struct File *) calloc(1, sizeof (struct File));
		if (sp->file == NULL) {
			(void) puts("OUT OF MEMORY");
			exit(0);
		}
		sp->file->index = sp - SHIP(0);
		sp->file->stern = nat[sp->nationality]++;
		sp->file->dir = sp->shipdir;
		sp->file->row = sp->shiprow;
		sp->file->col = sp->shipcol;
	}
	windspeed = cc->windspeed;
	winddir = cc->winddir;

	(void) signal(SIGHUP, choke);
	(void) signal(SIGINT, choke);

	hasdriver = sync_exists(game);
	if (sync_open() < 0) {
		perror("sail: syncfile");
		exit(1);
	}

	if (hasdriver) {
		(void) puts("Synchronizing with the other players...");
		(void) fflush(stdout);
		if (Sync() < 0)
			leave(LEAVE_SYNC);
	}
	for (;;) {
		foreachship(sp)
			if (sp->file->captain[0] == 0 && !sp->file->struck
			    && sp->file->captured == 0)
				break;
		if (sp >= ls) {
			(void) puts("All ships taken in that scenario.");
			foreachship(sp)
				free((char *)sp->file);
			sync_close(0);
			people = 0;
			goto reprint;
		}
		if (randomize) {
			player = sp - SHIP(0);
		} else {
			printf("%s\n\n", cc->name);
			foreachship(sp)
				printf("  %2d:  %-10s %-15s  (%-2d pts)   %s\n",
					sp->file->index,
					countryname[sp->nationality],
					sp->shipname,
					sp->specs->pts,
					saywhat(sp, 1));
			printf("\nWhich ship (0-%d)? ", cc->vessels-1);
			(void) fflush(stdout);
			if (scanf("%d", &player) != 1 || player < 0
			    || player >= cc->vessels) {
				while (getchar() != '\n')
					;
				(void) puts("Say what?");
				player = -1;
			} else
				while (getchar() != '\n')
					;
		}
		if (player < 0)
			continue;
		if (Sync() < 0)
			leave(LEAVE_SYNC);
		fp = SHIP(player)->file;
		if (fp->captain[0] || fp->struck || fp->captured != 0)
			(void) puts("That ship is taken.");
		else
			break;
	}

	ms = SHIP(player);
	mf = ms->file;
	mc = ms->specs;

	Write(W_BEGIN, ms, 0, 0, 0, 0, 0);
	if (Sync() < 0)
		leave(LEAVE_SYNC);

	(void) signal(SIGCHLD, child);
	if (!hasdriver && !nodriver) {
		char num[10];
		(void) sprintf(num, "%d", game);
		switch (fork()) {
		case 0:
			execl(DRIVER1, DRIVERNAME, num, 0);
			execl(DRIVER2, DRIVERNAME, num, 0);
			execl(DRIVER3, DRIVERNAME, num, 0);
			perror(DRIVERNAME);
			exit(1);
			break;
		case -1:
			perror("fork");
			leave(LEAVE_FORK);
			break;
		default:
			hasdriver++;
		}
	}

	printf("Your ship is the %s, a %d gun %s (%s crew).\n",
		ms->shipname, mc->guns, classname[mc->class],
		qualname[mc->qual]);
	if ((nameptr = (char *) getenv("SAILNAME")) && *nameptr)
		(void) strncpy(captain, nameptr, sizeof captain);
	else {
		(void) printf("Your name, Captain? ");
		(void) fflush(stdout);
		(void) gets(captain);
		if (!*captain)
			(void) strcpy(captain, "no name");
	}
	captain[sizeof captain - 1] = '\0';
	Write(W_CAPTAIN, ms, 1, (int)captain, 0, 0, 0);
	for (n = 0; n < 2; n++) {
		char buf[10];

		printf("\nInitial broadside %s (grape, chain, round, double): ",
			n ? "right" : "left");
		(void) fflush(stdout);
		(void) scanf("%s", buf);
		switch (*buf) {
		case 'g':
			load = L_GRAPE;
			break;
		case 'c':
			load = L_CHAIN;
			break;
		case 'r':
			load = L_ROUND;
			break;
		case 'd':
			load = L_DOUBLE;
			break;
		default:
			load = L_ROUND;
		}
		if (n) {
			mf->loadR = load;
			mf->readyR = R_LOADED|R_INITIAL;
		} else {
			mf->loadL = load;
			mf->readyL = R_LOADED|R_INITIAL;
		}
	}

	initscreen();
	draw_board();
	(void) sprintf(message, "Captain %s assuming command", captain);
	Write(W_SIGNAL, ms, 1, (int)message, 0, 0, 0);
	newturn();
}

/*
 * If we get here before a ship is chosen, then ms == 0 and
 * we don't want to update the score file, or do any Write's either.
 * We can assume the sync file is already created and may need
 * to be removed.
 * Of course, we don't do any more Sync()'s if we got here
 * because of a Sync() failure.
 */
leave(conditions)
int conditions;
{
	(void) signal(SIGHUP, SIG_IGN);
	(void) signal(SIGINT, SIG_IGN);
	(void) signal(SIGQUIT, SIG_IGN);
	(void) signal(SIGALRM, SIG_IGN);
	(void) signal(SIGCHLD, SIG_IGN);

	if (done_curses) {
		Signal("It looks like you've had it!",
			(struct ship *)0);
		switch (conditions) {
		case LEAVE_QUIT:
			break;
		case LEAVE_CAPTURED:
			Signal("Your ship was captured.",
				(struct ship *)0);
			break;
		case LEAVE_HURRICAN:
			Signal("Hurricane!  All ships destroyed.",
				(struct ship *)0);
			break;
		case LEAVE_DRIVER:
			Signal("The driver died.", (struct ship *)0);
			break;
		case LEAVE_SYNC:
			Signal("Synchronization error.", (struct ship *)0);
			break;
		default:
			Signal("A funny thing happened (%d).",
				(struct ship *)0, conditions);
		}
	} else {
		switch (conditions) {
		case LEAVE_QUIT:
			break;
		case LEAVE_DRIVER:
			printf("The driver died.\n");
			break;
		case LEAVE_FORK:
			perror("fork");
			break;
		case LEAVE_SYNC:
			printf("Synchronization error\n.");
			break;
		default:
			printf("A funny thing happened (%d).\n",
				conditions);
		}
	}

	if (ms != 0) {
		log(ms);
		if (conditions != LEAVE_SYNC) {
			makesignal(ms, "Captain %s relinquishing.",
				(struct ship *)0, mf->captain);
			Write(W_END, ms, 0, 0, 0, 0, 0);
			(void) Sync();
		}
	}
	sync_close(!hasdriver);
	cleanupscreen();
	exit(0);
}

choke()
{
	leave(LEAVE_QUIT);
}

child()
{
	union wait status;
	int pid;

	(void) signal(SIGCHLD, SIG_IGN);
	do {
		pid = wait3(&status, WNOHANG, (struct rusage *)0);
		if (pid < 0 || pid > 0 && !WIFSTOPPED(status))
			hasdriver = 0;
	} while (pid > 0);
	(void) signal(SIGCHLD, child);
}
SHAR_EOF
if test 7085 -ne "`wc -c sail/player1.c`"
then
echo shar: error transmitting sail/player1.c '(should have been 7085 characters)'
fi
cat << \SHAR_EOF > sail/player2.c
#ifndef lint
static	char *sccsid = "@(#)player2.c	2.3 83/12/09";
#endif

#include "player.h"

play()
{
	register struct ship *sp;

	for (;;) {
		switch (sgetch("~\b", (struct ship *)0, 0)) {
		case 'm':
			acceptmove();
			break;
		case 's':
			acceptsignal();
			break;
		case 'g':
			grapungrap();
			break;
		case 'u':
			unfoulplayer();
			break;
		case 'v':
			Signal("%s", (struct ship *)0, version);
			break;
		case 'b':
			acceptboard();
			break;
		case 'f':
			acceptcombat();
			break;
		case 'l':
			loadplayer();
			break;
		case 'c':
			changesail();
			break;
		case 'r':
			repair();
			break;
		case 'B':
			Signal("'Hands to stations!'", (struct ship *)0);
			unboard(ms, ms, 1);	/* cancel DBP's */
			unboard(ms, ms, 0);	/* cancel offense */
			break;
		case '\f':
			centerview();
			blockalarm();
			draw_board();
			draw_screen();
			unblockalarm();
			break;
		case 'L':
			mf->loadL = L_EMPTY;
			mf->loadR = L_EMPTY;
			mf->readyL = R_EMPTY;
			mf->readyR = R_EMPTY;
			Signal("Broadsides unloaded", (struct ship *)0);
			break;
		case 'q':
			Signal("Type 'Q' to quit", (struct ship *)0);
			break;
		case 'Q':
			leave(LEAVE_QUIT);
			break;
		case 'I':
			foreachship(sp)
				if (sp != ms)
					eyeball(sp);
			break;
		case 'i':
			if ((sp = closestenemy(ms, 0, 1)) == 0)
				Signal("No more ships left.");
			else
				eyeball(sp);
			break;
		case 'C':
			centerview();
			blockalarm();
			draw_view();
			unblockalarm();
			break;
		case 'U':
			upview();
			blockalarm();
			draw_view();
			unblockalarm();
			break;
		case 'D':
		case 'N':
			downview();
			blockalarm();
			draw_view();
			unblockalarm();
			break;
		case 'H':
			leftview();
			blockalarm();
			draw_view();
			unblockalarm();
			break;
		case 'J':
			rightview();
			blockalarm();
			draw_view();
			unblockalarm();
			break;
		case 'F':
			lookout();
			break;
		case 'S':
			dont_adjust = !dont_adjust;
			blockalarm();
			draw_turn();
			unblockalarm();
			break;
		}
	}
}
SHAR_EOF
if test 1980 -ne "`wc -c sail/player2.c`"
then
echo shar: error transmitting sail/player2.c '(should have been 1980 characters)'
fi
cat << \SHAR_EOF > sail/player3.c
#ifndef lint
static	char *sccsid = "@(#)player3.c	2.3 83/12/17";
#endif

#include "player.h"

acceptcombat()
{
	int men = 0;
	int target, temp;
	int n, r;
	int index, rakehim, sternrake;
	int hhits = 0, ghits = 0, rhits = 0, chits = 0;
	int crew[3];
	int load;
	int guns, car, ready, shootat, hit;
	int roll;
	struct ship *closest;

	crew[0] = mc->crew1;
	crew[1] = mc->crew2;
	crew[2] = mc->crew3;
	for (n = 0; n < 3; n++) {
		if (mf->OBP[n].turnsent)
			men += mf->OBP[n].mensent;
	}
	for (n = 0; n < 3; n++) {
		if (mf->DBP[n].turnsent)
			men += mf->DBP[n].mensent;
	}
	if (men) {
		crew[0] = men/100 ? 0 : crew[0] != 0;
		crew[1] = (men%100)/10 ? 0 : crew[1] != 0;
		crew[2] = men%10 ? 0 : crew[2] != 0;
	}
	for (r = 0; r < 2; r++) {
		if (r) {
			ready = mf->readyR;
			load = mf->loadR;
			guns = mc->gunR;
			car = mc->carR;
		} else {
			ready = mf->readyL;
			load = mf->loadL;
			guns = mc->gunL;
			car = mc->carL;
		}
		if (!guns && !car || load == L_EMPTY || (ready & R_LOADED) == 0)
			goto cant;
		if (mf->struck || !crew[2])
			goto cant;
		closest = closestenemy(ms, (r ? 'r' : 'l'), 1);
		if (closest == 0)
			goto cant;
		if (closest->file->struck)
			goto cant;
		target = range(ms, closest);
		if (target > rangeofshot[load] || !guns && target >= 3)
			goto cant;
		Signal("%s (%c%c) within range of %s broadside.",
			closest, r ? "right" : "left");
		if (load > L_CHAIN && target < 6) {
			switch (sgetch("Aim for hull or rigging? ",
				(struct ship *)0, 1)) {
			case 'r':
				shootat = RIGGING;
				break;
			case 'h':
				shootat = HULL;
				break;
			default:
				shootat = -1;
				Signal("'Avast there! Hold your fire.'",
					(struct ship *)0);
			}
		} else {
			if (sgetch("Fire? ", (struct ship *)0, 1) == 'n') {
				shootat = -1;
				Signal("Belay that! Hold your fire.",
					(struct ship *)0);
			} else
				shootat = RIGGING;
		}
		if (shootat == -1)
			continue;
		fired = 1;
		rakehim = gunsbear(ms, closest) && !gunsbear(closest, ms);
		temp = portside(closest, ms, 1) - closest->file->dir + 1;
		if (temp < 1)
			temp += 8;
		else if (temp > 8)
			temp -= 8;
		sternrake = temp > 4 && temp < 6;
		if (rakehim)
			if (!sternrake)
				Signal("Raking the %s!", closest);
			else
				Signal("Stern Rake! %s splintering!", closest);
		index = guns;
		if (target < 3)
			index += car;
		index = (index - 1)/3;
		index = index > 8 ? 8 : index;
		if (!rakehim)
			hit = HDT[index][target-1];
		else
			hit = HDTrake[index][target-1];
		if (rakehim && sternrake)
			hit++;
		hit += QUAL[index][mc->qual-1];
		for (n = 0; n < 3 && mf->captured == 0; n++)
			if (!crew[n])
				if (index <= 5)
					hit--;
				else
					hit -= 2;
		if (ready & R_INITIAL)
			if (index <= 3)
				hit++;
			else
				hit += 2;
		if (mf->captured != 0)
			if (index <= 1)
				hit--;
			else
				hit -= 2;
		hit += AMMO[index][load - 1];
		if (((temp = mc->class) >= 5 || temp == 1) && windspeed == 5)
			hit--;
		if (windspeed == 6 && temp == 4)
			hit -= 2;
		if (windspeed == 6 && temp <= 3)
			hit--;
		if (hit >= 0) {
			roll = die();
			if (load == L_GRAPE)
				chits = hit;
			else {
				struct Tables *t;
				if (hit > 10)
					hit = 10;
				t = &(shootat == RIGGING ? RigTable : HullTable)
					[hit][roll-1];
				chits = t->C;
				rhits = t->R;
				hhits = t->H;
				ghits = t->G;
				if (closest->file->FS)
					rhits *= 2;
				if (load == L_CHAIN) {
					ghits = 0;
					hhits = 0;
				}
			}
			table(shootat, load, hit, closest, ms, roll);
		}
		Signal("Damage inflicted on the %s:",
			(struct ship *)0, closest->shipname);
		Signal("\t%d HULL, %d GUNS, %d CREW, %d RIGGING",
			(struct ship *)0, hhits, ghits, chits, rhits);
		if (!r) {
			mf->loadL = L_EMPTY;
			mf->readyL = R_EMPTY;
		} else {
			mf->loadR = L_EMPTY;
			mf->readyR = R_EMPTY;
		}
		continue;
	cant:
		Signal("Unable to fire %s broadside",
			(struct ship *)0, r ? "right" : "left");
	}
	blockalarm();
	draw_stat();
	unblockalarm();
}

grapungrap()
{
	register struct ship *sp;
	register int i;

	foreachship(sp) {
		if (sp == ms || sp->file->dir == 0)
			continue;
		if (range(ms, sp) > 1 && !grappled2(ms, sp))
			continue;
		switch (sgetch("Attempt to grapple or ungrapple %s (%c%c): ",
			sp, 1)) {
		case 'g':
			if (die() < 3
			    || ms->nationality == capship(sp)->nationality) {
				Write(W_GRAP, ms, 0, sp->file->index, 0, 0, 0);
				Write(W_GRAP, sp, 0, player, 0, 0, 0);
				Signal("Attempt succeeds!", (struct ship *)0);
				makesignal(ms, "grappled with %s (%c%c)", sp);
			} else
				Signal("Attempt fails.", (struct ship *)0);
			break;
		case 'u':
			for (i = grappled2(ms, sp); --i >= 0;) {
				if (ms->nationality
					== capship(sp)->nationality
				    || die() < 3) {
					cleangrapple(ms, sp, 0);
					Signal("Attempt succeeds!",
						(struct ship *)0);
					makesignal(ms,
						"ungrappling with %s (%c%c)",
						sp);
				} else
					Signal("Attempt fails.",
						(struct ship *)0);
			}
			break;
		}
	}
}

unfoulplayer()
{
	register struct ship *to;
	register i;

	foreachship(to) {
		if (fouled2(ms, to) == 0)
			continue;
		if (sgetch("Attempt to unfoul with the %s (%c%c)? ", to, 1) != 'y')
			continue;
		for (i = fouled2(ms, to); --i >= 0;) {
			if (die() <= 2) {
				cleanfoul(ms, to, 0);
				Signal("Attempt succeeds!", (struct ship *)0);
				makesignal(ms, "Unfouling %s (%c%c)", to);
			} else
				Signal("Attempt fails.", (struct ship *)0);
		}
	}
}
SHAR_EOF
if test 5384 -ne "`wc -c sail/player3.c`"
then
echo shar: error transmitting sail/player3.c '(should have been 5384 characters)'
fi
cat << \SHAR_EOF > sail/player4.c
#ifndef lint
static	char *sccsid = "@(#)player4.c	2.3 84/12/12";
#endif

#include "player.h"

changesail()
{
	int rig, full;

	rig = mc->rig1;
	full = mf->FS;
	if (windspeed == 6 || windspeed == 5 && mc->class > 4)
		rig = 0;
	if (mc->crew3 && rig) {
		if (!full) {
			if (sgetch("Increase to Full sails? ",
				(struct ship *)0, 1) == 'y') {
				changed = 1;
				Write(W_FS, ms, 0, 1, 0, 0, 0);
			}
		} else {
			if (sgetch("Reduce to Battle sails? ",
				(struct ship *)0, 1) == 'y') {
				Write(W_FS, ms, 0, 0, 0, 0, 0);
				changed = 1;
			}
		}
	} else if (!rig)
		Signal("Sails rent to pieces", (struct ship *)0);
}

acceptsignal()
{
	char buf[60];
	register char *p = buf;

	*p++ = '"';
	sgetstr("Message? ", p, sizeof buf - 2);
	while (*p++)
		;
	p[-1] = '"';
	*p = 0;
	Write(W_SIGNAL, ms, 1, (int)buf, 0, 0, 0);
}

lookout()
{
	register struct ship *sp;
	char buf[3];
	register char c;

	sgetstr("What ship? ", buf, sizeof buf);
	foreachship(sp) {
		c = *countryname[sp->nationality];
		if ((c == *buf || tolower(c) == *buf || colours(sp) == *buf)
		    && (sp->file->stern == buf[1] || sterncolour(sp) == buf[1]
			|| buf[1] == '?')) {
			eyeball(sp);
		}
	}
}

char *
saywhat(sp, flag)
register struct ship *sp;
char flag;
{
	if (sp->file->captain[0])
		return sp->file->captain;
	else if (sp->file->struck)
		return "(struck)";
	else if (sp->file->captured != 0)
		return "(captured)";
	else if (flag)
		return "(available)";
	else
		return "(computer)";
}

eyeball(ship)
register struct ship *ship;
{
	int i;

	if (ship->file->dir != 0) {
		Signal("Sail ho! (range %d, %s)",
			(struct ship *)0, range(ms, ship), saywhat(ship, 0));
		i = portside(ms, ship, 1) - mf->dir;
		if (i <= 0)
			i += 8;
		Signal("%s (%c%c) %s %s %s.",
			ship, countryname[ship->nationality],
			classname[ship->specs->class], directionname[i]);
	}
}
SHAR_EOF
if test 1841 -ne "`wc -c sail/player4.c`"
then
echo shar: error transmitting sail/player4.c '(should have been 1841 characters)'
fi
cat << \SHAR_EOF > sail/player5.c
#ifndef lint
static	char *sccsid = "@(#)player5.c	2.5 83/12/21";
#endif

#include "player.h"

#define turnfirst(x) (*x == 'r' || *x == 'l')

acceptmove()
{
	int ta;
	int ma;
	char af;
	int moved = 0;
	int vma, dir;
	char prompt[60];
	char buf[60], last = '\0';
	register char *p;

	if (!mc->crew3 || snagged(ms) || !windspeed) {
		Signal("Unable to move", (struct ship *)0);
		return;
	}

	ta = maxturns(ms, &af);
	ma = maxmove(ms, mf->dir, 0);
	(void) sprintf(prompt, "move (%d,%c%d): ", ma, af ? '\'' : ' ', ta);
	sgetstr(prompt, buf, sizeof buf);
	dir = mf->dir;
	vma = ma;
	for (p = buf; *p; p++)
		switch (*p) {
		case 'l':
			dir -= 2;
		case 'r':
			if (++dir == 0)
				dir = 8;
			else if (dir == 9)
				dir = 1;
			if (last == 't') {
				Signal("Ship can't turn that fast.",
					(struct ship *)0);
				*p-- = '\0';
			}
			last = 't';
			ma--;
			ta--;
			vma = min(ma, maxmove(ms, dir, 0));
			if (ta < 0 && moved || vma < 0 && moved)
				*p-- = '\0';
			break;
		case 'b':
			ma--;
			vma--;
			last = 'b';
			if (ta < 0 && moved || vma < 0 && moved)
				*p-- = '\0';
			break;
		case '0':
		case 'd':
			*p-- = '\0';
			break;
		case '\n':
			*p-- = '\0';
			break;
		case '1': case '2': case '3': case '4':
		case '5': case '6': case '7':
			if (last == '0') {
				Signal("Can't move that fast.",
					(struct ship *)0);
				*p-- = '\0';
			}
			last = '0';
			moved = 1;
			ma -= *p - '0';
			vma -= *p - '0';
			if (ta < 0 && moved || vma < 0 && moved)
				*p-- = '\0';
			break;
		default:
			if (!isspace(*p)) {
				Signal("Input error.", (struct ship *)0);
				*p-- = '\0';
			}
		}
	if (ta < 0 && moved || vma < 0 && moved
	    || af && turnfirst(buf) && moved) {
		Signal("Movement error.", (struct ship *)0);
		if (ta < 0 && moved) {
			if (mf->FS == 1) {
				Write(W_FS, ms, 0, 0, 0, 0, 0);
				Signal("No hands to set full sails.",
					(struct ship *)0);
			}
		} else if (ma >= 0)
			buf[1] = '\0';
	}
	if (af && !moved) {
		if (mf->FS == 1) {
			Write(W_FS, ms, 0, 0, 0, 0, 0);
			Signal("No hands to set full sails.",
				(struct ship *)0);
		}
	}
	if (*buf)
		(void) strcpy(movebuf, buf);
	else
		(void) strcpy(movebuf, "d");
	Write(W_MOVE, ms, 1, (int)movebuf, 0, 0, 0);
	Signal("Helm: %s.", (struct ship *)0, movebuf);
}

acceptboard()
{
	register struct ship *sp;
	register int n;
	int crew[3];
	int men = 0;
	char c;

	crew[0] = mc->crew1;
	crew[1] = mc->crew2;
	crew[2] = mc->crew3;
	for (n = 0; n < NBP; n++) {
		if (mf->OBP[n].turnsent)
			    men += mf->OBP[n].mensent;
	}
	for (n = 0; n < NBP; n++) {
		if (mf->DBP[n].turnsent)
			    men += mf->DBP[n].mensent;
	}
	if (men) {
		crew[0] = men/100 ? 0 : crew[0] != 0;
		crew[1] = (men%100)/10 ? 0 : crew[1] != 0;
		crew[2] = men%10 ? 0 : crew[2] != 0;
	} else {
		crew[0] = crew[0] != 0;
		crew[1] = crew[1] != 0;
		crew[2] = crew[2] != 0;
	}
	foreachship(sp) {
		if (sp == ms || sp->file->dir == 0 || range(ms, sp) > 1)
			continue;
		if (ms->nationality == capship(sp)->nationality)
			continue;
		if (meleeing(ms, sp) && crew[2]) {
			c = sgetch("How many more to board the %s (%c%c)? ",
				sp, 1);
			parties(crew, sp, 0, c);
		} else if ((fouled2(ms, sp) || grappled2(ms, sp)) && crew[2]) {
			c = sgetch("Crew sections to board the %s (%c%c) (3 max) ?", sp, 1);
			parties(crew, sp, 0, c);
		}
	}
	if (crew[2]) {
		c = sgetch("How many sections to repel boarders? ",
			(struct ship *)0, 1);
		parties(crew, ms, 1, c);
	}
	blockalarm();
	draw_slot();
	unblockalarm();
}

parties(crew, to, isdefense, buf)
register struct ship *to;
int crew[3];
char isdefense;
char buf;
{
	register int k, j, men; 
	struct BP *ptr;
	int temp[3];

	for (k = 0; k < 3; k++)
		temp[k] = crew[k];
	if (isdigit(buf)) {
		ptr = isdefense ? to->file->DBP : to->file->OBP; 
		for (j = 0; j < NBP && ptr[j].turnsent; j++)
			;
		if (!ptr[j].turnsent && buf > '0') {
			men = 0;
			for (k = 0; k < 3 && buf > '0'; k++) {
				men += crew[k]
					* (k == 0 ? 100 : (k == 1 ? 10 : 1));
				crew[k] = 0;
				if (men)
					buf--;
			}
			if (buf > '0')
				Signal("Sending all crew sections.",
					(struct ship *)0);
			Write(isdefense ? W_DBP : W_OBP, ms, 0,
				j, turn, to->file->index, men);
			if (isdefense) {
				(void) wmove(slot_w, 2, 0);
				for (k=0; k < NBP; k++)
					if (temp[k] && !crew[k])
						(void) waddch(slot_w, k + '1');
					else
						(void) wmove(slot_w, 2, 1 + k);
				(void) mvwaddstr(slot_w, 3, 0, "DBP");
				makesignal(ms, "repelling boarders",
					(struct ship *)0);
			} else {
				(void) wmove(slot_w, 0, 0);
				for (k=0; k < NBP; k++)
					if (temp[k] && !crew[k])
						(void) waddch(slot_w, k + '1');
					else
						(void) wmove(slot_w, 0, 1 + k);
				(void) mvwaddstr(slot_w, 1, 0, "OBP");
				makesignal(ms, "boarding the %s (%c%c)", to);
			}
			blockalarm();
			(void) wrefresh(slot_w);
			unblockalarm();
		} else
			Signal("Sending no crew sections.", (struct ship *)0);
	}
}
SHAR_EOF
if test 4885 -ne "`wc -c sail/player5.c`"
then
echo shar: error transmitting sail/player5.c '(should have been 4885 characters)'
fi
cat << \SHAR_EOF > sail/player6.c
#ifndef lint
static	char *sccsid = "@(#)player6.c	2.3 84/02/23";
#endif

#include "player.h"

repair()
{
	char c;
	register char *repairs;
	register struct shipspecs *ptr = mc;
	register int count;

#define FIX(x, m) (m - ptr->x > count \
	? (ptr->x += count, count = 0) : (count -= m - ptr->x, ptr->x = m))

	if (repaired || loaded || fired || changed || turned()) {
		Signal("No hands free to repair", (struct ship *)0);
		return;
	}
	c = sgetch("Repair (hull, guns, rigging)? ", (struct ship *)0, 1);
	switch (c) {
		case 'h':
			repairs = &mf->RH;
			break;
		case 'g':
			repairs = &mf->RG;
			break;
		case 'r':
			repairs = &mf->RR;
			break;
		default:
			Signal("Avast heaving!", (struct ship *)0);
			return;
	}
	if (++*repairs >= 3) {
		count = 2;
		switch (c) {
		case 'h': {
			int max = ptr->guns/4;
			if (ptr->hull < max) {
				FIX(hull, max);
				Write(W_HULL, ms, 0, ptr->hull, 0, 0, 0);
			}
			break;
			}
		case 'g':
			if (ptr->gunL < ptr->gunR) {
				int max = ptr->guns/5 - ptr->carL;
				if (ptr->gunL < max) {
					FIX(gunL, max);
					Write(W_GUNL, ms, 0, ptr->gunL,
						ptr->carL, 0, 0);
				}
			} else {
				int max = ptr->guns/5 - ptr->carR;
				if (ptr->gunR < max) {
					FIX(gunR, max);
					Write(W_GUNR, ms, 0, ptr->gunR,
						ptr->carR, 0, 0);
				}
			}
			break;
		case 'r':
#define X 2
			if (ptr->rig4 >= 0 && ptr->rig4 < X) {
				FIX(rig4, X);
				Write(W_RIG4, ms, 0, ptr->rig4, 0, 0, 0);
			}
			if (count && ptr->rig3 < X) {
				FIX(rig3, X);
				Write(W_RIG3, ms, 0, ptr->rig3, 0, 0, 0);
			}
			if (count && ptr->rig2 < X) {
				FIX(rig2, X);
				Write(W_RIG2, ms, 0, ptr->rig2, 0, 0, 0);
			}
			if (count && ptr->rig1 < X) {
				FIX(rig1, X);
				Write(W_RIG1, ms, 0, ptr->rig1, 0, 0, 0);
			}
			break;
		}
		if (count == 2) {
			Signal("Repairs completed.", (struct ship *)0);
			*repairs = 2;
		} else {
			*repairs = 0;
			blockalarm();
			draw_stat();
			unblockalarm();
		}
	}
	blockalarm();
	draw_slot();
	unblockalarm();
	repaired = 1;
}

turned()
{
	register char *p;

	for (p = movebuf; *p; p++)
		if (*p == 'r' || *p == 'l')
			return 1;
	return 0;
}

loadplayer()
{
	char c;
	register loadL, loadR, ready, load;

	if (!mc->crew3) {
		Signal("Out of crew", (struct ship *)0);
		return;
	}
	loadL = mf->loadL;
	loadR = mf->loadR;
	if (!loadL && !loadR) {
		c = sgetch("Load which broadside (left or right)? ",
			(struct ship *)0, 1);
		if (c == 'r')
			loadL = 1;
		else
			loadR = 1;
	}
	if (!loadL && loadR || loadL && !loadR) {
		c = sgetch("Reload with (round, double, chain, grape)? ",
			(struct ship *)0, 1);
		switch (c) {
		case 'r':
			load = L_ROUND;
			ready = 0;
			break;
		case 'd':
			load = L_DOUBLE;
			ready = R_DOUBLE;
			break;
		case 'c':
			load = L_CHAIN;
			ready = 0;
			break;
		case 'g':
			load = L_GRAPE;
			ready = 0;
			break;
		default:
			Signal("Broadside not loaded.",
				(struct ship *)0);
			return;
		}
		if (!loadR) {
			mf->loadR = load;
			mf->readyR = ready|R_LOADING;
		} else {
			mf->loadL = load;
			mf->readyL = ready|R_LOADING;
		}
		loaded = 1;
	}
}
SHAR_EOF
if test 3064 -ne "`wc -c sail/player6.c`"
then
echo shar: error transmitting sail/player6.c '(should have been 3064 characters)'
fi
cat << \SHAR_EOF > sail/player7.c
#ifndef lint
static	char *sccsid = "@(#)player7.c	2.8 84/02/23";
#endif

#include "player.h"

/*
 * Display interface
 */

static char sc_hasprompt;
static char *sc_prompt;
static char *sc_buf;
static int sc_line;

initscreen()
{
	/* initscr() already done in SCREENTEST() */
	view_w = newwin(VIEW_Y, VIEW_X, VIEW_T, VIEW_L);
	slot_w = newwin(SLOT_Y, SLOT_X, SLOT_T, SLOT_L);
	scroll_w = newwin(SCROLL_Y, SCROLL_X, SCROLL_T, SCROLL_L);
	stat_w = newwin(STAT_Y, STAT_X, STAT_T, STAT_L);
	turn_w = newwin(TURN_Y, TURN_X, TURN_T, TURN_L);
	done_curses++;
	(void) leaveok(view_w, 1);
	(void) leaveok(slot_w, 1);
	(void) leaveok(stat_w, 1);
	(void) leaveok(turn_w, 1);
#ifdef SIGTSTP
	{
		int susp();
		(void) signal(SIGTSTP, susp);
	}
#endif
	noecho();
	crmode();
}

cleanupscreen()
{
	/* alarm already turned off */
	if (done_curses) {
		(void) wmove(scroll_w, SCROLL_Y - 1, 0);
		(void) wclrtoeol(scroll_w);
		draw_screen();
		endwin();
	}
}

newturn()
{
	repaired = loaded = fired = changed = 0;
	movebuf[0] = '\0';

	(void) alarm(0);
	if (mf->readyL & R_LOADING)
		if (mf->readyL & R_DOUBLE)
			mf->readyL = R_LOADING;
		else
			mf->readyL = R_LOADED;
	if (mf->readyR & R_LOADING)
		if (mf->readyR & R_DOUBLE)
			mf->readyR = R_LOADING;
		else
			mf->readyR = R_LOADED;
	if (!hasdriver)
		Write(W_DDEAD, SHIP(0), 0, 0, 0, 0, 0);

	if (sc_hasprompt) {
		(void) wmove(scroll_w, sc_line, 0);
		(void) wclrtoeol(scroll_w);
	}
	if (Sync() < 0)
		leave(LEAVE_SYNC);
	if (!hasdriver)
		leave(LEAVE_DRIVER);
	if (sc_hasprompt)
		(void) wprintw(scroll_w, "%s%s", sc_prompt, sc_buf);

	if (turn % 50 == 0)
		Write(W_ALIVE, SHIP(0), 0, 0, 0, 0, 0);
	if (mf->FS && (!mc->rig1 || windspeed == 6))
		Write(W_FS, ms, 0, 0, 0, 0, 0);
	if (mf->FS == 1)
		Write(W_FS, ms, 0, 2, 0, 0, 0);

	if (mf->struck)
		leave(LEAVE_QUIT);
	if (mf->captured != 0)
		leave(LEAVE_CAPTURED);
	if (windspeed == 7)
		leave(LEAVE_HURRICAN);

	adjustview();
	draw_screen();

	(void) signal(SIGALRM, newturn);
	(void) alarm(7);
}

/*VARARGS2*/
Signal(fmt, ship, a, b, c, d)
char *fmt;
register struct ship *ship;
int a, b, c, d;
{
	if (!done_curses)
		return;
	if (*fmt == '\7')
		putchar(*fmt++);
	if (ship == 0)
		(void) wprintw(scroll_w, fmt, a, b, c, d);
	else
		(void) wprintw(scroll_w, fmt, ship->shipname,
			colours(ship), sterncolour(ship), a, b, c, d);
	Scroll();
}

Scroll()
{
	if (++sc_line >= SCROLL_Y)
		sc_line = 0;
	(void) wmove(scroll_w, sc_line, 0);
	(void) wclrtoeol(scroll_w);
}

prompt(p, ship)
register char *p;
struct ship *ship;
{
	static char buf[60];

	if (ship != 0)
		p = sprintf(buf, p, ship->shipname, colours(ship),
			sterncolour(ship));
	sc_prompt = p;
	sc_buf = "";
	sc_hasprompt = 1;
	(void) waddstr(scroll_w, p);
}

endprompt(flag)
char flag;
{
	sc_hasprompt = 0;
	if (flag)
		Scroll();
}

sgetch(p, ship, flag)
char *p;
struct ship *ship;
char flag;
{
	register c;

	prompt(p, ship);
	blockalarm();
	(void) wrefresh(scroll_w);
	unblockalarm();
	while ((c = wgetch(scroll_w)) == EOF)
		;
	if (flag && c >= ' ' && c < 0x7f)
		(void) waddch(scroll_w, c);
	endprompt(flag);
	return c;
}

sgetstr(pr, buf, n)
char *pr;
register char *buf;
register n;
{
	register c;
	register char *p = buf;

	prompt(pr, (struct ship *)0);
	sc_buf = buf;
	for (;;) {
		*p = 0;
		blockalarm();
		(void) wrefresh(scroll_w);
		unblockalarm();
		while ((c = wgetch(scroll_w)) == EOF)
			;
		switch (c) {
		case '\n':
		case '\r':
			endprompt(1);
			return;
		case '\b':
			if (p > buf) {
				(void) waddstr(scroll_w, "\b \b");
				p--;
			}
			break;
		default:
			if (c >= ' ' && c < 0x7f && p < buf + n - 1) {
				*p++ = c;
				(void) waddch(scroll_w, c);
			} else
				(void) putchar(CTRL(g));
		}
	}
}

draw_screen()
{
	draw_view();
	draw_turn();
	draw_stat();
	draw_slot();
	(void) wrefresh(scroll_w);		/* move the cursor */
}

draw_view()
{
	register struct ship *sp;

	(void) werase(view_w);
	foreachship(sp) {
		if (sp->file->dir
		    && sp->file->row > viewrow
		    && sp->file->row < viewrow + VIEW_Y
		    && sp->file->col > viewcol
		    && sp->file->col < viewcol + VIEW_X) {
			(void) wmove(view_w, sp->file->row - viewrow,
				sp->file->col - viewcol);
			(void) waddch(view_w, colours(sp));
			(void) wmove(view_w,
				sternrow(sp) - viewrow,
				sterncol(sp) - viewcol);
			(void) waddch(view_w, sterncolour(sp));
		}
	}
	(void) wrefresh(view_w);
}

draw_turn()
{
	(void) wmove(turn_w, 0, 0);
	(void) wprintw(turn_w, "%cTurn %d", dont_adjust?'*':'-', turn);
	(void) wrefresh(turn_w);
}

draw_stat()
{
	(void) wmove(stat_w, STAT_1, 0);
	(void) wprintw(stat_w, "Points  %3d\n", mf->points);
	(void) wprintw(stat_w, "Fouls    %2d\n", fouled(ms));
	(void) wprintw(stat_w, "Grapples %2d\n", grappled(ms));

	(void) wmove(stat_w, STAT_2, 0);
	(void) wprintw(stat_w, "    0 %c(%c)\n",
		maxmove(ms, winddir + 3, -1) + '0',
		maxmove(ms, winddir + 3, 1) + '0');
	(void) waddstr(stat_w, "   \\|/\n");
	(void) wprintw(stat_w, "   -^-%c(%c)\n",
		maxmove(ms, winddir + 2, -1) + '0',
		maxmove(ms, winddir + 2, 1) + '0');
	(void) waddstr(stat_w, "   /|\\\n");
	(void) wprintw(stat_w, "    | %c(%c)\n",
		maxmove(ms, winddir + 1, -1) + '0',
		maxmove(ms, winddir + 1, 1) + '0');
	(void) wprintw(stat_w, "   %c(%c)\n",
		maxmove(ms, winddir, -1) + '0',
		maxmove(ms, winddir, 1) + '0');

	(void) wmove(stat_w, STAT_3, 0);
	(void) wprintw(stat_w, "Load  %c%c %c%c\n",
		loadname[mf->loadL], readyname(mf->readyL),
		loadname[mf->loadR], readyname(mf->readyR));
	(void) wprintw(stat_w, "Hull %2d\n", mc->hull);
	(void) wprintw(stat_w, "Crew %2d %2d %2d\n",
		mc->crew1, mc->crew2, mc->crew3);
	(void) wprintw(stat_w, "Guns %2d %2d\n", mc->gunL, mc->gunR);
	(void) wprintw(stat_w, "Carr %2d %2d\n", mc->carL, mc->carR);
	(void) wprintw(stat_w, "Rigg %d %d %d ", mc->rig1, mc->rig2, mc->rig3);
	if (mc->rig4 < 0)
		(void) waddch(stat_w, '-');
	else
		(void) wprintw(stat_w, "%d", mc->rig4);
	(void) wrefresh(stat_w);
}

draw_slot()
{
	if (!boarding(ms, 0)) {
		(void) mvwaddstr(slot_w, 0, 0, "   ");
		(void) mvwaddstr(slot_w, 1, 0, "   ");
	} else
		(void) mvwaddstr(slot_w, 1, 0, "OBP");
	if (!boarding(ms, 1)) {
		(void) mvwaddstr(slot_w, 2, 0, "   ");
		(void) mvwaddstr(slot_w, 3, 0, "   ");
	} else
		(void) mvwaddstr(slot_w, 3, 0, "DBP");

	(void) wmove(slot_w, SLOT_Y-4, 0);
	if (mf->RH)
		(void) wprintw(slot_w, "%dRH", mf->RH);
	else
		(void) waddstr(slot_w, "   ");
	(void) wmove(slot_w, SLOT_Y-3, 0);
	if (mf->RG)
		(void) wprintw(slot_w, "%dRG", mf->RG);
	else
		(void) waddstr(slot_w, "   ");
	(void) wmove(slot_w, SLOT_Y-2, 0);
	if (mf->RR)
		(void) wprintw(slot_w, "%dRR", mf->RR);
	else
		(void) waddstr(slot_w, "   ");

#define Y	(SLOT_Y/2)
	(void) wmove(slot_w, 7, 1);
	(void) wprintw(slot_w,"%d", windspeed);
	(void) mvwaddch(slot_w, Y, 0, ' ');
	(void) mvwaddch(slot_w, Y, 2, ' ');
	(void) mvwaddch(slot_w, Y-1, 0, ' ');
	(void) mvwaddch(slot_w, Y-1, 1, ' ');
	(void) mvwaddch(slot_w, Y-1, 2, ' ');
	(void) mvwaddch(slot_w, Y+1, 0, ' ');
	(void) mvwaddch(slot_w, Y+1, 1, ' ');
	(void) mvwaddch(slot_w, Y+1, 2, ' ');
	(void) wmove(slot_w, Y - dr[winddir], 1 - dc[winddir]);
	switch (winddir) {
	case 1:
	case 5:
		(void) waddch(slot_w, '|');
		break;
	case 2:
	case 6:
		(void) waddch(slot_w, '/');
		break;
	case 3:
	case 7:
		(void) waddch(slot_w, '-');
		break;
	case 4:
	case 8:
		(void) waddch(slot_w, '\\');
		break;
	}
	(void) mvwaddch(slot_w, Y + dr[winddir], 1 + dc[winddir], '+');
	(void) wrefresh(slot_w);
}

draw_board()
{
	register int n;

	(void) clear();
	(void) werase(view_w);
	(void) werase(slot_w);
	(void) werase(scroll_w);
	(void) werase(stat_w);
	(void) werase(turn_w);

	sc_line = 0;

	(void) move(BOX_T, BOX_L);
	for (n = 0; n < BOX_X; n++)
		(void) addch('-');
	(void) move(BOX_B, BOX_L);
	for (n = 0; n < BOX_X; n++)
		(void) addch('-');
	for (n = BOX_T+1; n < BOX_B; n++) {
		(void) mvaddch(n, BOX_L, '|');
		(void) mvaddch(n, BOX_R, '|');
	}
	(void) mvaddch(BOX_T, BOX_L, '+');
	(void) mvaddch(BOX_T, BOX_R, '+');
	(void) mvaddch(BOX_B, BOX_L, '+');
	(void) mvaddch(BOX_B, BOX_R, '+');
	(void) refresh();

#define WSaIM "Wooden Ships & Iron Men"
	(void) wmove(view_w, 2, (VIEW_X - sizeof WSaIM - 1) / 2);
	(void) waddstr(view_w, WSaIM);
	(void) wmove(view_w, 4, (VIEW_X - strlen(cc->name)) / 2);
	(void) waddstr(view_w, cc->name);
	(void) wrefresh(view_w);

	(void) move(LINE_T, LINE_L);
	(void) printw("Class %d %s (%d guns) '%s' (%c%c)",
		mc->class,
		classname[mc->class],
		mc->guns,
		ms->shipname,
		colours(ms),
		sterncolour(ms));
	(void) refresh();
}

centerview()
{
	viewrow = mf->row - VIEW_Y / 2;
	viewcol = mf->col - VIEW_X / 2;
}

upview()
{
	viewrow -= VIEW_Y / 3;
}

downview()
{
	viewrow += VIEW_Y / 3;
}

leftview()
{
	viewcol -= VIEW_X / 5;
}

rightview()
{
	viewcol += VIEW_X / 5;
}

adjustview()
{
	if (dont_adjust)
		return;
	if (mf->row < viewrow + VIEW_Y/4)
		viewrow = mf->row - (VIEW_Y - VIEW_Y/4);
	else if (mf->row > viewrow + (VIEW_Y - VIEW_Y/4))
		viewrow = mf->row - VIEW_Y/4;
	if (mf->col < viewcol + VIEW_X/8)
		viewcol = mf->col - (VIEW_X - VIEW_X/8);
	else if (mf->col > viewcol + (VIEW_X - VIEW_X/8))
		viewcol = mf->col - VIEW_X/8;
}

#ifdef SIGTSTP
susp()
{
	blockalarm();
	tstp();
	(void) signal(SIGTSTP, susp);
	unblockalarm();
}
#endif
SHAR_EOF
if test 9200 -ne "`wc -c sail/player7.c`"
then
echo shar: error transmitting sail/player7.c '(should have been 9200 characters)'
fi
#	End of shell archive
exit 0

yee@ucbvax.ARPA (Peter E. Yee) (01/24/85)

This is part 3 of the SAIL distribution.

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
-----cut here-----cut here-----cut here-----cut here-----
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	sail/:file
#	sail/:scene
#	sail/:ship
#	sail/:specs
#	sail/Makefile
#	sail/externs.h
#	sail/machdep.h
#	sail/sail.6
# This archive created: Wed Jan 23 19:49:11 1985
cat << \SHAR_EOF > sail/:file
./"index"16t"captain"nD20C
+/"points"8t"loadL"8t"loadR"8t"readyL"8t"readyL"ndbbbb2+36+36+
+/"struck"8t"capture"8t"pcrew"8t"movebuf"nb3+pd10C
+/"drift"8t"nfoul"8t"ngrap"nb1+dd
+/"foul:"8t"count"8t"turn"16t"count"8t"turn"
+,5/8tdd16tddn
+/"grap:"8t"count"8t"turn"16t"count"8t"turn"
+,5/8tdd16tddn
+/"RH"8t"RG"8t"RR"8t"FS"8t"explode"8t"sink"n6b
+/"dir"8t"col"8t"row"8t"loadwit"8t"stern"nb+2d2b
SHAR_EOF
if test 391 -ne "`wc -c sail/:file`"
then
echo shar: error transmitting sail/:file '(should have been 391 characters)'
fi
cat << \SHAR_EOF > sail/:scene
./"winddir	windspd	windchg	vessels"n4b
.+8/"ship:	"a
*(.-4)/S
SHAR_EOF
if test 62 -ne "`wc -c sail/:scene`"
then
echo shar: error transmitting sail/:scene '(should have been 62 characters)'
fi
cat << \SHAR_EOF > sail/:ship
./"name"16t"specs"16t"nation"nppb+
+/"row"8t"col"8t"dir"nddb+
+/"file"np
+/t
SHAR_EOF
if test 77 -ne "`wc -c sail/:ship`"
then
echo shar: error transmitting sail/:ship '(should have been 77 characters)'
fi
cat << \SHAR_EOF > sail/:specs
./"bs	bs	ta	guns	class	hull	qual"n3b+d3b
+/"crew1	crew2	crew3	gunL	gunR	carL	carR"n8b
+/"rig1	rig2	rig3	rig4	pts"n4b+d
SHAR_EOF
if test 119 -ne "`wc -c sail/:specs`"
then
echo shar: error transmitting sail/:specs '(should have been 119 characters)'
fi
cat << \SHAR_EOF > sail/Makefile
#
# Sail - Wooden Ships And Iron Men
#
# Makefile	@(#)Makefile	2.6 84/12/03
#
CC=	cc
CTAGS=	ctags -w
CFLAGS=	-O

DFILES=		driver1.c driver2.c driver3.c grap.c boarders.c
DOBJS=		driver1.o driver2.o driver3.o grap.o boarders.o
PFILES=		player1.c player2.c player3.c player4.c player5.c \
		player6.c player7.c version.c
POBJS=		player1.o player2.o player3.o player4.o player5.o \
		player6.o player7.o version.o
COMMONFILES=	assorted.c game.c globals.c misc.c parties.c sync.c
COMMONOBJS=	assorted.o game.o globals.o misc.o parties.o sync.o
LFILES=		sail.log.c
LOBJS=		sail.log.o
HDRS=		externs.h player.h driver.h machdep.h
OTHERFILES=	Makefile sail.6
CTAGFILES=	${DFILES} ${PFILES} ${LFILES} ${COMMONFILES}
JUNKFILES=	make.out
PLIBS=		-lcurses -ltermlib
DLIBS=
LLIBS=

SAILMASTER=	daemon
DRIVER=		lib/saildriver
LOGFILE=	lib/saillog
TARGET=		$(DESTDIR)/usr/games

all: sail driver sail.log

sail: ${POBJS} ${COMMONOBJS}
	cc -O ${COMMONOBJS} ${POBJS} ${PLIBS} -o sail

driver: ${DOBJS} ${COMMONOBJS}
	cc -O ${COMMONOBJS} ${DOBJS} ${DLIBS} -o driver

sail.log: ${LOBJS} globals.o
	cc -O ${LOBJS} globals.o -o sail.log

lint:
	lint -z $(PFILES) $(COMMONFILES) -lcurses
	lint -z $(DFILES) $(COMMONFILES)

tags: ${CTAGFILES}
	${CTAGS} ${CTAGFILES}

${HDRS} ${CTAGFILES}:
	sccs get $@;

clean: 
	rm -f ${DOBJS} ${POBJS} ${LOBJS} ${COMMONOBJS} ${JUNKFILES}

install: sail driver sail.log $(TARGET)/$(LOGFILE)
	install -c -s -m 4755 -o ${SAILMASTER} sail ${TARGET}/sail
	install -c -s -m 4755 -o ${SAILMASTER} driver ${TARGET}/${DRIVER}
	install -c -s -m 755 sail.log ${TARGET}/sail.log
	install -c sail.6 $(DESTDIR)/usr/man/man6

logfile $(TARGET)/$(LOGFILE):
	cp /dev/null ${TARGET}/${LOGFILE}
	chown ${SAILMASTER} ${TARGET}/${LOGFILE}
	chmod 644 ${TARGET}/${LOGFILE}
SHAR_EOF
if test 1763 -ne "`wc -c sail/Makefile`"
then
echo shar: error transmitting sail/Makefile '(should have been 1763 characters)'
fi
cat << \SHAR_EOF > sail/externs.h
/*
 * @(#)externs.h	2.4 84/02/23
 */
#include <stdio.h>
#include <signal.h>
#include <ctype.h>
#include "machdep.h"

#define die()		((rand() >> 3) % 6 + 1)
#define sqr(a)		((a) * (a))
#define abs(a)		((a) > 0 ? (a) : -(a))
#define min(a,b)	((a) < (b) ? (a) : (b))

#define grappled(a)	((a)->file->ngrap)
#define fouled(a)	((a)->file->nfoul)
#define snagged(a)	(grappled(a) + fouled(a))

#define grappled2(a, b)	((a)->file->grap[(b)->file->index].sn_count)
#define fouled2(a, b)	((a)->file->foul[(b)->file->index].sn_count)
#define snagged2(a, b)	(grappled2(a, b) + fouled2(a, b))

#define Xgrappled2(a, b) ((a)->file->grap[(b)->file->index].sn_turn < turn-1 ? grappled2(a, b) : 0)
#define Xfouled2(a, b)	((a)->file->foul[(b)->file->index].sn_turn < turn-1 ? fouled2(a, b) : 0)
#define Xsnagged2(a, b)	(Xgrappled2(a, b) + Xfouled2(a, b))

#define cleangrapple(a, b, c)	Cleansnag(a, b, c, 1)
#define cleanfoul(a, b, c)	Cleansnag(a, b, c, 2)
#define cleansnag(a, b, c)	Cleansnag(a, b, c, 3)

#define sterncolour(sp)	((sp)->file->stern+'0'-((sp)->file->captured?10:0))
#define sternrow(sp)	((sp)->file->row + dr[(sp)->file->dir])
#define sterncol(sp)	((sp)->file->col + dc[(sp)->file->dir])

#define capship(sp)	((sp)->file->captured?(sp)->file->captured:(sp))

#define readyname(r)	((r) & R_LOADING ? '*' : ((r) & R_INITIAL ? '!' : ' '))

/* loadL and loadR, should match loadname[] */
#define L_EMPTY		0		/* should be 0, don't change */
#define L_GRAPE		1
#define L_CHAIN		2
#define L_ROUND		3
#define L_DOUBLE	4
#define L_EXPLODE	5

/*
 * readyL and readyR, these are bits, except R_EMPTY
 */
#define R_EMPTY		0		/* not loaded and not loading */
#define R_LOADING	1		/* loading */
#define R_DOUBLE	2		/* loading double */
#define R_LOADED	4		/* loaded */
#define R_INITIAL	8		/* loaded initial */

#define HULL		0
#define RIGGING		1

#define W_CAPTAIN	1
#define W_CAPTURED	2
#define W_CLASS		3
#define W_CREW		4
#define W_DBP		5
#define W_DRIFT		6
#define W_EXPLODE	7
#define W_FILE		8
#define W_FOUL		9
#define W_GUNL		10
#define W_GUNR		11
#define W_HULL		12
#define W_MOVE		13
#define W_OBP		14
#define W_PCREW		15
#define W_UNFOUL	16
#define W_POINTS	17
#define W_QUAL		18
#define W_UNGRAP	19
#define W_RIGG		20
#define W_COL		21
#define W_DIR		22
#define W_ROW		23
#define W_SIGNAL	24
#define W_SINK		25
#define W_STRUCK	26
#define W_TA		27
#define W_ALIVE		28
#define W_TURN		29
#define W_WIND		30
#define W_FS		31
#define W_GRAP		32
#define W_RIG1		33
#define W_RIG2		34
#define W_RIG3		35
#define W_RIG4		36
#define W_BEGIN		37
#define W_END		38
#define W_DDEAD		39

#define NLOG 10
struct logs {
	char l_name[20];
	int l_uid;
	int l_shipnum;
	int l_gamenum;
	int l_netpoints;
};

struct BP {
	short turnsent;
	struct ship *toship;
	short mensent;
};

struct snag {
	short sn_count;
	short sn_turn;
};

#define NSCENE	nscene
#define NSHIP	10
#define NBP	3

#define NNATION	8
#define N_A	0
#define N_B	1
#define N_S	2
#define N_F	3
#define N_J	4
#define N_D	5
#define N_K	6
#define N_O	7

struct File {
	int index;
	char captain[20];		/* 0 */
	short points;			/* 20 */
	char loadL;			/* 22 */
	char loadR;			/* 24 */
	char readyL;			/* 26 */
	char readyR;			/* 28 */
	struct BP OBP[NBP];		/* 30 */
	struct BP DBP[NBP];		/* 48 */
	char struck;			/* 66 */
	struct ship *captured;		/* 68 */
	short pcrew;			/* 70 */
	char movebuf[10];		/* 72 */
	char drift;			/* 82 */
	short nfoul;
	short ngrap;
	struct snag foul[NSHIP];	/* 84 */
	struct snag grap[NSHIP];	/* 124 */
	char RH;			/* 224 */
	char RG;			/* 226 */
	char RR;			/* 228 */
	char FS;			/* 230 */
	char explode;			/* 232 */
	char sink;			/* 234 */
	char dir;
	short col;
	short row;
	char loadwith;
	char stern;
};

struct ship {
	char *shipname;			/* 0 */
	struct shipspecs *specs;	/* 2 */
	char nationality;		/* 4 */
	short shiprow;			/* 6 */
	short shipcol;			/* 8 */
	char shipdir;			/* 10 */
	struct File *file;		/* 12 */
};

struct scenario {
	char winddir;			/* 0 */
	char windspeed;			/* 2 */
	char windchange;		/* 4 */
	char vessels;			/* 12 */
	char *name;			/* 14 */
	struct ship ship[NSHIP];	/* 16 */
};
struct scenario scene[];
int nscene;

struct shipspecs {
	char bs;
	char fs;
	char ta;
	short guns;
	char class;
	char hull;
	char qual;
	char crew1;
	char crew2;
	char crew3;
	char gunL;
	char gunR;
	char carL;
	char carR;
	char rig1;
	char rig2;
	char rig3;
	char rig4;
	short pts;
};
struct shipspecs specs[];

struct scenario *cc;		/* the current scenario */
struct ship *ls;		/* &cc->ship[cc->vessels] */

#define SHIP(s)		(&cc->ship[s])
#define foreachship(sp)	for ((sp) = cc->ship; (sp) < ls; (sp)++)

struct windeffects {
	char A, B, C, D;
};
struct windeffects WET[7][6];

struct Tables {
	char H, G, C, R;
};
struct Tables RigTable[11][6];
struct Tables HullTable[11][6];

char AMMO[9][4];
char HDT[9][10];
char HDTrake[9][10];
char QUAL[9][5];
char MT[9][3];

char *countryname[];
char *classname[];
char *directionname[];
char *qualname[];
char loadname[];

char rangeofshot[];

char dr[], dc[];

int winddir;
int windspeed;
int turn;
int game;
int alive;
int people;
char isplayer;
char hasdriver;

char *info();
char *quality();
double arctan();
char *saywhat();
struct ship *closestenemy();

char *calloc();
char *strcpy();
char *strcat();
char *strncpy();
char *getenv();
char *gets();
SHAR_EOF
if test 5280 -ne "`wc -c sail/externs.h`"
then
echo shar: error transmitting sail/externs.h '(should have been 5280 characters)'
fi
cat << \SHAR_EOF > sail/machdep.h
/*
 * sccsid = "@(#)machdep.h	2.5 4/28/84";
 */
#define LOGFILE "/usr/games/lib/saillog"
#define DRIVER1 "driver"
#define DRIVER2 "/usr/games/lib/saildriver"
#define DRIVER3 "/usr/public/.driver"
#define DRIVERNAME "driver"
#define SETUID			/* player and driver run setuid */

#define TIMEOUT 300		/* Sync() time out */

#define BUFSIZE 4096

/* for 4.2bsd machines */
#define blockalarm()	((void) sigblock(1 << SIGALRM-1))
#define unblockalarm()	((void) sigsetmask(sigblock(0) & ~(1 << SIGALRM-1)))

/* for 2.9bsd machines (onyx)
typedef int void;
#define blockalarm()	((void) sighold(SIGALRM))
#define unblockalarm()	((void) sigrelse(SIGALRM))
*/
SHAR_EOF
if test 649 -ne "`wc -c sail/machdep.h`"
then
echo shar: error transmitting sail/machdep.h '(should have been 649 characters)'
fi
cat << \SHAR_EOF > sail/sail.6
.. @(#)sail.6	2.3 83/11/18
.TH SAIL PUBLIC 
.UC 4
.SH NAME
sail \- multi-user wooden ships and iron men
.SH SYNOPSIS
.B sail
[
.B num
]
.br
.fi
.SH DESCRIPTION
.I Sail
is a computer version of Avalon Hill's game of fighting sail
originally developed by S. Craig Taylor.
.PP
Players of
.I Sail
take command of an old fashioned Man of War and fight other
players or the computer.  They may re-enact one of the many
historical sea battles recorded in the game, or they can choose
a fictional battle.
.PP
As a sea captain in the 
.I Sail
Navy, the player has complete control over the workings of his ship.
He must order every maneuver, change the set of his sails, and judge the
right moment to let loose the terrible destruction of his broadsides.
In addition to fighting the enemy, he must harness the powers of the wind
and sea to make them work for him.  The outcome of many battles during the
age of sail was decided by the ability of one captain to hold the `weather
gage.'
.SH IMPLEMENTATION
.I Sail
is really two programs in one.  Each player starts up a process which
runs his own ship.  In addition, a
.I driver
program is execl'd (by the first player) to run the computer ships
and take care of global bookkeeping.
.PP
Because the
.I driver
must calculate moves for each ship it controls, the
more ships the computer is playing, the slower the game will appear.
.PP
If a player joins a game in progress, he will synchronize
with the other players (a rather slow process for everyone), and 
then he may play along with the rest.
.PP
To implement a multi-user game in Version 7 UNIX, which was the operating
system
.I Sail
was first written under, the communicating processes must use a common
temporary file as a place to read and write messages.  In addition, a
locking mechanism must be provided to ensure exclusive access to the
shared file.  For example,
.I Sail
uses a temporary file named /tmp/#sailsink.21 for scenario 21, and
corresponding file names for the other scenarios.  To provide exclusive
access to the temporary file, 
.I Sail
uses a technique stolen from an old game called "pubcaves" by Jeff Cohen.
Processes do a busy wait in the loop
.br
.sp
.ce 2
	for (n = 0; link(sync_file, sync_lock) < 0 && n < 30; n++)
		sleep(2);
.br
.sp
until they are able to create a link to a file named "/tmp/#saillock.??".
The "??" correspond to the scenario number of the game.  Since UNIX 
guarantees that a link will point to only one file, the process that succeeds
in linking will have exclusive access to the temporary file.
.PP
Whether or not this really works is open to speculation.  When ucbmiro
was rebooted after a crash, the file system check program found 3 links
between the
.I Sail
temporary file and its link file.
.SH CONSEQUENCES OF SEPARATE PLAYER AND DRIVER PROCESSES
When players do something of global interest, such as moving or firing,
the driver must coordinate the action with the other ships in the game.
For example, if a player wants to move in a certain direction, he writes a
message into the temporary file requesting the driver to move his ship.
Each ``turn,'' the driver reads all the messages sent from the players and
decides what happened.  It then writes back into the temporary file new
values of variables, etc.
.PP
The most noticeable effect this communication has on the game is the
delay in moving.  Suppose a player types a move for his ship and hits
return.  What happens then?  The player process saves up messages to
be written to the temporary file in a buffer.  Every 7 seconds or so, the
player process gets exclusive access to the temporary file and writes 
out its buffer to the file.  The driver, running asynchronously, must
read in the movement command, process it, and write out the results.  This
takes two exclusive accesses to the temporary file.  Finally, when the player 
process gets around to doing another 7 second update, the results of the
move are displayed on the screen.  Hence, every movement requires four
exclusive accesses to the temporary file (anywhere from 7 to 21 seconds
depending upon asynchrony) before the player sees the results of his moves.
.PP
In practice, the delays are not as annoying as they would appear.  There
is room for "pipelining" in the movement.  After the player writes out
a first movement message, a second movement command can then be issued.
The first message will be in the temporary file waiting for the driver, and
the second will be in the file buffer waiting to be written to the file.
Thus, by always typing moves a turn ahead of the time, the player can
sail around quite quickly.
.PP
If the player types several movement commands between two 7 second updates,
only the last movement command typed will be seen by the driver.  Movement
commands within the same update "overwrite" each other, in a sense.
.SH THE HISTORY OF SAIL 
I wrote the first version of
.I Sail
on a PDP 11/70 in the fall of 1980.  Needless to say, the code was horrendous,
not portable in any sense of the word, and didn't work.  The program was not
very modular and had fseeks() and fwrites() every few lines.  After a
tremendous rewrite from the top down, I got the first working version up by
1981.  There were several annoying bugs concerning firing broadsides and
finding angles.
.I Sail
uses no floating point, by the way, so the direction routines are rather 
tricky.
Ed Wang rewrote my angle() routine in 1981 to be more correct (although
it still doesn't work perfectly), and he added code to let a player select
which ship he wanted at the start of the game (instead of the first one
available).
.PP
Captain Happy (Craig Leres) is responsible for making
.I Sail
portable for the first time.  This was no easy task, by the way.  Constants
like 2 and 10 were very frequent in the code.  I also became famous for
using "Riggle Memorial Structures" in
.I Sail.
Many of my structure references are so long that they run off the line
printer page.  Here is an example, if you promise not to laugh.
.br
.sp
.ce
specs[scene[flog.fgamenum].ship[flog.fshipnum].shipnum].pts
.br
.sp
.PP
.I Sail
received its fourth and most thorough rewrite in the summer and fall
of 1983.  Ed Wang rewrote and modularized the code (a monumental feat)
almost from scratch.  Although he introduced many new bugs, the final
result was very much cleaner and (?) faster.  He added window movement
commands and find ship commands.
.SH HISTORICAL INFO
Old Square Riggers were very maneuverable ships capable of intricate
sailing.  Their only disadvantage was an inability to sail very 
close to the wind.  The design of a wooden ship allowed only for the
guns to bear to the left and right sides.  A few guns of small
aspect (usually 6 or 9 pounders) could point forward, but their
effect was small compared to a 68 gun broadside of 24 or 32 pounders.
The guns bear approximately like so:
.nf

       \\
        b----------------
    ---0
        \\
         \\
          \\     up to a range of ten (for round shot)
           \\
            \\
             \\

.fi
An interesting phenomenon occurred when a broadside was fired
down the length of an enemy ship.  The shot tended to bounce along
the deck and did several times more damage.  This phenomenon was called
a rake.  Because the bows of a ship are very strong and present a smaller
target than the stern, a stern rake (firing from the stern to the bow) causes
more damage than a bow rake.
.nf

                        b
                       00   ----  Stern rake!
                         a

.fi
Most ships were equipped with carronades, which were very large, close
range cannons.  American ships from the revolution until the War of 1812
were almost entirely armed with carronades.
.PP
The period of history covered in
.I Sail
is approximately from the 1770's until the end of Napoleanic France in 1815.
There are many excellent books about the age of sail.  My favorite author
is Captain Frederick Marryat.  More contemporary authors include C.S. Forester
and Alexander Kent.
.PP
Fighting ships came in several sizes classed by armament.  The mainstays of
any fleet were its "Ships of the Line", or "Line of Battle Ships".  They
were so named because these ships fought together in great lines.  They were
close enough for mutual support, yet every ship could fire both its broadsides.
We get the modern words "ocean liner," or "liner," and "battleship" from
"ship of the line."  The most common size was the the 74 gun two decked
ship of the line.  The two gun decks usually mounted 18 and 24 pounder guns.
.PP
The pride of the fleet were the first rates.  These were huge three decked
ships of the line mounting 80 to 136 guns.  The guns in the three tiers
were usually 18, 24, and 32 pounders in that order from top to bottom.
.PP
Various other ships came next.  They were almost all "razees," or ships
of the line with one deck sawed off.  They mounted 40-64 guns and were
a poor cross between a frigate and a line of battle ship.  They neither
had the speed of the former nor the firepower of the latter.
.PP
Next came the "eyes of the fleet."  Frigates came in many sizes mounting
anywhere from 32 to 44 guns.  They were very handy vessels.  They could
outsail anything bigger and outshoot anything smaller.  Frigates didn't
fight in lines of battle as the much bigger 74's did.  Instead, they
harassed the enemy's rear or captured crippled ships.  They were much
more useful in missions away from the fleet, such as cutting out expeditions
or boat actions.  They could hit hard and get away fast.
.PP
Lastly, there were the corvettes, sloops, and brigs.  These were smaller
ships mounting typically fewer than 20 guns.  A corvette was only slightly
smaller than a frigate, so one might have up to 30 guns.  Sloops were used
for carrying dispatches or passengers.  Brigs were something you built for 
land-locked lakes.
.SH SAIL PARTICULARS
Ships in
.I Sail
are represented by two characters.  One character represents the bow of
the ship, and the other represents the stern.  Ships have nationalities
and numbers.  The first ship of a nationality is number 0, the second
number 1, etc.  Therefore, the first British ship in a game would be
printed as "b0".  The second Brit would be "b1", and the fifth Don
would be "s4".  
.PP
Ships can set normal sails, called Battle Sails, or bend on extra canvas
called Full Sails.  A ship under full sail is a beautiful sight indeed,
and it can move much faster than a ship under Battle Sails.  The only
trouble is, with full sails set, there is so much tension on sail and
rigging that a well aimed round shot can burst a sail into ribbons where
it would only cause a little hole in a loose sail.  For this reason,
rigging damage is doubled on a ship with full sails set.  Don't let
that discourage you from using full sails.  I like to keep them up
right into the heat of battle.  A ship
with full sails set has a capital letter for its nationality.  E.g.
a Frog, "f0", with full sails set would be printed as "F0".
.PP
When a ship is battered into a listing hulk, the last man aboard "strikes
the colors."  This ceremony is the ship's formal surrender.  The nationality
character
of a surrendered ship is printed as "!".  E.g. the Frog of our last example
would soon be "!0".
.PP
A ship has a random chance of catching fire or sinking when it reaches the
stage of listing hulk.  A sinking ship has a "~" printed for its nationality,
and a ship on fire and about to explode has a "#" printed.
.PP
Captured ships become the nationality of the prize crew.  Therefore, if
an American ship captures a British ship, the British ship will have an
"a" printed for its nationality.  In addition, the ship number is changed
to "&","'", "(", ,")", "*", or "+" depending upon the original number,
be it 0,1,2,3,4, or 5.  E.g. the "b0" captured by an American becomes the
"a&".  The "s4" captured by a Frog becomes the "f*".
.PP
The ultimate example is, of course, an exploding Brit captured by an
American: "#&".
.SH MOVEMENT
Movement is the most confusing part of 
.I Sail
to many.  Ships can head in 8 directions:
.nf

                                 0      0      0
        b       b       b0      b       b       b       0b      b
        0        0                                             0

.fi
The stern of a ship moves when it turns.  The bow remains stationary.
Ships can always turn, regardless of the wind (unless they are becalmed).
All ships drift when they lose headway.  If a ship doesn't move forward
at all for two turns, it will begin to drift.  If a ship has begun to
drift, then it must move forward before it turns, if it plans to do
more than make a right or left turn, which is always possible.
.PP
Movement commands to 
.I Sail
are a string of forward moves and turns.  An example is "l3".  It will
turn a ship left and then move it ahead 3 spaces.  In the drawing above,
the "b0" made 7 successive left turns.  When 
.I Sail
prompts you for a move, it prints three characters of import.  E.g.
.nf
	move (7, 4): 
.fi
The first number is the maximum number of moves you can make,
including turns.  The second number is the maximum number of turns
you can make.  Between the numbers is sometimes printed a quote "'".
If the quote is present, it means that your ship has been drifting, and
you must move ahead to regain headway before you turn (see note above).
Some of the possible moves for the example above are as follows:
.nf

	move (7, 4): 7
	move (7, 4): 1
	move (7, 4): d		/* drift, or do nothing */
	move (7, 4): 6r
	move (7, 4): 5r1
	move (7, 4): 4r1r
	move (7, 4): l1r1r2
	move (7, 4): 1r1r1r1

.fi
Because square riggers performed so poorly sailing into the wind, if at
any point in a movement command you turn into the wind, the movement stops
there.  E.g.
.nf

	move (7, 4): l1l4
	Movement Error;
	Helm: l1l

.fi
Moreover, whenever you make a turn, your movement allowance drops to
min(what's left, what you would have at the new attitude).  In short,
if you turn closer to the wind, you most likely won't be able to sail the
full allowance printed in the "move" prompt.
.PP
Old sailing captains had to keep an eye constantly on the wind.  Captains
in 
.I Sail
are no different.  A ship's ability to move depends on its attitide to the
wind.  The best angle possible is to have the wind off your quarter, that is,
just off the stern.  The direction rose on the side of the screen gives the
possible movements for your ship at all positions to the wind.  Battle
sail speeds are given first, and full sail speeds are given in parenthesis.
.nf

				 0 1(2)
				\\|/
				-^-3(6)
				/|\\
				 | 4(7)
				3(6)  

.fi
Pretend the bow of your ship (the "^") is pointing upward and the wind is
blowing from the bottom to the top of the page.  The
numbers at the bottom "3(6)" will be your speed under battle or full
sails in such a situation.  If the wind is off your quarter, then you
can move "4(7)".  If the wind is off your beam, "3(6)".  If the wind is
off your bow, then you can only move "1(2)".  Facing into the wind, you
can't move at all.  Ships facing into the wind were said to be "in irons".
.SH WINDSPEED AND DIRECTION
The windspeed and direction is displayed as a little weather vane on the
side of the screen.  The number in the middle of the vane indicates the wind
speed, and the + to - indicates the wind direction.  The wind blows from
the + sign (high pressure) to the - sign (low pressure).  E.g.
.nf

				|
				3
				+

.fi
.PP
The wind speeds are 0 = becalmed, 1 = light breeze, 2 = moderate breeze,
3 = fresh breeze, 4 = strong breeze, 5 = gale, 6 = full gale, 7 = hurricane.
If a hurricane shows up, all ships are destroyed.
.SH GRAPPLING AND FOULING
If two ships collide, they run the risk of becoming tangled together.  This
is called "fouling."  Fouled ships are stuck together, and neither can move.
They can unfoul each other if they want to.  Boarding parties can only be
sent across to ships when the antagonists are either fouled or grappled.
.PP
Ships can grapple each other by throwing grapnels into the rigging of
the other.
.PP
The number of fouls and grapples you have are displayed on the upper
right of the screen.
.SH BOARDING
Boarding was a very costly venture in terms of human life.  Boarding parties
may be formed in 
.I Sail
to either board an enemy ship or to defend your own ship against attack.
Men organized as Defensive Boarding Parties fight twice as hard to save
their ship as men left unorganized.
.PP
The boarding strength of a crew depends upon its quality and upon the
number of men sent.
.SH CREW QUALITY
The British seaman was world renowned for his sailing abilities.  American
sailors, however, were actually the best seamen in the world.  Because the
American Navy offered twice the wages of the Royal Navy, British seamen 
who liked the sea defected to America by the thousands.
.PP
In 
.I Sail,
crew quality is quantized into 5 energy levels.  "Elite" crews can outshoot
and outfight all other sailors.  "Crack" crews are next.  "Mundane" crews
are average, and "Green" and "Mutinous" crews are below average.  A good
rule of thumb is that "Crack" or "Elite" crews get one extra hit
per broadside compared to "Mundane" crews.  Don't expect too much from
"Green" crews.
.SH BROADSIDES
Your two broadsides may be loaded with four kinds of shot: grape, chain,
round, and double.  You have guns and carronades in both the port and starboard
batteries.  Carronades only have a range of two, so you have to get in
close to be able to fire them.  You have the choice of firing at the hull
or rigging of another ship.  If the range of the ship is greater than 6,
then you may only shoot at the rigging.
.PP
The types of shot and their advantages are:
.SH ROUND
Range of 10.  Good for hull or rigging hits.
.SH DOUBLE
Range of 1.  Extra good for hull or rigging hits.
Double takes two turns to load.
.SH CHAIN
Range of 3.  Excellent for tearing down rigging.
Cannot damage hull or guns, though.
.SH GRAPE
Range of 1.  Sometimes devastating against enemy crews.
.PP
On the side of the screen is displayed some vital information about your
ship:
.nf

			Load  D! R!
			Hull  9  
			Crew  4  4  2
			Guns  4  4  
			Carr  2  2 
			Rigg  5 5 5 5

.fi
"Load" shows what your port (left) and starboard (right) broadsides are
loaded with.  A "!" after the type of shot indicates that it is an initial
broadside.  Initial broadside were loaded with care before battle and before
the decks ran red with blood.  As a consequence, initial broadsides are a
little more effective than broadsides loaded later.  A "*" after the type of
shot indicates that the gun
crews are still loading it, and you cannot fire yet.  "Hull" shows how much
hull you have left.  "Crew" shows your three sections of crew.  As your
crew dies off, your ability to fire decreases.  "Guns" and "Carr" show
your port and starboard guns.  As you lose guns, your ability to fire
decreases.  "Rigg" shows how much rigging you have on your 3 or 4 masts.
As rigging is shot away, you lose mobility.
.SH EFFECTIVENESS OF FIRE
It is very dramatic when a ship fires its thunderous broadsides, but the
mere opportunity to fire them does not guarantee any hits.  Many factors
influence the destructive force of a broadside.  First of all, and the chief
factor, is distance.  It is harder to hit a ship at range ten than it is
to hit one sloshing alongside.  Next is raking.  Raking fire, as
mentioned before, 
can sometimes dismast a ship at range ten.  Next, crew size and quality affects
the damage done by a broadside.   The number of guns firing also bears on the
point,
so to speak.  Lastly, weather affects the accuracy of a broadside.  If the
seas are high (5 or 6), then the lower gunports of ships of the line can't
even be opened to run out the guns.  This gives frigates and other flush
decked vessels an advantage in a storm.  The scenario 
.I Pellew vs. The Droits de L'Homme
takes advantage of this peculiar circumstance.
.SH REPAIRS
Repairs may be made to your Hull, Guns, and Rigging at the slow rate of
two points per three turns.  The message "Repairs Completed" will be
printed if no more repairs can be made.
.SH PECULIARITIES OF COMPUTER SHIPS
Computer ships in 
.I Sail
follow all the rules above with a few exceptions.  Computer ships never
repair damage.  If they did, the players could never beat them.  They
play well enough as it is.  As a consolation, the computer ships can fire double
shot every turn.  That fluke is a good reason to keep your distance.  The
.I
Driver
figures out the moves of the computer ships.   It computes them with a typical
A.I. distance function and a depth first search to find the maximum "score."
It seems to work fairly well, although I'll be the first to admit it isn't
perfect.
.SH HOW TO PLAY
Commands are given to 
.I Sail
by typing a single character.  You will then be prompted for further
input.  A brief summary of the commands follows.
.bp
.SH COMMAND SUMMARY
.nf

    'f'  Fire broadsides if they bear
    'l'  Reload
    'L'  Unload broadsides (to change ammo)
    'm'  Move 
    'i'  Print the closest ship
    'I'  Print all ships
    'F'  Find a particular ship or ships (e.g. "a?" for all Americans)
    's'  Send a message around the fleet
    'b'  Attempt to board an enemy ship
    'B'  Recall boarding parties
    'c'  Change set of sail
    'r'  Repair
    'u'  Attempt to unfoul
    'g'  Grapple/ungrapple
    'v'  Print version number of game
   '^L'  Redraw screen
    'Q'  Quit

    'C'      Center your ship in the window
    'U'	     Move window up
    'D','N'  Move window down
    'H'	     Move window left
    'J'	     Move window right
    'S'      Toggle window to follow your ship or stay where it is

.fi
.bg
.SH SCENARIOS
Here is a summary of the scenarios in 
.I Sail:

.br
.SH Ranger vs. Drake:
.nf
Wind from the N, blowing a fresh breeze.

(a) Ranger            19 gun Sloop (crack crew) (7 pts)
(b) Drake             17 gun Sloop (crack crew) (6 pts)
.SH The Battle of Flamborough Head:
.nf
Wind from the S, blowing a fresh breeze.

.fi
This is John Paul Jones' first famous battle.  Aboard the Bonhomme
Richard, he was able to overcome the Serapis's greater firepower
by quickly boarding her.
.nf

(a) Bonhomme Rich     42 gun Corvette (crack crew) (11 pts)
(b) Serapis           44 gun Frigate (crack crew) (12 pts)
.SH Arbuthnot and Des Touches:
.nf
Wind from the N, blowing a gale.

(b) America           64 gun Ship of the Line (crack crew) (20 pts)
(b) Befford           74 gun Ship of the Line (crack crew) (26 pts)
(b) Adamant           50 gun Ship of the Line (crack crew) (17 pts)
(b) London            98 gun 3 Decker SOL (crack crew) (28 pts)
(b) Royal Oak         74 gun Ship of the Line (crack crew) (26 pts)
(f) Neptune           74 gun Ship of the Line (average crew) (24 pts)
(f) Duc Bougogne      80 gun 3 Decker SOL (average crew) (27 pts)
(f) Conquerant        74 gun Ship of the Line (average crew) (24 pts)
(f) Provence          64 gun Ship of the Line (average crew) (18 pts)
(f) Romulus           44 gun Ship of the Line (average crew) (10 pts)
.SH Suffren and Hughes:
.nf

Wind from the S, blowing a fresh breeze.

(b) Monmouth          74 gun Ship of the Line (average crew) (24 pts)
(b) Hero              74 gun Ship of the Line (crack crew) (26 pts)
(b) Isis              50 gun Ship of the Line (crack crew) (17 pts)
(b) Superb            74 gun Ship of the Line (crack crew) (27 pts)
(b) Burford           74 gun Ship of the Line (average crew) (24 pts)
(f) Flamband          50 gun Ship of the Line (average crew) (14 pts)
(f) Annibal           74 gun Ship of the Line (average crew) (24 pts)
(f) Severe            64 gun Ship of the Line (average crew) (18 pts)
(f) Brilliant         80 gun Ship of the Line (crack crew) (31 pts)
(f) Sphinx            80 gun Ship of the Line (average crew) (27 pts)
.SH Nymphe vs. Cleopatre:
.nf
Wind from the S, blowing a fresh breeze.

(b) Nymphe            36 gun Frigate (crack crew) (11 pts)
(f) Cleopatre         36 gun Frigate (average crew) (10 pts)
.SH Mars vs. Hercule:
Wind from the S, blowing a fresh breeze.
.nf
(b) Mars              74 gun Ship of the Line (crack crew) (26 pts)
(f) Hercule           74 gun Ship of the Line (average crew) (23 pts)
.SH Ambuscade vs. Baionnaise:
.nf
Wind from the N, blowing a fresh breeze.

(b) Ambuscade         32 gun Frigate (average crew) (9 pts)
(f) Baionnaise        24 gun Corvette (average crew) (9 pts)
.SH Constellation vs. Insurgent:
.nf
Wind from the S, blowing a gale.

(a) Constellation     38 gun Corvette (elite crew) (17 pts)
(f) Insurgent         36 gun Corvette (average crew) (11 pts)
.SH Constellation vs. Vengeance:
.nf
Wind from the S, blowing a fresh breeze.

(a) Constellation     38 gun Corvette (elite crew) (17 pts)
(f) Vengeance         40 gun Frigate (average crew) (15 pts)
.SH The Battle of Lissa:
.nf
Wind from the S, blowing a fresh breeze.

(b) Amphion           32 gun Frigate (elite crew) (13 pts)
(b) Active            38 gun Frigate (elite crew) (18 pts)
(b) Volage            22 gun Frigate (elite crew) (11 pts)
(b) Cerberus          32 gun Frigate (elite crew) (13 pts)
(f) Favorite          40 gun Frigate (average crew) (15 pts)
(f) Flore             40 gun Frigate (average crew) (15 pts)
(f) Danae             40 gun Frigate (crack crew) (17 pts)
(f) Bellona           32 gun Frigate (green crew) (9 pts)
(f) Corona            40 gun Frigate (green crew) (12 pts)
(f) Carolina          32 gun Frigate (green crew) (7 pts)
.SH Constitution vs. Guerriere:
.nf
Wind from the SW, blowing a gale.

(a) Constitution      44 gun Corvette (elite crew) (24 pts)
(b) Guerriere         38 gun Frigate (crack crew) (15 pts)
.SH United States vs. Macedonian:
.nf
Wind from the S, blowing a fresh breeze.

(a) United States     44 gun Frigate (elite crew) (24 pts)
(b) Macedonian        38 gun Frigate (crack crew) (16 pts)
.SH Constitution vs. Java:
.nf
Wind from the S, blowing a fresh breeze.

(a) Constitution      44 gun Corvette (elite crew) (24 pts)
(b) Java              38 gun Corvette (crack crew) (19 pts)
.SH Chesapeake vs. Shannon:
.nf
Wind from the S, blowing a fresh breeze.

(a) Chesapeake        38 gun Frigate (average crew) (14 pts)
(b) Shannon           38 gun Frigate (elite crew) (17 pts)
.SH The Battle of Lake Erie:
.nf
Wind from the S, blowing a light breeze.

(a) Lawrence          20 gun Sloop (crack crew) (9 pts)
(a) Niagara           20 gun Sloop (elite crew) (12 pts)
(b) Lady Prevost      13 gun Brig (crack crew) (5 pts)
(b) Detroit           19 gun Sloop (crack crew) (7 pts)
(b) Q. Charlotte      17 gun Sloop (crack crew) (6 pts)
.SH Wasp vs. Reindeer:
.nf
Wind from the S, blowing a light breeze.

(a) Wasp              20 gun Sloop (elite crew) (12 pts)
(b) Reindeer          18 gun Sloop (elite crew) (9 pts)
.SH Constitution vs. Cyane and Levant:
.br
Wind from the S, blowing a moderate breeze.

(a) Constitution      44 gun Corvette (elite crew) (24 pts)
(b) Cyane             24 gun Sloop (crack crew) (11 pts)
(b) Levant            20 gun Sloop (crack crew) (10 pts)
.br
.SH Pellew vs. Droits de L'Homme:
.nf
Wind from the N, blowing a gale.

(b) Indefatigable     44 gun Frigate (elite crew) (14 pts)
(b) Amazon            36 gun Frigate (crack crew) (14 pts)
(f) Droits L'Hom      74 gun Ship of the Line (average crew) (24 pts)
.SH Algeciras:
.nf
Wind from the SW, blowing a moderate breeze.

(b) Caesar            80 gun Ship of the Line (crack crew) (31 pts)
(b) Pompee            74 gun Ship of the Line (crack crew) (27 pts)
(b) Spencer           74 gun Ship of the Line (crack crew) (26 pts)
(b) Hannibal          98 gun 3 Decker SOL (crack crew) (28 pts)
(s) Real-Carlos       112 gun 3 Decker SOL (green crew) (27 pts)
(s) San Fernando      96 gun 3 Decker SOL (green crew) (24 pts)
(s) Argonauta         80 gun Ship of the Line (green crew) (23 pts)
(s) San Augustine     74 gun Ship of the Line (green crew) (20 pts)
(f) Indomptable       80 gun Ship of the Line (average crew) (27 pts)
(f) Desaix            74 gun Ship of the Line (average crew) (24 pts)
.SH Lake Champlain:
.nf
Wind from the N, blowing a fresh breeze.

(a) Saratoga          26 gun Sloop (crack crew) (12 pts)
(a) Eagle             20 gun Sloop (crack crew) (11 pts)
(a) Ticonderoga       17 gun Sloop (crack crew) (9 pts)
(a) Preble            7 gun Brig (crack crew) (4 pts)
(b) Confiance         37 gun Frigate (crack crew) (14 pts)
(b) Linnet            16 gun Sloop (elite crew) (10 pts)
(b) Chubb             11 gun Brig (crack crew) (5 pts)
.SH Last Voyage of the USS President:
.nf
Wind from the N, blowing a fresh breeze.

(a) President         44 gun Frigate (elite crew) (24 pts)
(b) Endymion          40 gun Frigate (crack crew) (17 pts)
(b) Pomone            44 gun Frigate (crack crew) (20 pts)
(b) Tenedos           38 gun Frigate (crack crew) (15 pts)
.SH Hornblower and the Natividad:
.nf
Wind from the E, blowing a gale.

.fi
A scenario for you Horny fans.  Remember, he sank the Natividad
against heavy odds and winds.  Hint: don't try to board the Natividad,
her crew is much bigger, albeit green.
.nf

(b) Lydia             36 gun Frigate (elite crew) (13 pts)
(s) Natividad         50 gun Ship of the Line (green crew) (14 pts)
.SH Curse of the Flying Dutchman:
.nf
Wind from the S, blowing a fresh breeze.

Just for fun, take the Piece of cake.

(s) Piece of Cake     24 gun Corvette (average crew) (9 pts)
(f) Flying Dutchy     120 gun 3 Decker SOL (elite crew) (43 pts)
.SH The South Pacific:
.nf
Wind from the S, blowing a strong breeze.

(a) USS Scurvy        136 gun 3 Decker SOL (mutinous crew) (27 pts)
(b) HMS Tahiti        120 gun 3 Decker SOL (elite crew) (43 pts)
(s) Australian        32 gun Frigate (average crew) (9 pts)
(f) Bikini Atoll      7 gun Brig (crack crew) (4 pts)
.SH Hornblower and the battle of Rosas bay:
.nf
Wind from the E, blowing a fresh breeze.

The only battle Hornblower ever lost.  He was able to dismast one
ship and stern rake the others though.  See if you can do as well.
.nf

(b) Sutherland        74 gun Ship of the Line (crack crew) (26 pts)
(f) Turenne           80 gun 3 Decker SOL (average crew) (27 pts)
(f) Nightmare         74 gun Ship of the Line (average crew) (24 pts)
(f) Paris             112 gun 3 Decker SOL (green crew) (27 pts)
(f) Napolean          74 gun Ship of the Line (green crew) (20 pts)
.SH Cape Horn:
.nf
Wind from the NE, blowing a strong breeze.

(a) Concord           80 gun Ship of the Line (average crew) (27 pts)
(a) Berkeley          98 gun 3 Decker SOL (crack crew) (28 pts)
(b) Thames            120 gun 3 Decker SOL (elite crew) (43 pts)
(s) Madrid            112 gun 3 Decker SOL (green crew) (27 pts)
(f) Musket            80 gun 3 Decker SOL (average crew) (27 pts)
.SH New Orleans:
.nf
Wind from the SE, blowing a fresh breeze.

Watch that little Cypress go!

(a) Alligator         120 gun 3 Decker SOL (elite crew) (43 pts)
(b) Firefly           74 gun Ship of the Line (crack crew) (27 pts)
(b) Cypress           44 gun Frigate (elite crew) (14 pts)
.SH Botany Bay:
.nf
Wind from the N, blowing a fresh breeze.

(b) Shark             64 gun Ship of the Line (average crew) (18 pts)
(f) Coral Snake       44 gun Corvette (elite crew) (24 pts)
(f) Sea Lion          44 gun Frigate (elite crew) (24 pts)
.SH Voyage to the Bottom of the Sea:
.nf
Wind from the NW, blowing a fresh breeze.

This one is dedicated to Richard Basehart and David Hedison.

(a) Seaview           120 gun 3 Decker SOL (elite crew) (43 pts)
(a) Flying Sub        40 gun Frigate (crack crew) (17 pts)
(b) Mermaid           136 gun 3 Decker SOL (mutinous crew) (27 pts)
(s) Giant Squid       112 gun 3 Decker SOL (green crew) (27 pts)
.SH Frigate Action:
.nf
Wind from the E, blowing a fresh breeze.

(a) Killdeer          40 gun Frigate (average crew) (15 pts)
(b) Sandpiper         40 gun Frigate (average crew) (15 pts)
(s) Curlew            38 gun Frigate (crack crew) (16 pts)
.SH The Battle of Midway:
.nf
Wind from the E, blowing a moderate breeze.

(a) Enterprise        80 gun Ship of the Line (crack crew) (31 pts)
(a) Yorktown          80 gun Ship of the Line (average crew) (27 pts)
(a) Hornet            74 gun Ship of the Line (average crew) (24 pts)
(j) Akagi             112 gun 3 Decker SOL (green crew) (27 pts)
(j) Kaga              96 gun 3 Decker SOL (green crew) (24 pts)
(j) Soryu             80 gun Ship of the Line (green crew) (23 pts)

.SH Star Trek:
.nf
Wind from the S, blowing a fresh breeze.

(a) Enterprise        450 gun Ship of the Line (elite crew) (75 pts)
(a) Yorktown          450 gun Ship of the Line (elite crew) (75 pts)
(a) Reliant           450 gun Ship of the Line (elite crew) (75 pts)
(a) Galileo           450 gun Ship of the Line (elite crew) (75 pts)
(k) Kobayashi Maru    450 gun Ship of the Line (elite crew) (75 pts)
(k) Klingon II        450 gun Ship of the Line (elite crew) (75 pts)
(o) Red Orion         450 gun Ship of the Line (elite crew) (75 pts)
(o) Blue Orion        450 gun Ship of the Line (elite crew) (75 pts)

.SH CONCLUSION

.I Sail
has been a group effort.

.SH "Ken Arnold Code"
curses library (pu!)
.SH AUTHOR
Dave Riggle
.SH CO-AUTHOR
Ed Wang 
.SH REFITTING
Craig Leres
.SH CONSULTANTS
.nf
Chris Guthrie
Captain Happy
Horatio Nelson
Nancy Reagan
	and many valiant others...
.fi
.SH "REFERENCES"
.nf
Wooden Ships & Iron Men, by Avalon Hill
Captain Horatio Hornblower Novels, (13 of them) by C.S. Forester
Captain Richard Bolitho Novels, (12 of them) by Alexander Kent
The Complete Works of Captain Frederick Marryat, (about 20) especially
	Mr. Midshipman Easy
	Peter Simple
	Jacob Faithful
	Japhet in Search of a Father
	Snarleyyow, or The Dog Fiend
	Frank Mildmay, or The Naval Officer
.fi
.SH "SEE ALSO"
midway(PUBLIC)
.SH BUGS
Probably a few, and please report them to "riggle@ernie" and "edward@arpa."
SHAR_EOF
if test 33830 -ne "`wc -c sail/sail.6`"
then
echo shar: error transmitting sail/sail.6 '(should have been 33830 characters)'
fi
#	End of shell archive
exit 0

yee@ucbvax.ARPA (Peter E. Yee) (01/24/85)

This is part 4 of the SAIL distribution.

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
-----cut here-----cut here-----cut here-----cut here-----
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	sail/assorted.c
#	sail/boarders.c
#	sail/game.c
#	sail/globals.c
#	sail/grap.c
#	sail/misc.c
#	sail/parties.c
#	sail/sail.log.c
#	sail/sync.c
#	sail/version.c
# This archive created: Wed Jan 23 19:50:19 1985
cat << \SHAR_EOF > sail/assorted.c
#ifndef lint
static	char *sccsid = "@(#)assorted.c	2.4 84/02/03";
#endif

#include "externs.h"

table(rig, shot, hittable, on, from, roll)
struct ship *on, *from;
int rig, shot, hittable, roll;
{
	register int hhits = 0, chits = 0, ghits = 0, rhits = 0;
	int Ghit = 0, Hhit = 0, Rhit = 0, Chit = 0;
	int guns, car, pc, hull;
	int crew[3];
	register int n;
	int rigg[4];
	char *message;
	struct Tables *tp;

	pc = on->file->pcrew;
	hull = on->specs->hull;
	crew[0] = on->specs->crew1;
	crew[1] = on->specs->crew2;
	crew[2] = on->specs->crew3;
	rigg[0] = on->specs->rig1;
	rigg[1] = on->specs->rig2;
	rigg[2] = on->specs->rig3;
	rigg[3] = on->specs->rig4;
	if (shot == L_GRAPE)
		Chit = chits = hittable;
	else {
		tp = &(rig ? RigTable : HullTable)[hittable][roll-1];
		Chit = chits = tp->C;
		Rhit = rhits = tp->R;
		Hhit = hhits = tp->H;
		Ghit = ghits = tp->G;
		if (on->file->FS)
			rhits *= 2;
		if (shot == L_CHAIN) {
			Ghit = ghits = 0;
			Hhit = hhits = 0;
		}
	}
	if (on->file->captured != 0) {
		pc -= (chits + 1) / 2;
		chits /= 2;
	}
	for (n = 0; n < 3; n++)
		if (chits > crew[n]) {
			chits -= crew[n];
			crew[n] = 0;
		} else {
			crew[n] -= chits;
			chits = 0;
		}
	for (n = 0; n < 3; n++)
		if (rhits > rigg[n]){
			rhits -= rigg[n];
			rigg[n] = 0;
		} else {
			rigg[n] -= rhits;
			rhits = 0;
		}
	if (rigg[3] != -1 && rhits > rigg[3]) {
		rhits -= rigg[3];
		rigg[3] = 0;
	} else if (rigg[3] != -1) {
		rigg[3] -= rhits;
	}
	if (rig && !rigg[2] && (!rigg[3] || rigg[3] == -1))
		makesignal(on, "dismasted!", (struct ship *)0);
	if (portside(from, on, 0)) {
		guns = on->specs->gunR;
		car = on->specs->carR;
	} else {
		guns = on->specs->gunL;
		car = on->specs->carL;
	}
	if (ghits > car) {
		ghits -= car;
		car = 0;
	} else {
		car -= ghits;
		ghits = 0;
	}
	if (ghits > guns){
		ghits -= guns;
		guns = 0;
	} else {
		guns -= ghits;
		ghits = 0;
	}
	hull -= ghits;
	if (Ghit)
		Write(portside(from, on, 0) ? W_GUNR : W_GUNL,
			on, 0, guns, car, 0, 0);
	hull -= hhits;
	hull = hull < 0 ? 0 : hull;
	if (on->file->captured != 0 && Chit)
		Write(W_PCREW, on, 0, pc, 0, 0, 0);
	if (Hhit)
		Write(W_HULL, on, 0, hull, 0, 0, 0);
	if (Chit)
		Write(W_CREW, on, 0, crew[0], crew[1], crew[2], 0);
	if (Rhit)
		Write(W_RIGG, on, 0, rigg[0], rigg[1], rigg[2], rigg[3]);
	switch (shot) {
	case L_ROUND:
		message = "firing round shot on %s (%c%c)";
		break;
	case L_GRAPE:
		message = "firing grape shot on %s (%c%c)";
		break;
	case L_CHAIN:
		message = "firing chain shot on %s (%c%c)";
		break;
	case L_DOUBLE:
		message = "firing double shot on %s (%c%c)";
		break;
	case L_EXPLODE:
		message = "exploding shot on %s (%c%c)";
	}
	makesignal(from, message, on);
	if (roll == 6 && rig) {
		switch(Rhit) {
		case 0:
			message = "fore topsail sheets parted";
			break;
		case 1:
			message = "mizzen shrouds parted";
			break;
		case 2:
			message = "main topsail yard shot away";
			break;
		case 4:
			message = "fore topmast and foremast shrouds shot away";
			break;
		case 5:
			message = "mizzen mast and yard shot through";
			break;
		case 6:
			message = "foremast and spritsail yard shattered";
			break;
		case 7:
			message = "main topmast and mizzen mast shattered";
			break;
		}
		makesignal(on, message, (struct ship *)0);
	} else if (roll == 6) {
		switch (Hhit) {
		case 0:
			message = "anchor cables severed";
			break;
		case 1:
			message = "two anchor stocks shot away";
			break;
		case 2:
			message = "quarterdeck bulwarks damaged";
			break;
		case 3:
			message = "three gun ports shot away";
			break;
		case 4:
			message = "four guns dismounted";
			break;
		case 5:
			message = "rudder cables shot through";
			Write(W_TA, on, 0, 0, 0, 0, 0);
			break;
		case 6:
			message = "shot holes below the water line";
			break;
		}
		makesignal(on, message, (struct ship *)0);
	}
	/*
	if (Chit > 1 && on->file->readyL&R_INITIAL && on->file->readyR&R_INITIAL) {
		on->specs->qual--;
		if (on->specs->qual <= 0) {
			makesignal(on, "crew mutinying!", (struct ship *)0);
			on->specs->qual = 5;
			Write(W_CAPTURED, on, 0, on->file->index, 0, 0, 0);
		} else 
			makesignal(on, "crew demoralized", (struct ship *)0);
		Write(W_QUAL, on, 0, on->specs->qual, 0, 0, 0);
	}
	*/
	if (!hull)
		strike(on, from);
}

Cleansnag(from, to, all, flag)
register struct ship *from, *to;
char all, flag;
{
	if (flag & 1) {
		Write(W_UNGRAP, from, 0, to->file->index, all, 0, 0);
		Write(W_UNGRAP, to, 0, from->file->index, all, 0, 0);
	}
	if (flag & 2) {
		Write(W_UNFOUL, from, 0, to->file->index, all, 0, 0);
		Write(W_UNFOUL, to, 0, from->file->index, all, 0, 0);
	}
	if (!snagged2(from, to)) {
		if (!snagged(from)) {
			unboard(from, from, 1);		/* defense */
			unboard(from, from, 0);		/* defense */
		} else
			unboard(from, to, 0);		/* offense */
		if (!snagged(to)) {
			unboard(to, to, 1);		/* defense */
			unboard(to, to, 0);		/* defense */
		} else
			unboard(to, from, 0);		/* offense */
	}
}

strike(ship, from)
register struct ship *ship, *from;
{
	int points;

	if (ship->file->struck)
		return;
	Write(W_STRUCK, ship, 0, 1, 0, 0, 0);
	points = ship->specs->pts + from->file->points;
	Write(W_POINTS, from, 0, points, 0, 0, 0);
	unboard(ship, ship, 0);		/* all offense */
	unboard(ship, ship, 1);		/* all defense */
	switch (die()) {
	case 3:
	case 4:		/* ship may sink */
		Write(W_SINK, ship, 0, 1, 0, 0, 0);
		break;
	case 5:
	case 6:		/* ship may explode */
		Write(W_EXPLODE, ship, 0, 1, 0, 0, 0);
		break;
	}
	Write(W_SIGNAL, ship, 1, (int) "striking her colours!", 0, 0, 0);
}
SHAR_EOF
if test 5526 -ne "`wc -c sail/assorted.c`"
then
echo shar: error transmitting sail/assorted.c '(should have been 5526 characters)'
fi
cat << \SHAR_EOF > sail/boarders.c
#ifndef lint
static	char *sccsid = "@(#)boarders.c	2.1 83/10/31";
#endif
#include "externs.h"

subtract(from, totalfrom, crewfrom, fromcap, pcfrom)
struct ship *from, *fromcap;
int pcfrom;
register int  totalfrom, crewfrom[3];
{
	register int n;

	if (fromcap == from && totalfrom) {		/* if not captured */
		for (n = 0; n < 3; n++) {
			if (totalfrom > crewfrom[n]) {
				totalfrom -= crewfrom[n];
				crewfrom[n] = 0;
			} else {
				crewfrom[n] -= totalfrom;
				totalfrom = 0;
			}
		}
		Write(W_CREW, from, 0, crewfrom[0], crewfrom[1], crewfrom[2], 0);
	} else if (totalfrom) {
		pcfrom -= totalfrom;
		pcfrom = pcfrom < 0 ? 0 : pcfrom;
		Write(W_PCREW, from, 0, pcfrom, 0, 0, 0);
	}
}

mensent(from, to, crew, captured, pc, isdefense)
struct ship *from, *to, **captured;
int crew[3], *pc;
char isdefense;
{					/* returns # of crew squares sent */
	int men = 0;
	register int n;
	int c1, c2, c3;
	register struct BP *bp;

	*pc = from->file->pcrew;
	*captured = from->file->captured;
	crew[0] = from->specs->crew1;
	crew[1] = from->specs->crew2;
	crew[2] = from->specs->crew3;
	bp = isdefense ? from->file->DBP : from->file->OBP;
	for (n=0; n < NBP; n++, bp++) {
		if (bp->turnsent && bp->toship == to)
			men += bp->mensent;
	}
	if (men) {
		c1 = men/100 ? crew[0] : 0;
		c2 = (men%100)/10 ? crew[1] : 0;
		c3 = men/10 ? crew[2] : 0;
		c3 = *captured == 0 ? crew[2] : *pc;
	} else
		c1 = c2 = c3 = 0;
	return(c1 + c2 + c3);
}
SHAR_EOF
if test 1432 -ne "`wc -c sail/boarders.c`"
then
echo shar: error transmitting sail/boarders.c '(should have been 1432 characters)'
fi
cat << \SHAR_EOF > sail/game.c
#ifndef lint
static	char *sccsid = "@(#)game.c	2.1 83/10/31";
#endif

#include "externs.h"

maxturns(ship, af)
register struct ship *ship;
char *af;
{
	register int turns;

	turns = ship->specs->ta;
	if (*af = (ship->file->drift > 1 && turns)) {
		turns--;
		if (ship->file->FS == 1)
			turns = 0;
	}
	return turns;
}

maxmove(ship, dir, fs)
register struct ship *ship;
int dir, fs;
{
	register int riggone = 0, Move, flank = 0;

	Move = ship->specs->bs;
	if (!ship->specs->rig1)
		riggone++;
	if (!ship->specs->rig2)
		riggone++;
	if (!ship->specs->rig3)
		riggone++;
	if (!ship->specs->rig4)
		riggone++;
	if ((ship->file->FS || fs) && fs != -1) {
		flank = 1;
		Move = ship->specs->fs;
	}
	if (dir == winddir)
		Move -= 1 + WET[windspeed][ship->specs->class-1].B;
	else if (dir == winddir + 2 || dir == winddir - 2 || dir == winddir - 6 || dir == winddir + 6)
		Move -= 1 + WET[windspeed][ship->specs->class-1].C;
	else if (dir == winddir + 3 || dir == winddir - 3 || dir == winddir - 5 || dir == winddir + 5)
		Move = (flank ? 2 : 1) - WET[windspeed][ship->specs->class-1].D;
	else if (dir == winddir + 4 || dir == winddir - 4)
		Move = 0;
	else 
		Move -= WET[windspeed][ship->specs->class-1].A;
	Move -= riggone;
	Move = Move < 0 ? 0 : Move;
	return(Move);
}
SHAR_EOF
if test 1265 -ne "`wc -c sail/game.c`"
then
echo shar: error transmitting sail/game.c '(should have been 1265 characters)'
fi
cat << \SHAR_EOF > sail/globals.c
/*LINTLIBRARY*/
#ifndef lint
static	char *sccsid = "@(#)globals.c	2.1 83/10/31";
#endif

#include "externs.h"

struct scenario scene[] = {
	/*
	 * int winddir;
	 * int windspeed;
	 * int windchange;
	 * int vessels;
	 * char *name;
	 * struct ship ship[NSHIP];
	 */
	5, 3, 5, 2, "Ranger vs. Drake",
	{
		{ "Ranger",		specs+0,  N_A,  7, 20, 4, 0 },
		{ "Drake",		specs+1,  N_B,  7, 31, 5, 0 }
	},
	1, 3, 6, 2, "The Battle of Flamborough Head",
	{
		{ "Bonhomme Rich",	specs+2,  N_A, 13, 40, 2, 0 },
		{ "Serapis",		specs+3,  N_B,  2, 42, 2, 0 }
	},
	5, 5, 5, 10, "Arbuthnot and Des Touches",
	{
		{ "America",		specs+4,  N_B,  7, 37, 4, 0 },
		{ "Befford",		specs+5,  N_B,  5, 35, 4, 0 },
		{ "Adamant",		specs+6,  N_B,  3, 33, 4, 0 },
		{ "London",		specs+7,  N_B,  1, 31, 4, 0 },
		{ "Royal Oak",		specs+8,  N_B, -1, 29, 4, 0 },
		{ "Neptune",		specs+9,  N_F,  6, 44, 4, 0 },
		{ "Duc Bougogne",	specs+10, N_F,  8, 46, 4, 0 },
		{ "Conquerant",		specs+48, N_F, 10, 48, 4, 0 },
		{ "Provence",		specs+11, N_F, 12, 50, 4, 0 },
		{ "Romulus",		specs+12, N_F, 20, 58, 4, 0 }
	},
	1, 3, 5, 10, "Suffren and Hughes",
	{
		{ "Monmouth",		specs+52, N_B,  9, 45, 2, 0 },
		{ "Hero",		specs+5,  N_B, 13, 49, 2, 0 },
		{ "Isis",		specs+6,  N_B, 12, 48, 2, 0 },
		{ "Superb",		specs+50, N_B, 10, 46, 2, 0 },
		{ "Burford",		specs+48, N_B, 11, 47, 2, 0 },
		{ "Flamband",		specs+13, N_F,  7, 59, 4, 0 },
		{ "Annibal",		specs+9,  N_F,  4, 56, 4, 0 },
		{ "Severe",		specs+11, N_F,  2, 54, 4, 0 },
		{ "Brilliant",		specs+49, N_F, -1, 51, 4, 0 },
		{ "Sphinx",		specs+51, N_F, -5, 47, 4, 0 }
	},
	1, 3, 4, 2, "Nymphe vs. Cleopatre",
	{
		{ "Nymphe",		specs+14, N_B, 13, 30, 2, 0 },
		{ "Cleopatre",		specs+15, N_F,  3, 41, 2, 0 }
	},
	1, 3, 5, 2, "Mars vs. Hercule",
	{
		{ "Mars",		specs+16, N_B, 13, 30, 2, 0 },
		{ "Hercule",		specs+17, N_F,  3, 41, 2, 0 }
	},
	5, 3, 5, 2, "Ambuscade vs. Baionnaise",
	{
		{ "Ambuscade",		specs+18, N_B, 13, 30, 2, 0 },
		{ "Baionnaise",		specs+19, N_F,  3, 41, 2, 0 }
	},
	1, 5, 6, 2, "Constellation vs. Insurgent",
	{
		{ "Constellation",	specs+20, N_A,  9, 50, 8, 0 },
		{ "Insurgent",		specs+22, N_F,  4, 24, 2, 0 }
	},
	1, 3, 5, 2, "Constellation vs. Vengeance",
	{
		{ "Constellation",	specs+20, N_A, 12, 40, 2, 0 },
		{ "Vengeance",		specs+21, N_F,  1, 43, 2, 0 }
	},
	1, 3, 6, 10, "The Battle of Lissa",
	{
		{ "Amphion",		specs+23, N_B,  8, 50, 4, 0 },
		{ "Active",		specs+24, N_B,  6, 48, 4, 0 },
		{ "Volage",		specs+25, N_B,  4, 46, 4, 0 },
		{ "Cerberus",		specs+26, N_B,  2, 44, 4, 0 },
		{ "Favorite",		specs+27, N_F,  9, 34, 2, 0 },
		{ "Flore",		specs+21, N_F, 13, 39, 2, 0 },
		{ "Danae",		specs+64, N_F, 15, 37, 2, 0 },
		{ "Bellona",		specs+28, N_F, 17, 35, 2, 0 },
		{ "Corona",		specs+29, N_F, 12, 31, 2, 0 },
		{ "Carolina",		specs+30, N_F, 15, 28, 2, 0 }
	},
	2, 5, 6, 2, "Constitution vs. Guerriere",
	{
		{ "Constitution",	specs+31, N_A,  7, 35, 1, 0 },
		{ "Guerriere",		specs+32, N_B,  7, 47, 4, 0 }
	},
	1, 3, 5, 2, "United States vs. Macedonian",
	{
		{ "United States",	specs+33, N_A,  1, 52, 6, 0 },
		{ "Macedonian",		specs+34, N_B, 14, 40, 1, 0 }
	},
	1, 3, 6, 2, "Constitution vs. Java",
	{
		{ "Constitution",	specs+31, N_A,  1, 40, 2, 0 },
		{ "Java",		specs+35, N_B, 11, 40, 2, 0 }
	},
	1, 3, 5, 2, "Chesapeake vs. Shannon",
	{
		{ "Chesapeake",		specs+36, N_A, 13, 40, 2, 0 },
		{ "Shannon",		specs+37, N_B,  1, 42, 2, 0 }
	},
	1, 1, 6, 5, "The Battle of Lake Erie",
	{
		{ "Lawrence",		specs+38, N_A,  4, 55, 8, 0 },
		{ "Niagara",		specs+42, N_A,  7, 61, 8, 0 },
		{ "Lady Prevost",	specs+39, N_B,  4, 25, 2, 0 },
		{ "Detroit",		specs+40, N_B,  7, 22, 2, 0 },
		{ "Q. Charlotte",	specs+41, N_B, 10, 19, 2, 0 }
	},
	1, 1, 5, 2, "Wasp vs. Reindeer",
	{
		{ "Wasp",		specs+42, N_A,  3, 41, 2, 0 },
		{ "Reindeer",		specs+43, N_B, 10, 48, 2, 0 }
	},
	1, 2, 5, 3, "Constitution vs. Cyane and Levant",
	{
		{ "Constitution",	specs+31, N_A, 10, 45, 2, 0 },
		{ "Cyane",		specs+44, N_B,  3, 37, 2, 0 },
		{ "Levant",		specs+45, N_B,  5, 35, 2, 0 }
	},
	5, 5, 5, 3, "Pellew vs. Droits de L'Homme",
	{
		{ "Indefatigable",	specs+46, N_B, 12, 45, 6, 0 },
		{ "Amazon",		specs+47, N_B,  9, 48, 6, 0 },
		{ "Droits L'Hom",	specs+48, N_F,  3, 28, 5, 0 }
	},
	2, 2, 3, 10, "Algeciras",
	{
		{ "Caesar",		specs+49, N_B,  7, 70, 6, 0 },
		{ "Pompee",		specs+50, N_B,  5, 72, 6, 0 },
		{ "Spencer",		specs+5,  N_B,  3, 74, 6, 0 },
		{ "Hannibal",		specs+7,  N_B,  1, 76, 6, 0 },
		{ "Real-Carlos",	specs+53, N_S,  9, 20, 3, 0 },
		{ "San Fernando",	specs+54, N_S, 11, 16, 3, 0 },
		{ "Argonauta",		specs+55, N_S, 10, 14, 4, 0 },
		{ "San Augustine",	specs+56, N_S,  6, 22, 4, 0 },
		{ "Indomptable",	specs+51, N_F,  7, 23, 5, 0 },
		{ "Desaix",		specs+52, N_F,  7, 27, 7, 0 }
	},
	5, 3, 6, 7, "Lake Champlain",
	{
		{ "Saratoga",		specs+60, N_A,  8, 10, 1, 0 },
		{ "Eagle",		specs+61, N_A,  9, 13, 2, 0 },
		{ "Ticonderoga",	specs+62, N_A, 12, 17, 3, 0 },
		{ "Preble",		specs+63, N_A, 14, 20, 2, 0 },
		{ "Confiance",		specs+57, N_B,  4, 70, 6, 0 },
		{ "Linnet",		specs+58, N_B,  7, 68, 6, 0 },
		{ "Chubb",		specs+59, N_B, 10, 65, 6, 0 }
	},
	5, 3, 6, 4, "Last Voyage of the USS President",
	{
		{ "President",		specs+67, N_A, 12, 42, 5, 0 },
		{ "Endymion",		specs+64, N_B,  5, 42, 5, 0 },
		{ "Pomone",		specs+65, N_B,  7, 82, 6, 0 },
		{ "Tenedos",		specs+66, N_B,  7, -1, 4, 0 }
	},
	7, 5, 5, 2, "Hornblower and the Natividad",
	{
		{ "Lydia",		specs+68, N_B, 12, 40, 2, 0 },
		{ "Natividad",		specs+69, N_S,  2, 40, 4, 0 }
	},
	1, 3, 6, 2, "Curse of the Flying Dutchman",
	{
		{ "Piece of Cake",	specs+19, N_S,  7, 40, 2, 0 },
		{ "Flying Dutchy",	specs+71, N_F,  7, 41, 1, 0 }
	},
	1, 4, 1, 4, "The South Pacific",
	{
		{ "USS Scurvy",		specs+70, N_A,  7, 40, 1, 0 },
		{ "HMS Tahiti",		specs+71, N_B, 12, 60, 1, 0 },
		{ "Australian",		specs+18, N_S,  5, 20, 8, 0 },
		{ "Bikini Atoll",	specs+63, N_F,  2, 60, 4, 0 }
	},
	7, 3, 6, 5, "Hornblower and the battle of Rosas bay",
	{
		{ "Sutherland",		specs+5,  N_B, 13, 30, 2, 0 },
		{ "Turenne",		specs+10, N_F,  9, 35, 6, 0 },
		{ "Nightmare",		specs+9,  N_F,  7, 37, 6, 0 },
		{ "Paris",		specs+53, N_F,  3, 45, 4, 0 },
		{ "Napolean",		specs+56, N_F,  1, 40, 6, 0 }
	},
	6, 4, 7, 5, "Cape Horn",
	{
		{ "Concord",		specs+51, N_A,  3, 20, 4, 0 },
		{ "Berkeley",		specs+7,  N_A,  5, 50, 5, 0 },
		{ "Thames",		specs+71, N_B, 10, 40, 1, 0 },
		{ "Madrid",		specs+53, N_S, 13, 60, 8, 0 },
		{ "Musket",		specs+10, N_F, 10, 60, 7, 0 }
	},
	8, 3, 7, 3, "New Orleans",
	{
		{ "Alligator",		specs+71, N_A, 13,  5, 1, 0 },
		{ "Firefly",		specs+50, N_B, 10, 20, 8, 0 },
		{ "Cypress",		specs+46, N_B,  5, 10, 6, 0 }
	},
	5, 3, 7, 3, "Botany Bay",
	{
		{ "Shark",		specs+11, N_B,  6, 15, 4, 0 },
		{ "Coral Snake",	specs+31, N_F,  3, 30, 6, 0 },
		{ "Sea Lion",		specs+33, N_F, 13, 50, 8, 0 }
	},
	4, 3, 6, 4, "Voyage to the Bottom of the Sea",
	{
		{ "Seaview",		specs+71, N_A,  6, 3,  3, 0 },
		{ "Flying Sub",		specs+64, N_A,  8, 3,  3, 0 },
		{ "Mermaid",		specs+70, N_B,  2, 5,  5, 0 },
		{ "Giant Squid",	specs+53, N_S, 10, 30, 8, 0 }
	},
	7, 3, 6, 3, "Frigate Action",
	{
		{ "Killdeer",		specs+21, N_A,  7, 20, 8, 0 },
		{ "Sandpiper",		specs+27, N_B,  5, 40, 8, 0 },
		{ "Curlew",		specs+34, N_S, 10, 60, 8, 0 }
	},
	7, 2, 5, 6, "The Battle of Midway",
	{
		{ "Enterprise",		specs+49, N_A, 10, 70, 8, 0 },
		{ "Yorktown",		specs+51, N_A,  3, 70, 7, 0 },
		{ "Hornet",		specs+52, N_A,  6, 70, 7, 0 },
		{ "Akagi",		specs+53, N_J,  6, 10, 4, 0 },
		{ "Kaga",		specs+54, N_J,  4, 12, 4, 0 },
		{ "Soryu",		specs+55, N_J,  2, 14, 4, 0 }
	},
	1, 3, 4, 8, "Star Trek",
	{
		{ "Enterprise",		specs+76, N_D,-10, 60, 7, 0 },
		{ "Yorktown",		specs+77, N_D,  0, 70, 7, 0 },
		{ "Reliant",		specs+78, N_D, 10, 70, 7, 0 },
		{ "Galileo",		specs+79, N_D, 20, 60, 7, 0 },
		{ "Kobayashi Maru",	specs+80, N_K,  0,120, 7, 0 },
		{ "Klingon II",		specs+81, N_K, 10,120, 7, 0 },
		{ "Red Orion",		specs+82, N_O,  0,  0, 3, 0 },
		{ "Blue Orion",		specs+83, N_O, 10,  0, 3, 0 }
	}
};
int nscene = sizeof scene / sizeof (struct scenario);

struct shipspecs specs[] = {
/*      bs fs ta guns   hull  crew1   crew3    gunR  carR   rig2  rig4 pts */
/*                 class   qual   crew2    gunL   carL   rig1  rig3        */
/*00*/	4, 7, 3,  19, 5,  5, 4,  2,  2,  2,  2,  2, 0, 0,  4, 4, 4,  4,  7,
/*01*/	4, 7, 3,  17, 5,  5, 4,  2,  2,  2,  0,  0, 4, 4,  3, 3, 3,  3,  6,
/*02*/	3, 5, 2,  42, 4,  7, 4,  2,  2,  2,  2,  2, 0, 0,  5, 5, 5, -1, 11,
/*03*/	4, 6, 3,  44, 3,  7, 4,  2,  2,  2,  3,  3, 0, 0,  5, 5, 5,  5, 12,
/*04*/	3, 5, 2,  64, 2, 17, 4,  8,  6,  6, 12, 12, 2, 2,  7, 7, 7, -1, 20,
/*05*/	3, 5, 2,  74, 2, 20, 4,  8,  8,  8, 16, 16, 2, 2,  7, 7, 7, -1, 26,
/*06*/	3, 5, 2,  50, 2, 12, 4,  6,  4,  4,  8,  8, 2, 2,  6, 6, 6, -1, 17,
/*07*/	3, 5, 1,  98, 1, 23, 4, 10, 10, 10, 18, 18, 2, 2,  8, 8, 8, -1, 28,
/*08*/	3, 5, 2,  74, 2, 20, 4,  8,  8,  8, 16, 16, 2, 2,  7, 7, 7, -1, 26,
/*09*/	3, 5, 2,  74, 2, 21, 3, 10, 10,  8, 20, 20, 0, 0,  7, 7, 7, -1, 24,
/*10*/	3, 5, 1,  80, 1, 23, 3, 12, 12, 10, 22, 22, 0, 0,  7, 7, 7, -1, 27,
/*11*/	3, 5, 2,  64, 2, 18, 3,  8,  8,  6, 12, 12, 0, 0,  7, 7, 7, -1, 18,
/*12*/	3, 5, 2,  44, 2, 11, 3,  4,  4,  4,  6,  6, 2, 2,  5, 5, 5, -1, 10,
/*13*/	3, 5, 2,  50, 2, 14, 3,  6,  6,  4,  8,  8, 0, 0,  6, 6, 6, -1, 14,
/*14*/	4, 6, 3,  36, 3, 11, 4,  4,  4,  2,  4,  4, 2, 2,  5, 5, 5,  5, 11,
/*15*/	4, 6, 3,  36, 3, 11, 3,  4,  4,  4,  4,  4, 2, 2,  5, 5, 5,  5, 10,
/*16*/	3, 5, 2,  74, 2, 21, 4, 10,  8,  8, 18, 18, 2, 2,  7, 7, 7, -1, 26,
/*17*/	3, 5, 2,  74, 2, 21, 3, 10, 10,  8, 20, 20, 2, 2,  7, 7, 7, -1, 23,
/*18*/	4, 6, 3,  32, 3,  8, 3,  4,  2,  2,  4,  4, 2, 2,  5, 5, 5,  5,  9,
/*19*/	4, 6, 3,  24, 4,  6, 3,  4,  4,  4,  2,  2, 0, 0,  4, 4, 4,  4,  9,
/*20*/	4, 7, 3,  38, 4, 14, 5,  6,  4,  4,  4,  4, 6, 6,  5, 5, 5,  5, 17,
/*21*/	4, 6, 3,  40, 3, 15, 3,  8,  6,  6,  6,  6, 4, 4,  5, 5, 5,  5, 15,
/*22*/	4, 7, 3,  36, 4, 11, 3,  6,  6,  4,  4,  4, 2, 2,  5, 5, 5,  5, 11,
/*23*/	4, 6, 3,  32, 3, 11, 5,  4,  4,  2,  4,  4, 2, 2,  5, 5, 5,  5, 13,
/*24*/	4, 6, 3,  38, 3, 14, 5,  4,  4,  4,  6,  6, 4, 4,  5, 5, 5,  5, 18,
/*25*/	4, 6, 3,  22, 3,  6, 5,  2,  2,  2,  0,  0, 8, 8,  4, 4, 4,  4, 11,
/*26*/	4, 6, 3,  32, 3, 11, 5,  4,  4,  2,  4,  4, 2, 2,  5, 5, 5,  5, 13,
/*27*/	4, 6, 3,  40, 3, 14, 3,  6,  6,  4,  6,  6, 4, 4,  5, 5, 5,  5, 15,
/*28*/	4, 6, 3,  32, 3, 11, 2,  4,  4,  4,  4,  4, 0, 0,  5, 5, 5,  5,  9,
/*29*/	4, 6, 3,  40, 3, 14, 2,  6,  6,  4,  6,  6, 4, 4,  5, 5, 5,  5, 12,
/*30*/	4, 6, 3,  32, 3,  8, 2,  4,  4,  1,  2,  2, 0, 0,  4, 4, 4,  4,  7,
/*31*/	4, 7, 3,  44, 4, 18, 5,  6,  6,  6,  8,  8, 6, 6,  6, 6, 6,  6, 24,
/*32*/	4, 6, 3,  38, 3, 14, 4,  4,  4,  2,  6,  6, 4, 4,  5, 5, 5,  5, 15,
/*33*/	4, 5, 3,  44, 3, 18, 5,  8,  6,  6,  8,  8, 8, 8,  6, 6, 6,  6, 24,
/*34*/	4, 6, 3,  38, 3, 14, 4,  4,  4,  4,  6,  6, 4, 4,  5, 5, 5,  5, 16,
/*35*/	4, 7, 3,  38, 4, 14, 4,  6,  6,  6,  6,  6, 6, 6,  5, 5, 5,  5, 19,
/*36*/	4, 6, 3,  38, 3, 14, 3,  6,  6,  4,  6,  6, 6, 6,  5, 5, 5,  5, 14,
/*37*/	4, 6, 3,  38, 3, 14, 5,  6,  4,  4,  6,  6, 6, 6,  5, 5, 5,  5, 17,
/*38*/	4, 7, 3,  20, 5,  6, 4,  4,  2,  2,  0,  0, 6, 6,  4, 4, 4,  4,  9,
/*39*/	4, 7, 3,  13, 6,  3, 4,  0,  2,  2,  0,  0, 2, 2,  2, 2, 2,  2,  5,
/*40*/	4, 7, 3,  19, 5,  5, 4,  2,  2,  2,  2,  2, 0, 0,  4, 4, 4,  4,  7,
/*41*/	4, 7, 3,  17, 5,  5, 4,  2,  2,  2,  2,  2, 0, 0,  3, 3, 3,  3,  6,
/*42*/	4, 7, 3,  20, 5,  6, 5,  4,  2,  2,  0,  0, 6, 6,  4, 4, 4,  4, 12,
/*43*/	4, 7, 3,  18, 5,  5, 5,  2,  2,  2,  0,  0, 6, 6,  4, 4, 4,  4,  9,
/*44*/	4, 7, 3,  24, 5,  6, 4,  4,  2,  2,  0,  0,10,10,  4, 4, 4,  4, 11,
/*45*/	4, 7, 3,  20, 5,  6, 4,  2,  2,  2,  0,  0, 8, 8,  4, 4, 4,  4, 10,
/*46*/	4, 6, 3,  44, 3, 11, 5,  4,  4,  4,  4,  4, 2, 2,  5, 5, 5,  5, 14,
/*47*/	4, 6, 3,  36, 3, 12, 4,  4,  4,  4,  6,  6, 2, 2,  5, 5, 5,  5, 14,
/*48*/	3, 5, 2,  74, 2, 21, 3, 10,  8,  8, 20, 20, 2, 2,  4, 4, 7, -1, 24,
/*49*/	3, 5, 2,  80, 2, 24, 4, 10,  8,  8, 20, 20, 2, 2,  8, 8, 8, -1, 31,
/*50*/	3, 5, 2,  74, 2, 21, 4,  8,  8,  6, 16, 16, 4, 4,  7, 7, 7, -1, 27,
/*51*/	3, 5, 2,  80, 2, 24, 3, 12, 12, 10, 22, 22, 2, 2,  7, 7, 7, -1, 27,
/*52*/	3, 5, 2,  74, 2, 21, 3, 10, 10,  8, 20, 20, 2, 2,  7, 7, 7, -1, 24,
/*53*/	3, 5, 1, 112, 1, 27, 2, 12, 12, 12, 24, 24, 0, 0,  9, 9, 9, -1, 27,
/*54*/	3, 5, 1,  96, 1, 24, 2, 12, 12, 10, 20, 20, 0, 0,  8, 8, 8, -1, 24,
/*55*/	3, 5, 2,  80, 2, 23, 2, 10, 10,  8, 20, 20, 0, 0,  7, 7, 7, -1, 23,
/*56*/	3, 5, 2,  74, 2, 21, 2, 10,  8,  8, 16, 16, 4, 4,  7, 7, 7, -1, 20,
/*57*/	4, 6, 3,  37, 3, 12, 4,  4,  4,  2,  6,  6, 4, 4,  5, 5, 5,  5, 14,
/*58*/	4, 7, 3,  16, 5,  5, 5,  2,  2,  2,  0,  0, 4, 4,  4, 4, 4,  4, 10,
/*59*/	4, 7, 3,  11, 6,  3, 4,  2,  2,  2,  0,  0, 2, 2,  2, 2, 2,  2,  5,
/*60*/	4, 7, 3,  26, 5,  6, 4,  4,  2,  2,  2,  2, 6, 6,  4, 4, 4,  4, 12,
/*61*/	4, 7, 3,  20, 5,  6, 4,  4,  2,  2,  0,  0, 6, 6,  4, 4, 4,  4, 11,
/*62*/	4, 7, 3,  17, 5,  5, 4,  2,  2,  2,  0,  0, 6, 6,  4, 4, 4,  4,  9,
/*63*/	4, 7, 3,   7, 6,  3, 4,  0,  2,  2,  0,  0, 2, 2,  2, 2, 2,  2,  4,
/*64*/	4, 6, 3,  40, 3, 15, 4,  4,  4,  4,  8,  8, 6, 6,  5, 5, 5,  5, 17,
/*65*/	4, 6, 3,  44, 3, 15, 4,  8,  8,  6, 10, 10, 2, 2,  6, 6, 6,  6, 20,
/*66*/	4, 6, 3,  38, 3, 14, 4,  4,  4,  4,  6,  6, 6, 6,  5, 5, 5,  5, 15,
/*67*/	4, 5, 3,  44, 3, 18, 5,  8,  6,  6,  8,  8, 8, 8,  6, 6, 6,  6, 24,
/*68*/	4, 6, 3,  36, 3,  9, 5,  4,  4,  2,  4,  4, 2, 2,  5, 5, 5,  5, 13,
/*69*/	3, 5, 2,  50, 2, 14, 2,  6,  6,  6,  8,  8, 0, 0,  6, 6, 6, -1, 14,
/*70*/	3, 5, 1, 136, 1, 30, 1,  8, 14, 14, 28, 28, 0, 0,  9, 9, 9, -1, 27,
/*71*/	3, 5, 1, 120, 1, 27, 5, 16, 14, 14, 28, 28, 2, 2,  9, 9, 9, -1, 43,
/*72*/	3, 5, 1, 120, 2, 21, 5, 15, 17, 15, 25, 25, 7, 7,  9, 9, 9, -1, 36,
/*73*/	3, 5, 1,  90, 3, 18, 4, 13, 15, 13, 20, 20, 6, 6,  5, 5, 5,  5, 28,
/*74*/	4, 7, 3,   6, 6,  3, 4,  2,  2,  2, 20, 20, 6, 6,  2, 2, 3,  3,  5,
/*75*/	3, 5, 1, 110, 2, 20, 4, 14, 15, 11, 26, 26, 8, 8,  7, 8, 9, -1, 34,
/*76*/	4, 7, 3, 450, 1, 99, 5, 50, 40, 40, 50, 50,25,25,  9, 9, 9, -1, 75,
/*77*/	4, 7, 3, 450, 1, 99, 5, 50, 40, 40, 50, 50,25,25,  9, 9, 9, -1, 75,
/*78*/	4, 7, 3, 450, 1, 99, 5, 50, 40, 40, 50, 50,25,25,  9, 9, 9, -1, 75,
/*79*/	4, 7, 3, 450, 1, 99, 5, 50, 40, 40, 50, 50,25,25,  9, 9, 9, -1, 75,
/*80*/	4, 7, 3, 450, 1, 99, 5, 50, 40, 40, 50, 50,25,25,  9, 9, 9, -1, 75,
/*81*/	4, 7, 3, 450, 1, 99, 5, 50, 40, 40, 50, 50,25,25,  9, 9, 9, -1, 75,
/*82*/	4, 7, 3, 450, 1, 99, 5, 50, 40, 40, 50, 50,25,25,  9, 9, 9, -1, 75,
/*83*/	4, 7, 3, 450, 1, 99, 5, 50, 40, 40, 50, 50,25,25,  9, 9, 9, -1, 75,
/*      bs fs ta guns   hull  crew1   crew3    gunR  carR   rig2  rig4 pts */
/*                 class   qual   crew2    gunL   carL   rig1  rig3        */
};

struct windeffects WET[7][6] = {
	{ {9,9,9,9}, {9,9,9,9}, {9,9,9,9}, {9,9,9,9}, {9,9,9,9}, {9,9,9,9} },
	{ {3,2,2,0}, {3,2,1,0}, {3,2,1,0}, {3,2,1,0}, {2,1,0,0}, {2,1,0,0} },
	{ {1,1,1,0}, {1,1,0,0}, {1,0,0,0}, {1,0,0,0}, {1,0,0,0}, {1,0,0,0} },
	{ {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0} },
	{ {0,0,0,0}, {1,0,0,0}, {1,1,0,0}, {1,1,0,0}, {2,2,1,0}, {2,2,1,0} },
	{ {1,0,0,0}, {1,1,0,0}, {1,1,1,0}, {1,1,1,0}, {3,2,2,0}, {3,2,2,0} },
	{ {2,1,1,0}, {3,2,1,0}, {3,2,1,0}, {3,2,1,0}, {3,3,2,0}, {3,3,2,0} }
};

struct Tables RigTable[11][6] = {
	{ {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,1}, {0,0,1,0} },
	{ {0,0,0,0}, {0,0,0,0}, {0,0,0,1}, {0,0,1,0}, {1,0,0,1}, {0,1,1,1} },
	{ {0,0,0,0}, {0,0,0,1}, {0,0,1,1}, {0,1,0,1}, {0,1,0,1}, {1,0,1,2} },
	{ {0,0,0,0}, {0,0,1,1}, {0,1,0,1}, {0,0,0,2}, {0,1,0,2}, {1,0,1,2} },
	{ {0,1,0,1}, {1,0,0,1}, {0,1,1,2}, {0,1,0,2}, {0,0,1,3}, {1,0,1,4} },
	{ {0,0,1,1}, {0,1,0,2}, {1,0,0,3}, {0,1,1,3}, {1,0,0,4}, {1,1,1,4} },
	{ {0,0,1,2}, {0,1,1,2}, {1,1,0,3}, {0,1,0,4}, {1,0,0,4}, {1,0,1,5} },
	{ {0,0,1,2}, {0,1,0,3}, {1,1,0,3}, {1,0,2,4}, {0,2,1,5}, {2,1,0,5} },
	{ {0,2,1,3}, {1,0,0,3}, {2,1,0,4}, {0,1,1,4}, {0,1,0,5}, {1,0,2,6} },
	{ {1,1,0,4}, {1,0,1,4}, {2,0,0,5}, {0,2,1,5}, {0,1,2,6}, {0,2,0,7} },
	{ {1,0,1,5}, {0,2,0,6}, {1,2,0,6}, {1,1,1,6}, {2,0,2,6}, {1,1,2,7} }
};
struct Tables HullTable[11][6] = {
	{ {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {1,0,0,0}, {0,1,0,0} },
	{ {0,0,0,0}, {0,0,0,0}, {0,1,0,0}, {1,1,0,0}, {1,0,1,0}, {1,0,1,1} },
	{ {0,1,0,0}, {1,0,0,0}, {1,1,0,0}, {1,0,1,0}, {1,0,1,1}, {2,1,0,0} },
	{ {0,1,1,0}, {1,0,0,0}, {1,1,1,0}, {2,0,0,1}, {2,0,1,0}, {2,2,0,0} },
	{ {0,1,1,0}, {1,0,0,1}, {2,1,0,1}, {2,2,1,0}, {3,0,1,0}, {3,1,0,0} },
	{ {1,1,1,0}, {2,0,2,1}, {2,1,1,0}, {2,2,0,0}, {3,1,0,1}, {3,1,1,0} },
	{ {1,2,2,0}, {2,0,2,1}, {2,1,0,1}, {2,2,0,0}, {3,1,1,0}, {4,2,1,0} },
	{ {2,1,1,0}, {2,0,1,1}, {3,2,2,0}, {3,2,0,0}, {4,2,1,0}, {4,2,1,1} },
	{ {2,1,2,0}, {3,1,1,1}, {3,2,2,0}, {4,2,1,0}, {4,1,0,2}, {4,2,2,0} },
	{ {2,3,1,0}, {3,2,2,0}, {3,2,2,1}, {4,2,2,0}, {4,1,0,3}, {5,1,2,0} },
	{ {2,2,4,0}, {3,3,1,1}, {4,2,1,1}, {5,1,0,2}, {5,1,2,1}, {6,2,2,0} },
};

char AMMO[9][4] = {
	{ -1, 1, 0, 1 },
	{ -1, 1, 0, 1 },
	{ -1, 1, 0, 1 },
	{ -2, 1, 0, 2 },
	{ -2, 2, 0, 2 },
	{ -2, 2, 0, 2 },
	{ -3, 2, 0, 2 },
	{ -3, 2, 0, 3 },
	{ -3, 2, 0, 3 }
};
	
char HDT[9][10] = {
	{ 1, 0,-1,-2,-3,-3,-4,-4,-4,-4 },
	{ 1, 1, 0,-1,-2,-2,-3,-3,-3,-3 },
	{ 2, 1, 0,-1,-2,-2,-3,-3,-3,-3 },
	{ 2, 2, 1, 0,-1,-1,-2,-2,-2,-2 },
	{ 3, 2, 1, 0,-1,-1,-2,-2,-2,-2 },
	{ 3, 3, 2, 1, 0, 0,-1,-1,-1,-1 },
	{ 4, 3, 2, 1, 0, 0,-1,-1,-1,-1 },
	{ 4, 4, 3, 2, 1, 1, 0, 0, 0, 0 },
	{ 5, 4, 3, 2, 1, 1, 0, 0, 0, 0 }
};

char HDTrake[9][10] = {
	{ 2, 1, 0,-1,-2,-2,-3,-3,-3,-3 },
	{ 2, 2, 1, 0,-1,-1,-2,-2,-2,-2 },
	{ 3, 2, 1, 0,-1,-1,-2,-2,-2,-2 },
	{ 4, 3, 2, 1, 0, 0,-1,-1,-1,-1 },
	{ 5, 4, 3, 2, 1, 1, 0, 0, 0, 0 },
	{ 6, 5, 4, 3, 2, 2, 1, 1, 1, 1 },
	{ 7, 6, 5, 4, 3, 3, 2, 2, 2, 2 },
	{ 8, 7, 6, 5, 4, 4, 3, 3, 3, 3 },
	{ 9, 8, 7, 6, 5, 5, 4, 4, 4, 4 }
};

char QUAL[9][5] = {
	{ -1, 0, 0, 1, 1 },
	{ -1, 0, 0, 1, 1 },
	{ -1, 0, 0, 1, 2 },
	{ -1, 0, 0, 1, 2 },
	{ -1, 0, 0, 2, 2 },
	{ -1,-1, 0, 2, 2 },
	{ -2,-1, 0, 2, 2 },
	{ -2,-1, 0, 2, 2 },
	{ -2,-1, 0, 2, 3 }
};

char MT[9][3] = {
	{ 1, 0, 0 },
	{ 1, 1, 0 },
	{ 2, 1, 0 },
	{ 2, 1, 1 },
	{ 2, 2, 1 },
	{ 3, 2, 1 },
	{ 3, 2, 2 },
	{ 4, 3, 2 },
	{ 4, 4, 2 }
};

char rangeofshot[] = {
	0,
	1,		/* grape */
	3,		/* chain */
	10,		/* round */
	1		/* double */
};

char *countryname[] = {
	"American", "British", "Spanish", "French", "Japanese",
	"Federation", "Klingon", "Orion"
};

char *classname[] = {
	"Drift wood",
	"Ship of the Line",
	"Ship of the Line",
	"Frigate",
	"Corvette",
	"Sloop",
	"Brig"
};

char *directionname[] = {
	"dead ahead",
	"off the starboard bow",
	"off the starboard beam",
	"off the starboard quarter",
	"dead astern",
	"off the port quarter",
	"off the port beam",
	"off the port bow",
	"dead ahead"
};

char *qualname[] = { "dead", "mutinous", "green", "mundane", "crack", "elite" };

char loadname[] = { '-', 'G', 'C', 'R', 'D', 'E' };

char dr[] = { 0, 1, 1, 0, -1, -1, -1, 0, 1 };
char dc[] = { 0, 0, -1, -1, -1, 0, 1, 1, 1 };
SHAR_EOF
if test 18869 -ne "`wc -c sail/globals.c`"
then
echo shar: error transmitting sail/globals.c '(should have been 18869 characters)'
fi
cat << \SHAR_EOF > sail/grap.c
#ifndef lint
static	char *sccsid = "@(#)grap.c	2.2 83/12/17";
#endif
#include "externs.h"

ungrap(from, to)
register struct ship *from, *to;
{
	register k;
	char friend;

	if ((k = grappled2(from, to)) == 0)
		return;
	friend = capship(from)->nationality == capship(to)->nationality;
	while (--k >= 0) {
		if (friend || die() < 3) {
			cleangrapple(from, to, 0);
			makesignal(from, "ungrappling %s (%c%c)", to);
		}
	}
}

grap(from, to)
register struct ship *from, *to;
{
	if (capship(from)->nationality != capship(to)->nationality && die() > 2)
		return;
	Write(W_GRAP, from, 0, to->file->index, 0, 0, 0);
	Write(W_GRAP, to, 0, from->file->index, 0, 0, 0);
	makesignal(from, "grappled with %s (%c%c)", to);
}
SHAR_EOF
if test 711 -ne "`wc -c sail/grap.c`"
then
echo shar: error transmitting sail/grap.c '(should have been 711 characters)'
fi
cat << \SHAR_EOF > sail/misc.c
#ifndef lint
static	char *sccsid = "@(#)misc.c	2.3 84/02/23";
#endif
#include "externs.h"

#define distance(x,y) (abs(x) >= abs(y) ? abs(x) + abs(y)/2 : abs(y) + abs(x)/2)

/* XXX */
range(from, to)
struct ship *from, *to;
{
	register bow1r, bow1c, bow2r, bow2c;
	int stern1r, stern1c, stern2c, stern2r;
	register int bb, bs, sb, ss, result;

	if (!to->file->dir)
		return -1;
	stern1r = bow1r = from->file->row;
	stern1c = bow1c = from->file->col;
	stern2r = bow2r = to->file->row;
	stern2c = bow2c = to->file->col;
	result = bb = distance(bow2r - bow1r, bow2c - bow1c);
	if (bb < 5) {
		stern2r += dr[to->file->dir];
		stern2c += dc[to->file->dir];
		stern1r += dr[from->file->dir];
		stern1c += dc[from->file->dir];
		bs = distance((bow2r - stern1r), (bow2c - stern1c));
		sb = distance((bow1r - stern2r), (bow1c - stern2c));
		ss = distance((stern2r - stern1r) ,(stern2c - stern1c));
		result = min(bb, min(bs, min(sb, ss)));
	}
	return result;
}

struct ship *
closestenemy(from, side, anyship)
register struct ship *from;
char side, anyship;
{
	register struct ship *sp;
	register char a;
	int olddist = 30000, dist;
	struct ship *closest = 0;

	a = capship(from)->nationality;
	foreachship(sp) {
		if (sp == from)
			continue;
		if (sp->file->dir == 0)
			continue;
		if (a == capship(sp)->nationality && !anyship)
			continue;
		if (side && gunsbear(from, sp) != side)
			continue;
		dist = range(from, sp);
		if (dist < olddist) {
			closest = sp;
			olddist = dist;
		}
	}
	return closest;
}

angle(dr, dc)
register dr, dc;
{
	register i;

	if (dc >= 0 && dr > 0)
		i = 0;
	else if (dr <= 0 && dc > 0)
		i = 2;
	else if (dc <= 0 && dr < 0)
		i = 4;
	else
		i = 6;
	dr = abs(dr);
	dc = abs(dc);
	if ((i == 0 || i == 4) && dc * 2.4 > dr) {
		i++;
		if (dc > dr * 2.4)
			i++;
	} else if ((i == 2 || i == 6) && dr * 2.4 > dc) {
		i++;
		if (dr > dc * 2.4)
			i++;
	}
	return i % 8 + 1;
}

gunsbear(from, to)		/* checks for target bow or stern */
register struct ship *from, *to;
{
	int Dr, Dc, i;
	register ang;

	Dr = from->file->row - to->file->row;
	Dc = to->file->col - from->file->col;
	for (i = 2; i; i--) {
		if ((ang = angle(Dr, Dc) - from->file->dir + 1) < 1)
			ang += 8;
		if (ang >= 2 && ang <= 4)
			return 'r';
		if (ang >= 6 && ang <= 7)
			return 'l';
		Dr += dr[to->file->dir];
		Dc += dc[to->file->dir];
	}
	return 0;
}

portside(from, on, quick)
register struct ship *from, *on;
int quick;			/* returns true if fromship is */
{				/* shooting at onship's starboard side */
	register ang;
	register Dr, Dc;

	Dr = from->file->row - on->file->row;
	Dc = on->file->col - from->file->col;
	if (quick == -1) {
		Dr += dr[on->file->dir];
		Dc += dc[on->file->dir];
	}
	ang = angle(Dr, Dc);
	if (quick != 0)
		return ang;
	ang = (ang + 4 - on->file->dir - 1) % 8 + 1;
	return ang < 5;
}

colours(sp)
register struct ship *sp;
{
	register char flag;

	if (sp->file->struck)
		flag = '!';
	if (sp->file->explode)
		flag = '#';
	if (sp->file->sink)
		flag = '~';
	if (sp->file->struck)
		return flag;
	flag = *countryname[capship(sp)->nationality];
	return sp->file->FS ? flag : tolower(flag);
}

#include <sys/file.h>
log(s)
register struct ship *s;
{
	FILE *fp;
	int persons;
	int n;
	struct logs log[NLOG];
	float net;
	register struct logs *lp;

	if ((fp = fopen(LOGFILE, "r+")) == NULL)
		return;
#ifdef LOCK_EX
	if (flock(fileno(fp), LOCK_EX) < 0)
		return;
#endif
	net = (float)s->file->points / s->specs->pts;
	persons = getw(fp);
	n = fread((char *)log, sizeof(struct logs), NLOG, fp);
	for (lp = &log[n]; lp < &log[NLOG]; lp++)
		lp->l_name[0] = lp->l_uid = lp->l_shipnum
			= lp->l_gamenum = lp->l_netpoints = 0;
	rewind(fp);
	if (persons < 0)
		(void) putw(1, fp);
	else
		(void) putw(persons + 1, fp);
	for (lp = log; lp < &log[NLOG]; lp++)
		if (net > (float)lp->l_netpoints
		    / scene[lp->l_gamenum].ship[lp->l_shipnum].specs->pts) {
			(void) fwrite((char *)log,
				sizeof (struct logs), lp - log, fp);
			(void) strcpy(log[NLOG-1].l_name, s->file->captain);
			log[NLOG-1].l_uid = getuid();
			log[NLOG-1].l_shipnum = s->file->index;
			log[NLOG-1].l_gamenum = game;
			log[NLOG-1].l_netpoints = s->file->points;
			(void) fwrite((char *)&log[NLOG-1],
				sizeof (struct logs), 1, fp);
			(void) fwrite((char *)lp,
				sizeof (struct logs), &log[NLOG-1] - lp, fp);
			break;
		}
#ifdef LOCK_EX
	(void) flock(fileno(fp), LOCK_UN);
#endif
	(void) fclose(fp);
}
SHAR_EOF
if test 4396 -ne "`wc -c sail/misc.c`"
then
echo shar: error transmitting sail/misc.c '(should have been 4396 characters)'
fi
cat << \SHAR_EOF > sail/parties.c
#ifndef lint
static	char *sccsid = "@(#)parties.c	2.2 83/12/17";
#endif

#include "externs.h"

meleeing(from, to)
struct ship *from;
register struct ship *to;
{
	register struct BP *p = from->file->OBP;
	register struct BP *q = p + NBP;

	for (; p < q; p++)
		if (p->turnsent && p->toship == to)
			return 1;
	return 0;
}

boarding(from, isdefense)
register struct ship *from;
char isdefense;
{
	register struct BP *p = isdefense ? from->file->DBP : from->file->OBP;
	register struct BP *q = p + NBP;

	for (; p < q; p++)
		if (p->turnsent)
			return 1;
	return 0;
}

unboard(ship, to, isdefense)
register struct ship *ship, *to;
register char isdefense;
{
	register struct BP *p = isdefense ? ship->file->DBP : ship->file->OBP;
	register n;

	for (n = 0; n < NBP; p++, n++)
		if (p->turnsent && (p->toship == to || isdefense || ship == to))
			Write(isdefense ? W_DBP : W_OBP, ship, 0, n, 0, 0, 0);
}
SHAR_EOF
if test 902 -ne "`wc -c sail/parties.c`"
then
echo shar: error transmitting sail/parties.c '(should have been 902 characters)'
fi
cat << \SHAR_EOF > sail/sail.log.c
#ifndef lint
static	char *sccsid = "@(#)sail.log.c	2.1 83/10/31";
#endif

/*
 * Print out the top ten SAILors
 *
 * sail.log [-s/l]
 *
 *  -s force a short listing (without real usernames)
 *  -l force a long listing (print out real usernames)
 */
#include <pwd.h>
#include "externs.h"

char *title[] = {
	"Admiral", "Commodore", "Captain", "Captain",
	"Captain", "Captain", "Captain", "Commander",
	"Commander", "Lieutenant"
};

main(argc, argv)
int argc;
char **argv;
{
	FILE *fp;
	char sbuf[32];
	int n = 0, people;
	int usrnam = 0;
	struct passwd *getpwuid(), *pass;
	struct logs log;
	struct ship *ship;

	if (argc > 1 && argc == 2)
		if (strcmp(argv[1], "-s") == 0)
			usrnam = 0;
		else if (strcmp(argv[1], "-l") == 0)
			usrnam = 1;
		else {
			fprintf(stderr, "usage: %s: [-s/l]\n", argv[0]);
			exit(1);
		}
	if ((fp = fopen(LOGFILE, "r")) == 0) {
		perror(LOGFILE);
		exit(1);
	}
	switch (fread((char *)&people, sizeof people, 1, fp)) {
	case 0:
		printf("Nobody has sailed yet.\n");
		exit(0);
	case 1:
		break;
	default:
		perror(LOGFILE);
		exit(1);
	}
	while (fread((char *)&log, sizeof log, 1, fp) == 1
	       && log.l_name[0] != '\0') {
		if (usrnam && (pass = getpwuid(log.l_uid)) != NULL)
			(void) sprintf(sbuf, "%10.10s (%s)",
				log.l_name, pass->pw_name);
		else
			(void) sprintf(sbuf, "%20.20s", log.l_name);
		ship = &scene[log.l_gamenum].ship[log.l_shipnum];
		printf("%-10s %21s of the %15s %3d points, %5.2f equiv\n",
			title[n++], sbuf, ship->shipname, log.l_netpoints,
			(float) log.l_netpoints / ship->specs->pts);
	}
	printf("\n%d people have played.\n", people);
}
SHAR_EOF
if test 1603 -ne "`wc -c sail/sail.log.c`"
then
echo shar: error transmitting sail/sail.log.c '(should have been 1603 characters)'
fi
cat << \SHAR_EOF > sail/sync.c
#ifndef lint
static	char *sccsid = "@(#)sync.c	2.6 84/04/28";
#endif

#include "externs.h"
#include <sys/file.h>
#include <sys/errno.h>

static char sync_buf[BUFSIZE];
static char *sync_bp = sync_buf;
static char sync_lock[25];
static char sync_file[25];
static long sync_seek;
static FILE *sync_fp;
#define SF "/tmp/#sailsink.%d"
#define LF "/tmp/#saillock.%d"

/*VARARGS3*/
makesignal(from, fmt, ship, a, b, c)
struct ship *from;
char *fmt;
register struct ship *ship;
{
	char message[80];

	if (ship == 0)
		(void) sprintf(message, fmt, a, b, c);
	else
		(void) sprintf(message, fmt,
			ship->shipname, colours(ship),
			sterncolour(ship), a, b, c);
	Write(W_SIGNAL, from, 1, (int)message, 0, 0, 0);
}

#include <sys/types.h>
#include <sys/stat.h>
sync_exists(game)
{
	char buf[sizeof sync_file];
	struct stat s;
	time_t t;

	(void) sprintf(buf, SF, game);
	(void) time(&t);
	if (stat(buf, &s) < 0)
		return 0;
	if (s.st_mtime < t - 60*60*2) {		/* 2 hours */
		(void) unlink(buf);
		(void) sprintf(buf, LF, game);
		(void) unlink(buf);
		return 0;
	} else
		return 1;
}

sync_open()
{
	(void) sprintf(sync_lock, LF, game);
	(void) sprintf(sync_file, SF, game);
	if (access(sync_file, 0) < 0) {
		int omask;
#ifdef SETUID
		omask = umask(077);
#else
		omask = umask(011);
#endif
		sync_fp = fopen(sync_file, "w+");
		(void) umask(omask);
	} else
		sync_fp = fopen(sync_file, "r+");
	if (sync_fp == 0)
		return -1;
	sync_seek == 0;
	return 0;
}

sync_close(remove)
char remove;
{
	if (sync_fp != 0)
		(void) fclose(sync_fp);
	if (remove)
		(void) unlink(sync_file);
}

Write(type, ship, isstr, a, b, c, d)
int type;
struct ship *ship;
char isstr;
int a, b, c, d;
{
	if (isstr)
		(void) sprintf(sync_bp, "%d %d %d %s\n",
			type, ship->file->index, isstr, a);
	else
		(void) sprintf(sync_bp, "%d %d %d %d %d %d %d\n",
			type, ship->file->index, isstr, a, b, c, d);
	while (*sync_bp++)
		;
	sync_bp--;
	if (sync_bp >= &sync_buf[sizeof sync_buf])
		abort();
	(void) sync_update(type, ship, a, b, c, d);
}

Sync()
{
	int (*sig1)(), (*sig2)();
	register n;
	int type, shipnum, isstr, a, b, c, d;
	char buf[80];
	char erred = 0;
	extern errno;

	sig1 = signal(SIGHUP, SIG_IGN);
	sig2 = signal(SIGINT, SIG_IGN);
	for (n = TIMEOUT; --n >= 0;) {
#ifdef LOCK_EX
		if (flock(fileno(sync_fp), LOCK_EX|LOCK_NB) >= 0)
			break;
		if (errno != EWOULDBLOCK)
			return -1;
#else
		if (link(sync_file, sync_lock) >= 0)
			break;
		if (errno != EEXIST)
			return -1;
#endif
		sleep(1);
	}
	if (n <= 0)
		return -1;
	(void) fseek(sync_fp, sync_seek, 0);
	for (;;) {
		switch (fscanf(sync_fp, "%d%d%d", &type, &shipnum, &isstr)) {
		case 3:
			break;
		case EOF:
			goto out;
		default:
			goto bad;
		}
		if (shipnum < 0 || shipnum >= cc->vessels)
			goto bad;
		if (isstr != 0 && isstr != 1)
			goto bad;
		if (isstr) {
			register char *p;
			for (p = buf;;) {
				switch (*p++ = getc(sync_fp)) {
				case '\n':
					p--;
				case EOF:
					break;
				default:
					if (p >= buf + sizeof buf)
						p--;
					continue;
				}
				break;
			}
			*p = 0;
			for (p = buf; *p == ' '; p++)
				;
			a = (int)p;
			b = c = d = 0;
		} else
			if (fscanf(sync_fp, "%d%d%d%d", &a, &b, &c, &d) != 4)
				goto bad;
		if (sync_update(type, SHIP(shipnum), a, b, c, d) < 0)
			goto bad;
	}
bad:
	erred++;
out:
	if (!erred && sync_bp != sync_buf) {
		(void) fseek(sync_fp, 0L, 2);
		(void) fputs(sync_buf, sync_fp);
		(void) fflush(sync_fp);
		sync_bp = sync_buf;
	}
	sync_seek = ftell(sync_fp);
#ifdef LOCK_EX
	(void) flock(fileno(sync_fp), LOCK_UN);
#else
	(void) unlink(sync_lock);
#endif
	(void) signal(SIGHUP, sig1);
	(void) signal(SIGINT, sig2);
	return erred ? -1 : 0;
}

sync_update(type, ship, a, b, c, d)
int type;
register struct ship *ship;
int a, b, c, d;
{
	switch (type) {
	case W_DBP: {
		register struct BP *p = &ship->file->DBP[a];
		p->turnsent = b;
		p->toship = SHIP(c);
		p->mensent = d;
		break;
		}
	case W_OBP: {
		register struct BP *p = &ship->file->OBP[a];
		p->turnsent = b;
		p->toship = SHIP(c);
		p->mensent = d;
		break;
		}
	case W_FOUL: {
		register struct snag *p = &ship->file->foul[a];
		if (SHIP(a)->file->dir == 0)
			break;
		if (p->sn_count++ == 0)
			p->sn_turn = turn;
		ship->file->nfoul++;
		break;
		}
	case W_GRAP: {
		register struct snag *p = &ship->file->grap[a];
		if (SHIP(a)->file->dir == 0)
			break;
		if (p->sn_count++ == 0)
			p->sn_turn = turn;
		ship->file->ngrap++;
		break;
		}
	case W_UNFOUL: {
		register struct snag *p = &ship->file->foul[a];
		if (p->sn_count > 0)
			if (b) {
				ship->file->nfoul -= p->sn_count;
				p->sn_count = 0;
			} else {
				ship->file->nfoul--;
				p->sn_count--;
			}
		break;
		}
	case W_UNGRAP: {
		register struct snag *p = &ship->file->grap[a];
		if (p->sn_count > 0)
			if (b) {
				ship->file->ngrap -= p->sn_count;
				p->sn_count = 0;
			} else {
				ship->file->ngrap--;
				p->sn_count--;
			}
		break;
		}
	case W_SIGNAL:
		if (isplayer)
			Signal("\7%s (%c%c): %s", ship, a);
		break;
	case W_CREW: {
		register struct shipspecs *s = ship->specs;
		s->crew1 = a;
		s->crew2 = b;
		s->crew3 = c;
		break;
		}
	case W_CAPTAIN:
		(void) strncpy(ship->file->captain, (char *)a,
			sizeof ship->file->captain - 1);
		ship->file->captain[sizeof ship->file->captain - 1] = 0;
		break;
	case W_CAPTURED:
		if (a < 0)
			ship->file->captured = 0;
		else
			ship->file->captured = SHIP(a);
		break;
	case W_CLASS:
		ship->specs->class = a;
		break;
	case W_DRIFT:
		ship->file->drift = a;
		break;
	case W_EXPLODE:
		if ((ship->file->explode = a) == 2)
			ship->file->dir = 0;
		break;
	case W_FS:
		ship->file->FS = a;
		break;
	case W_GUNL: {
		register struct shipspecs *s = ship->specs;
		s->gunL = a;
		s->carL = b;
		break;
		}
	case W_GUNR: {
		register struct shipspecs *s = ship->specs;
		s->gunR = a;
		s->carR = b;
		break;
		}
	case W_HULL:
		ship->specs->hull = a;
		break;
	case W_MOVE:
		(void) strncpy(ship->file->movebuf, (char *)a,
			sizeof ship->file->movebuf - 1);
		ship->file->movebuf[sizeof ship->file->movebuf - 1] = 0;
		break;
	case W_PCREW:
		ship->file->pcrew = a;
		break;
	case W_POINTS:
		ship->file->points = a;
		break;
	case W_QUAL:
		ship->specs->qual = a;
		break;
	case W_RIGG: {
		register struct shipspecs *s = ship->specs;
		s->rig1 = a;
		s->rig2 = b;
		s->rig3 = c;
		s->rig4 = d;
		break;
		}
	case W_RIG1:
		ship->specs->rig1 = a;
		break;
	case W_RIG2:
		ship->specs->rig2 = a;
		break;
	case W_RIG3:
		ship->specs->rig3 = a;
		break;
	case W_RIG4:
		ship->specs->rig4 = a;
		break;
	case W_COL:
		ship->file->col = a;
		break;
	case W_DIR:
		ship->file->dir = a;
		break;
	case W_ROW:
		ship->file->row = a;
		break;
	case W_SINK:
		if ((ship->file->sink = a) == 2)
			ship->file->dir = 0;
		break;
	case W_STRUCK:
		ship->file->struck = a;
		break;
	case W_TA:
		ship->specs->ta = a;
		break;
	case W_ALIVE:
		alive = 1;
		break;
	case W_TURN:
		turn = a;
		break;
	case W_WIND:
		winddir = a;
		windspeed = b;
		break;
	case W_BEGIN:
		(void) strcpy(ship->file->captain, "begin");
		people++;
		break;
	case W_END:
		*ship->file->captain = 0;
		ship->file->points = 0;
		people--;
		break;
	case W_DDEAD:
		hasdriver = 0;
		break;
	default:
		fprintf(stderr, "sync_update: unknown type %d\r\n", type);
		return -1;
	}
	return 0;
}
SHAR_EOF
if test 7246 -ne "`wc -c sail/sync.c`"
then
echo shar: error transmitting sail/sync.c '(should have been 7246 characters)'
fi
cat << \SHAR_EOF > sail/version.c
char version[] = "Wooden Ships and Iron Men, Version 2.4 (84/02/23)";
SHAR_EOF
if test 70 -ne "`wc -c sail/version.c`"
then
echo shar: error transmitting sail/version.c '(should have been 70 characters)'
fi
#	End of shell archive
exit 0