v02i038: multiplayer startrek game, Part04/07

Mike Wexler mikew at wyse.wyse.com
Fri Dec 9 12:00:44 AEST 1988


Submitted-by: ddickey at gonzo.eta.com (Dan A. Dickey)
Posting-number: Volume 2, Issue 38
Archive-name: xtrek/part04

#! /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 4 (of 7)."
# Contents:  input.c rmove.c subdaemon.c
# Wrapped by mikew at wyse on Thu Dec  8 17:51:41 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'input.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'input.c'\"
else
echo shar: Extracting \"'input.c'\" \(17920 characters\)
sed "s/^X//" >'input.c' <<'END_OF_FILE'
Xstatic char sccsid[] = "@(#)input.c	1.2";
X/*
X
X	Copyright (c) 1986 	Chris Guthrie
X
XPermission to use, copy, modify, and distribute this
Xsoftware and its documentation for any purpose and without
Xfee is hereby granted, provided that the above copyright
Xnotice appear in all copies and that both that copyright
Xnotice and this permission notice appear in supporting
Xdocumentation.  No representations are made about the
Xsuitability of this software for any purpose.  It is
Xprovided "as is" without express or implied warranty.
X
X*/
X
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <stdio.h>
X#include <math.h>
X#include <sys/types.h>
X#include <sys/socket.h>
X#ifdef SUN40
X#include <sys/filio.h>
X#else SUN40
X#define	FD_SET(n, s)	(((s)->fds_bits[0]) |= (1 << n))
X#define	FD_CLR(n, s)	(((s)->fds_bits[0]) &= ~(1 << n))
X#define	FD_ZERO(s)	bzero((char *)(s), sizeof (*(s)))
X#define	FD_ISSET(n, s)	(((s)->fds_bits[0]) & (1 << n))
X#include <sys/ioctl.h>
X#endif
X#ifdef hpux
X#include <time.h>
X#else hpux
X#include <sys/time.h>
X#endif hpux
X#include <signal.h>
X#include <errno.h>
X#include "defs.h"
X#include "data.h"
X
X#define WINSIDE 500
X
Xstatic int	doTheRedrawDude, skipUpdates = 1;
Xint		peerdied;
X
Xextern Window	openStats();
Xextern char	*newwin();
X
Xinitinput(p)
Xregister struct player	*p;
X{
X    XSelectInput(p->display, p->iconWin, ExposureMask);
X    XSelectInput(p->display, p->w, 
X	KeyPressMask|ButtonPressMask|ButtonReleaseMask|ExposureMask);
X    XSelectInput(p->display, p->mapw, 
X	KeyPressMask|ButtonPressMask|ButtonReleaseMask|ExposureMask);
X    XSelectInput(p->display, p->messagew, 
X	KeyPressMask|ButtonPressMask|ButtonReleaseMask|ExposureMask);
X    XSelectInput(p->display, p->tstatw, ExposureMask);
X
X    /*  May want this for a later refresh 
X    XSelectInput(p->display, p->war,
X	ButtonPressMask|ButtonReleaseMask|ExposureMask);
X    */
X
X    XSelectInput(p->display, p->warf, ButtonPressMask|ButtonReleaseMask|ExposureMask);
X    XSelectInput(p->display, p->warr, ButtonPressMask|ButtonReleaseMask|ExposureMask);
X    XSelectInput(p->display, p->wark, ButtonPressMask|ButtonReleaseMask|ExposureMask);
X    XSelectInput(p->display, p->waro, ButtonPressMask|ButtonReleaseMask|ExposureMask);
X    XSelectInput(p->display, p->wargo, ButtonPressMask|ButtonReleaseMask|ExposureMask);
X    XSelectInput(p->display, p->warno, ButtonPressMask|ButtonReleaseMask|ExposureMask);
X    XSelectInput(p->display, p->helpWin, ExposureMask);
X    XSelectInput(p->display, p->planetw, ExposureMask);
X    XSelectInput(p->display, p->playerw, ExposureMask);
X}
X
XsetRedrawFlag()
X{
X	if (skipUpdates)
X		doTheRedrawDude = 1;
X	else
X		doTheRedrawDude++;
X}
X
Xdeadpeer() {
X	fprintf(stderr, "SIGPIPE\n");
X	peerdied = 1;
X}
X
Xint	playerchange;
Xint	nplayers;
Xint	nrobots;
X
Xinput()
X{
X    register struct player	*p;
X    register int		pno;
X    XEvent data;
X    XEvent *tmp;
X    char buf[40];
X    char sbuf[40];
X    char	new_display[50], new_login[50];
X    int nchar;
X    fd_set	ofdset, fdset;
X    struct itimerval	udt;
X    int			didevent;
X    long		elapsed;
X    int			noplayer_updates;
X    struct sockaddr	addr;
X    int			addrlen;
X    int			ns;
X    int			on = 1;
X    int			si;
X
X    signal(SIGALRM, setRedrawFlag);
X    udt.it_interval.tv_sec = 0L;
X    udt.it_interval.tv_usec = UPDATE;
X    udt.it_value.tv_sec = 0L;
X    udt.it_value.tv_usec = UPDATE;
X    setitimer(ITIMER_REAL, &udt, 0);
X
X    tmp = &data;
X
X    signal(SIGPIPE, SIG_DFL);
X    FD_ZERO(&ofdset);
X    FD_ZERO(&fdset);
X    playerchange = 1;
X    nplayers = 0;
X    nrobots = 0;
X    noplayer_updates = 0;
X    didevent = 1;
X    ns = -1;
X    while (1) {
X	if (ns < 0 && !nplayers && (noplayer_updates++ > (30 * UPS))) {
X		save_planets();
X		exit(0);
X	}
X	if (!didevent) {
X		fdset = ofdset;
X		pno = select(32, &fdset, (fd_set *) NULL, (fd_set *) NULL, (struct timeval *) NULL);
X		if (pno < 0) {
X			FD_CLR(xtrek_socket, &fdset);
X			if (ns > 0)
X				FD_CLR(ns, &fdset);
X		}
X	}
X	if (FD_ISSET(xtrek_socket, &fdset) || (ns > 0 && FD_ISSET(ns, &fdset))) {
X		addrlen = sizeof (addr);
X		errno = 0;
X		if (ns == -1) {
X			ns = accept(xtrek_socket, &addr, &addrlen);
X			if (ns > 0) {
X				si = 0;
X				peerdied = 0;
X				signal(SIGPIPE, deadpeer);
X				ioctl(ns, FIONBIO, &on);
X				FD_SET(ns, &ofdset);
X			}
X		}
X		errno = 0;
X		if (ns > 0) {
X			pno = read(ns, &sbuf[si], 1);
X			if (pno > 0)
X				si += pno;
X			if (pno == 0)
X				peerdied = 1;
X			if (pno > 0 && si >= 2 && sbuf[si-2] == '\015' && sbuf[si-1] == '\012') {
X				sbuf[si-2] = '\0';
X				if (sscanf(sbuf, "Display: %s Login: %s", new_display, new_login) != 2) {
X					write(ns, "Bad format\n", 11);
X					close(ns);
X					ns = -1;
X				} else {
X					write(ns, "Creating connection on ", 23);
X					write(ns, new_display, strlen(new_display));
X					pno = findslot();
X					if (pno == MAXPLAYER) {
X						write(ns, "No more room in game\n", 21);
X					} else {
X						strcpy(players[pno].p_monitor, new_display);
X						strcpy(players[pno].p_login, new_login);
X						players[pno].p_status = PSETUP;
X						sprintf(sbuf, " as player number %d\n", pno);
X						write(ns, sbuf, strlen(sbuf));
X					}
X				}
X				playerchange = 1;
X			}
X		}
X	}
X	if (peerdied) {
X		peerdied = 0;
X		playerchange = 1;
X	}
X	if (playerchange) {
X		FD_ZERO(&ofdset);
X		FD_SET(xtrek_socket, &ofdset);
X		if (ns > 0)
X			FD_SET(ns, &ofdset);
X		nplayers = 0;
X		nrobots = 0;
X		signal(SIGPIPE, SIG_DFL);
X		for (pno = 0, p = &players[pno]; pno < MAXPLAYER; pno++, p++) {
X			if (p->p_status != PFREE) {
X				nplayers++;
X				if ((p->p_flags & PFROBOT) == 0) {
X					FD_SET(p->xcn, &ofdset);
X				} else
X					nrobots++;
X			}
X		}
X		if (nplayers)
X			noplayer_updates = 0;
X		playerchange = 0;
X	}
X
X	while (doTheRedrawDude-- > 0) {
X		intrupt();
X	}
X
X	didevent = 0;
X	for (pno = 0, p = &players[pno]; pno < MAXPLAYER; pno++, p++) {
X		if (p->p_status == PFREE)
X			continue;
X
X		if (p->p_status == PSETUP) {
X			char	*rval;
X
X			playerchange = 1;
X			rval = newwin(p);
X			if (rval == (char *) NULL)		/* Create new windows */
X				p->p_team = (FED|ROM|KLI|ORI);	/* Team's they can pick from */
X			else {
X				write(ns, rval, strlen(rval));
X				write(ns, "\n", 1);
X				p->p_status = PFREE;
X			}
X			close(ns);
X			ns = -1;
X			if (p->p_status == POUTFIT)
X				mapAll(p);		/* Map 'em... */
X		}
X
X		if (p->p_status == POUTFIT) {
X			if (!(p->p_flags & PFENTER)) {
X				p->p_flags |= PFENTER;
X				entrywindow(p);	/* Show them the entry window */
X			} else {
X				elapsed = time(0) - p->startTime;
X				if (elapsed > AUTOQUIT) {
X					playerchange = 1;
X					XCloseDisplay(p->display);
X					p->display = (Display *) NULL;
X					p->p_status = PFREE;
X					p->p_flags &= ~PFENTER;
X				} else {
X					showTimeLeft(p, elapsed, AUTOQUIT, 0);
X					redrawFed(p, p->fwin, 0);
X					redrawRom(p, p->rwin, 0);
X					redrawKli(p, p->kwin, 0);
X					redrawOri(p, p->owin, 0);
X				}
X			}
X		}
X
X		if (!(FD_ISSET(p->xcn, &fdset)))
X			continue;
X
X		if (!XPending(p->display))
X			continue;
X
X		didevent = 1;
X		XNextEvent(p->display, (XEvent *)&data);	/* grab the event */
X		if ((!(p->copilot /*|| watch*/)) && (p->p_updates > p->delay)) {
X		    p->p_flags &= ~(PFWAR);
X		}
X
X		switch ((int) data.type) {
X
X		    case KeyPress:
X			if (p->p_status == POUTFIT) {
X				int	team;
X
X				team = -1;
X				if (data.xkey.window == p->fwin)
X					team = 0;
X				else if (data.xkey.window == p->rwin)
X					team = 1;
X				else if (data.xkey.window == p->kwin)
X					team = 2;
X				else if (data.xkey.window == p->owin)
X					team = 3;
X				else if (data.xkey.window == p->qwin) {
X					playerchange = 1;
X					XCloseDisplay(p->display);
X					p->display = (Display *) NULL;
X					p->p_status = PFREE;
X					p->p_flags &= ~PFENTER;
X				}
X				if (team >= 0) {
X					del_entrywindow(p);
X					XClearWindow(p->display, p->w);
X					p->p_flags &= ~PFENTER;
X					enter(team, XDisplayString(p->display), pno);
X					playerchange = 1;
X				}
X				continue;
X			}
X			if (inputIgnored(p))
X			    continue;
X			if ((p->p_flags & PFSELFDEST) /*&& (!watch)*/) {
X			    p->p_flags &= ~PFSELFDEST;
X			    warning(p, "Self Destruct has been canceled");
X			}
X			nchar = XLookupString(&tmp->xkey, buf, sizeof buf,
X				(KeySym *)NULL, (XComposeStatus *)NULL);
X			if (nchar > 0) {
X			    if (data.xkey.window == p->messagew)
X				smessage(p, *buf);
X			    else
X				keyaction(p, *buf, &tmp->xkey);
X			}
X			break;
X
X		    case ButtonPress:
X			if (p->p_status == POUTFIT) {
X				int	team;
X
X				team = -1;
X				if (data.xkey.window == p->fwin)
X					team = 0;
X				else if (data.xkey.window == p->rwin)
X					team = 1;
X				else if (data.xkey.window == p->kwin)
X					team = 2;
X				else if (data.xkey.window == p->owin)
X					team = 3;
X				else if (data.xkey.window == p->qwin) {
X					playerchange = 1;
X					XCloseDisplay(p->display);
X					p->display = (Display *) NULL;
X					p->p_status = PFREE;
X					p->p_flags &= ~PFENTER;
X				}
X				if (team >= 0) {
X					del_entrywindow(p);
X					XClearWindow(p->display, p->w);
X					p->p_flags &= ~PFENTER;
X					enter(team, XDisplayString(p->display), pno);
X					playerchange = 1;
X				}
X				continue;
X			}
X			if (inputIgnored(p))
X				continue;
X			if ((p->p_flags & PFSELFDEST) /*&& (!watch)*/) {
X			    p->p_flags &= ~PFSELFDEST;
X			    warning(p, "Self Destruct has been canceled");
X			}
X			if (data.xbutton.window == p->warf) 
X			    waraction(p, &tmp->xbutton);
X			else if (data.xbutton.window == p->warr) 
X			    waraction(p, &tmp->xbutton);
X			else if (data.xbutton.window == p->wark) 
X			    waraction(p, &tmp->xbutton);
X			else if (data.xbutton.window == p->waro) 
X			    waraction(p, &tmp->xbutton);
X			else if (data.xbutton.window == p->wargo) 
X			    waraction(p, &tmp->xbutton);
X			else if (data.xbutton.window == p->warno) 
X			    waraction(p, &tmp->xbutton);
X			else
X			    buttonaction(p, &tmp->xbutton);
X			break;
X
X
X		    case Expose:
X			if (p->p_status == POUTFIT) {
X				if (data.xexpose.window == p->fwin)
X					redrawFed(p, p->fwin, 1);	
X				else if (data.xexpose.window == p->rwin)
X					redrawRom(p, p->rwin, 1);	
X				else if (data.xexpose.window == p->kwin)
X					redrawKli(p, p->kwin, 1);	
X				else if (data.xexpose.window == p->owin)
X					redrawOri(p, p->owin, 1);	
X				else if (data.xexpose.window == p->w)
X					showMotd(p);
X				else if (data.xexpose.window == p->qwin) {
X					redrawQuit(p, p->qwin);	
X					elapsed = time(0) - p->startTime;
X					showTimeLeft(p, elapsed, AUTOQUIT, 1);
X				}
X			}
X			if (data.xexpose.window == p->statwin && (p->p_flags & PFSHOWSTATS))
X				redrawStats(p, p->statwin);
X			else if (data.xexpose.window == p->tstatw)
X				redrawTstats(p);
X			else if (data.xexpose.window == p->mapw)
X			    p->redrawall = 1;
X			else if (data.xexpose.window == p->iconWin)
X			    drawIcon(p);
X			else if (data.xexpose.window == p->helpWin)
X			    fillhelp(p);
X			else if (data.xexpose.window == p->playerw)
X			    playerlist(p);
X			else if (data.xexpose.window == p->planetw)
X			    planetlist(p);
X			break;
X		    default:
X			break;
X		} /* switch */
X	}
X    } /* (infinite) loop */
X}
X
Xkeyaction(p, key, data)
Xstruct player	*p;
Xchar key;
XXKeyEvent *data;
X{
X    char buf[80];
X    unsigned char course;
X    struct obtype *gettarget(), *target;
X    struct player *p2;
X    struct planet *pl;
X
X#ifdef notdef
X    if (watch && !index("LPSMiQ?hw ", key)) {
X	char	buf[BUFSIZ];
X
X	sprintf(buf, "'%c' command is not permitted in watch mode.", key);
X	warning(buf);
X	return;
X    }
X#endif
X    switch (key) {
X	case '0':
X	case '1':
X	case '2':
X	case '3':
X	case '4':
X	case '5':
X	case '6':
X	case '7':
X	case '8':
X	case '9':
X	    set_speed(p, key - '0');
X	    break;
X	case 'k': /* k = set course */
X	    course = getcourse(p, data->window, data->x, data->y);
X	    set_course(p, course);
X	    p->p_flags &= ~(PFPLOCK | PFPLLOCK);
X	    break;
X	case 'p': /* p = fire phasers */
X	    course = getcourse(p, data->window, data->x, data->y);
X	    phaser(p, course);
X	    break;
X	case 't': /* t = launch torps */
X	    course = getcourse(p, data->window, data->x, data->y);
X	    ntorp(p, course, TMOVE);
X	    break;
X	case 'd': /* d = detonate other torps */
X	    detothers(p);
X	    break;
X	case 'D': /* D = detonate my torps */
X	    detmine(p);
X	    break;
X	case '+': /* + = Put shields up */
X	    shield_up(p);
X	    break;
X	case '-': /* - = Put shields down */
X	    shield_down(p);
X	    break;
X	case 'u': /* u = toggle shields */
X	    shield_tog(p);
X	    break;
X	case 'b': /* b = bomb planet */
X	    bomb_planet(p);
X	    break;
X	case 'z': /* z = beam up */
X	    beam_up(p);
X	    break;
X	case 'x': /* x = beam down */
X	    beam_down(p);
X	    break;
X	case 'R': /* R = Go into repair mode */
X	    p->p_flags &= ~(PFPLOCK | PFPLLOCK);
X	    repair(p);
X	    break;
X	case 'o': /* o = orbit nearest planet */
X	    p->p_flags &= ~(PFPLOCK | PFPLLOCK);
X	    orbit(p);
X	    break;
X	case 'Q':
X	    if (p->copilot /*|| watch*/)
X		exit(1);
X	    p->p_flags |= PFSELFDEST;
X	    p->selfdest = p->p_updates + PSELFDESTTIME;
X	    warning(p, "Self destruct initiated");
X	    break;
X	case '?': /* ? = Redisplay all messages */
X	    repeat_message(p);
X	    break;
X	case 'c': /* c = cloak */
X	    cloak(p);
X	    break;
X	case 'C': /* C = coups */
X	    coup(p);
X	    break;
X	case 'l': /* l = lock onto */
X	    /* since a robot would never use this function (it's user
X	       Interface dependent,) all the work is done here instead
X	       of in interface.c */
X	    target = gettarget(p, data->window, data->x, data->y,
X		TARG_PLAYER|TARG_PLANET);
X	    if (target->o_type == PLAYERTYPE) {
X		p->p_flags |= PFPLOCK;
X		p->p_flags &= ~(PFPLLOCK|PFORBIT|PFBEAMUP|PFBEAMDOWN|PFBOMB);
X		p->p_playerl = target->o_num;
X		p2 = &players[target->o_num];
X		sprintf(buf, "Locking onto %s (%c%d)",
X		    p2->p_name,
X		    teamlet[p2->p_team],
X		    p2->p_no);
X		warning(p, buf);
X	    }
X	    else { 	/* It's a planet */
X		p->p_flags |= PFPLLOCK;
X		p->p_flags &= ~(PFPLOCK|PFORBIT|PFBEAMUP|PFBEAMDOWN|PFBOMB);
X		p->p_planet = target->o_num;
X		pl = &planets[target->o_num];
X		sprintf(buf, "Locking onto %s",
X		    pl->pl_name);
X		warning(p, buf);
X	    }
X	    break;
X	case '@': /* @ = toggle copilot permissions */
X	    p->p_flags ^= PFCOPILOT;
X	    break;
X	case '*': /* * = send in practice robot */
X	    /* Only if no other players on OTHER teams. */
X	    if (tcount[p->p_team] - (nplayers - nrobots) == 0)
X		    startrobot(p->p_team, PFRHOSTILE);
X	    break;
X	case '&': /* & = send in harder robot */
X	    /* Only if no other players on OTHER teams. */
X	    if (tcount[p->p_team] - (nplayers - nrobots) == 0)
X		    startrobot(p->p_team, PFRHARD | PFRHOSTILE);
X	    break;
X
X	/* Start of display functions */
X	case ' ': /* ' ' = clear special windows */
X	    if (ismapped(p, p->playerw))
X		XUnmapWindow(p->display, p->playerw);
X	    if (ismapped(p, p->planetw))
X		XUnmapWindow(p->display, p->planetw);
X	    if (p->infomapped)
X		destroyInfo(p);
X	    if (ismapped(p, p->war))
X		XUnmapWindow(p->display, p->war);
X	    break;
X	case 'L': /* L = Player list */
X	    if (ismapped(p, p->playerw)) {
X		XUnmapWindow(p->display, p->playerw);
X	    } else {
X		XMapWindow(p->display, p->playerw);
X	    }
X	    break;
X	case 'P': /* P = Planet list */
X	    if (ismapped(p, p->planetw)) {
X		XUnmapWindow(p->display, p->planetw);
X	    } else {
X		XMapWindow(p->display, p->planetw);
X	    }
X	    break;
X	case 'S': /* S = Score list */
X	    if (p->infomapped)
X		destroyInfo(p);
X	    scorelist(p);
X	    break;
X	case 's': /* s = toggle stat mode */
X	   if (p->p_flags & PFSHOWSTATS) {
X		p->p_flags &= ~PFSHOWSTATS;
X		closeStats(p, p->statwin);
X	   } else {
X		p->statwin = openStats(p);
X		p->p_flags |= PFSHOWSTATS;
X	   }
X	   break;
X	case 'U': /* U = toggle show shields */
X	   p->showShields = !p->showShields;
X	   break;
X	case 'M': /* M = Toggle Map mode */
X	    p->mapmode = !p->mapmode;
X	    break;
X	case 'N': /* N = Toggle Name mode */
X	    p->namemode = !p->namemode;
X	    break;
X	case 'i': /* i = get information */
X	    if (!p->infomapped)
X		inform(p, data->window, data->x, data->y);
X	    else
X		destroyInfo(p);
X	    break;
X	case 'h': /* h = Map help window */
X	    if (ismapped(p, p->helpWin)) {
X		XUnmapWindow(p->display, p->helpWin);
X	    } else {
X		XMapWindow(p->display, p->helpWin);
X	    }
X	    break;
X	case 'w': /* w = map war stuff */
X	    if (p->copilot) {
X		warning(p, "Copilots cannot alter war settings");
X		break;
X	    }
X	    if (ismapped(p, p->war)) {
X		XUnmapWindow(p->display, p->war);
X		p->redrawall = 1;
X	    } else
X		warwindow(p);
X	    break;
X	default:
X	    XBell(p->display, 0);
X	    break;
X    }
X}
X
Xbuttonaction(p, data)
Xregister struct player	*p;
XXButtonEvent *data;
X{
X    unsigned char course;
X#ifdef notdef
X    struct obtype *gettarget(), *target;
X
X    if (watch) {	/* Special case */
X	target = gettarget(data->window, data->x, data->y,
X	    TARG_PLAYER|TARG_CLOAK);
X	setwatch(target->o_num);
X	return;
X    }
X#endif
X
X    if ((data->button & Button3) == Button3) {
X	course = getcourse(p, data->window, data->x, data->y);
X	p->p_desdir = course;
X	p->p_flags &= ~(PFPLOCK | PFPLLOCK);
X    }
X    else if ((data->button & Button1) == Button1) {
X	course = getcourse(p, data->window, data->x, data->y);
X	ntorp(p, course, TMOVE);
X    }
X    else if ((data->button & Button2) == Button2) {
X	course = getcourse(p, data->window, data->x, data->y);
X	phaser(p, course);
X    }
X}
X
Xgetcourse(p, ww, x, y)
Xregister struct player	*p;
XWindow ww;
Xint x, y;
X{
X    if (ww == p->mapw) {
X	int	me_x, me_y;
X
X	me_x = p->p_x * WINSIDE / GWIDTH;
X	me_y = p->p_y * WINSIDE / GWIDTH;
X	return((unsigned char) (atan2((double) (x - me_x),
X	    (double) (me_y - y)) / 3.14159 * 128.));
X    }
X    else
X	return((unsigned char) (atan2((double) (x - WINSIDE/2),
X	    (double) (WINSIDE/2 - y))
X		/ 3.14159 * 128.));
X}
X
XinputIgnored(p)
Xregister struct player	*p;
X{
X#ifdef notdef
X	if (watch)
X	    return(0);
X#endif
X	if (p->p_status != PALIVE)
X	    return (1);
X	if (p->p_flags & PFWAR) {
X	    warning(p, "Battle computers being re-programmed");
X	    return (1);
X	}
X	return (0);
X}
X
Xsetwatch(pno)
Xint pno;
X{
X    register struct player	*p;
X
X    p = &players[pno];
X    p->lastm = mctl->mc_current;
X    p->redrawall = 1;
X    if (p->p_flags & PFSHOWSTATS) {
X	closeStats(p, p->statwin);
X	p->statwin = openStats(p);
X    }
X}
END_OF_FILE
if test 17920 -ne `wc -c <'input.c'`; then
    echo shar: \"'input.c'\" unpacked with wrong size!
