Sail (Part 1 of 4)

Peter E. Yee yee at ucbvax.ARPA
Thu Jan 24 13:56:31 AEST 1985


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



More information about the Comp.sources.unix mailing list