DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T m

⟦812f91199⟧ TextFile

    Length: 17967 (0x462f)
    Types: TextFile
    Names: »main.c.orig«

Derivation

└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen
    └─ ⟦this⟧ »cph85dist/search/main.c.orig« 

TextFile

#ifndef lint
static char rcsid[] = "$Header: main.c,v 2.2 85/08/06 22:26:37 matt Exp $";
#endif
/*
 *
 * search
 *
 * multi-player and multi-system search and destroy.
 *
 * Original by Greg Ordy	1979
 * Rewrite by Sam Leffler	1981
 * Socket code by Dave Pare	1983
 * Ported & improved
 *      by Matt Crawford	1985
 *
 * main game iteration loop
 *
 * Copyright (c) 1979
 *
 * $Log:	main.c,v $
 * Revision 2.2  85/08/06  22:26:37  matt
 * Victims lose 20% of their points to their killers.
 * 
 * Change handling of messages to provide echo of text.
 * (per hastings@navajo)
 * 
 * Revision 2.1  85/04/10  17:31:23  matt
 * Major de-linting and minor restructuring.
 * 
 * Revision 1.6  85/02/11  15:02:50  matt
 * Inform new player that game is in GUTS mode
 * 
 * Revision 1.5  85/02/11  12:46:33  matt
 * fixed spelling of "bonzai"
 * 
 * Revision 1.4  85/02/11  12:43:54  matt
 * added GUTS mode
 * 
 * Revision 1.3  85/02/10  19:18:59  matt
 * Added more realistic orbiting.
 * 
 * Revision 1.2  85/02/09  23:49:49  matt
 * Eliminated the dependence on the value of the mask after
 * select() times out.  Use the return value to distinguish
 * a timeout!!
 * 
 */

#include <stdio.h>
#include <sgtty.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <netdb.h>
#include <sys/file.h>
#include <sys/time.h>

#include "defines.h"
#include "structs.h"

/*
 * Major data bases
 */
t_torps		torps[NTORP];		/* torpedoes data base */
t_sbase		sbase[NBASE];		/* star bases data base */
t_planet	planet;			/* planet data base */
t_alien		alien[NALIEN];		/* aliens data base */
t_burst		bursts[NBURST];		/* shrapnel data base */
t_player	player[NPLAYER];	/* players */

int		dtabsiz;		/* descriptor table size */
int		pfd;			/* playerfile fd */
int		loc_sock;		/* local socket */
int		errfile;		/* error log file */
int		nplayer;		/* # of players currently in game */
int		nobody;			/* is anybody playing? */
#ifdef INET
int		in_sock;		/* internet socket */
#endif

t_player	*whoscab;		/* identity of current scab */
int		TDIST;			/* max distance a torpedo can go */
char		xxi;
char		yyi;
char		ppx;			/* planet x-coord */
char		ppy;			/* planet y-coord */
char		dx;
char		dy;
long		ptime;			/* search playing time counter */

int		NALIENS = NALIEN;
extern		int errno;
/*
 * Solar flare stuff
 */
int		sfcount;		/* solar flare timer */
int		sfflag;			/* solar flare in progress */

int		gutsflag;		/* playing in guts mode */

int		numbnode;
struct plist	*avl;
t_player	*wholist;
char		visual[NPLAYER][NPLAYER];/* group visibility matrix */
struct		timeval tim_inp;


