COSMOS Game (XENIX Specific), Part 03/03

Karl Denninger karl at ddsw1.MCS.COM
Fri Nov 18 15:57:47 AEST 1988


Part 3 of 3, see part 1 for details

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 3)."
# Contents:  cosmos.c funcs.c
# Wrapped by karl at ddsw1 on Thu Nov 17 23:53:11 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'cosmos.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cosmos.c'\"
else
echo shar: Extracting \"'cosmos.c'\" \(23237 characters\)
sed "s/^X//" >'cosmos.c' <<'END_OF_FILE'
X/*	Spacewar	- The final frontier
X
X	This package is Copyright 1988 Karl Denninger.  All rights reserved.
X	
X	All unauthorized mutants shall be destroyed, fed to vermin, and the
X	remains from this process will be prosecuted.
X
X*/
X
X/*	Definitions go below - Make sure you have these in front of include
X	files as these definitions should override the include files	*/
X
X
X#include	"cosmos.h"
X
extern	void clrin();				/* Interrupt handler */
extern	void die();				/* Death by disconnect */
X
int	extx, exty;
int	quit;					/* Halt variable */
char	*buffer;				/* Buffer pointer */
int	numcomp;				/* # of computer players */
char	home[128];				/* Home directory */
int	superuser, su2;				/* Uid of the superuser */
int	window;					/* Window size, must be < 20 */
int	foundchar = 0;				/* Found character? */
int	oldchar;				/* Old character if one */
struct	nameblock	*ship;			/* Pointer to ship's data */
struct	nameblock	name[MAXSHIPS];
struct	grid		onegrid;
struct	grid		oldgrid;
X
X
int	squares[SIZE];				/* Squares table */
int	drone = 0;				/* Not a drone */
long	numsecs;				/* Seconds since epoch */
long	nowsecs;				/* Time now */
long	startime;
long	minsday;				/* Minutes/day */
long	origmins;				/* Original minutes */
long	layoff;					/* How long to reset limits */
int	free_game;				/* Is this a free game? */
X
main(argc, argv)
int	argc;
char	*argv[];
X
X{
X
X	static	long	points;		/* Points accumulated */
X	static	int	type;		/* Class of ship */
X	char	shipname[40];
X	
X	struct	grid	tempgrid;
X	int	limited = 0;		/* Limited user */ 
X	int	timed = 0;		/* Timed user? */
X	long	now;
X	int	tenwarned = 0;		/* Warning flags */
X	int	fivewarned = 0;
X	int	twowarned = 0;
X	int	destx = -1;
X	int	nomove = 0;
X	int	desty = -1;
X	int	safe = -1;		/* Initially safe from collisions */
X	int	standir = 0;
X	int	shipcount;
X	int	scancount = 0, zx;
X	int	ntfree = 0;		/* Number of torpedoes free */
X	int	docked = 0;
X	int	tmpint;		/* Temp integer */
X	int	cheat = 0;
X
X	int	seg;			/* Shared segment number */
X	
X	int	status;			/* Status (ok/not ok) */
X	int	qcount = 0;		/* Quit counter */
X	int	energy_count = 0;	/* Temporary iterative counter */
X	int	stale_msg = TIME_PER_MSG;/* Stale message count */
X	int	tempenergy;
X	long	size;
X	int	oldx, oldy;
X	int	key;
X	int	tempint = 0;
X	
X	static	int	delta_x	= 0;	/* Initial delta 'x' */
X	static	int	delta_y = 0;	/* Initial delta 'y' */
X
X	int	semid;
X	int	flags;
X	char	tempstr[80];		/* 80 Character string */
X	char	tempstr2[80];		/* 80 Character string */
X	char	tmp[80];
X	FILE	*fid;
X	int	scanned = 0;
X
X	struct	nameblock	namebuf;
X	struct	torps	torparray[MAXFTORPS];
X					/* Array of torpedo coords */
X
X	long	game = sizeof(ccount) + (sizeof(onename) * MAXSHIPS) + 
X			(sizeof(onegrid) * MAXGRID) + (sizeof(onemsg) * MAXMSG);
X
X	size = (game);			/* Get size of game module */
X	quit = 0;
X	printf("Cosmos V%s\n", VERSION);
X	printf("Copyright 1988 MCS Inc. & Karl Denninger\n");
X#ifdef	LICENSEE
X	printf("Licensed to %s\n", LICENSEE);
X#endif
X	fflush(stdout);
X	for (extx = 0; extx < SIZE; extx++)
X		squares[extx] = (extx * extx);
X	for (extx = 0; extx < MAXFTORPS; extx++)
X		torparray[extx].inuse = 0;	/* Mark torpedo not in use */
X	sprintf(tmp, "%s", HOME);
X	if ((fid = fopen(tmp, "r")) != NULL) {
X		fscanf(fid, "%s %d %d %d %d %d %d %d", home, &superuser, &su2, 
X			&numcomp, &minsday, &origmins, &layoff, &free_game);
X		fclose(fid);
X	}
X	if ((seg = shmget(122L, size, IPC_CREAT|0660)) == -1) {
X		perror("create");
X		puts("Cannot execute due to shared-segment create fault");
X		exit(1);
X	}
X	if ((buffer = shmat(seg, (char *) NULL, 0)) == (char *) -1) {
X		perror("attach");
X		puts("Cannot execute due to shared-segment attach fault");
X		exit(1);
X	}
X	if ((semid = semget(122L, 1, 0660)) == -1) {
X		if ((semid = semget(122L, 1, 0660|IPC_CREAT)) == -1) {
X			perror("semaphone create");
X			exit(1);
X		}
X	} else {
X		acquire(semid);
X	}
X	signal(SIGHUP, die);			/* Save on hangups */
X	signal(SIGINT, clrin);			/* Clear input on ^C */
X	signal(SIGQUIT, SIG_IGN);
X	signal(SIGCLD, SIG_IGN);		/* No Zombies */
X
X#ifdef	ACCOUNTING
X/*	Now start accounting and figure out what time it is */
X
X	numsecs = addplayer(&limited, &timed, argc, argv[1]);/* Do accounting */
X	startime = time((int *) 0L);		/* Get current time */
X	nowsecs = startime + numsecs;		/* Set limit */
X	if (numsecs <= 0) {
X		release(semid);
X		printf("You are out of time at present to play COSMOS\n");
X		if (numsecs < 0) { 		/* No more credit */
X			printf("Your account balance has reached zero\n");
X			printf("Please contact the administrator\n");
X		} else
X			printf("You must wait for %d minutes before playing again\n", layoff);
X		exit(0);
X	}
X/*	End time accounting stuff */
X#endif
X
X	release(semid);
X	initscr();
X	acquire(semid);
X	noecho();
X	cbreak();
X	intrflush(stdscr, FALSE);		/* No flush on interrupt */
X#ifdef	M_TERMINFO
X	typeahead(-1);				/* No typeahead checks */
X#endif
X	srand((unsigned) time ((long *) 0L));
X	if (argc == 1)
X		showfile("Hello", semid, 0);
X	erase();
X	readgrid(0, 0, &onegrid);
X	if (onegrid.type == 0) {
X		mvaddstr(22,0,"Initializing game grid...");
X		refresh();
X		for (extx = 0; extx < SIZE; extx++) {
X			for (exty = 0; exty < SIZE; exty++) {
X				tempint = rand();
X				if (tempint < 500) {
X					if (tempint < 30) {
X						if (tempint < 10) {
X							onegrid.type = NEGBASE;
X							onegrid.energy = 1000000L;
X							onegrid.shield = 100;
X						} else {
X							onegrid.type = VOID;
X							onegrid.energy = roll(SIZE);
X							onegrid.shield = roll(SIZE);
X						}
X					} else {
X						if (tempint < 250) {
X							onegrid.type = STAR;
X							onegrid.energy = 2000000L;
X						} else { 
X							onegrid.type = PLANET;
X							onegrid.energy = 1000000L;
X						}
X						onegrid.shield = 0;
X					}
X				} else {
X					onegrid.type = EMPTY;
X					onegrid.shield = 0;
X					onegrid.energy = 0L;
X				}
X				storegrid(extx, exty, onegrid);
X			}
X		}
X		move(22,0);
X		clrtoeol();
X		refresh();
X	} 
X	if ((ship = (struct nameblock *) getship(argc, argv[1], semid, &extx, &exty)) == NULL) {
X#ifdef	ACCOUNTING
X		delplayer(argc, argv[1], startime);
X#endif
X		endwin();
X		puts("Fatal placement error");	/* Can't place the ship */
X		release(semid);			/* Release semaphore */
X		exit(0);			/* Quit */
X	}
X#ifdef	RANDOM_START
X	extx = roll(SIZE);
X	exty = roll(SIZE);
X#endif
X	if ((extx == 0) && (exty == 0)) {
X		extx = roll(SIZE); 
X		exty = roll(SIZE);
X	}
X	window = window_size[ship->type];
X	sprintf(tmp, "Welcome %s (%c)", ship->name, ship->token);
X	putmsg(tmp);
X
X/*	Now place the user's ship in the game.  	*/
X	
X	tempint = 0;
X	while (quit == 0) {
X		while ((extx < 0) || (extx >= SIZE))
X			extx = roll(SIZE);
X		while ((exty < 0) || (exty >= SIZE))
X			exty = roll(SIZE);
X		readgrid(extx, exty, &onegrid);
X		if (onegrid.type == EMPTY) 
X			quit++;
X		else {
X			extx = roll(SIZE); exty = roll(SIZE);
X			tempint++;
X			if (tempint >= 200) {
X				endwin();
X				release(semid);
X				puts("Cannot place ship!");
X			}
X		}
X	}
X	onegrid.type = ship->token;
X	onegrid.shield = ship->shield;
X	onegrid.energy = ship->energy;
X	onegrid.align = 0;			/* Neutral alignment */
X	ship->human = 1;			/* Human ship */
X	storegrid(extx, exty, onegrid);
X	quit = 0;
X	erase();
X	standout();
X	mvaddstr(23,20," Press the <?> key for assistance on COSMOS ");
X	standend();
X	while (quit == 0) {
X
X/* Move torpedoes */
X		movetorps(torparray, &ntfree); 
X		readgrid(extx, exty, &onegrid);
X		if (onegrid.type == EMPTY) {
X			if (!limited)
X				penalize();		/* Make it hurt :-) */
X			sprintf(tmp, "The %s (%c) explodes!", ship->name, ship->token);
X			putmsg(tmp);
X			explode(extx, exty, (ship->type * EXPLOSION), ship->type);/* Kill people near 'ya :-) */
X			ship->token = 0;	/* Delete from grid */
X			ship->name[0] = 0;
X			onegrid.type = EMPTY;
X			onegrid.shield = 0;
X			onegrid.energy = 0;
X			onegrid.align = 0;
X			storegrid(extx, exty, onegrid);
X			release(semid);		/* Release locks */
X			(void) dispstatus(extx, exty, window, docked);
X			refresh();
X			sleep(10);
X			erase();		/* Exit out from game */
X			refresh();
X			endwin();
X			puts("Your ship has disintegrated!");
X#ifdef	ACCOUNTING
X			if (!limited)
X				delplayer(argc, argv[1]);
X#endif
X			exit(0);
X		}
X
X/* Insert here any routines which should be performed after each turn --
X   specifically, those things which take energy when engaged such as shields */
X		
X		if (scancount > 0) {
X			scancount--;
X			if (!scancount) {
X				mvaddstr(1, 44, "                      ");
X				for (zx = 2; zx < 17; zx++) {
X					mvaddstr(zx, 44, "              ");
X				}
X			}
X		}
X		energy_count--;
X		if (energy_count < 0) {
X			energy_count = TIME_PER_EUNIT;
X			onegrid.energy--;
X		}
X#ifdef	RETIRE_MSGS
X		if (stale_msg-- <= 0) {
X			putmsg("");
X			stale_msg = TIME_PER_MSG;
X		}
X#endif
X		if (ship->wstatus & SHIELD_UP) {
X			onegrid.energy -= (ship->type * SHIELD_COST);
X			docked = 0;		/* Undock the craft */
X		}
X		if (ship->energy > onegrid.energy)
X			ship->energy = onegrid.energy;
X		if (ship->shield > onegrid.shield)
X			ship->shield = onegrid.shield;
X		if (ship->shield <= 0) {
X			ship->wstatus &= ~(SHIELD_UP);
X			ship->wstatus |= SHIELD_DEAD;
X		} else
X			ship->wstatus &= ~(SHIELD_DEAD);
X		if (ship->torps <= 0) {
X			ship->wstatus &= ~(TORPEDO_LOCK);
X			ship->wstatus |= TORPEDO_DEAD;
X			ship->numtorps = 0;	/* Blown off */
X		} else 
X			if (num_torps[ship->type] > 0)
X				ship->wstatus &= ~(TORPEDO_DEAD);
X		if (ship->mines <= 0) {
X			ship->wstatus &= ~(MINE_LOCK);
X			ship->wstatus |= MINE_DEAD;
X			ship->nummines = 0;	/* Blown off */
X		} else 
X			if (num_mines[ship->type] > 0)
X				ship->wstatus &= ~(MINE_DEAD);
X		ship->align = onegrid.align;		/* Alignment */
X		if (onegrid.hit) {
X			beep();
X			move(23,20);
X			standout();
X			if (onegrid.hit == 1)
X				printw("You've been hit!", onegrid.hit);
X			else
X				printw("You've been hit %d times!", onegrid.hit);
X			standend();
X			clrtoeol();
X			docked = 0;
X			onegrid.hit = 0;
X		}
X		storegrid(extx, exty, onegrid);
X		if ((ship->energy < 0) || (ship->life < 0) || (ship->hull < 0) || (ship->crew < 0)) {
X			if (!limited)
X				penalize();		/* Make it hurt :-) */
X			sprintf(tmp, "The %s (%c) explodes!", ship->name, ship->token);
X			putmsg(tmp);
X			explode(extx, exty, (ship->type * EXPLOSION), ship->type);/* Kill people near 'ya :-) */
X			ship->token = 0;	/* Delete from grid */
X			ship->name[0] = 0;
X			onegrid.type = EMPTY;
X			onegrid.shield = 0;
X			onegrid.energy = 0;
X			onegrid.align = 0;
X			storegrid(extx, exty, onegrid);
X			release(semid);		/* Release locks */
X			(void) dispstatus(extx, exty, window, docked);
X			refresh();
X			sleep(10);
X			erase();		/* Exit out from game */
X			refresh();
X			endwin();
X			puts("Your ship has disintegrated!");
X#ifdef	ACCOUNTING
X			delplayer(argc, argv[1]);
X#endif
X			exit(0);
X		}
X		status = dispstatus(extx, exty, window, docked);
X		if (ship->scanned) {
X			mvaddstr(23,20, "Captain!  We're being scanned!!");
X			ship->scanned = 0;
X		}
X		if (timed) {
X			now = time((long *) 0L);
X			if (now >= (nowsecs + 600)) {
X				if (!tenwarned) {
X					mvaddstr(23,20,"10 Minute warning!!!!");
X					clrtoeol();
X					beep();
X				}
X				tenwarned++;
X			}
X			if (now >= (nowsecs + 300)) {
X				if (!fivewarned) {
X					mvaddstr(23,20,"5 Minute warning!!!!");
X					clrtoeol();
X					beep();
X				}
X				fivewarned++;
X			}
X			if (now >= (nowsecs + 120)) {
X				if (!twowarned) {
X					mvaddstr(23,20,">TWO< Minute warning!!!! QUIT NOW!!");
X					clrtoeol();
X					beep();
X				}
X				twowarned++;
X			}
X			if (now >= (nowsecs)) {
X				mvaddstr(23,20,"TIME HAS EXPIRED");
X				clrtoeol();
X				beep();
X				release(semid);
X				refresh();
X				sleep(10);
X				acquire(semid);
X				quit++;		/* Exit the game next turn */
X			}
X		}
X		release(semid);		/* Release lock */
X		mvaddstr(22,20,"Command -> ");
X		clrtoeol();
X		oldx = extx;
X		oldy = exty;
X		extx = extx;
X		exty = exty;
X/*
X	The purpose of this section of code is to insure that there is
X	something to do before going off and reading input.  If there is
X	nothing to do, wait a second, then go update the display and try
X	again.
X*/
X		key = 0;
X		refresh();			/* Paint screen */
X		nap(NAPTIME);
X#ifdef	SLOWDOWN
X		if (((ship->type >= 10) && (shipcount < 5)) || (cheat))/* Marauder... */
X			shipcount = 5;		/* Nearly always can move... */
X		if (shipcount++ <= (ship->type / 3)) {/* If delay not expired */
X			nomove = 0;
X			key = 0;		/* No input allowed */
X		} else {			/* Otherwise... */
X#endif
X			nomove++;
X			shipcount = 0;		/* Reset counter to zero */
X			tempint = rdchkx(0);	/* Check stdin for input */
X			if (tempint) {		/* If key has been hit */
X				key = getchx();	/* Read it (special) */
X				move(23,20);
X				clrtoeol();
X			} 
X#ifdef	SLOWDOWN
X		}
X#endif
X		acquire(semid);			/* Regain lock on segment */
X
X/* End non-portable section */
X		if (!status)			/* If green */
X			qcount = 0;		/* Then reset exit marker */
X		if ((key >= '0') && (key <= '9')) {
X			destx = -1;		/* Clear if move key hit */
X			desty = -1;
X		}
X		if (key == 0) {
X			if ((nomove) && (destx != -1) && (desty != -1)) {
X				key = give_dir(extx, exty, destx, desty);
X				if (key == -1) {	/* Autopilot */
X					destx = -1;
X					desty = -1;
X					mvaddstr(23,20,"Arrived at destination, Captain");
X					clrtoeol();
X				}
X			}
X		}
X		switch (key) {
X			case 0:
X				break;	
X			case 24:		/* ^X - only superuser */
X				if ((getuid() == superuser) || (getuid() == su2)) { 
X					modgame(semid);
X					oldx = extx;
X					oldy = exty;
X					erase();
X				}
X				break;
X			case 23:		/* ^W - only for superuser */
X				if ((getuid() == superuser) || (getuid() == su2)){
X					window = 20;
X					erase();
X				}
X				break;
X			case 3:
X				if ((getuid() == superuser) || (getuid() == su2)) 
X					cheat ^= (-1);	/* Toggle cheat mode */
X				break;
X			case 16:		/* ^P - only superuser */
X				if ((getuid() == superuser) || (getuid() == su2)) {
X					ship->points += ship->points;
X				}
X				break;
X			case '+':
X				release(semid);
X				execit("drone","drone");/* Execute drone */
X				mvaddstr(23,20,"Enemy ship started...");
X				clrtoeol();
X				acquire(semid);
X				break;
X			case 'P':		/* PLAYERS command */
X				showplayers(semid, docked);
X				break;
X			case 'N':		/* Name (rename ship) command */
X				mvaddstr(22,20,"New Ship Name -> ");
X				release(semid);
X				refresh();
X				get_str(tempstr);
X				acquire(semid);
X				strncpy(ship->name, tempstr, 19);
X				ship->name[19] = 0;
X				break;
X			case 12:
X				clear();
X				break;
X			case 'Q':
X				if (status) {
X					if (++qcount == 1) {
X						mvaddstr(23,20,"Hit <Q> twice more to DESTRUCT");
X						clrtoeol();
X					} else {
X						if (qcount == 3)
X							quit++;
X					}
X				} else
X					quit++;
X				break;
X			case '?':
X				showfile("Help", semid, 1);
X				break;
X			case '8':
X				exty = exty + 1;
X				break;
X			case '7':
X				exty = exty + 1;
X				extx = extx - 1;
X				break;
X			case '1':
X				exty = exty - 1;
X				extx = extx - 1;
X				break;
X			case '9':
X				extx = extx + 1;
X				exty = exty + 1;
X				break;
X			case '3':
X				exty = exty - 1;
X				extx = extx + 1;
X				break;
X			case '2':
X				exty = exty - 1;
X				break;
X			case '4':
X				extx = extx - 1;
X				break;
X			case '6':
X				extx = extx + 1;
X				break;
X			case 'D':
X				docked = dock(extx, exty, &window);
X				break;
X			case 'B':
X				buildbase(semid, extx, exty);
X				break;
X			case 'b':
X				release(semid);
X				mvaddstr(22,20,"Broadcast -> ");
X				clrtoeol();
X				refresh();
X				get_str(tempstr);
X				sprintf(tempstr2, "%c: %s", ship->token, tempstr);
X				acquire(semid);
X				putmsg(tempstr2);
X				break;
X			case 'M':		
X				enter_smove(&destx, &desty, semid);
X				if ((destx < 0) || (destx >= SIZE) || (desty < 0) || (desty >= SIZE)) {
X					destx = -1;
X					desty = -1;
X				} else {
X					move(23,20);
X					sprintf(tmp, "Autopilot engaged, destination %d %d", destx, desty);
X					addstr(tmp);
X					clrtoeol();
X				}
X				break;	
X			case 'l':
X				if (ship->lasers > 30)
X					phasers(semid, extx, exty);
X				else
X					if (roll(200) < ship->lasers) 
X						phasers(semid, extx, exty);
X					else {
X						standout();
X						mvaddstr(23,20,"Laser malfunction!");
X						standend();
X						clrtoeol();
X					}
X				break;
X			case 'm':
X				if (ship->mines > 30)
X					mines(semid, extx, exty);
X				else {
X					if (roll(200) < ship->mines) 
X						mines(semid, extx, exty);
X					else {
X						standout();
X						mvaddstr(23,20,"Mine launcher malfunction!");
X						standend();
X						clrtoeol();
X					}
X				}
X				break;
X			case 'S':
X				scanned = scan(semid, extx, exty, window);/* Look */
X				if (scanned) 
X					scancount = 50;
X				ship->energy -= roll(100);
X				break;
X			case 's':
X				if (ship->shield > 30)
X					ship->wstatus = ship->wstatus ^ SHIELD_UP;
X				else {
X					if (roll(200) < ship->shield) 
X						ship->wstatus = ship->wstatus ^ SHIELD_UP;
X					else {
X						standout();
X						mvaddstr(23,20,"Shield control malfunction!");
X						standend();
X						clrtoeol();
X					}
X				}
X				break;
X			case 'R':		/* Range/RAM Control */
X				safe ^= -1;	/* XOR it... */
X				if (safe) 
X					mvaddstr(23,20,"Ramming SAFETY ON");
X				else {
X					standout();
X					mvaddstr(23,20,"Ramming SAFETY OFF");
X					standend();
X					beep();
X				}
X				clrtoeol();
X				break;
X			case 't':		/* Torpedoes! */
X				if (ship->torps > 30) {
X					if (num_torps[ship->type])
X						firetorps(extx, exty, torparray, semid, &ntfree, window);
X					else {
X						mvaddstr(23,20, "No torpedo capability");
X						clrtoeol();
X					}
X				} else {
X					if (roll(200) < ship->torps) 
X						firetorps(extx, exty, torparray, semid, &ntfree, window);
X					else {
X						standout();
X						mvaddstr(23,20,"Torpedo tube malfunction!");
X						standend();
X						clrtoeol();
X					}
X				}
X				break;
X				
X		}
X		if (extx < 0)
X			extx = 0;
X		if (exty < 0)
X			exty = 0;
X		if (extx >= SIZE)
X			extx = SIZE - 1;
X		if (exty >= SIZE)
X			exty = SIZE - 1;
X
X/* Now check to see if the engines are working... */
X
X		if (ship->engines < 30) {
X			if (roll(200) > ship->engines) {
X				extx = oldx;	/* If not, no movement! */
X				exty = oldy;
X				standout();
X				mvaddstr(23,20, "Engine failure!");
X				standend();
X				clrtoeol();
X			}
X		}
X
X/* End Engine check */
X
X		if ((extx != oldx) || (exty != oldy)) {
X			docked = 0;			/* Undock craft */
X			readgrid(extx, exty, &oldgrid);
X			if (oldgrid.type == VOID) {	/* Black hole */
X				extx = oldgrid.energy;
X				exty = oldgrid.shield;	/* Get new coords */
X				readgrid(extx, exty, &oldgrid);/* Switch! */
X			}
X			if (oldgrid.type != EMPTY) {	/* Collision! */
X				if ((safe) && (oldgrid.type != MINE)) {
X					extx = oldx;
X					exty = oldy;
X					readgrid(extx, exty, &tempgrid);
X					tempgrid.energy -= 300;
X					storegrid(extx, exty, tempgrid);
X					ship->energy -= 300;
X					destx = -1;
X					desty = -1;	/* Cancel move */
X					mvaddstr(23,20,"Collision avoided!");
X					clrtoeol();
X				} else {
X				mvaddstr(23,20, "Collision!");
X				tempenergy = oldgrid.energy;
X				readgrid(oldx, oldy, &onegrid);
X				oldgrid.energy -= ((onegrid.energy / 2) + 1000);
X				if (oldgrid.energy < 0) {
X					if ((oldgrid.type >= 'A') && (oldgrid.type <= 'Z')) {
X						namebuf.token = oldgrid.type;
X						tempint = locship(&namebuf, 1);
X						namebuf.token = 0;
X						namebuf.name[0] = 0;
X						storename(tempint, namebuf);
X					} else {
X						if (oldgrid.type == MINE) {
X							mvaddstr(23,20,"The mine explodes!");
X							refresh();
X							explode(extx, exty, (MINE_BOOM * EXPLOSION), MINE_BOOM);
X						} else {
X
X							mvaddstr(23,20, "FLASH!  The item you hit is DESTROYED!");
X							explode(extx, exty, (BIG_BOOM * EXPLOSION), BIG_BOOM);
X						}
X					}
X					clrtoeol();
X					oldgrid.type = EMPTY;
X				}
X				storegrid(extx, exty, oldgrid);
X				extx = oldx;		/* Go backwards */
X				exty = oldy;
X				if (tempenergy < 0)
X					tempenergy = 0 - tempenergy;
X				onegrid.energy -= ((tempenergy / 2) + 1000);
X				storegrid(extx, exty, onegrid);
X				}
X			} else {
X				move(22,0);
X				clrtoeol();
X				readgrid(oldx, oldy, &onegrid);
X		
X				onegrid.energy -= ((int) sqr(((extx - oldx) * (extx - oldx)) + ((exty - oldy) * (exty - oldy))) * (roll(E_RAND_PER_MOVE) + E_PER_MOVE));
X				storegrid(extx, exty, onegrid);
X				onegrid.type = EMPTY;
X				onegrid.energy = 0L;
X				onegrid.shield = 0L;
X				onegrid.align = (char) 0;
X				storegrid(oldx, oldy, onegrid);
X			}
X		}
X		
X		readgrid(extx, exty, &onegrid);
X		if (onegrid.hit) 		/* If we have been hit */
X			docked = 0;		/* Undock craft for sure */
X		if (docked) {			/* If docked with the base */
X			tmpint = (roll(RANDADD)+EADD) * ship->type;
X			onegrid.energy += (tmpint * docked);
X			ship->energy += (tmpint * docked);
X			if (onegrid.energy > e_require[ship->type]) {
X				onegrid.energy = e_require[ship->type];
X				ship->energy = e_require[ship->type];
X			}
X			if ((ship->shield < 100) && (ship->shield > 0)) {
X				if (docked != -1) {
X					ship->shield++;
X					onegrid.shield++;
X				} else {
X					ship->shield--;
X					onegrid.shield--;
X				}
X			}
X			if ((ship->engines < 100) && (ship->engines > 0))
X				ship->engines += docked;
X			if ((ship->life < 100) && (ship->life > 0))
X				ship->life += docked;
X			if ((ship->crew < 100) && (ship->crew > 0))
X				ship->crew += docked;
X			if ((ship->hull < 100) && (ship->hull > 0))
X				ship->hull += docked;
X			if ((ship->lasers < 100) && (ship->lasers > 0))
X				ship->lasers += docked;
X			if ((ship->mines < 100) && (ship->mines > 0))
X				ship->mines += docked;
X			if ((ship->torps < 100) && (ship->torps > 0))
X				ship->torps += docked;
X			if (docked != -1) {
X				ship->numtorps++;
X				ship->nummines++;
X			} else {
X				ship->numtorps--;
X				ship->nummines--;
X			}
X		}
X		if (energy_count == 0) {	/* If it's time */
X			if ((ship->shield < 100) && (ship->shield > 0)) {
X				ship->shield++;
X				onegrid.shield++;
X			}
X			if ((ship->engines < 100) && (ship->engines > 0))
X				ship->engines += 1;
X			if ((ship->life < 100) && (ship->life > 0))
X				ship->life += 1;
X			if ((ship->crew < 100) && (ship->crew > 0))
X				ship->crew += 1;
X			if ((ship->hull < 100) && (ship->hull > 0))
X				ship->hull += 1;
X			if ((ship->lasers < 100) && (ship->lasers > 0))
X				ship->lasers += 1;
X			if ((ship->torps< 100) && (ship->torps> 0))
X				ship->torps += 1;
X			if ((ship->mines < 100) && (ship->mines> 0))
X				ship->mines += 1;
X		}
X		if (ship->shield > 100) {
X			ship->shield = 100;
X			onegrid.shield = 100;
X		}
X		if (ship->engines > 100)
X			ship->engines = 100;
X		if (ship->life > 100)
X			ship->life = 100;
X		if (ship->crew > 100)
X			ship->crew = 100;
X		if (ship->hull > 100)
X			ship->hull = 100;
X		if (ship->torps > 100)
X			ship->torps = 100;
X		if (ship->lasers > 100)
X			ship->lasers = 100;
X		if (ship->mines > 100)
X			ship->mines = 100;
X		if (ship->numtorps > num_torps[ship->type])
X			ship->numtorps = num_torps[ship->type];
X		if (ship->nummines > num_mines[ship->type])
X			ship->nummines = num_mines[ship->type];
X		if (ship->nummines < 0)
X			ship->nummines = 0;
X		if (ship->numtorps < 0)
X			ship->numtorps = 0;
X		storegrid(extx, exty, onegrid);
X	}
X	sprintf(tmp, "%s (%c) leaves COSMOS", ship->name, ship->token);
X	putmsg(tmp);
X	if ((!status) && (!limited))
X		saveship(extx, exty);		/* Save position */
X	clear();
X	refresh();
X	endwin();
X	printf("Leaving the game with %d points\n", ship->points);
X	readgrid(extx, exty, &onegrid);		/* Delete ship */
X	onegrid.type = EMPTY;
X	storegrid(extx, exty, onegrid);
X	namebuf.token = ship->token;
X	tempint = locship(&namebuf, 1);
X	namebuf.token = 0;
X	namebuf.name[0] = 0;
X	storename(tempint, namebuf);
X	release(semid);
X	puts("Good bye!");
X	shmdt(buffer);				/* Detach shared segment */
X#ifdef	ACCOUNTING
X	delplayer(argc, argv[1]);
X#endif
X	exit(0);
X}
END_OF_FILE
if test 23237 -ne `wc -c <'cosmos.c'`; then
    echo shar: \"'cosmos.c'\" unpacked with wrong size!