fi
# end of 'input.c'
fi
if test -f 'rmove.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rmove.c'\"
else
echo shar: Extracting \"'rmove.c'\" \(14848 characters\)
sed "s/^X//" >'rmove.c' <<'END_OF_FILE'
Xstatic char sccsid[] = "@(#)rmove.c	1.1";
X#ifndef lint
Xstatic char *rcsid_rmove_c = "$Header: /uraid2/riedl/src/xceltrek/RCS/rmove.c,v 1.1 88/04/18 16:10:39 riedl Exp Locker: riedl $";
X#endif	lint
X/* Copyright (c) 1986 	Chris Guthrie */
X
X#include <X11/Xlib.h>
X#include <stdio.h>
X#include "defs.h"
X#include "data.h"
X
X#define AVOID_TIME		4
X
X#define STAY	0x1
X#define RUN	0x2
X#define ATTACK	0x3
X#define REPAIR	0x4
X#define AVOID	0x5
X
X#define NORMALIZE(d) 		((((d) % 256) + 256) % 256)
X#define rgetcourse		newcourse
X
X#define rstatus (p->p_rmode)
X#define avoidTime (p->p_timer)
X
Xextern int debug;
Xextern int playerchange;
Xextern int nplayers;
Xextern int nrobots;
X
Xextern long isin[], icos[];
Xextern unsigned char iatan2();
X
Xdouble hypot();
Xextern unsigned char newcourse();
Xint calculate_hit();
X
Xrmove(p)
Xstruct player	*p;
X{
X  struct player *enemy;
X  int edist;
X  unsigned char ecourse;
X  register int i;
X  register struct player *j;
X  register int burst;
X  register int numHits, tDir;
X  int		avDir;
X  int torp_can_hit;
X
X    double dx, dy;
X    int tdist;
X    unsigned char tcourse = 10;
X
X    /* Find an enemy */
X    enemy = p;
X    edist = GWIDTH + 1;
X    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
X	if ((j->p_status != PALIVE) || (j == p) ||
X	    ((j->p_flags & PFROBOT) && (!(p->p_flags & PFRHOSTILE))))
X	    continue;
X	if (((j->p_swar | j->p_hostile) & p->p_team) ||
X	    ((p->p_swar | p->p_hostile) & j->p_team)) {
X	    /* We have an enemy */
X	    /* Get his range */
X	    dx = j->p_x - p->p_x;
X	    dy = j->p_y - p->p_y;
X	    /* No way this enemy can be closer than known enemy */
X	    if (dx > edist || dy > edist) continue; 
X	    tdist = hypot(dx, dy);
X	    /* Check to see if ship is in our space. */
X	    if (!(p->p_flags & PFRHOSTILE)) {
X		if (tdist > 15000) {
X		    switch (p->p_team) {
X			case FED:
X			    if ((j->p_x > GWIDTH/2) || (j->p_y < GWIDTH/2))
X				continue;
X			    break;
X			case ROM:
X			    if ((j->p_x > GWIDTH/2) || (j->p_y > GWIDTH/2))
X				continue;
X			    break;
X			case KLI:
X			    if ((j->p_x < GWIDTH/2) || (j->p_y > GWIDTH/2))
X				continue;
X			    break;
X			case ORI:
X			    if ((j->p_x < GWIDTH/2) || (j->p_y < GWIDTH/2))
X				continue;
X			    break;
X		    }
X		}
X	    }
X	    if (debug)
X		fprintf(stderr, "%d) found enemy %d in our space at %d,%d\n",
X		    p->p_no,
X		    j->p_no,
X		    j->p_x,
X		    j->p_y);
X	    if (tdist < edist) {
X		enemy = j;
X		edist = tdist;
X		continue;
X	    }
X	}
X    }
X    /** level 1 **/
X    if (enemy == p) {
X      if (!(p->p_flags & PFRSTICKY) || (nplayers - nrobots) == 0) {		/* No more enemies */
X	if (p->p_explode == 0)
X	  p->p_explode = p->p_updates + RGIVEUPTIME;
X	if (p->p_updates >= p->p_explode) {
X	  playerchange = 1;
X	  p->p_status = PFREE;
X	  return(0);
X	}
X	go_home(p);
X      } else {
X	p->p_explode = 0;
X	go_home(p);
X      }
X      return(0);
X    }
X    /** level 1 **/
X    /* Get course for torp to nearest enemy */
X
X/*
X      torp_can_hit = calculate_hit
X	(p->p_ship.s_torpspeed*WARP1, p->p_x, p->p_y, 
X	 enemy->p_speed*WARP1, enemy->p_dir, enemy->p_x, enemy->p_y,
X	 &impact_dir, &impact_time, &impact_dist, 
X	 &impact_x, &impact_y);
X*/
X
X      /*
X       * This code figures out how to shoot at the enemy chosen above.
X       * For the old style torps that have a fixed velocity I have an 
X       * analytical solution in calculate_hit (below), but for the fancy
X       * new torps that pick up the velocity of the ship that shoots them I
X       * have to compute the direction iteratively.  The approach is:
X       *
X       * for each time from 0 to (a guess at how long a torp lasts)
X       *   compute where the enemy will be at that time if he doesn't turn
X       *     (this is the potential impact point)
X       *
X       *   determine the course that we should aim a torpedo to get
X       *     from where we are to where he will be.  This involves
X       *     calculating an adjusted impact point by subtracting the
X       *     total influence of the robot's speed over i turns from the
X       *     primary impact point.
X       *
X       *   figure out where a `normal' torpedo (one that doesn't get the
X       *     velocity of the ship added in) aimed in that direction will 
X       *     be at the impact time.
X       *
X       *   see if the adjusted torpedo will be close enough at impact time 
X       *     to the adjusted impact point to make the shot worthwhile.
X       *
X       *   currently, we check through all possible times and choose the
X       *     best possible hit.  This is probably a mistake since a late
X       *     "perfect" hit is unlikely to succeed since the enemy will
X       *     have plenty of time to dodge.  Better is to choose the first
X       *     reasonable hit, but that will have to wait until I think up
X       *     a good definition of reasonable.  Choosing the first hit also
X       *     has the advantage of being faster.
X       */
X    {
X      int i;
X      int impact_x, impact_y, impact_dx, impact_dy;
X      int adjust_impact_dx, adjust_impact_dy;
X      int torp_dx, torp_dy, torp_x, torp_y;
X      double error, best_error;
X      int new_tcourse;
X
X      best_error = 10000;
X      torp_can_hit = 0;
X      adjust_impact_dx = (icos[p->p_dir] * p->p_speed * WARP1) >> TRIGSCALE;
X      adjust_impact_dy = (isin[p->p_dir] * p->p_speed * WARP1) >> TRIGSCALE;
X
X      impact_dx = (icos[enemy->p_dir] * enemy->p_speed * WARP1) >> TRIGSCALE;
X      impact_dy = (isin[enemy->p_dir] * enemy->p_speed * WARP1) >> TRIGSCALE;
X
X      for (i = 0, impact_x = enemy->p_x, impact_y = enemy->p_y; 
X	   i < 50; 
X	   i++, impact_x += impact_dx - adjust_impact_dx, 
X	        impact_y += impact_dy - adjust_impact_dy) {
X
X	new_tcourse = rgetcourse(p, impact_x, impact_y);
X
X	torp_dx = p->p_ship.s_torpspeed * icos[new_tcourse] * WARP1;
X	torp_dy = p->p_ship.s_torpspeed * isin[new_tcourse] * WARP1;
X	torp_dx = (torp_dx + (TRIGSCALE>>1)) >> TRIGSCALE;
X	torp_dy = (torp_dy + (TRIGSCALE>>1)) >> TRIGSCALE;
X
X	torp_x = p->p_x + torp_dx*i;
X	torp_y = p->p_y + torp_dy*i;
X
X	error = hypot((double)(torp_x-impact_x), (double)(torp_y-impact_y));
X	if (error < best_error) {
X	  torp_can_hit = (error < EXPDIST);
X	  best_error = error;
X	  tcourse = new_tcourse;
X	}
X      }
X
X      if (debug) {
X	if (torp_can_hit) {
X	  printf("Aim in dir %d to hit in time %d at adjusted x=%d, y=%d\n",
X		 tcourse, i, impact_x, impact_y);
X	} 
X	else {
X	  printf("Can't hit\n");
X	}
X      }
X    }
X    /** level 1 **/
X    ecourse = rgetcourse(p, enemy->p_x, enemy->p_y);
X    if (debug)
X	fprintf(stderr, "Course to enemy is %d (%d)\n", (int)ecourse, 
X		(int) ecourse * 360 / 256);
X
X    if ((edist > 40000) && !((p->p_flags & PFRHOSTILE))) {
X	if (p->p_damage > 0) {
X	    p->p_desspeed = 0;
X	    shield_down(p);
X	    repair(p);
X	    if (debug)
X		fprintf(stderr, "%d) repairing damage at %d\n",
X		    p->p_no,
X		    p->p_damage);
X	}
X	else {
X	    rstatus = STAY;
X	    go_home(p);
X	}
X	return;
X    }
X    if (enemy == p) go_home(p);
X
X    /** level 1 **/
X    if ((p->p_damage > 20 || p->p_fuel < 1000) && edist < 25000) {
X      /* Run away */
X	p->p_desspeed = 6;
X	if (!(p->p_flags & PFCLOAK) && p->p_fuel > 2000)
X		cloak(p);
X	shield_down(p);
X	p->p_desdir = ecourse - 128;
X    } 
X    else if (rstatus == AVOID) {
X	if (--avoidTime <= 0)
X	    rstatus = ATTACK;
X	if (debug)
X	    fprintf(stderr, "avoiding: dir = %d\n", p->p_desdir);
X    } else {
X	rstatus = ATTACK;
X	if (p->p_flags & PFCLOAK)
X		cloak(p);
X
X	if (p->p_desdir != p->p_dir)
X	    p->p_desspeed = 2;
X	else if (p->p_etemp > 900)		/* 90% of 1000 */
X	    p->p_desspeed = 4;
X	else
X	    p->p_desspeed = 6;
X
X	shield_up(p);
X	if (edist < 15000) {
X	    numHits = projectDamage(p, enemy->p_no, &avDir);
X	    if (debug) {
X		fprintf(stderr, "%d hits expected from %d from dir = %d\n",
X			numHits, enemy->p_no, avDir);
X	    }
X	    if (numHits == 0) {
X              p->p_desdir = ecourse + 32;
X	    }
X	    else {
X		/*
X		 * Avoid Torps
X		 */ 
X		avoidTime = AVOID_TIME;
X		tDir = avDir - p->p_dir;
X		/* put into 0->255 range */
X		tDir = NORMALIZE(tDir);
X
X		switch (tDir / 64) {
X		case 0:
X		case 1:
X		  p->p_desdir = NORMALIZE(avDir + 64);
X		  break;
X		case 2:
X		case 3:
X		  p->p_desdir = NORMALIZE(avDir - 64);
X		  break;
X		}
X		if (!(p->p_flags & PFCLOAK) && p->p_fuel > 2000)
X		  cloak(p);
X
X		rstatus = AVOID;
X		if (debug)
X		  fprintf(stderr, "evading to dir = %d\n", p->p_desdir);
X	}
X      } else {
X	      if (!(p->p_flags & PFRHARD))
X		p->p_desdir = ecourse;
X	      else { /* try to go where he will be when we catch with him */
X		int can_hit;
X		int impact_dir, impact_x, impact_y;
X		double impact_dist, impact_time;
X
X		can_hit = calculate_hit
X		  (p->p_speed*WARP1, p->p_x, p->p_y, 
X		   enemy->p_speed*WARP1, enemy->p_dir, enemy->p_x, enemy->p_y,
X		   &impact_dir, &impact_time, &impact_dist, 
X		   &impact_x, &impact_y);
X
X		if (can_hit)
X		  p->p_desdir = impact_dir;
X		else 
X		  p->p_desdir = ecourse; /* go straight at him */
X	      }
X	}
X    }
X    /** level 1 **/
X    /* Fire weapons!!! */
X    if (p->p_fuel > 0 && (float)edist/p->p_fuel < 1.0000 && torp_can_hit) {
X	for (burst = 0; (burst < 1) && (p->p_ntorp < MAXTORP); burst++) {
X	    if (p->p_flags & PFCLOAK)
X		cloak(p);
X	    if (!(p->p_flags & PFRHARD))
X		ntorp(p, tcourse, TMOVE);
X	    else
X		ntorp(p, tcourse, TSTRAIGHT);
X	}
X    }
X    /** level 1 **/
X    if ((edist < 5000) && (p->p_flags & PFRHARD) && p->p_fuel > 1000) {
X	if (p->p_flags & PFCLOAK)
X	    cloak(p);
X	phaser(p, ecourse);
X    }
X}
X
X
X
X/*
X * calculate_hit: figure out what direction to aim to hit somebody.
X * - works with torps/ships/...
X * - doesn't work with torps anymore since some of their speed depends
X *   on the speed and direction of the ship that fires them.  Oh well.
X * 
X * We'll call the robot's current position A the enemy's current position
X * B, and the place where the torpedo hits C.  T will be the time at
X * which the torpedo and enemy both reach C.  We'll call the internal
X * angle in ABC at A alpha, at B beta and at C gamma.  a and b are the
X * speeds of the robot and enemy, and c is the distance between them.
X *
X * To solve the problem we'll use the first compute beta as the difference
X * between the enemy's current direction (beta1) and the direction from 
X * the enemy to the robot (beta2).  Now we can use the law of sines to 
X * compute alpha from
X * 	sin(alpha) / b*T = sin(beta) / a*T
X * since the T's (which we don't yet know!) cancel
X *
X * This gives delta = pi - alpha - beta since alpha, beta and delta are
X * the three angles of a triangle.  Now we apply the law of sines again
X * to compute T from
X * 	sin(alpha) / b*T = sin(delta) / d
X *
X * Since we now know the time to collision and we know the speed and 
X * direction of the enemy it is easy to compute where the enemy will be
X * when the collision takes place (C).  Knowing C and A it is trivial
X * to compute the angle between them.
X *
X * We'll return a 0 if a hit is impossible and a 1 if it is possible.
X * Note that some `possible' hits will take place a long time in the 
X * future.
X *
X * Sorry about the ridiculous number of arguments.  Most of them are
X * pretty obvious with the exception that the speeds used by this 
X * routine must be multiplied by the constant WARP1 by the calling
X * procedure.
X * 		John Riedl
X */
X
Xint
Xcalculate_hit(me_speed, me_x, me_y, 
X	      enemy_speed, enemy_dir, enemy_x, enemy_y,
X	      pimpact_dir, pimpact_time, pimpact_dist, pimpact_x, pimpact_y)
Xint me_speed, me_x, me_y, enemy_speed, enemy_x, enemy_y;
Xunsigned char enemy_dir;
Xint *pimpact_dir, *pimpact_x, *pimpact_y;
Xdouble *pimpact_time, *pimpact_dist;
X{
X  int normal_isin();
X  extern unsigned char iatan2();
X  extern long isin[], icos[];
X  unsigned char beta1;
X  unsigned char beta2;
X  unsigned char alpha, beta, delta;
X  double asin_input, pi = 3.14159;
X  double hypot(), rint(), asin();
X  double fabs();
X
X  beta1 = enemy_dir;
X  beta2 = iatan2(me_x - enemy_x, enemy_y - me_y);
X  beta = beta1 - beta2;
X  beta = beta>128 ? 256-beta : beta;
X  asin_input = (double) (enemy_speed * normal_isin(beta))
X    / (double) (me_speed << TRIGSCALE);
X  if (fabs(asin_input) > 1) { /* No way to hit */
X    return(0);
X  }
X  else {
X    alpha = (unsigned char) rint(asin(asin_input) / pi * 128.0);
X    alpha = alpha>128 ? 256-alpha: alpha;
X
X    /* Choose the more acute of the solution angles (quicker hit) */
X    alpha = 128-alpha < alpha ? 128-alpha : alpha;
X
X    delta = 128 - alpha - beta;
X
X    /* calculate the time to the impact */
X    *pimpact_dist = hypot((double)(enemy_x - me_x), 
X		 (double)(enemy_y - me_y));
X
X    *pimpact_time = (double) normal_isin(alpha) / normal_isin(delta) * 
X      (double) *pimpact_dist / enemy_speed;
X    
X    /* calculate the location of the impact */
X    *pimpact_x = enemy_x + 
X      rint((enemy_speed*icos[enemy_dir]*(*pimpact_time))/(1<<TRIGSCALE));
X    *pimpact_y = enemy_y + 
X      rint((enemy_speed*isin[enemy_dir]*(*pimpact_time))/(1<<TRIGSCALE));
X
X    *pimpact_dir = iatan2(*pimpact_x - me_x, me_y - *pimpact_y);
X    if (debug)
X      printf("Aim in direction %d to hit in time %lf at x=%d, y=%d\n",
X	     *pimpact_dir, *pimpact_time, *pimpact_x, *pimpact_y);
X
X  }
X  return(1);
X}
X
X/*
X * Stupid Sun 3.2 tan routine calls matherr and *prints* a message if
X * it returns something other that 1.
X */
Xint matherr()
X{
X  return(1);
X}
X
X
Xstruct {
X    int x;
X    int y;
X} center[] = { {0, 0},
X		{GWIDTH / 4, GWIDTH * 3 / 4},		/* Fed */
X		{GWIDTH / 4, GWIDTH / 4},		/* Rom */
X		{0, 0},
X		{GWIDTH * 3 / 4, GWIDTH  / 4},		/* Kli */
X		{0, 0},
X		{0, 0},
X		{0, 0},
X		{GWIDTH * 3 / 4, GWIDTH * 3 / 4}};	/* Ori */
X
X/* This function will send the robot back to the center of it's
X   space when it has nothing better to do.  Centers are defined
X   above.
X*/
Xgo_home(p)
Xstruct player	*p;
X{
X    int x, y;
X    double dx, dy;
X
X    x = center[p->p_team].x;
X    y = center[p->p_team].y;
X    if ((ABS(x - p->p_x) < 100) && (ABS(y - p->p_y) < 100))
X	p->p_desspeed = 0;
X    else {
X	p->p_desdir = rgetcourse(p, x, y);
X	dx = x - p->p_x;
X	dy = y - p->p_y;
X	p->p_desspeed = (hypot(dx, dy) / 10000) + 1;
X    }
X}
X
XprojectDamage(p, eNum, dirP)
Xstruct player	*p;
X	int	*dirP;
X{
X	register int		i, j, numHits = 0, mx, my, tx, ty, dx, dy;
X	long			tdx, tdy, mdx, mdy;
X	register struct torp	*t;
X
X	*dirP = 0;
X
X/* XX Fix this like the tcourse computation above */
X	for (i = 0, t = &torps[eNum * MAXTORP]; i < MAXTORP; i++, t++) {
X		if (t->t_status == TFREE)
X			continue;
X		tx = t->t_x; ty = t->t_y;
X		mx = p->p_x; my = p->p_y;
X		tdx = (t->t_speed * icos[t->t_dir] * WARP1) >> TRIGSCALE;
X		tdy = (t->t_speed * isin[t->t_dir] * WARP1) >> TRIGSCALE;
X		mdx = (p->p_speed * icos[p->p_dir] * WARP1) >> TRIGSCALE;
X		mdy = (p->p_speed * isin[p->p_dir] * WARP1) >> TRIGSCALE;
X		for (j = t->t_fuse; j > 0; j--) {
X			tx += tdx; ty += tdy;
X			mx += mdx; my += mdy;
X			dx = tx - mx; dy = ty - my;
X			if (ABS(dx) < EXPDIST && ABS(dy) < EXPDIST) {
X				numHits++;
X				*dirP += t->t_dir;
X				break;
X			}
X		}
X
X	}
X	if (numHits > 0)
X		*dirP /= numHits;
X	return (numHits);
X}
END_OF_FILE
if test 14848 -ne `wc -c <'rmove.c'`; then
    echo shar: \"'rmove.c'\" unpacked with wrong size!