main(argc, argv)
int argc;
char  *argv[];
{
	extern	t_player *newplayer();
	extern	void	apilot(),
			autopi(),
			bcast(),
			bflush(),
			cput(),
			dock(),
			done(),
			enteritem(),
			facts(),
			fnode(),
			gathermsg(),
			groupm(),
			home(),
			init(),
			initplayer(),
			invisible(),
			joing(),
			launch(),
			lookg(),
			magnif(),
			makeburst(),
			makeflare(),
			makescab(),
			movealien(),
			moveburst(),
			nuke(),
			orbit(),
			orbmove(),
			outgame(),
			phaser(),
			pmesg(),
			prompt(),
			pstatus(),
			quitg(),
			rmsg(),
			seeall(),
			seescab(),
			sethome(),
			set_delay(),
			uplst(),
			xploit();
			
	register t_player *p;
	register t_player *pl;
	register t_alien *pa;
	register t_burst *pb;
	register t_sbase *ps;
	register t_torps *pt;
	t_player *np;
	char	x, y;
	int	mf;
	int	gutsvote;
	char	buf[255];
	char	xx, yy, c;
	int	port_num = DEFAULT_IN_PORT;
	int	nfds;
	int	mask;
	int	save_mask;

	dtabsiz = getdtablesize();

#ifdef INET
	if (argc > 2) {
		printf("searchd: arg count error\n");
		exit(1);
	}
	if (argc == 2)
		port_num = atoi(argv[1]);
#endif
#ifndef DEBUG
	if (fork())
		exit(0);
	{ int s;
	  for (s = 0; s < dtabsiz; s++)
		(void) close(s);
	  (void) open("/", 0);
	  (void) dup2(0, 1);
	  (void) dup2(0, 2);
	  s = open("/dev/tty", 2);
	  if (s >= 0) {
		(void)ioctl(s, TIOCNOTTY, NULLCH);
		(void)close(s);
	  }
	}
#endif
	/*
	 * set up data bases
	 */
	init();
	/*
	 * set up sockets: port number doesn't matter
	 * if INET isn't defined
	 */
	if (!initsocks(port_num))
		exit(1);
	/*
	 * block indefinitely until the first player enters the game
	 * then start the player loop
	 */
	save_mask = 0;
#ifdef INET
	save_mask = 01<<loc_sock | 01<<in_sock;
#else
	save_mask = 01<<loc_sock;
#endif
	nobody = 1;
	/*
	 * Main loop -- works in a hard run polling the input socket
	 * of each player.  Each turn around the loop defines a time
	 * unit in search.
	 */
	for (;;) {
		ptime++;		/* time marches on ... */
		if (--sfcount == 0) {	/* ring a ding, time for a flare */
			makeflare();
			NALIENS = NALIEN-nplayer;
		}
		/*
		 * if nobody's playing, wait until someone generates
		 * some sort of request
		 */
		if (nobody || !nplayer) {
			gutsflag = FALSE;
			tim_inp.tv_usec = 0L;
			tim_inp.tv_sec = 3600L;
			do {
				mask = save_mask;
				nfds = select(dtabsiz, &mask, NULLINT, NULLINT, &tim_inp);
			} while (nfds == 0);
			tim_inp.tv_sec = 0L;
			nobody = 0;
		}
		if ((ptime % 16) == 0) {
			np = newplayer(save_mask);
			if (np != NULL) {
				nplayer++;
				initplayer(np);
				sprintf(buf, "new player %s\n", np->plname);
				errlog(buf);
				for (p = player; p < &player[NPLAYER]; p++)
					if (p->status.alive == TRUE && p != np)
						pmesg(p, "From scanners-- NEW PLAYER");
				if (gutsflag)
					pmesg(np, "This game is in GUTS mode");
			}
		} else
			set_delay();
		/*
		 * Command scanning loop...
		 */
		nobody = 0;
		gutsvote = !gutsflag;
		for (p = player; p < &player[NPLAYER]; p++) {
			if (p->status.alive == FALSE) {
				nobody++;
				continue;
			}
			gutsvote = gutsflag ? gutsvote || p->status.guts
					    : gutsvote && p->status.guts;
			if (p->status.ap == TRUE)	/* update autopilot */
				apilot(p);
			if (p->status.orb == TRUE)	/* update orbiting */
				orbmove(p);
			x = p->offx;
			y = p->offy;
			if (!p->ninput)
				if (pinput(p) < 0)
					continue;
			if (p->ninput <= 0)
				goto constvel;
			c = (*p->pinputq++)&0177;
			p->ninput--;
			/*
			 * Two letter commands (e.g. launch torpedo) are
			 *  marked as a command pending, so that when the
			 *  second char comes in it can be processed entirely.
			 */
			if (p->cmdpend > 0) {
				switch (p->cmd) {
				case 'h': 
					home(p, c);
					break;
				case '5':
				case 't': 
					p->status.ap = FALSE;
					launch((thing *)p, c, PLAYER, x, y,
						1, p->curx, p->cury, 0);
					break;
				case 'g':
					groupm(p, c);
					break;
				case 'q':
					quitg(p, c);
					break;
				case 'n':
					nuke(p, c);
					break;
				case 'j':
					joing(p, c);
					break;
				case 's': 
					sethome(p, c);
					break;
				case 'b': 
					bcast(p, c);
					break;
				case 'a': 
					autopi(p, c);
					break;
				case 'r': 
					rmsg(p, c);
					break;
				case 'm': 
					magnif(p, c);
					break;
				case 'Q':
					if (c != 'Y' && c != 'y') {
						p->cmd = p->cmdpend = 0;
						prompt(p, "");
						goto constvel;
					}
					done(p);
					break;
				}
				goto constvel;
			}
			switch (c) {
			case 'e': 
				if (p->energy != p->preve) {
					cput(EGYDATA, p, "%d", p->energy);
					p->preve = p->energy;
				}
				break;
			case 'p': 
				if (p->points != p->prevp) {
					cput(PTDATA, p, "%d", p->points);
					p->prevp = p->points;
				}
				break;
			case 'f': 
				facts(p);
				break;
			case 'l':
				lookg(p);
				break;
			case 'x': 
				xploit(p);
				break;
			case '0': 
				if (p->whocent == 0)
					break;
				if (isalien(p->whocent)) {
					pa = (t_alien *)p->whocent;
					/*
					 * Register a hit on an alien
					 */
					pa->hit++;
					if (pa->hit > 25)
						pa->stats = DEAD;
					pa->cix = -1;
					pa->ciy = (rand()%3)-1;
					p->points = p->points+4;
					write(p->socket, "\007", 1);
				}
				break;
			case 'i': 
				invisible(p);
				break;
			case 'c': 
				cput(TMDATA, p, "%d", (int)ptime);
				break;
			case 'o': 
				orbit(p);
				x = p->offx;
				y = p->offy;
				break;
			case 'z': 
				seescab(p);
				break;
			case 'd': 
				dock(p);
				break;
			case 'v': 
				cput(VLDATA, p, "%d %d", p->offx, p->offy);
				break;
			case 'G':
				p->status.guts = TRUE;
				break;
			case 'W':
				p->status.guts = FALSE;
				break;
			case '\014':	/* ^L */
			case '@': 
				fnode(p->plstp);
				initplayer(p);
				break;
			case 'Q':
				prompt(p, "Really quit?");
				goto savecmd;
			case 'q':
			case 'j':
				prompt(p, "enter group members");
				goto savecmd;
			case 'b':
			case 'g':
				gathermsg(p);
				/*FALL THRU*/
			case 'r':
			case 'h':
			case 't':
			case 'a':
			case 'm':
			case 's':
			case 'n':
			case '5':
			savecmd:
				p->cmdpend++;
				p->cmd = c;
				break;
			default: 
				goto vel;
			}
			goto constvel;
		vel: 
			/*
			 * Velocity changes handled here...
			 */
			p->status.ap = p->status.orb = FALSE;
			switch (c) {
			case NO: 
				y--;
				break;
			case NE: 
				x++;
				y--;
				break;
			case EA: 
				x++;
				break;
			case SE: 
				x++;
				y++;
				break;
			case SO: 
				y++;
				break;
			case SW: 
				x--;
				y++;
				break;
			case WE: 
				x--;
				break;
			case NW: 
				x--;
				y--;
				break;
			default:
				goto constvel;
			}
			p->offx = x;
			p->offy = y;
			cput(VLDATA, p, "%d %d", p->offx, p->offy);
	constvel:
			/*
			 * Update energy total for player:
			 *  standing still adds one unit/iteration
			 *  magnification costs energy proportional to M-factor
			 *  velocity > 1 in any direction costs one unit/iter
			 *  invisibility costs INCOST/iteration
			 */
			p->curx = p->curx+x;
			p->cury = p->cury+y;
			if ((x > 1 || x < -1) || (y > 1 || y < -1))
				p->energy--;
			if (x == 0 && y == 0)
				p->energy++;
			if (p->mflg > 1)
				p->energy -= p->mflg;
			if (p->status.invis == TRUE)
				p->energy = p->energy-INCOST;
			if (p->energy > p->maxe)
				p->energy = p->maxe;
			if (p->energy <= 0)
				outgame(p);
			if (p->status.crash == TRUE) {
				pstatus(p, "Crash into planet--all is lost!!");
				if (p->points >= 50)
					p->points -= 50;
				p->status.killed = TRUE;
				done(p);
			}
			/*
			 * Update energy display only every 16 iterations --
			 *  otherwise, it would be constantly updated at
			 *  great expense
			 */
			if (p->energy != p->preve && (ptime&017) == 0) {
				cput(EGYDATA, p, "%d", p->energy);
				p->preve = p->energy;
			}
			if (p->points != p->prevp) {
				cput(PTDATA, p, "%d", p->points);
				p->prevp = p->points;
			}
		}
		if (nobody < NPLAYER)
			nobody = 0;
		if (gutsvote && !gutsflag)
			seeall("\07Entering GUTS mode-- beware!");
		else if (gutsflag && !gutsvote)
			for (p = player; p < &player[NPLAYER]; p++)
				if (p->status.alive == TRUE)
					pmesg(p, "Entering WIMP mode");
		gutsflag = gutsvote;
		moveburst();
		/*
		 * Update the state of the aliens...
		 */
		for (pa = alien; pa < &alien[NALIEN]; pa++) {
			if (pa->stats == DEAD)
				continue;
			if (pa->type == WANDER) {
				pa->count--;
				/* time to change direction */
				if (pa->count == 0) {
					pa->cix = (rand()%3)-1;
					pa->ciy = (rand()%3)-1;
					pa->count = (rand()%50)+30;
				}
			}
			/* shankers "dance" */
			if (pa->type == SHANK && pa->aname == NAMESH)
				movealien(pa);
			else {
				pa->cx = pa->cx + pa->cix;
				pa->cy = pa->cy + pa->ciy;
			}
		}
		/*
		 * Update motion of torpedoes
		 */
		for (pt = torps; pt < &torps[NTORP]; pt++) {
			if (pt->owner == 0)
				continue;
			pt->torx += pt->xinc;
			pt->tory += pt->yinc;
			pt->tcount--;
			/*
			 * Check for alien hits
			 */
			for (pa = alien; pa < &alien[NALIEN]; pa++) {
				if (pa->stats == DEAD)
					continue;
				if (pa->cx == pt->torx && pa->cy == pt->tory) {
					/* shot by a shanker */
					if(isalien(pt->owner))
						continue;
					pa->hit++;
					if (pa->hit > 25) {
						makeburst(pa->cx, pa->cy);
						pa->stats = DEAD;
					}
					pl = (t_player *)pt->owner;
					/* 6 points for any hit on an alien */
					pl->points += 6;
					pl->ahits++;
					/* X-aliens are worth 20 points */
					if (pa->type == WANDER)
						pl->points += 20;
					/*
					 * move off in a random direction
					 *  after a hit
					 */
					pa->cix = (rand()%3)-1;
					pa->ciy = (rand()%3)-1;
					if (pa->cix == 0 && pa->ciy == 0)
						pa->cix = pa->ciy = 1;
					/*
					 * Hit a shanker -- they fight back
					 */
					if (pa->type == SHANK) {
						pa->aname = NAMESH;
						pa->whotoget = pt->owner;
						pl->points += 20;
						pa->count = 0;
						pmesg(pl, "From a shanker-- bonzai!");
					}
					pstatus(pl, "\007Torpedo hit on alien!");
					pt->owner = 0;
				}
			}
			if (pt->tcount == 0)
				pt->owner = 0;
		}
		/*
		 * Main screen update loop...
		 */
		for (p = player; p < &player[NPLAYER]; p++) {
			if (p->status.alive == FALSE)
				continue;
			wholist = p;
			x = p->curx;
			y = p->cury;
			mf = p->mflg;
			p->whocent = 0;
			dx = x-ppx;
			dy = y-ppy;
			/*
			 * Display any portion of Quartone visible
			 */
			if (dx > -18 && dx < 18 && dy > -10 && dy < 10) {
				register int pp;

				for (pp = 0; pp != 17; pp++) {
					dx = planet.places[pp][0];
					dy = planet.places[pp][1];
					if (!onscreen (dx, dy, x, y))
						continue;
					if (dx == x && dy == y)
						p->status.crash = TRUE;
					xx = (dx-x)/mf+XWIND;
					yy = (dy-y)/mf+YWIND;
					enteritem(xx, yy, NAMEP);
				}
			}
			/*
			 * Shrapnel around?
			 */
			for (pb = bursts; pb < &bursts[NBURST]; pb++) {
				if (pb->cbactive == 0)
					continue;
				dx = x-pb->cbx;
				dy = y-pb->cby;
				if (dx > -21 && dx < 21 && dy > -13 && dy < 13) {
					register int is;

					for (is = 0; is != 9; is++) {
						dx = pb->shrap[is][0];
						dy = pb->shrap[is][1];
						if (dx == 0 && dy == 0)
							continue;
						if (!onscreen (dx, dy, x, y))
							continue;
						/* a piece hit -- mark it */
						if (dx == x && dy == y)
							p->status.bur = TRUE;
						xx = (dx-x)/mf+XWIND;
						yy = (dy-y)/mf+YWIND;
						enteritem(xx, yy, '.');
					}
				}
			}
			/*
			 * Any star bases visible?
			 */
			for (ps = sbase; ps < &sbase[NBASE]; ps++) {
				if (!onscreen (ps->xpos, ps->ypos, x, y))
					continue;
				if (ps->xpos == x && ps->ypos == y)
					p->whocent = (thing *)ps;
				xx = (ps->xpos-x)/mf+XWIND;
				yy = (ps->ypos-y)/mf+YWIND;
				enteritem(xx, yy, '*');
			}
			/*
			 * Show other players -- take care of groups
			 */
			for (pl = player; pl < &player[NPLAYER]; pl++) {
				register int shift;

				if (pl == p)
					continue;
				if (pl->status.alive == FALSE)
					continue;
				if (!onscreen (pl->curx, pl->cury, x, y))
					continue;
				if (pl->status.invis == TRUE) {
					if (!visual[pl-player][p-player])
						continue;
					shift = 'a'-'A';
				} else
					shift = 0;
				if (pl->curx == x && pl->cury == y) {
					p->whocent = (thing *)pl;
					pl->whocent = (thing *)p;
				}
				xx = (pl->curx-x)/mf+XWIND;
				yy = (pl->cury-y)/mf+YWIND;
				c = (pl-player)+'A'+shift;
				enteritem(xx, yy, c);
			}
			/*
			 * Show visible aliens...
			 */
			for (pa = alien; pa < &alien[NALIEN]; pa++) {
				if (pa->stats == DEAD)
					continue;
				if (!onscreen (pa->cx, pa->cy, x, y))
					continue;
				if (pa->cx == x && pa->cy == y)
					p->whocent = (thing *)pa;
				xx = (pa->cx-x)/mf+XWIND;
				yy = (pa->cy-y)/mf+YWIND;
				enteritem(xx, yy, pa->aname);
				if (pa->type == SHANK && (t_player *)(pa->whotoget) == p)
					pa->onscr = ON;
			}
			/*
			 * Track torpedoes...
			 */
			for (pt = torps; pt < &torps[NTORP]; pt++) {
				if (pt->owner == 0)
					continue;
				if (!onscreen (pt->torx, pt->tory, x, y))
					continue;
				if (pt->torx == x && pt->tory == y)
					p->whocent = (thing *)pt;
				xx = (pt->torx-x)/mf+XWIND;
				yy = (pt->tory-y)/mf+YWIND;
				enteritem(xx, yy, '+');
			}
			/*
			 * Update the display -- attempts minimal changes
			 */
			uplst();
			if (p->offx != 0)
				cput(POS1DATA, p, "%d", p->curx); 
			if (p->offy != 0)
				cput(POS2DATA, p, "%d", p->cury);
			if (p->status.bur == TRUE) {	/* shrapnel damage */
				pmesg(p, "From damage control-- Shrapnel!!");
				cput(INDATA, p, "off");
				p->status.bur = FALSE;
				p->status.invis = FALSE;
				p->energy -= SHRAPCOST;
				if (p->energy < 0)
					p->energy = 0;
				p->maxe -= SHRAPCOST;
			}
			/*
			 * Check for damage
			 */
			if (isalien(p->whocent) && ((t_alien *)p->whocent)->type == WANDER) {
				/*
				 * X-alien collision
				 */
				p->maxe = p->maxe-15;
				if (p->energy > p->maxe)
					p->energy = p->maxe;
				pmesg(p, "From engine room-- Collision!!");
			}
			/*
			 * Torpedo hit, and not in orbit
			 */
			if (istorp(p->whocent) &&
			    (gutsflag || p->status.orb == FALSE)) {
				pt = (t_torps *)p->whocent;
				/*
				 * If it's a shanker, let it get back to
				 *  wandering -- it's done its job
				 */
				if (isalien(pt->owner)) {
					phaser((t_alien *)pt->owner, p);
					pt->owner = 0;
					continue;
				}
				/*
				 * Torpedo hit by a player
				 */
				pl = (t_player *)pt->owner;
				if (pl == p) {
					pt->owner = 0;
					pmesg(p, "From damage control-- SELF HIT!!!");
					p->points -= 75;
					if (p->points < 0)
						p->points = 0;
					continue;
				}
				pt->owner = 0;
				pstatus(pl, "\007Hit on %c", (p-player)+'A');
				pstatus(p, "\007Torpedo damage suffered!");
				pl->points += 50;
				pl->phits++;
				p->maxe -= 50;
				if (p->energy > p->maxe)
					p->energy = p->maxe;
				if (p->maxe <= 0) {
					int	booty = p->points / 5;
					pmesg(p, "From damage control-- FATAL HIT!");
					pmesg(pl, "From navigation-- TOTAL DESTRUCTION!");
					pl->points += 5 + booty;
					pl->pkills++;
					p->points -= booty;
					/*
					 * Time for a new scab??
					 */
					if ((pl->pkills%4) == 0)
						makescab(pl);
					makeburst(p->curx, p->cury);
					p->status.killed = TRUE;
					done(p);
				}
			}
		}
		/*
		 * trying to minimize the number of writes to the sockets.
		 */
		for (p = player; p < &player[NPLAYER]; p++) {
			if (p->status.alive == TRUE)
				bflush(p);
		}
	}
}