xref: /original-bsd/games/sail/pl_1.c (revision 264c46cb)
1 #ifndef lint
2 static	char *sccsid = "@(#)pl_1.c	1.8 83/05/20";
3 #endif
4 
5 #include "player.h"
6 #include <sys/types.h>
7 
8 WINDOW *view,*slot;
9 char done_curses = 0;
10 
11 acceptcombat()
12 {
13 	int crew[3], men = 0, rangeofshot, target, temp;
14 	int n, r, guns[2], load[2], car[2], roll[2];
15 	int ready[2], index, rakehim, sternrake;
16 	int shootat[2], hit[2], closest[2], ship;
17 	int hhits = 0, ghits = 0, rhits = 0, chits = 0;
18 	int buf;
19 	struct shipspecs *ptr;
20 	struct File *ptr1;
21 
22 	ptr = &specs[scene[game].ship[player].shipnum];
23 	ptr1 = scene[game].ship[player].file;
24 	crew[0] = ptr -> crew1;
25 	crew[1] = ptr -> crew2;
26 	crew[2] = ptr -> crew3;
27 	ready[0] = ptr1 -> readyL;
28 	ready[1] = ptr1 -> readyR;
29 	load[0] = ptr1 -> loadL;
30 	load[1] = ptr1 -> loadR;
31 	guns[0] = ptr -> gunL;
32 	guns[1] = ptr -> gunR;
33 	car[0] = ptr -> carL;
34 	car[1] = ptr -> carR;
35 	for (n = 0; n < 3; n++) {
36 		if (ptr1 -> OBP[n].turnsent)
37 			men += ptr1 -> OBP[n].mensent;
38 	}
39 	for (n = 0; n < 3; n++) {
40 		if (ptr1 -> DBP[n].turnsent)
41 			men += ptr1 -> DBP[n].mensent;
42 	}
43 	if (men) {
44 		crew[0] = men/100 ? 0 : crew[0] != 0;
45 		crew[1] = (men%100)/10 ? 0 : crew[1] != 0;
46 		crew[2] = men%10 ? 0 : crew[2] != 0;
47 	}
48 	for (r = 0; r < 2; r++) {
49 		if ((guns[r] || car[r]) && crew[2] && load[r] && ready[r] <= 0 && !ptr1 -> struck && ((closest[r] = closestenemy(player, (r ? 'r' : 'l'), 1)) != 30000)) {
50 			switch(load[r]) {
51 			case GRAPE:
52 				rangeofshot = 1;
53 				break;
54 			case CHAIN:
55 				rangeofshot = 3;
56 				break;
57 			case DOUBLE:
58 				rangeofshot = 1;
59 				break;
60 			case ROUND:
61 				rangeofshot = 10;
62 				break;
63 			}
64 			if ((target = range(player, closest[r])) <= rangeofshot && !scene[game].ship[closest[r]].file -> struck && (guns[r] || (car[r] && target < 3))) {
65 				Signal("%s (%c%c) within range of %s broadside.", closest[r], (r?"right":"left"));
66 				if (load[r] > CHAIN && target < 6) {
67 					Signal("Aim for hull or rigging? ", -1, 0);
68 					while ((buf = getch()) == EOF);
69 					addch(buf);
70 					if(buf == 'r')
71 						shootat[r] = RIGGING;
72 					else if (buf == 'h')
73 						shootat[r] = HULL;
74 					else {
75 						shootat[r] = -1;
76 						Signal("'Avast there! Hold your fire.'", -1, 0);
77 					}
78 				} else {
79 					shootat[r] = RIGGING;
80 					Signal("Fire? ", -1, 0);
81 					while ((buf = getch()) == EOF);
82 					addch(buf);
83 					if (buf == 'n') {
84 						shootat[r] = -1;
85 						Signal("Belay that! Hold your fire.", -1, 0);
86 					}
87 				}
88 				if (shootat[r] != -1) {
89 					fired = 1;
90 					rakehim = gunsbear(player, closest[r]) && !gunsbear(closest[r], player);
91 					temp = portside(closest[r], player, 1) - pos[closest[r]].dir + 1;
92 					if (temp < 1)
93 						temp += 8;
94 					if (temp > 8)
95 						temp -= 8;
96 					sternrake = temp > 4 && temp < 6;
97 					if (rakehim && !sternrake)
98 						Signal("Raking the %s!", closest[r], 0);
99 					else if (rakehim && sternrake)
100 						Signal("Stern Rake! %s splintering!", closest[r], 0);
101 					index = guns[r];
102 					if (target < 3)
103 						index += car[r];
104 					index = (index - 1)/3;
105 					index = index > 8 ? 8 : index;
106 					if (!rakehim)
107 						hit[r] = HDT[index][target-1];
108 					else
109 						hit[r] = HDTrake[index][target-1];
110 					if (rakehim && sternrake)
111 						hit[r]++;
112 					hit[r] += QUAL[index][ptr -> qual-1];
113 					for (n=0; n < 3 && ptr1 -> captured < 0; n++)
114 						if (!crew[n])
115 							if (index <= 5)
116 								hit[r]--;
117 							else
118 								hit[r] -= 2;
119 					if (ready[r] <= -30000)
120 						if (index <= 3)
121 							hit[r]++;
122 						else
123 							hit[r] += 2;
124 					if (ptr1 -> captured > -1)
125 						if (index <= 1)
126 							hit[r]--;
127 						else
128 							hit[r] -= 2;
129 					hit[r] += AMMO[index][load[r] - 1];
130 					if (((temp = ptr -> class) >= 5 || temp == 1) && windspeed == 5)
131 						hit[r]--;
132 					if (windspeed == 6 && temp == 4)
133 						hit[r] -= 2;
134 					if (windspeed == 6 && temp <= 3)
135 						hit[r]--;
136 					if (hit[r] >= 0) {
137 						roll[r] = die();
138 						if (load[r] == GRAPE)
139 							chits = hit[r];
140 						else {
141 							struct Tables *t;
142 							hit[r] = hit[r] > 10 ? 10 : hit[r];
143 							t = &(shootat[r] ? RigTable : HullTable)[hit[r]][roll[r]-1];
144 							chits = t->C;
145 							rhits = t->R;
146 							hhits = t->H;
147 							ghits = t->G;
148 							if (scene[game].ship[closest[r]].file -> FS)
149 								rhits *= 2;
150 							if (load[r] == CHAIN) {
151 								ghits = 0;
152 								hhits = 0;
153 							}
154 						}
155 						table(shootat[r], load[r], hit[r], closest[r], player, roll[r]);
156 					}
157 					scroll = 18;
158 					move(scroll++, 0);
159 					clearline();
160 					printw("Damage inflicted on the %s:", scene[game].ship[closest[r]].shipname);
161 					move(scroll++, 0);
162 					clearline();
163 					printw("\t%d HULL, %d GUNS, %d CREW, %d RIGGING", hhits, ghits, chits, rhits);
164 					load[r] = 0;
165 					if (!r) {
166 						ptr1 -> loadL = 0;
167 						ptr1 -> readyL = 0;
168 					} else {
169 						ptr1 -> loadR = 0;
170 						ptr1 -> readyR = 0;
171 					}
172 				}
173 			} else {
174 				load[r] = 0;
175 				Signal("Unable to fire %s broadside", -1, (r?"right":"left"));
176 			}
177 		} else
178 			Signal("Unable to fire %s broadside", -1, (r?"right":"left"));
179 	}
180 }
181 
182 leave(conditions)
183 int conditions;
184 {
185 	FILE *fp;
186 	int people;
187 	float net;
188 	char * capn;
189 	char message[60];
190 	register int n;
191 	struct logs log[10], temp;
192 
193 	signal(SIGHUP, SIG_IGN);
194 	signal(SIGINT, SIG_IGN);
195 	signal(SIGQUIT, SIG_IGN);
196 	signal(SIGALRM, SIG_IGN);
197 	signal(SIGCHLD, SIG_IGN);
198 
199 	if (conditions != -1) {
200 		capn = scene[game].ship[player].file -> captain;
201 		sprintf(message,"Captain %s relinquishing.",capn);
202 		Write(FILES + player, 1, 164, message);
203 
204 		if (fp = fopen(LOGFILE, "r+")) {
205 			net = (float) (scene[game].ship[player].file -> points) / specs[scene[game].ship[player].shipnum].pts;
206 			people = getw(fp);
207 			n = fread(log, sizeof(struct logs), 10, fp);
208 			for (; n < 10; n++)
209 				log[n].fname[0] = log[n].uid = log[n].fshipnum = log[n].fgamenum = log[n].netpoints = 0;
210 			rewind(fp);
211 			if(people < 0)
212 				putw(1, fp);
213 			else
214 				putw(people+1, fp);
215 			for (n=0; n < 10; n++)
216 				if (net > (float) log[n].netpoints / specs[scene[log[n].fgamenum].ship[log[n].fshipnum].shipnum].pts) {
217 					fwrite(log, sizeof(struct logs), n, fp);
218 					strcpy(temp.fname, capn);
219 					temp.uid = getuid();
220 					temp.fshipnum = player;
221 					temp.fgamenum = game;
222 					temp.netpoints = scene[game].ship[player].file -> points;
223 					fwrite(&temp, sizeof(struct logs), 1, fp);
224 					fwrite(log + n, sizeof(struct logs), 9 - n, fp);
225 					break;
226 				}
227 			fclose(fp);
228 		}
229 		Write(FILES + player, 1, 0, " ");
230 		Write(SCENARIO, 0, 8, scene[game].people - 1);
231 		if (done_curses) {
232 			screen();
233 			Signal("It looks like you've had it!", -1, 0);
234 			if (conditions == 1)
235 				Signal("Your ship was captured.", -1, 0);
236 			else if (conditions == 2)
237 				Signal("No more enemies.", -1, 0);
238 			else if (conditions == 3)
239 				Signal("Hurricane!  All ships destroyed.",
240 					-1, 0);
241 			else if (conditions == 4)
242 				Signal("The driver died.", -1, 0);
243 			move(0, LINES-1);
244 			scroll = LINES;
245 			clearline();
246 			refresh();
247 		} else {
248 			if (conditions == 4)
249 				printf("The driver died.\n");
250 		}
251 		fclose(syncfile);
252 	}
253 	if (done_curses) {
254 		nocrmode();
255 		echo();
256 		endwin();
257 	}
258 	exit(0);
259 }
260 
261 choke()
262 {
263 	leave(0);
264 }
265 
266 #include <wait.h>
267 
268 child()
269 {
270 	union wait status;
271 	int pid;
272 
273 	signal(SIGCHLD, SIG_IGN);
274 	do {
275 		pid = wait3(&status, WNOHANG|WUNTRACED, 0);
276 		if (pid < 0 || pid > 0 && !WIFSTOPPED(status))
277 			leave(4);
278 	} while (pid != 0);
279 	signal(SIGCHLD, child);
280 }
281 
282 grapungrap()
283 {
284 	register int n, k, l, number, captured;
285 	int buf;
286 
287 	for (n=0; n < scene[game].vessels ; n++) {
288 		if (n != player && (range(player, n) <= 1 || grapple(player, n))) {
289 			if ((captured = scene[game].ship[n].file -> captured) < 0)
290 				captured = n;
291 			Signal("Attempt to grapple or ungrapple %s (%c%c): ", n, 0);
292 			while ((buf = getch()) == EOF);
293 			addch(buf);
294 			if (buf == 'g') {
295 				number = die() < 3;
296 				if (!number && scene[game].ship[player].nationality == scene[game].ship[captured].nationality)
297 					number = 1;
298 				if (number) {
299 					for (l=0; l < 10 && scene[game].ship[player].file -> grapples[l].turnfoul; l++);
300 					if (!scene[game].ship[player].file -> grapples[l].turnfoul) {
301 						Write(FILES + player, 0, 124 + l*4, turn);
302 						Write(FILES + player, 0, 124 + l*4 + 2, n);
303 					}
304 					for (l=0; l < 10 && scene[game].ship[n].file -> grapples[l].turnfoul; l++);
305 					if (!scene[game].ship[n].file -> grapples[l].turnfoul) {
306 						Write(FILES + n, 0, 124 + l*4, turn);
307 						Write(FILES + n, 0, 124 + l*4 + 2, player);
308 					}
309 				}
310 				if (number) {
311 					Signal("Attempt succeeds!", 0, 0);
312 					makesignal("grappled with %s (%c%c)", n, player);
313 				} else
314 					Signal("Attempt fails.", 0, 0);
315 			}
316 			if (buf == 'u') {
317 				for (k=0; k < 10; k++) {
318 					if (scene[game].ship[player].file -> grapples[k].turnfoul && n == scene[game].ship[player].file -> grapples[k].toship) {
319 						if (die() < 3 || scene[game].ship[player].nationality == scene[game].ship[captured].nationality) {
320 							cleangrapple(player, n, k);
321 							Signal("Attempt succeeds!", 0, 0);
322 							makesignal("ungrappling with %s (%c%c)", n, player);
323 						} else
324 							Signal("Attempt fails.", 0, 0);
325 					}
326 				}
327 			}
328 		}
329 	}
330 }
331 
332 unfoulplayer()
333 {
334 	register int n, toship;
335 	int buf;
336 
337 	for (n=0; n < 10; n++) {
338 		if (scene[game].ship[player].file -> fouls[n].turnfoul) {
339 			Signal("Attempt to unfoul with the %s (%c%c)? ", (toship = scene[game].ship[player].file -> fouls[n].toship), 0);
340 			while ((buf = getch()) == EOF);
341 			addch(buf);
342 			if (buf == 'y' && die() < 3) {
343 				cleanfoul(player, toship, n);
344 				Signal("Attempt succeeds!", 0, 0);
345 				makesignal("unfouling %s (%c%c)", toship, player);
346 			} else if (buf == 'y')
347 				Signal("Attempt fails.", 0, 0);
348 		}
349 	}
350 }
351 
352 initialize(nodriver, randomize, debug)
353 char randomize, nodriver, debug;
354 {
355 	char comm[80], file[25], capn;
356 	char message[60];
357 	int load = ROUND, ready = -30000;
358 	int people = 0;
359 	int pid;
360 	register int n;
361 	register int k;
362 	char *nameptr;
363 
364 	srand(pid = getpid());
365 
366 	if (game < 0) {
367 		puts("Choose a scenario:\n");
368 		puts("\n\tNUMBER\tSHIPS\tIN PLAY\tTITLE");
369 		for (n=0; n < NUMOFSCENES; n++) {
370 			sprintf(file, "/tmp/.%d", n);
371 			printf("\t%d):\t%d", n, scene[n].vessels);
372 			if (access(file, 0) >= 0)
373 				printf("\tYES");
374 			else
375 				printf("\tno");
376 			printf("\t%s\n", scene[n].name);
377 		}
378 reprint:
379 		printf("\nScenario number? ");
380 		fflush(stdout);
381 		scanf("%d", &game);
382 		while (getchar() != '\n');
383 	}
384 	if (game < 0 || game >= NUMOFSCENES) {
385 		puts("Very funny.");
386 		exit(1);
387 	}
388 	sprintf(file, "/tmp/.%d", game);
389 	if (access(file, 0) < 0) {
390 		int omask;
391 #ifdef SETUID
392 		omask = umask(077);
393 #else
394 		omask = umask(011);
395 #endif
396 		syncfile = fopen(file, "w+");
397 		umask(omask);
398 	} else {
399 		syncfile = fopen(file, "r+");
400 		people = 1;
401 	}
402 	lastsync = 0;
403 	for (n=0; n < scene[game].vessels; n++) {
404 		nation[scene[game].ship[n].nationality + 1] = n + 1;
405 		if ((scene[game].ship[n].file =  (struct File *) calloc(1, sizeof(struct File))) == NULL) {
406 			puts("OUT OF MEMORY");
407 			exit(0);
408 		}
409 		scene[game].ship[n].file -> captured = -1;
410 	}
411 	if (!nation[2])
412 		nation[2] = nation[1];
413 	if (!nation[3])
414 		nation[3] = nation[2];
415 	if (people > 0) {
416 		puts("Synchronizing with the other players...");
417 		fflush(stdout);
418 		sync();
419 		capn = 1;
420 		for (n=0; n < scene[game].vessels && capn; n++) {
421 			capn = scene[game].ship[n].file -> captain[0];
422 			if (scene[game].ship[n].file -> struck || scene[game].ship[n].file -> captured > -1)
423 				capn = 1;
424 		}
425 		if (!capn)
426 			player = n-1;
427 		else {
428 			puts("All ships taken in that scenario.");
429 			for (n=0; n < scene[game].vessels; n++)
430 				free(scene[game].ship[n].file);
431 			people = 0;
432 			for (n=0; n < 5; n++)
433 				nation[n] = 0;
434 			fclose(syncfile);
435 			goto reprint;
436 		}
437 	} else
438 		player = 0;
439 	while (randomize) {
440 		static char *color[] =
441 			{ "(American)", "(British)", "(Spanish)", "(French)" };
442 		puts(scene[game].name);
443 		putchar('\n');
444 		for (n=0; n < scene[game].vessels; n++) {
445 			printf("  %2d:  %-10s %-15s  (%-2d pts)   ",
446 				n,
447 				color[scene[game].ship[n].nationality],
448 				scene[game].ship[n].shipname,
449 				specs[scene[game].ship[n].shipnum].pts);
450 			if(scene[game].ship[n].file -> captain[0])
451 				puts(scene[game].ship[n].file -> captain);
452 			else if (scene[game].ship[n].file -> struck)
453 				puts("(struck)");
454 			else if(scene[game].ship[n].file -> captured > -1)
455 				puts("(captured)");
456 			else
457 				puts("(available)");
458 		}
459 		putchar('\n');
460 		printf("Which ship do you want (0-%d)? ",scene[game].vessels-1);
461 		fflush(stdout);
462 		if (scanf("%d",&player) != 1 || player < 0 || player >= scene[game].vessels) {
463 			while (getchar() != '\n');
464 			puts("Say what?");
465 		} else {
466 			while (getchar() != '\n');
467 			sync();
468 			if (scene[game].ship[player].file -> captain[0] || scene[game].ship[player].file -> struck || scene[game].ship[player].file -> captured > -1)
469 				puts("Sorry, that ship is taken.");
470 			else
471 				break;
472 		}
473 	}
474 
475 	signal(SIGHUP, choke);
476 	signal(SIGINT, choke);
477 	signal(SIGQUIT, choke);
478 	signal(SIGCHLD, child);
479 
480 	Write(FILES + player, 1, 0, "begin");  /* he now exists */
481 	if (people)
482 		Write(SCENARIO, 0, 8, scene[game].people + 1);
483 	sync();
484 	printf("Your ship is the %s, a %s (%s crew).\n", scene[game].ship[player].shipname, info(player, message), quality(player));
485 	if ((nameptr = (char *) getenv("NAME")) && *nameptr)
486 		strcpy(comm,nameptr);
487 	else {
488 		fputs("Your name, Captain? ", stdout);
489 		fflush(stdout);
490 		gets(comm);
491 		if (!*comm) strcpy(comm, "no name");
492 	}
493 	comm[19] = '\0';
494 	for (k=0; k < 2; k++) {
495 		printf("\nInitial broadside %s (grape, chain, round, double): ", (k ? "right" : "left"));
496 		fflush(stdout);
497 		scanf("%s", file);
498 		switch(*file) {
499 		case 'g':
500 			load = GRAPE;
501 			break;
502 		case 'c':
503 			load = CHAIN;
504 			break;
505 		case 'r':
506 			load = ROUND;
507 			break;
508 		case 'd':
509 			load = DOUBLE;
510 			break;
511 		}
512 		if (k) {
513 			scene[game].ship[player].file -> loadR = load;
514 			scene[game].ship[player].file -> readyR = ready;
515 		} else {
516 			scene[game].ship[player].file -> loadL = load;
517 			scene[game].ship[player].file -> readyL = ready;
518 		}
519 	}
520 	Write(FILES + player, 1, 0, comm);
521 	if (!people && !nodriver) {
522 		char num[10];
523 		sprintf(num, "%d", game);
524 		if (!fork()) {
525 			if (debug)
526 				execl(DEBUGDRIVER, DRIVERNAME, num, 0);
527 			else
528 				execl(DRIVER, DRIVERNAME, num, 0);
529 			perror(DRIVER);
530 			kill(pid, SIGKILL);
531 			exit(1);
532 		}
533 	}
534 
535 	initscr();
536 	view = newwin(ROWSINVIEW, COLSINVIEW, 2, 1);
537 	slot = newwin(ROWSINVIEW, 3, 2, 1+COLSINVIEW);
538 	done_curses++;
539 	noecho();
540 	crmode();
541 
542 	board();
543 	sprintf(message, "Captain %s assuming command",comm);
544 	Write(FILES + player, 1, 164, message);
545 	windspeed = scene[game].windspeed;
546 	winddir = scene[game].winddir;
547 	turn = scene[game].turn;
548 
549 	iplotships();	/* new turn */
550 }
551 
552 /*
553  * Returns the NUMBER of the closest ship
554  */
555 closestenemy(fromship, side, anyship)
556 int fromship;
557 char side, anyship;
558 {
559 	register int n, olddist = 30000, ident, captured;
560 	register int dist, eclosest = 30000;
561 
562 	if ((ident = scene[game].ship[fromship].file -> captured) < 0)
563 		ident = fromship;
564 	for (n=0; n < scene[game].vessels; n++) {
565 		if ((captured = scene[game].ship[n].file -> captured) < 0)
566 			captured = n;
567 		if (n != fromship && pos[n].dir && (scene[game].ship[ident].nationality != scene[game].ship[captured].nationality || anyship)) {
568 			if (!side || gunsbear(fromship, n) == side) {
569 				dist = range(fromship, n);
570 				if (dist < olddist) {
571 					eclosest = n;
572 					olddist = dist;
573 				}
574 			}
575 		}
576 	}
577 	if (!side && olddist == 30000)
578 		leave(2);
579 	return(eclosest);
580 }
581 
582 main(argc, argv)
583 int argc;
584 char ** argv;
585 {
586 	register int crew, aheadfirst, ma, n;
587 	int ta;
588 	char message[60], ch;
589 	int uid;
590 	char nodrive = 0, randomize = 0, debug = 0;
591 	char *badstring();
592 	extern char _sobuf[];
593 
594 	setbuf(stdout, _sobuf);
595 	if (timetoplay() != 0 && gooduid(uid) != 0) {
596 		printf("Sorry Captain, but since you are not an Admiral and this is\n");
597 		printf("a weekday between %s, you are not permitted to\n",badstring());
598 		printf("sail.  Come back again some time when the harbor is open.\n");
599 		exit(1);
600 	}
601 
602 	while (*++argv && **argv == '-')
603 		switch (*++*argv) {
604 		case 'd':
605 			nodrive = 1;
606 			break;
607 		case 'D':
608 			debug++;
609 			break;
610 		case 'x':
611 			randomize = 1;
612 			break;
613 		default:
614 			printf("Unknown flag '%s'\n",*argv);
615 			break;
616 		}
617 	if (*argv)
618 		game = atoi(*argv);
619 	else
620 		game = -1;
621 	initialize(nodrive, randomize, debug);
622 	Signal("Aye aye, Sir", 0, 0);
623 	for(;;) {
624 		move(scroll++,0);
625 		clearline();
626 		addch('~');
627 		move(--scroll,0);
628 		refresh();
629 		ch = getch();
630 		switch(ch) {
631 		case 'm':
632 			crew = specs[scene[game].ship[player].shipnum].crew3;
633 			if (crew && !grappled(player) && !fouled(player) && windspeed) {
634 				ta = maxturns(player);
635 				aheadfirst = ta & 0100000;
636 				ma = maxmove(player, pos[player].dir, 0);
637 				ta &= 077777;
638 				acceptmove(ma, ta, aheadfirst);
639 			} else
640 				Signal("Unable to move", 0, 0);
641 			break;
642 		case 's':
643 			acceptsignal();
644 			break;
645 		case 'g':
646 			grapungrap();
647 			break;
648 		case 'u':
649 			unfoulplayer();
650 			break;
651 		case 'v':
652 			version();
653 			break;
654 		case 'b':
655 			boarding();
656 			break;
657 		case 'f':
658 			acceptcombat();
659 			break;
660 		case 'l':
661 			loadplayer();
662 			break;
663 		case 'c':
664 			changesail();
665 			break;
666 		case 'r':
667 			repair();
668 			break;
669 		case 'B':
670 			Signal("'Hands to stations!'", 0, 0);
671 			unboard(player, player, 1);	/* cancel DBP's */
672 			unboard(player, player, 0);	/* cancel offense */
673 			break;
674 		case '\f':
675 			signal(SIGALRM, SIG_IGN);
676 			viewrow = pos[player].row - ROWSINVIEW / 2;
677 			viewcol = pos[player].col - COLSINVIEW / 2;
678 			board();
679 			plotships(); /* don't create new turn */
680 			break;
681 		case 'L':
682 			scene[game].ship[player].file -> loadL = 0;
683 			scene[game].ship[player].file -> loadR = 0;
684 			scene[game].ship[player].file -> readyL = 0;
685 			scene[game].ship[player].file -> readyR = 0;
686 			Signal("Broadsides unloaded", 0, 0);
687 			break;
688 		case 'q':
689 			Signal("Type 'Q' to quit", 0, 0);
690 			break;
691 		case 'Q':
692 			leave(0);
693 			break;
694 		case 'I':
695 			for (n = 0; n < scene[game].vessels; n++)
696 				eyeball(player, n);
697 			break;
698 		case 'i':
699 			n = closestenemy(player, 0, 1);
700 			eyeball(player, n);
701 			break;
702 		}
703 		signalflags();
704 		lost();
705 	}
706 }
707 
708 char *saywhat(n)
709 int n;
710 {
711 	if(scene[game].ship[n].file -> captain[0])
712 		return(scene[game].ship[n].file -> captain);
713 	else if (scene[game].ship[n].file -> struck)
714 		return("(struck)");
715 	else if(scene[game].ship[n].file -> captured > -1)
716 		return("(captured)");
717 	else
718 		return("(computer)");
719 }
720 
721 eyeball(player, n)
722 int player, n;
723 {
724 	char message[80];
725 	register i;
726 
727 	if (scene[game].ship[n].shipdir) {
728 		sprintf(message, "%d, %s", range(player, n), saywhat(n));
729 		Signal("Sail ho! (range %s)", -1, message);
730 		switch(scene[game].ship[n].nationality) {
731 		case 0:
732 			strcpy(message, "American ");
733 			break;
734 		case 1:
735 			strcpy(message, "British ");
736 			break;
737 		case 2:
738 			strcpy(message, "Spanish ");
739 			break;
740 		case 3:
741 			strcpy(message, "French ");
742 			break;
743 		default:
744 			strcpy(message, "Gremlin ");
745 			break;
746 		}
747 		switch(specs[scene[game].ship[n].shipnum].class) {
748 		case 1:
749 		case 2:
750 			strcat(message, "Ship of the Line ");
751 			break;
752 		case 3:
753 		case 4:
754 			strcat(message, "Frigate ");
755 			break;
756 		case 5:
757 		case 6:
758 			strcat(message, "Sloop ");
759 			break;
760 		}
761 		switch(portside(player, n, 1) - pos[player].dir) {
762 		case -7:
763 		case 1:
764 			strcat(message, "off the starboard bow.");
765 			break;
766 		case -6:
767 		case 2:
768 			strcat(message, "off the starboard beam.");
769 			break;
770 		case -5:
771 		case 3:
772 			strcat(message, "off the starboard quarter.");
773 			break;
774 		case -4:
775 		case 4:
776 			strcat(message, "dead astern.");
777 			break;
778 		case -3:
779 		case 5:
780 			strcat(message, "off the port quarter.");
781 			break;
782 		case -2:
783 		case 6:
784 			strcat(message, "off the port beam.");
785 			break;
786 		case -1:
787 		case 7:
788 			strcat(message, "off the port bow.");
789 			break;
790 		case 0:
791 			strcat(message, "dead ahead.");
792 			break;
793 		}
794 		Signal(message, 0, 0);
795 	}
796 }
797