fi
# end of 'rmove.c'
fi
if test -f 'subdaemon.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'subdaemon.c'\"
else
echo shar: Extracting \"'subdaemon.c'\" \(18229 characters\)
sed "s/^X//" >'subdaemon.c' <<'END_OF_FILE'
Xstatic char sccsid[] = "@(#)subdaemon.c	1.1";
X#ifndef lint
Xstatic char *rcsid_daemon_c = "$Header: /uraid2/riedl/src/xceltrek/RCS/subdaemon.c,v 1.1 88/04/18 16:10:46 riedl Exp Locker: riedl $";
X#endif	lint
X/* Copyright (c) 1986 	Chris Guthrie */
X
X#include <X11/Xlib.h>
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/ipc.h>
X#include <sys/shm.h>
X#include <sys/time.h>
X#include <sys/file.h>
X#include <sys/wait.h>
X#include <sys/ioctl.h>
X#include <signal.h>
X#include <setjmp.h>
X#include "defs.h"
X#include "data.h"
Xextern long isin[], icos[];
X#include "planets.h"
X
X#define fuse(X) ((udcounter % (X)) == 0)
X/* Run the game */
X
Xdouble sqrt();
Xdouble pow();
Xdouble hypot();
X
Xstatic int debug = 0;
Xstatic int plfd;
X
X/*
X * subdaemon - allocate memory and initialize subdaemon
X */
Xsubdaemon()
X{
X    register int i;
X    int move();
X    int reaper();
X
X    for (i = 0; i < MAXPLAYER; i++)
X	players[i].p_status = PFREE;
X
X    plfd = open(PLFILE, O_RDWR, 0777);
X    if (plfd < 0) {
X	fprintf(stderr, "No planet file.  Restarting galaxy\n");
X	bcopy(pdata, planets, sizeof(pdata));
X    }
X    else {
X	if (read(plfd, planets, sizeof(pdata)) != sizeof(pdata)) {
X	    fprintf(stderr, "Planet file wrong size.  Restarting galaxy\n");
X	    bcopy(pdata, planets, sizeof(pdata));
X	    for (i = 0; i < 40; i++) {
X		if (planets[i].pl_flags & PLHOME)
X		    planets[i].pl_flags |= (PLREPAIR|PLFUEL);
X		if (random() % 4 == 0)
X		    planets[i].pl_flags |= PLREPAIR;
X		if (random() % 2 == 0)
X		    planets[i].pl_flags |= PLFUEL;
X	    }
X	}
X    }
X
X    status->active = 0;
X}
X
X#ifdef notdef
Xexitgame(p, status)
Xstruct player	*p;
Xint status;
X{
X  if (!copilot) savestats(p);
X  exit(status);
X}
X#endif
X
Xsave_planets() {
X  if (plfd > 0) {
X    lseek(plfd, 0, 0);
X    write(plfd, planets, sizeof(pdata));
X  }
X}
X
X/* These specify how often special actions will take place in
X   UPDATE units (0.20 seconds, currently.)
X*/
X
X#define PLAYERFUSE	1
X#define TORPFUSE	1
X#define PHASERFUSE	1
X#define TEAMFUSE	3
X#define PLFIGHTFUSE	2
X#define BEAMFUSE	5
X#define PLANETFUSE	301
X#define REFRESHFUSE	1
X#define ROBOTFUSE	1
X
Xmove()
X{
X	register int		i;
X	register struct player	*p;
X
X	for (i = 0, p = &players[0]; i < MAXPLAYER; i++, p++) {
X		if (fuse(PLAYERFUSE) && (p->p_status != PFREE)) {
X			udplayer(p);
X		}
X		if (fuse(BEAMFUSE) && (p->p_status == PALIVE)) {
X			beam(p);
X		}
X	}
X
X	/* Per tick things...one time for all players */
X	if (fuse(TORPFUSE)) {
X		udtorps();
X	}
X	if (fuse(PHASERFUSE)) {
X		udphaser();
X	}
X	if (fuse(TEAMFUSE)) {
X		teamtimers();
X	}
X	if (fuse(PLFIGHTFUSE)) {
X		plfight();	/* Planet fire */
X	}
X	if (fuse(PLANETFUSE)) {
X		udplanets();
X	}
X
X	/* Remaining player things... */
X	for (i = 0, p = &players[0]; i < MAXPLAYER; i++, p++) {
X		if (fuse(ROBOTFUSE) &&
X		    (p->p_status == PALIVE) &&
X		    (p->p_flags & PFROBOT)) {
X			udrobot(p);
X		}
X		if (fuse(REFRESHFUSE) &&
X		    (p->p_status == PALIVE || p->p_status == PEXPLODE) &&
X		    (p->p_flags & PFROBOT) == 0) {
X			redraw(p);
X		}
X	}
X}
X
Xudplayer(j)
Xregister struct player *j;
X{
X    tcount[FED] = tcount[ROM] = tcount[KLI] = tcount[ORI] = 0;
X	auto_features(j);
X      switch (j->p_status) {
X      case PDEAD:
X	if (--j->p_explode <= 0 && j->p_ntorp <= 0) {
X	  j->p_status = PFREE;
X
X	    XSync(j->display, 1);
X	    j->redrawall = 1;
X	}
X	break;
X      case PEXPLODE:
X	j->p_updates++;
X	j->p_flags &= ~PFCLOAK;
X	if (j->p_explode == PEXPTIME)
X	  blowup(j);		/* damage everyone else around */
X	if (--j->p_explode <= 0) {
X		if (j->p_stats.st_maxkills < j->p_kills)
X			j->p_stats.st_maxkills = j->p_kills;
X		j->p_stats.st_kills += j->p_kills;
X		death(j);
X	}
X	break;
X      case PALIVE:
X#ifdef notdef
X	status->active += (1<<i);
X#endif
X	tcount[j->p_team]++;
X	j->p_updates++;
X
X	/* cool weapons */
X	cool_weapons(j);
X
X	/* cool engine */
X	cool_engines(j);
X
X	/* Add fuel */
X	add_fuel(j);
X
X	/* repair shields */
X	repair_shields(j);
X
X	/* repair damage */
X	repair_damage(j);
X
X	/* Charge for cloaking */
X	cloak_charge(j);
X
X	/* Move Player in orbit */
X	player_orbit(j);
X
X	/* Move player through space */
X	space_move(j);
X
X	/* Set player's alert status */
X	adjust_alert(j);
X	break;
X      }				/* end switch */
X}
X
Xudtorps()
X{
X    register int i;
X    register struct torp *j;
X
X    for (i = 0, j = &torps[i]; i < MAXPLAYER * MAXTORP; i++, j++) {
X	switch (j->t_status) {
X	    case TFREE:
X		continue;
X	    case TMOVE:
X	    case TSTRAIGHT:
X		j->t_x += (j->t_speed * icos[j->t_dir] * WARP1) >> TRIGSCALE;
X		if (j->t_x < 0) {
X		    j->t_x = 0;
X		    explode(j);
X		    break;
X		}
X		else if (j->t_x > GWIDTH) {
X		    j->t_x = GWIDTH;
X		    explode(j);
X		    break;
X		}
X		j->t_y += (j->t_speed * isin[j->t_dir] * WARP1) >> TRIGSCALE;
X		if (j->t_y < 0) {
X		    j->t_y = 0;
X		    explode(j);
X		    break;
X		}
X		else if (j->t_y > GWIDTH) {
X		    j->t_y = GWIDTH;
X		    explode(j);
X		    break;
X		}
X
X		/* Make sure that player torps wobble */
X		if (j->t_status == TMOVE)
X		    j->t_dir += (random() % 3) - 1;
X
X		if (near(j) || (j->t_fuse-- <= 0)) {
X 		    explode(j);
X		}
X		break;
X	    case TDET:
X		j->t_x += (j->t_speed * icos[j->t_dir] * WARP1) >> TRIGSCALE;
X		if (j->t_x < 0)
X		    j->t_x += GWIDTH;
X		else if (j->t_x > GWIDTH)
X		    j->t_x -= GWIDTH;
X		j->t_y += (j->t_speed * isin[j->t_dir] * WARP1) >> TRIGSCALE;
X		if (j->t_y < 0)
X		    j->t_y += GWIDTH;
X		else if (j->t_y > GWIDTH)
X		    j->t_y -= GWIDTH;
X		explode(j);
X		break;
X	    case TEXPLODE:
X		if (j->t_fuse-- <= 0) {
X		    j->t_status = TFREE;
X		    players[j->t_owner].p_ntorp--;
X		}
X		break;
X	    case TOFF:
X		j->t_status = TFREE;
X		players[j->t_owner].p_ntorp--;
X		break;
X	}
X    }
X}
X
X/* See if there is someone close enough to explode for */
Xnear(torp)
Xstruct torp *torp;
X{
X    register int i;
X    int dx, dy;
X    register struct player *j;
X
X    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
X       if (!(j->p_status == PALIVE))
X	  continue;
X       if (torp->t_owner == j->p_no)
X	  continue;
X       if ((!(torp->t_war & j->p_team)) &&
X	   (!(torp->t_team & (j->p_swar | j->p_hostile))))
X	  continue;
X       dx = torp->t_x - j->p_x;
X       dy = torp->t_y - j->p_y;
X       if (ABS(dx) > EXPDIST || ABS(dy) > EXPDIST)
X	  continue;
X       if (dx * dx + dy * dy < EXPDIST * EXPDIST)
X	  return 1;
X    }
X    return 0;
X}
X
X    
X
X/* Do damage to all surrounding players */
X
Xexplode(torp)
Xstruct torp *torp;
X{
X    register int i;
X    int dx, dy, dist;
X    int damage;
X    register struct player *j;
X
X    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
X	if (!(j->p_status == PALIVE))
X	    continue;
X	if (torp->t_owner == j->p_no)
X	    continue;
X	dx = torp->t_x - j->p_x;
X	dy = torp->t_y - j->p_y;
X	if (ABS(dx) > TDAMDIST || ABS(dy) > TDAMDIST)
X	    continue;
X	dist = dx * dx + dy * dy;
X	if (dist > TDAMDIST * TDAMDIST)
X	    continue;
X	if (dist > EXPDIST * EXPDIST) {
X	    damage = torp->t_damage * (TDAMDIST - sqrt((double) dist)) /
X		(TDAMDIST - EXPDIST);
X	}
X	else {
X	    damage = torp->t_damage;
X	}
X	if (damage > 0) {
X	    /* First, check to see if torp owner has started a war */
X	    if (players[torp->t_owner].p_hostile & j->p_team) {
X		players[torp->t_owner].p_swar |= j->p_team;
X	    }
X	    /* Note that if a player is at peace with the victim, then
X	       the torp has caused damage either accidently, or because
X	       the victim was at war with, or hostile to, the player.
X	       In either case, we don't consider the damage to be
X	       an act of war. */
X
X	    if (j->p_flags & PFSHIELD) {
X		j->p_shield -= damage;
X		if (j->p_shield < 0) {
X		    j->p_damage -= j->p_shield;
X		    j->p_shield = 0;
X		}
X	    }
X	    else {
X		j->p_damage += damage;
X	    }
X	    if (j->p_damage >= 100) {
X		j->p_status = PEXPLODE;
X		j->p_explode = PEXPTIME;
X		/* no points for killing yourself! */
X		if (torp->t_owner != j->p_no)
X		  players[torp->t_owner].p_kills += 1.0
X			+ j->p_armies * 0.1 + j->p_kills * 0.1;
X		killmess(j, &players[torp->t_owner]);
X		j->p_stats.st_losses++;
X		j->p_whydead = KTORP;
X		j->p_whodead = torp->t_owner;
X	    }
X	}
X    }
X    torp->t_status = TEXPLODE;
X    torp->t_fuse = TEXPTIME;
X}
X
Xudplanets()
X{
X    register int i;
X    register struct planet *l;
X
X    for (i = 0, l = &planets[i]; i < MAXPLANETS; i++, l++) {
X	if (l->pl_armies == 0)
X	    continue;
X	if ((random() % 3000) < l->pl_armies)
X	    l->pl_armies -= (random() % l->pl_armies);
X	if ((l->pl_armies < 4) && ((random() % 20) == 0)) {
X	    l->pl_armies++;
X	    continue;
X	}
X	if ((random() % 10) == 0)
X	    l->pl_armies += (random() % 3) + 1;
X	    
X    }
X}
X
Xudphaser()
X{
X    register int i;
X    register struct phaser *j;
X    register struct player *victim;
X
X    for (i = 0, j = &phasers[i]; i < MAXPLAYER; i++, j++) {
X	switch (j->ph_status) {
X	    case PHFREE:
X		continue;
X	    case PHMISS:
X		if (j->ph_fuse-- == 1)
X		    j->ph_status = PHFREE;
X		break;
X	    case PHHIT:
X		if (j->ph_fuse-- == PFIRETIME) {
X		    victim = &players[j->ph_target];
X		    /* the victim may have been killed by a torp already */
X		    if (victim->p_status != PALIVE) continue;
X
X		    if (victim->p_flags & PFSHIELD) {
X			victim->p_shield -= j->ph_damage;
X			if (victim->p_shield < 0) {
X			    victim->p_damage -= victim->p_shield;
X			    victim->p_shield = 0;
X			}
X		    }
X		    else {
X			victim->p_damage += j->ph_damage;
X		    }
X		    if (victim->p_damage >= 100) {
X			victim->p_status = PEXPLODE;
X			victim->p_explode = PEXPTIME;
X			players[i].p_kills += 1.0
X			    + victim->p_armies * 0.1 + victim->p_kills * 0.1;
X			killmess(victim, &players[i]);
X			victim->p_stats.st_losses++;
X			victim->p_whydead = KPHASER;
X			victim->p_whodead = i;
X		    }
X		}
X		if (j->ph_fuse == 0)
X		    j->ph_status = PHFREE;
X		break;
X	}
X    }
X}
X
Xint pl_warning[MAXPLANETS];	/* To keep planets shut up for awhile */
Xint tm_robots[MAXTEAM + 1];		/* To limit the number of robots */
Xint tm_coup[MAXTEAM + 1];		/* To allow a coup */
X
Xteamtimers()
X{
X    register int i;
X    for (i = 0; i <= MAXTEAM; i++) {
X	if (tm_robots[i] > 0)
X	    tm_robots[i]--;
X	if (tm_coup[i] > 0)
X	    tm_coup[i]--;
X    }
X}
X
Xplfight()
X{
X    register int h, i;
X    register struct player *j;
X    register struct planet *l;
X    int dx, dy;
X    int damage;
X    int dist;
X    int rnd;
X    char buf[80];
X    char buf1[80];
X
X    for (h = 0, l = &planets[h]; h < MAXPLANETS; h++, l++) {
X	if (l->pl_flags & PLCOUP) {
X	    l->pl_flags &= ~PLCOUP;
X	    l->pl_owner = (l->pl_flags & ALLTEAM);
X	}
X	l->pl_flags &= ~PLREDRAW;
X	if (pl_warning[h] > 0)
X	    pl_warning[h]--;
X	for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
X	    switch (j->p_status) {
X		case PFREE:
X		case PDEAD:
X		case PEXPLODE:
X		    continue;
X		case PALIVE:
X		    /* Do damage by planets */
X			dx = ABS(l->pl_x - j->p_x);
X			dy = ABS(l->pl_y - j->p_y);
X			if (dx < 3 * PFIREDIST && dy < 3 * PFIREDIST)
X			    l->pl_flags |= PLREDRAW;
X			if (dx > PFIREDIST || dy > PFIREDIST)	/*XXX*/
X			    continue;
X			dist = (int) hypot((double) dx, (double) dy);
X			if (dist > PFIREDIST)
X			    continue;
X		    if ((j->p_swar | j->p_hostile) & l->pl_owner) {
X			if (l->pl_armies > 0)
X			    damage = l->pl_armies / 10 + 2;
X			else
X			    damage = 0;
X			if (damage > 0) {
X			    if (j->p_flags & PFSHIELD) {
X				j->p_shield -= damage;
X				if (j->p_shield < 0) {
X				    j->p_damage -= j->p_shield;
X				    j->p_shield = 0;
X				}
X			    }
X			    else {
X				j->p_damage += damage;
X			    }
X			    if (j->p_damage >= 100) {
X			    j->p_explode = PEXPTIME;
X			    j->p_status = PEXPLODE;
X			    j->p_stats.st_losses++;
X			    sprintf(buf, "%s (%c%x) killed by %s (%c)",
X				j->p_name,
X				teamlet[j->p_team],
X				j->p_no,
X				l->pl_name,
X				teamlet[l->pl_owner]);
X			    pmessage(buf, 0, MALL, "GOD->ALL");
X			    j->p_whydead = KPLANET;
X			    j->p_whodead = h;
X			    }
X			}
X		    }
X		    /* do bombing */
X		    if ((!(j->p_flags & PFORBIT)) || (!(j->p_flags & PFBOMB)))
X			continue;
X		    if (j->p_planet != l->pl_no)
X			continue;
X		    if (!((j->p_swar | j->p_hostile) & l->pl_owner))
X			continue;
X		    if (l->pl_armies < 5)
X			continue;
X
X			/* Warn owning team */
X		    if (pl_warning[h] <= 0) {
X			pl_warning[h] = 50/PLFIGHTFUSE; 
X			sprintf(buf, "We are under attack.  Please send aid");
X			sprintf(buf1, "%-3s->%-3s",
X			    l->pl_name, teamshort[l->pl_owner]);
X			pmessage(buf, l->pl_owner, MTEAM, buf1);
X		    }
X
X		    rnd = random() % 100;
X		    if (rnd < 50) {
X			continue;
X		    }
X		    else if (rnd < 80) {
X			l->pl_armies -= 1;
X			j->p_kills += 0.02;
X			j->p_stats.st_armsbomb++;
X		    }
X		    else if (rnd < 90) {
X			l->pl_armies -= 2;
X			j->p_kills += 0.04;
X			j->p_stats.st_armsbomb += 2;
X		    }
X		    else  {
X			l->pl_armies -= 3;
X			j->p_kills += 0.06;
X			j->p_stats.st_armsbomb += 3;
X		    }
X
X		    /* Send in a robot if there are no other defenders 
X			and the planet is in the team's home space */
X
X		    if ((tcount[l->pl_owner] == 0) && 
X			(l->pl_flags & l->pl_owner) &&
X			    tm_robots[l->pl_owner] == 0) {
X				startrobot(l->pl_owner, PFRSTICKY | PFRHARD);
X	
X			tm_robots[l->pl_owner] = (60 + 
X				    (random() % 60)) /
X				    TEAMFUSE;
X		    }
X
X	    }
X	}
X    }
X}
X
X/* udrobot - Check if any of the robots in the player list deserve
X * their chance to execute this tick.  Note that hard robots 
X * get to recalculate more often.  In order not to kill the game
X * they only recalculate every other call; the other times they just
X * fire an additional torp.
X */
Xudrobot(j)
Xregister struct player *j;
X{
X	if (j->p_flags & PFRHARD) { /* hard robots recalculate more often */
X	    if (udcounter % 2 == j->p_no % 2) rmove(j);
X	} else {
X	    if (udcounter % 10 == j->p_no % 10) rmove(j);
X	}
X}
X
Xbeam(j)
Xregister struct player *j;
X{
X    register int h, i;
X    register struct planet *l;
X    char buf[80];
X
X	/* do beaming */
X	if (!(j->p_flags & PFORBIT))
X		return;
X
X      for (h = 0, l = &planets[h]; h < MAXPLANETS; h++, l++) {
X		    if (j->p_planet != l->pl_no)
X			continue;
X		    if (j->p_flags & PFBEAMUP) {
X			if (l->pl_armies < 5)
X			    continue;
X			if (j->p_armies == j->p_ship.s_maxarmies)
X			    continue;
X			/* XXX */
X			if (j->p_armies == floor(j->p_kills * 2.0))
X			    continue;
X			if (j->p_team != l->pl_owner)
X			    continue;
X			j->p_armies++;
X			l->pl_armies--;
X		    }
X		    if (j->p_flags & PFBEAMDOWN) {
X			if (j->p_armies == 0)
X			    continue;
X			if (j->p_team != l->pl_owner) {
X			    j->p_armies--;
X			    if (l->pl_armies) {
X				l->pl_armies--;
X				j->p_kills += 0.02;
X				j->p_stats.st_armsbomb++;
X			    }
X			    else { 	/* planet taken over */
X				l->pl_armies++;
X				l->pl_owner = j->p_team;
X				j->p_stats.st_planets++;
X				j->p_kills += 0.25;
X				checkwin(j);
X				sprintf(buf, "%s taken over by %s (%c%x)",
X				    l->pl_name,
X				    j->p_name,
X				    teamlet[j->p_team],
X				    j->p_no);
X				pmessage(buf, 0, MALL, "GOD->ALL");
X			    }
X			}
X			else {
X			    j->p_armies--;
X			    l->pl_armies++;
X			}
X		    }
X
X	}
X}
X
Xblowup(sh)
Xstruct player *sh;
X{
X    register int i;
X    int dx, dy, dist;
X    int damage;
X    register struct player *j;
X
X    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
X	if (j->p_status == PFREE || j->p_status == PDEAD || j->p_status == PEXPLODE)
X	    continue;
X	if (sh == j)
X	    continue;
X	dx = sh->p_x - j->p_x;
X	dy = sh->p_y - j->p_y;
X	if (ABS(dx) > TDAMDIST || ABS(dy) > TDAMDIST)
X	    continue;
X	dist = dx * dx + dy * dy;
X	if (dist > TDAMDIST * TDAMDIST)
X	    continue;
X	if (dist > EXPDIST * EXPDIST) {
X	    damage = 100 * (TDAMDIST - sqrt((double) dist)) /
X		(TDAMDIST - EXPDIST);
X	}
X	else {
X	    damage = 100;
X	}
X	if (damage > 0) {
X	    if (j->p_flags & PFSHIELD) {
X		j->p_shield -= damage;
X		if (j->p_shield < 0) {
X		    j->p_damage -= j->p_shield;
X		    j->p_shield = 0;
X		}
X	    }
X	    else {
X		j->p_damage += damage;
X	    }
X	    if (j->p_damage >= 100) {
X		j->p_status = PEXPLODE;
X		j->p_explode = PEXPTIME;
X		sh->p_kills += 1.0 + j->p_armies * 0.1 + j->p_kills * 0.1;
X		killmess(j, sh);
X		j->p_stats.st_losses++;
X		j->p_whydead = KSHIP;
X		j->p_whodead = sh->p_no;
X	    }
X	}
X    }
X}
X
X/* This function is called when a planet has been taken over.
X   It checks all the planets to see if the victory conditions
X   are right.  If so, it blows everyone out of the game and
X   resets the galaxy
X*/
Xcheckwin(winner)
Xstruct player *winner;
X{
X    register int i, h;
X    register struct planet *l;
X    register struct player *j;
X    int team[MAXTEAM + 1];
X
X    for (i = 0; i < 4; i++)
X	team[1<<i] = 0;
X    
X    for (i = 0, l = &planets[i]; i < MAXPLANETS; i++, l++)
X	team[l->pl_owner]++;
X
X    for (i = 0; i < 4; i++) {
X	if (team[1<<i] == MAXPLANETS) {
X	    /* We have a winning team */
X	    for (h = 0, j = &players[0]; h < MAXPLAYER; h++, j++) {
X		j->p_status = PDEAD;
X		j->p_whydead = KWINNER;
X		j->p_whodead = winner->p_no;
X		j->p_ntorp = 0;
X		j->p_team = (FED|ROM|KLI|ORI);	/* Allow them to repick any team */
X	    }
X	    winner->p_stats.st_conqs++;
X	    bcopy(pdata, planets, sizeof(pdata));
X	    for (i = 0; i < 40; i++) {
X		if (random() % 4 == 0)
X		    planets[i].pl_flags |= PLREPAIR;
X		if (random() % 2 == 0)
X		    planets[i].pl_flags |= PLFUEL;
X	    }
X	    save_planets();
X	}
X    }
X}
X
Xkillmess(victim, killer)
Xstruct player *victim, *killer;
X{
X    char buf[80];
X
X    sprintf(buf, "%s (%c%x) was kill %0.2f for %s (%c%x)",
X	victim->p_name,
X	teamlet[victim->p_team],
X	victim->p_no,
X	killer->p_kills,
X	killer->p_name,
X	teamlet[killer->p_team],
X	killer->p_no);
X	pmessage(buf, 0, MALL, "GOD->ALL");
X}
X
Xdumpmessages()
X{
X    register int i;
X    register struct message *j;
X
X    for (i = 0, j = &messages[0]; i < MAXMESSAGE; i++, j++)
X	if (j->m_flags & MVALID)
X	    printf("%d, %s\n", i, j->m_data);
X}
X
Xstartrobot(team, flags)
Xint team;
Xint flags;
X{
X    register struct player	*p;
X    int rpno, tno;
X    extern char *rnames[4];
X
X    if ((rpno = findslot()) >= MAXPLAYER) return;
X    switch (team) {
X    case FED: tno = 0; break;
X    case ROM: tno = 1; break;
X    case KLI: tno = 2; break;
X    case ORI: tno = 3; break;
X    }
X    p = &players[rpno];
X    enter(tno, "Nowhere", rpno);
X    p->p_status = PALIVE;
X    p->p_flags |= PFROBOT | PFCOPILOT;		/* Mark as a robot */
X    strncpy(p->p_login, "Robot", strlen("Robot"));
X    p->p_login[strlen("Robot")] = NULL;
X    strncpy(p->p_name, rnames[tno], strlen(rnames[tno]));
X    p->p_name[strlen(rnames[tno])] = NULL;
X    p->p_ship.s_phasercost = 0;
X    p->p_ship.s_torpcost = 0;
X    /* Set robot difficulty */
X    p->p_flags |= flags;
X    if (p->p_flags & PFRHOSTILE)
X	p->p_hostile |= team;
X}
X
END_OF_FILE
if test 18229 -ne `wc -c <'subdaemon.c'`; then
    echo shar: \"'subdaemon.c'\" unpacked with wrong size!
fi
# end of 'subdaemon.c'
fi
echo shar: End of archive 4 \(of 7\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 7 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 7 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
-- 
Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330
Moderator of comp.sources.x



More information about the Comp.sources.x mailing list