fi
# end of 'cosmos.c'
fi
if test -f 'funcs.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'funcs.c'\"
else
echo shar: Extracting \"'funcs.c'\" \(17674 characters\)
sed "s/^X//" >'funcs.c' <<'END_OF_FILE'
X/*	Spacewar	- The final frontier
X
X	This package is Copyright 1988 Karl Denninger.  All rights reserved.
X	
X	All unauthorized mutants shall be destroyed, fed to vermin, and the
X	remains from this process will be prosecuted.
X
X*/
X
X/*	Definitions go below - Make sure you have these in front of include
X	files as these definitions should override the include files	*/
X
X#include	"cosmos.h"
X
extern	char	*buffer;
extern	int	quit;
extern	char	home[128];
X
extern	struct	nameblock	*ship;
extern	struct	nameblock	name[MAXSHIPS];
extern	struct	grid		onegrid;
extern	int	extx, exty, window;
X
extern	int	oldchar;		/* The character pre-read */
extern	int	foundchar;		/* If one was pre-read */
X
extern	int	drone;			/* If this is a drone ship */
extern	int	squares[];
X
char	xq[2] = {7, 0};
X
execit(file, arg0)
char	*file;
char	*arg0;
X{
X	if (!fork()) { 			/* If child */
X		close(0);
X		close(1);
X		close(2);
X		setpgrp();
X		execlp(file, arg0, (char *) NULL);
X		exit(0);
X	} 
X	return;
X}
X
void die()
X{
X	signal(SIGHUP, SIG_IGN);		/* Ignore further hangups */
X	quit++;					/* Insure we exit */
X	return;
X}
X
sqr(x)
int	x;
X{
X	int	last[2];
X	int	llim = 0;
X	int	ulim = SIZE;
X	int	p;
X	
X	last[0] = (SIZE / 2);
X	last[1] = 0;
X	
X	if (!x)
X		return(0);
X	while (x != squares[last[0]]) {
X		if ((squares[last[0]] <= x) && (squares[last[0] + 1] > x))
X			return(last[0]);
X		if (squares[last[0]] < x) {	/* If we're too low */
X			llim = last[0];		/* Lower limit reset */
X			p = last[0] + ((ulim - last[0]) / 2);
X			last[1] = last[0];
X			last[0] = p;
X		} else {
X			ulim = last[0];		/* If too high */
X			p = last[0] - ((last[0] - llim) / 2);
X			last[1] = last[0];
X			last[0] = p;
X		}
X	}
X	return(last[0]);
X}
X
X
void	clrin()
X{
X
X	signal(SIGINT, clrin);		/* Reset handler */
X	ioctl(0, TCFLSH, 0);		/* Flush input */
X	return;
X}
X
void	beep()
X{	
X	
X	write(1, xq, 1);
X	return;
X}
X
X#ifndef	M_TERMINFO
X
char	*get_str(string)		/* Get a string with proper echoing */
char	*string;
X{
X	char	*ptr;
X	int	key;
X	
X	ptr = string;
X	while ((key = getchx()) != 10) {		/* While not newline */
X		if (key == 13) 
X			return(string);
X		if ((key == 8) || (key == 127))	{ 	/* Backspace? */
X			if (ptr != string) {		/* If not empty */
X				ptr--;
X				*ptr = 0;
X				addch(8);
X				addch(32);
X				addch(8);
X			} else 
X				continue;
X		} else {
X			*ptr = key;
X			ptr++;
X			addch(key);
X		}
X		refresh();
X	}
X	*ptr = 0;		/* Null terminate */
X	refresh();
X	return(string);
X}
X	
X#else
X
get_str(string)
char	*string;
X{
X
X	echo();
X	getstr(string);
X	noecho();
X	return;
X}
X#endif
X
X/* Give direction code from source to destination  */
X
give_dir(x, y, destx, desty)
int	x;
int	y;
int	destx;
int	desty;
X{
X	int	xx, yy;
X	int	key = 0;
X
X	xx = abs(x - destx);		/* Get absolute distances */
X	yy = abs(y - desty);
X	if (!xx && !yy)			/* If both are 0 away... */
X		return(-1);		/* We are there */
X	if (xx == yy) {				/* If equal then use diagonal */
X		if ((x < destx) && (y < desty))	/* If going up and right */
X			key = '9';		/* Enter '9' */
X		if ((x < destx) && (y > desty))	/* If going down and right */
X			key = '3';		/* Enter '3' */
X		if ((x > destx) && (y < desty))	/* If going up and right */
X			key = '7';		/* Enter '1' */
X		if ((x > destx) && (y > desty))	/* If going up and right */
X			key = '1';		/* Enter '7' */
X	} else {				/* Otherwise move horiz. */	
X		if (xx > yy) {			/* If 'x' axis is longer */
X			if (x < destx)		/* If we're left of dest */
X				key = '6';	/* Move that way */
X			else
X				key = '4';	/* If we're right of dest */
X		} else {
X			if (y < desty)		/* If we're left of dest */
X				key = '8';	/* Move that way */
X			else
X				key = '2';	/* If we're right of dest */
X		}
X	}
X	return(key);				/* Return direction code */
X}
X
enter_smove(x, y, semid)
int	*x, *y;
int	semid;
X{
X	static	char	line[80];
X	int	key;
X	char	tmp[80];
X	
X	if (ship->type < 3) {		/* If a dinky ship return */
X		mvaddstr(23,20,"Captain, we don't have a navigational mode.");
X		clrtoeol();
X		return(0);
X	}
X	release(semid);
X	mvaddstr(22,20,"Destination -> ");
X	refresh();
X	get_str(tmp);
X	acquire(semid);
X	if (tmp[0] == 0) {		/* If line is blank */
X		if (line[0] == 0)	/* If no prior move */
X			return(0);	/* do nothing at all */
X		strcpy(tmp, line);	/* Otherwise resume old destination */
X		move(23,20);
X		printw("Resuming course to %s", tmp);
X	} else 
X		strcpy(line, tmp);	/* Save coordinates for later use */
X	return(sscanf(tmp, "%d %d", x, y));
X}
X
X/* This routine locates the closest of an object or class of objects within
X   the screen window.  Used all over the place, especially by the drone.  */
X
int	findobj(x, y, dist, lowobj, highobj, window)/* Locate direction */
int	*x, *y;					/* Current location */
int	*dist;					/* Distance to object */
int	lowobj, highobj;			/* Object desired */
int	window;
X	
X{
X	struct	grid	ourgrid;	/* Grid entry */
X	int	xx, yy;			/* Temporary storage for search */
X	int	retval = 0;
X	int	xr, yr;
X	int	lastfound;
X	int	dx, dy, dt;
X	
X	lastfound = (window/2) + 1;	/* Initial location vector */
X	for (xx = (*x - (window/2)); xx <= (*x + (window/2)); xx++) {
X		for (yy = (*y - (window/2)); yy <= (*y + (window/2)); yy++) {
X			if ((xx >= 0) && (xx < SIZE) && (yy >= 0) && (yy < SIZE)) {
X				readgrid(xx, yy, &ourgrid);
X				dx = abs(xx - *x);
X				dy = abs(yy - *y);
X				if (dx > dy)
X					dt = dx;
X				else
X					dt = dy;
X				if ((ourgrid.type >= lowobj) && 
X					(ourgrid.type <= highobj) && 
X					(ourgrid.type != ship->token) && 
X#ifdef	FASTMATH
X					(sqr((dx * dx) + (dy * dy)) < lastfound)  
X					)  {
X						lastfound = (int) sqr((dx * dx) + (dy * dy));
X#else
X					(dt < lastfound)  
X					)  {
X						lastfound = dt;
X#endif
X						retval = give_dir(*x, *y, xx, yy);
X						xr = xx; yr = yy;
X				}
X			}
X		}
X	}
X	*dist = lastfound;		/* Show distance to target */
X	*x = xr;			/* Where it was found */
X	*y = yr;			/* in x,y notation system */
X	return(retval);			/* Exit w/character to get there */
X}
X
X
X#ifdef	NO_RDCHK
X
int	getchx()
X
X{
X	int	chx;
X	if (!foundchar) {
X		read(0,&chx,1);
X		return(chx & 127);
X	} else {
X		foundchar = 0;
X		return(oldchar & 127);
X	}
X}
X
X
int	rdchkx(fd)
int	fd;
X{
X	char	chx[2];
X	int	flagtx;
X	int	tmpx;
X
X	if (foundchar == 0) {
X		flagtx = fcntl(0, F_GETFL, 0);		/* Get flags */
X		flagtx |= O_NDELAY;			/* turn O_NDELAY on */
X		fcntl(0, F_SETFL, flagtx);		/* Set it */
X		tmpx = read(0, chx, 1);
X		if (tmpx > 0) {
X			foundchar++;			/* We have one */
X			oldchar = chx[0];		/* Save the character */
X		} 
X		flagtx = fcntl(0, F_GETFL, 0);		/* Get flags */
X		flagtx &= ~O_NDELAY;			/* turn O_NDELAY on */
X		fcntl(0, F_SETFL, flagtx);		/* Set it */
X	} 
X	return(foundchar);				/* Tell 'em if read */
X}
X
X#else
X
rdchkx(fid)
int	fid;
X{
X	return(rdchk(fid));
X}
X
getchx()
X{
X	return(getch());
X}
X
X#endif
X
extern	void 	givedamage();
X
X
int	proximity(x, y, unit, distance, itemx, itemy)
int	x, y;
int	unit;
int	distance;
int	*itemx, *itemy;
X{
X	struct	grid	mygrid;
X	int	xx, yy;
X	int	exitval = 0;
X
X	for (xx = (x - distance); xx <= (x + distance); xx++) {
X		for (yy = (y - distance); yy <= (y + distance); yy++) {
X			if ((xx != x) || (yy != y)) {
X				readgrid(xx, yy, &mygrid);
X				if (unit) {
X					if (mygrid.type == unit) {
X						exitval = 1;
X						*itemx = xx;
X						*itemy = yy;
X						break;
X					}
X				} else {
X
X					if ((mygrid.type >= 'A') && (mygrid.type <= 'Z')) {
X						exitval = 1;
X						*itemx = xx;
X						*itemy = yy;
X						break;
X					}
X					if (mygrid.type == BASE) {
X						exitval = 2;
X						*itemx = xx;
X						*itemy = yy;
X						break;
X					}
X				}
X			}
X		}
X	}
X	return(exitval);
X}
X
void	explode(x, y, energy, dia)	/* Explode - take damage next to boom */
int	x, y, energy;
int	dia;				/* Diameter of the blast */
X
X/*	This can be recursively called, do not use static variables!	*/
X
X{
X	int	xx, yy;
X	struct	grid	expgrid;
X	char	tmp[80];
X	int	radius;
X	int	dx, dy, dt;
X
X	radius = dia / 2;		/* Divide by 2, produce radius */
X
X	sprintf(tmp, "Explosion at %d %d!", x, y);
X	putmsg(tmp);
X	if (drone == 0)
X		refresh();
X	for (xx = (x - radius); xx <= (x + radius); xx++) {
X		for (yy = (y - (radius)); yy <= (y + (radius)); yy++) {
X			if ((xx >= 0) && (xx < SIZE) && (yy >= 0) && (yy < SIZE )) {
X				dx = abs(xx - x);
X				dy = abs(yy - y);
X				if (dx > dy)
X					dt = dx;
X				else
X					dt = dy;
X				readgrid(xx, yy, &expgrid);
X				if ((xx != x) || (yy != y)) {
X#ifdef	FASTMATH
X					givedamage(xx, yy, (int) energy / (int) sqr(((dx * dx) + (dy * dy))), (char *) NULL, 1);
X#else
X					givedamage(xx, yy, (int) energy / dt, (char *) NULL, 1);
X#endif
X				}
X			}
X		}
X	}
X	return;
X}
X
void	showplayers(semid, docked)/* Show the players in the game */
int	semid;
int	docked;
X{
X	int	x, count;
X	struct	nameblock	entry;
X	struct	passwd		*psw;
X
X	release(semid);
X	erase();
X	if (docked)
X		mvaddstr(1,15,"Ships in Use - From The Galactic Intelligence Agency");
X	else
X		mvaddstr(1,15," Your ships' status in points, class & token");
X	mvaddstr(3,0,"Tkn   User          Ship Name               Class            Points");
X	x = 4;
X	count = 0;
X	while (count < MAXSHIPS) {
X		readname(count, &entry);
X		if (entry.token) {
X			if (entry.human)
X				psw = getpwuid(entry.uid);
X			else
X				psw = NULL;
X			if (entry.token == ship->token)
X				standout();
X			if ((entry.token == ship->token) || (docked)) {
X				entry.name[MAXNAME-1] = 0;/* Just in case */
X				mvaddch(x,1,entry.token);
X				if ((psw != NULL) && (entry.human))
X					mvaddstr(x,6,psw->pw_name); 
X				mvaddstr(x,20,entry.name);
X				move(x,44);
X				addstr(shiptypes[entry.type]);
X				move(x,61);
X				printw("%ld", entry.points);/* Current points */
X				x++;
X			}
X			if (entry.token == ship->token)
X				standend();
X		}
X		count++;
X	}
X	mvaddstr(23,0,"<<<ENTER>>> To Continue Your Game (others are still playing!)");
X	refresh();
X	x = getchx();
X	erase();
X	acquire(semid);
X	return;
X}
X
int	cdock(x, y, window)
int	x, y;
int	*window;
X{
X	int	xx, yy;
X	int	dist;
X	int	located;
X
X	xx = x; yy = y;
X	located = findobj(&xx, &yy, &dist, BASE, BASE, *window);
X	if ((abs(xx - x) < 2) && (abs(yy - y) < 2))  {
X		while (ship->points > pts[ship->type]) {
X			ship->type++;
X			ship->energy = (long) e_require[ship->type];
X			*window = window_size[ship->type];	/* Change viewer */
X		}
X		return(1);
X	} else
X		return(0);
X}
X
int	dock(x, y, window)
int	x, y;
int	*window;
X{
X
X	int	xx = -1;
X	int	yy = -1;
X	int	retval = 0;
X	struct	grid	tmpgrid;
X	int	negbase;
X
X	for (xx = -1; xx < 2; xx++) {
X		for (yy = -1; yy < 2; yy++) {
X			if (((xx + x) >= 0) && ((yy + y) >= 0) && ((xx + x) < SIZE) && ((yy + y) < SIZE)) {
X				readgrid((x + xx), (y + yy), &onegrid);
X				if ((onegrid.type == BASE) || (onegrid.type == NEGBASE)) {
X					if (onegrid.align == ship->align ) {
X						retval++;
X						negbase = onegrid.type;
X					} else {
X						mvaddstr(23,20,"Not your alliance!");
X						clrtoeol();
X					}
X				}
X			}
X		}
X	}
X	if (retval == 0) {
X		mvaddstr(23,20,"Nothing to dock with in range Sir.");
X		clrtoeol();
X	} else {
X		while (ship->points > pts[ship->type]) {
X			beep();
X			(ship->type)++;
X			move(23,20);
X			printw("Congratuations!  You now command a %s", shiptypes[ship->type]);
X			clrtoeol();
X			*window = window_size[ship->type];	/* Change viewer */
X			ship->energy = e_require[ship->type];	/* Get max energy */
X			clear();
X			readgrid(x, y, &tmpgrid);
X			tmpgrid.energy = ship->energy;
X			storegrid(x, y, tmpgrid);
X		}
X	}
X	if (negbase == '-') 
X		retval = -1;
X	return(retval);
X}
X	
putmsg(msg)
char	*msg;
X
X{
X	
X	char	*ptr;
X	struct	grid	onegrid;
X	struct	nameblock	name;
X	int	*cur_msg;
X	long	sizegrid;
X	int	msgnum;
X
X	sizegrid = (sizeof(onegrid) * SIZE * SIZE);
X	cur_msg = (int *) (buffer + sizeof(ccount) + (sizeof(name) * MAXSHIPS) + sizegrid);
X	msgnum = *cur_msg;
X	ptr = (char *) cur_msg;			/* Get pointer */
X	ptr += sizeof(msgnum);			/* Point past index */
X	ptr += (msgnum * MSGLEN);		/* Point to next msg to store */
X	strncpy(ptr, msg, 39);			/* Store message */
X	*(ptr + 35) = 0;			/* Null terminate at 35 chars */
X	msgnum++;
X	if (msgnum >= MAXMSG)
X		msgnum = 0;
X	*cur_msg = msgnum;
X	return(0);
X}
X
dspmsg()
X{
X
X	static	int	current_msg;
X	static	int	last_placed = 0;
X	int	dispmsg;
X	char	*ptr;
X	struct	grid	onegrid;
X	struct	nameblock	name;
X	static	char	msg0[40] = {0};
X	static	char	msg1[40] = {0};
X	static	char	msg2[40] = {0};
X	static	char	msg3[40] = {0};
X	int	*iptr;
X
X	iptr = (int *) (buffer + sizeof(ccount) + (sizeof(name) * MAXSHIPS) + (sizeof(onegrid) * SIZE * SIZE));
X	current_msg = *iptr++;
X	ptr = (char *) iptr;
X	while (last_placed != current_msg) {
X		strcpy(msg3, msg2);		/* Everyone down one */
X		strcpy(msg2, msg1);
X		strcpy(msg1, msg0);
X		strcpy(msg0, (ptr + (MSGLEN * last_placed)));
X		last_placed++;
X		if (last_placed == MAXMSG) {
X			last_placed = 0;
X		}
X	}
X	mvaddstr(21,44,msg0);
X	clrtoeol();
X	mvaddstr(20,44,msg1);
X	clrtoeol();
X	mvaddstr(19,44,msg2);
X	clrtoeol();
X	mvaddstr(18,44,msg3);
X	clrtoeol();
X	return(0);
X}
X
X
saveship(x, y)
int	x, y;
X{
X	
X	int	uid;
X	int	fid;
X	char	fname[80];
X	int	count;
X	struct	shiprecord	record;
X
X	uid = getuid();			/* Who are we (really) */
X	sprintf(fname, "%s/space.scorefile", HOMEDIR);
X	if ((fid = open(fname, O_RDWR|O_CREAT, 0660)) < 0) {
X		perror("scorefile");
X		endwin();
X		return(1);
X	}
X	count = 0;
X	while (read(fid, &record, sizeof(record)) == sizeof(record)) {
X		if (record.uid == uid)  {
X			count++;		/* Found record */		
X			lseek(fid, 0L - (sizeof(record)), 1);
X			break;
X		}
X	}
X	record.points = ship->points;
X	record.uid = uid;
X	record.type = ship->type;
X	record.x = x;
X	record.y = y;
X	record.energy = ship->energy;
X	strcpy(record.shipname, ship->name);
X	if (write(fid, &record, sizeof(record)) != sizeof(record))
X		perror("saveship");
X	close(fid);
X	return(0);
X}
X
penalize()
X{
X	
X	int	uid;
X	int	fid;
X	char	fname[80];
X	int	count;
X	struct	shiprecord	record;
X
X	uid = getuid();			/* Who are we (really) */
X	sprintf(fname, "%s/space.scorefile", HOMEDIR);
X	if ((fid = open(fname, O_RDWR|O_CREAT, 0660)) < 0) {
X		perror("scorefile");
X		endwin();
X		return(1);
X	}
X	count = 0;
X	while (read(fid, &record, sizeof(record)) == sizeof(record)) {
X		if (record.uid == uid)  {
X			count++;		/* Found record */		
X			lseek(fid, 0L - (sizeof(record)), 1);
X			break;
X		}
X	}
X	if (count > 0) {
X		record.points = (ship->points / 2);
X		ship->points = ship->points / 2;
X		record.uid = uid;
X		if (record.type > 1)			/* Demoted... */
X			record.type--;
X		record.energy = e_require[record.type];	/* Energy starting */
X		record.x = roll(SIZE);
X		record.y = roll(SIZE);
X		strcpy(record.shipname, ship->name);
X		write(fid, &record, sizeof(record));
X	}
X	close(fid);
X	return(0);
X}
X
X
int	roll(max) 
int	max;
X{
X	int	x;
X	int	mult;
X
X	mult = 32767/max;		/* Counts per unit */
X	x = rand();
X	return(x / mult);
X}
X
X
int	locship(entry, flag)
struct	nameblock	*entry;
int	flag;
X
X{
X	int	b = 0;
X	static	int	match;			/* Match indicator */
X	struct	nameblock locbuf;
X	
X	match = -1;
X	while (b < MAXSHIPS) {
X		readname(b, &locbuf);
X		if (flag == 0) {
X			if (strcmp(locbuf.name, entry->name) == 0) {
X				match = b;
X				break;
X			}
X		} else {
X			if (locbuf.token == entry->token) {
X				match = b;
X				break;
X			}
X		}
X		b++;
X	}
X	return(match);
X}
X
X
X
X
acquire(semid)
int	semid;
X{
X	semoper(semid, -1);
X}
X
release(semid)
int	semid;
X{
X	semoper(semid, 1);
X}
X
semoper(semid, op)
int	semid;
int	op;
X
X{
X	struct	{
X		short	sem_num;
X		short	sem_op;
X		short	sem_flg;
X	} sembuf;
X
X	sembuf.sem_num = 0;
X	sembuf.sem_op = op;
X	sembuf.sem_flg = 0;
X	signal(SIGINT, SIG_IGN);
X	if (semop(semid, &sembuf, 1) == -1) {	
X		if (drone == 0)
X			endwin();
X		perror("semop");
X		puts("FATAL ERROR: Please re-run the game");
X		exit(1);
X	}
X	signal(SIGINT, clrin);
X}
X
showfile(file, semid, ind)
char	*file;
int	semid;
int	ind;
X{
X	int	x = 0, y;
X	FILE	*fid;
X	char	tmp[80];
X	int	key;
X
X	release(semid);
X	clear();
X	sprintf(tmp, "%s/%s", HOMEDIR, file);
X	if ((fid = fopen(tmp, "r")) == NULL)  {
X		acquire(semid);
X		return;
X	}
X	if (ind) {
X		x = 2;
X		mvaddstr(0,0,"--> COSMOS Online Library Display               Status >> ");
X		mvaddstr(1,0,"-------------------------------------------------------------------------------");
X	} else
X		x = 0;
X	while (fgets(tmp, 80, fid) != NULL) {
X		if (x >= 22) {
X			if (ind) {
X				mvaddstr(22,0,"-------------------------------------------------------------------------------");
X			}
X			mvaddstr(23,0,"             <<<< SPACE >>>> for the next page, <Q> to quit");
X			if (ind) {
X				while (!rdchkx(0)) {
X					if (calcstatus(extx, exty, window, 0))  {
X						standout();
X						mvaddstr(0,60,"RED");
X						standend();
X					} else
X						mvaddstr(0,60,"GREEN");
X					clrtoeol();
X					refresh();
X					sleep(1);
X				}
X			}
X			refresh();
X			key = getchx();
X			if (ind) {
X				for (y = 2; y < 22; y++) {
X					move(y, 0);
X					clrtoeol();
X				}
X			} else {
X				for (y = 0; y < 23; y++) {
X					move(y, 0);
X					clrtoeol();
X				}
X			}
X			if ((key == 'q') || (key == 'Q'))  {
X				acquire(semid);
X				erase();
X				return;
X			}
X			if (ind)
X				x = 2;
X			else
X				x = 0;
X		}
X		mvaddstr(x++, 0, tmp);
X		clrtoeol();
X	}
X	fclose(fid);
X	refresh();
X	(void) getchx();
X	erase();
X	acquire(semid);
X	return;
X}
X
readname(x, entry)
int	x;
struct	nameblock *entry;
X{
X	struct	nameblock locrec;
X	char	*ptr;
X
X	ptr = buffer + sizeof(ccount) + (sizeof(locrec) * x);
X	memcpy(entry, ptr, sizeof(locrec));
X	return(0);
X}
X
char	*storename(x, entry)
int	x;
struct	nameblock entry;
X{
X	char	*ptr;
X
X	ptr = buffer + sizeof(ccount) + (sizeof(entry) * x);
X	return((char *) memcpy(ptr, &entry, sizeof(entry)));
X}
X
readgrid(x, y, entry) 
int	x;
int	y;
struct	grid	*entry;
X
X{
X	int	incr;
X	char	*ptr;
X	long	*ptrl;
X	
X	incr = sizeof(ccount) + sizeof(name) + (x * sizeof(onegrid) * SIZE);
X	incr += y * sizeof(onegrid);
X	ptr = (buffer + incr);
X	memcpy(entry, ptr, sizeof(onegrid));
X	return(0);
X}
X
storegrid(x, y, entry) 
int	x;
int	y;
struct	grid	entry;
X{
X	int	incr;
X	char	*ptr;
X
X	incr = sizeof(ccount) + sizeof(name) + (x * sizeof(onegrid) * SIZE);
X	incr += y * sizeof(onegrid);
X	ptr = (buffer + incr);
X	memcpy(ptr, &entry, sizeof(entry));
X	return(0);
X}
END_OF_FILE
if test 17674 -ne `wc -c <'funcs.c'`; then
    echo shar: \"'funcs.c'\" unpacked with wrong size!
fi
# end of 'funcs.c'
fi
echo shar: End of archive 3 \(of 3\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

--
Karl Denninger (karl at ddsw1.MCS.COM, ddsw1!karl)
Data: [+1 312 566-8912], Voice: [+1 312 566-8910]
Macro Computer Solutions, Inc.    	"Quality solutions at a fair price"



More information about the Alt.sources mailing list