[comp.sources.x] v09i072: acm, X aerial combat simulation, Part04/05

riley@mipsdal.mips.com (Riley Rainey) (10/08/90)

Submitted-by: riley@mipsdal.mips.com (Riley Rainey)
Posting-number: Volume 9, Issue 72
Archive-name: acm/part04

echo x - ./fsim/acm.1
sed 's/^X//' >./fsim/acm.1 <<'*-*-END-of-./fsim/acm.1-*-*'
X.TH ACM l "4 September 1990"
X.SH NAME
Xacm \- an aerial combat simulator for X
X.SH SYNOPSIS
X.B acm [ server ] [ options \]  
X.LP
X
X.SH DESCRIPTION
X
Xacm is an air combat simulator that runs under the X window system.  Up to
Xeight players can engage in simultaneous air combat.  Players fly jet aircraft
Xequipped with radar, heat seeking missiles and cannon.
X
XThe program, "acm", calls a deamon already running on the specified
Xserver_hostname and requests that your enter the game.  The shell variable
X"ACMSERVER" optionally specifies the name of the server host.
X
XEach player flies something close to either an F-16C Falcon or MIG-23.
X
X
X.SH USAGE REFERENCE
X
XTo begin play, the flight simulator server must be started manually on a
Xsystem that is accessible to all players. 
X
XThe following command line will do that:
X
X.LP
X.TP
X	% acms
X
XThe following command line options are recognized by acm:
X.LP
X.TP
X-geometry geometry_spec
XAn X compatible window geometry specification
X.TP
X-team <1 or 2>
XSpecifies the starting airfield.  Airfields are about 50 nm apart.
XTeam 1 flies F-16's, team 2 flies MIG-23's.
X
X
X.SH HOW TO TAKE-OFF
X
X
XYour mouse is the control stick.  The neutral position is the center of your
Xview display -- denoted by the dot in the center of your heads-up-display (HUD).
XMoving the mouse away from you pitches the plane down, moving it back
Xpitches the plane up.  Left and right inputs roll the aircraft in the
Xcorresponding direction.  On the ground at speeds up to 100 kts, nose
Xwheel steering guides the aircraft.
X
XTo take off for the first time, select 20 degrees of flaps (press H twice),
Xthen press the full throttle key (the 4 key on the main keyboard).  Keep the
Xmouse in the neutral position until you are moving at about 140 kts, then pull
Xthe mouse about two-thirds of the way down the view window.  You should pitch
Xup and lift off the ground fairly easily.  Gradually move the stick closer
Xto the neutral position and let your airspeed build -- don't move it back to
Xneutral too quickly or you will end up back on the ground again!  As your
Xairspeed passes about 250 kts, raise the flaps (press Y twice). Congratulations,
Xyou're flying a multi-million dollar jet.
X
X
X.SH ENGINE CONTROLS
X
X
XThe following keys control your engine thrust:
X
X.LP
X	4	Full Power
X.LP
X	3	Increase Power (about 2 percent)
X.LP
X	2	Decrease Power (about the same amount)
X.LP
X	1	Idle Power
X.LP
X	A	Toggle Afterburner
X
XYour engine gauge displays the power that you are generating.  Below that,
Xyou have displays showing your total fuel remaining as well as your current
Xfuel consumption rate.  The afterburner uses fuel at an amazing rate; use it
Xwisely.
X
X
X.SH LOOKING AROUND
X
X
XThe keys of the numeric keypad control which direction you're looking outside
Xof the cockpit:
X
X.LP
X		8 Forward
X.LP	
X	4 Left	5 Up	6 Right
X.LP
X		2 Aft
X
XIt pays to look around when you're in a combat environment.  Your chances
Xof staying alive increase remarkably.
X
X
X.SH THE HEADS UP DISPLAY (HUD)
X
X
XOn the left side of the HUD is a ladder showing your current airspeed in
Xnautical miles per hour (it displays true airspeed).  Above that, in the
Xupper left corner, is a G-meter.  
X
XThe right ladder shows altitude; above that
Xis a readout of your current angle-of-attack in degrees ("a=X.X").  
XYour
Xjet will stall at a 30 degrees positive angle of attack and negative 16 
Xdegrees. 
X
XThe airplane symbol (something like "-O-") shows the direction
Xthat the relative wind is coming from.  The relative wind combines your
Xcurrent angles of attack and sideslip.  A ladder in the center of the
XHUD show your aircraft's current attitude. 
X
XThe lower, horizontal ladder shows your current heading.  Discretes in the
Xlower left-hand corner show the state of your weapons systems.  Slightly
Xabove them is a readout of your current thrust percentage as well as the
Xstate of your engine's afterburner -- the "AB" symbol means the
Xafterburner is on.
X
X
X.SH USING YOUR RADAR DISPLAY
X
X
XThe radar system has a field of view of 130 degrees vertically and side-to-side.
XRadar automatically locks onto the closest threat in its field of view.  A
Xlocked target is displayed as a solid block.  Other hostile targets are 
Xdisplayed as hollow squares.
X
XTargetting information is displayed in the lower right corner of the display.
XThe top number is the heading of the locked target, the next number is the
Xrelative heading you should steer to intercept the target (displayed as
X"ddd R", and the third number is the rate that you are closing with this
Xtarget, expressed in knots.
X
XYou can lock onto other targets by pressing the target designator key (Q).
X
X
X.SH WHO'S GUNNING FOR ME?
X
X
XRadar sets that are tracking your aircraft can be detected.  Your Threat
XEarly Warning System (TEWS) display warns you of potential threats.  This
Xcircular display shows the relative direction of radars (other aircraft)
Xthat are looking at you.
X
X.SH ARMAMENTS
X
X
XYour aircraft is equipped with heat-seeking missiles and a 20 millimeter
Xcannon.  Weapon information is displayed in the lower left-hand corner of
Xyour HUD.  Different weapons may be selected by pressing mouse button 3.
X
XThe missiles are patterned after U.S. AIM-9M Sidewinders.  They can
Xdetect infared (IR) targets at any aspect (not just from the rear).  Their
Xrange varies dramatically with the altitude and closure rate.  The
Xmissile subsystem couples with your radar set to provide time-to-impact
Xinformation when AIM-9's are selected.
X
X
X.SH EXAMPLES
X
X acm bismarck 
X
X acm bismarck -geometry 1000x500
X
X.SH KEYBOARD COMMAND LIST
X
X
X
XEngine Controls
X
X.LP
X4 -- Full Power
X.LP
X3 -- Increase Power
X.LP
X2 -- Decrease Power
X.LP
X1 -- Idle
X.LP
XA -- Toggle Afterburner State
X
X
X
XRadar Controls
X
X.LP
XR -- Toggle Radar State (On/Standby)
X.LP
XQ -- Target Designator
X
X
X
XFlaps
X
X.LP
XH -- Extend 10 degrees
X.LP
XY -- Retract 10 degrees
X
X
X
XSpeed Brakes
X
X.LP
XS -- Extend
X.LP
XW -- Retract
X
X
X
XOther Controls
X
X.LP
XP -- Self-Destruct (Quit the game)
X.LP
XL -- Launch a target drone
X
X
X
XView Controls (Numeric Keypad)
X
X.LP
X8 -- Forward
X.LP
X2 -- Aft
X.LP
X4 -- Left
X.LP
X6 -- Right
X.LP
X5 -- Up
X
X
X.SH NOTES FOR THE ADVANCED USER
X
XIf you turn your radar set to standby (the R key toggles your radar sets
XON/STANDBY state), you don't emit radar signals, and, hence "disappear" from
Xeveryone elses TEWS display.  It's harder to acquire targets visually, but it
Xmay allow you to close in for the kill without alerting an opponent.
X
X
X
X.SH AUTHOR
XRiley Rainey, riley@mips.com
*-*-END-of-./fsim/acm.1-*-*
echo x - ./fsim/manifest.h
sed 's/^X//' >./fsim/manifest.h <<'*-*-END-of-./fsim/manifest.h-*-*'
X/*
X *  UPDATE_INTERVAL define the number of microseconds between
X *  each position update when the game is running.
X */
X 
X#define UPDATE_INTERVAL		125000
X
X/*
X *  REDRAW_EVERY defines the number of update intervals between each
X *  redraw of player screens.
X */
X
X#define REDRAW_EVERY		4
X
X/*
X *  ACM_PORT define the internet port number to be used in the game 
X *  startup handshaking.
X */
X
X#define ACM_PORT		3232
X
X/*
X *  ACM becomes the name used to lookup X resources on a particular
X *  X server.
X */
X
X#define ACM			"acm"
X
X/*
X *  Linear response to control stick inputs can make the plane harder
X *  to fly.
X */
X
X/* #define LINEAR_CONTROL_RESPONSE */
*-*-END-of-./fsim/manifest.h-*-*
echo x - ./fsim/newPlayer.c
sed 's/^X//' >./fsim/newPlayer.c <<'*-*-END-of-./fsim/newPlayer.c-*-*'
X/*
X *	xflight : an aerial combat simulator for X
X *
X *	Written by Riley Rainey,  riley@mips.com
X *
X *	Permission to use, copy, modify and distribute (without charge) this
X *	software, documentation, images, etc. is granted, provided that this 
X *	comment and the author's name is retained.
X *
X */
X 
X#include "pm.h"
X#include <stdio.h>
X#include <X11/Xutil.h>
X
X#define BORDER	1
X#define FONT			"*courier-bold-r-normal--17*"
X#define	ARG_FONT		"font"
X#define ARG_RADAR_FONT		"radarFont"
X#define	ARG_BORDER_COLOR	"borderColor"
X#define ARG_BORDER		"borderWidth"
X#define	ARG_GEOMETRY		"geometry"
X#define DEFAULT_BACKGROUND	"#93bde4"	/* my version of sky blue */
X#define DEFAULT_BORDER		"black"
X#define DEFAULT_RADAR_FONT	"fixed"
X
X#define SW_BORDER	1
X#define SW_BACKGROUND	2
X#define SW_HUDFONT	3
X#define SW_GEOM		4
X#define SW_RADARFONT	5
X#define SW_TEAM		6
X
Xstruct {
X	char	*sw;
X	int	value;
X	}	swt[] = {
X	"-bw", SW_BORDER,
X	"-skycolor", SW_BACKGROUND,
X	"-hudfont",  SW_HUDFONT,
X	"-radarfont",SW_RADARFONT,
X	"-geometry", SW_GEOM,
X	"-team",     SW_TEAM,
X	NULL, 0}, *swp;
X
XXWMHints	xwmh = {
X    (InputHint|StateHint),	/* flags */
X    False,			/* input */
X    NormalState,		/* initial_state */
X    0,				/* icon pixmap */
X    0,				/* icon window */
X    0, 0,			/* icon location */
X    0,				/* icon mask */
X    0,				/* Window group */
X};
X
Xvoid	recoverAcmArgv (args, argc, argv)
Xchar	*args;
Xint	*argc;
Xchar	*argv[]; {
X
X	char *s;
X
X	argv[0] = ACM;
X	argv[1] = args;
X
X	if (*args == '\0') {
X		*argc = 1;
X		argv[1] = (char *) NULL;
X		return;
X	}
X	else
X		*argc = 2;
X
X	for (s=args; *s;) {
X		if (*s == '|') {
X			*s = '\0';
X			argv[(*argc)++] = ++s;
X		}
X		else
X			++s;
X	}
X
X	argv[*argc] = (char *) NULL;
X}
X
Xint	newPlayer(s, display, logname, switches)
Xint	s;
Xchar	*display;
Xchar	*logname;
Xchar	*switches; {
X
X    char       *fontName;	/* Name of font for string */
X    XSizeHints	xsh;		/* Size hints for window manager */
X    Colormap	cmap;
X    GC		curGC;
X    XGCValues	gcv;
X    unsigned long pad;		/* Font size parameters */
X    unsigned long bd;		/* Pixel values */
X    unsigned long bw;		/* Border width */
X    char       *tempstr;	/* Temporary string */
X    XColor      color;		/* Temporary color */
X    char       *geomSpec;	/* Window geometry string */
X    XSetWindowAttributes xswa;	/* Temporary Set Window Attribute struct */
X    char	**c;
X    char	err[64];
X    static char	*background = NULL;
X    int		borderWidth = 1;
X    int		i, player;
X    int		width, height;
X    viewer	*u;
X    craft	*cf;
X    double	scale;
X    int		argc;
X    char	*argv[32];
X    int		screen, mono;
X    char	*hudfont = NULL, *radarfont = NULL;
X    int		team = 1;
X    char	*plane;		/* name of plane type */
X
X    recoverAcmArgv (switches, &argc, argv);
X
X
X    geomSpec = NULL;
X    u = (viewer *) malloc (sizeof(viewer));
X
X/*
X *  Parse command line
X */
X
X    for (c = &argv[1]; *c != (char *) NULL; ++c)
X	if (**c == '-') {
X	    for (swp = &swt[0]; swp->value != 0; ++swp)
X		if (strcmp (swp->sw, *c) == 0) {
X
X			switch (swp->value) {
X
X			case SW_GEOM: 
X				geomSpec = *(++c);
X				break;
X
X			case SW_BORDER:
X				borderWidth = atoi (*(++c));
X				break;
X
X			case SW_BACKGROUND:
X				background = *(++c);
X				break;
X
X			case SW_HUDFONT:
X				hudfont = *(++c);
X				break;
X
X			case SW_RADARFONT:
X				radarfont = *(++c);
X				break;
X
X			case SW_TEAM:
X				team = atoi (*(++c));
X				break;
X			}
X		        break;
X		}
X	    if (swp->value == 0) {
X		free ((char *) u);
X		ptbl[player].type = CT_FREE;
X		sprintf (err, "%s: invalid switch %s", ACM, *c);
X		write (s, err, strlen(err));
X		exit (1);
X	    }
X	}
X
X    if (team == 1)
X	plane = "f-16c";
X    else
X	plane = "mig-23";
X
X    if ((player = newPlane (plane)) < 0) {
X	sprintf (err, "Sorry, acm is popular -- no room for \
Xany more players at this moment.\n");
X	write (s, err, strlen(err));
X	return -1;
X    }
X
X/*
X *  assign a (kludged) team location.
X */
X
X    if (team == 2) {
X	ptbl[player].Sg.x = -0.6 * NM + 50.0;
X	ptbl[player].Sg.y = 49.0 * NM;
X    }
X
X    if ((u->dpy = XOpenDisplay(display)) == (Display *) NULL) {
X	free ((char *) u);
X	ptbl[player].type = CT_FREE;
X	sprintf(err, "%s: can't open %s\n", ACM, display);
X	write (s, err, strlen(err));
X	return -1;
X    }
X    screen = DefaultScreen (u->dpy);
X    mono = (DisplayPlanes (u->dpy, screen) == 1) ? 1 : 0;
X
X    if ((fontName = XGetDefault(u->dpy, ACM, ARG_FONT)) == NULL) {
X	fontName = FONT;
X    }
X    if ((u->font = XLoadQueryFont(u->dpy, fontName)) == NULL) {
X	XCloseDisplay (u->dpy);
X	free ((char *) u);
X	ptbl[player].type = CT_FREE;
X	sprintf(err, "%s: display %s doesn't know font %s\n",
X		ACM, display, fontName);
X	write (s, err, strlen(err));
X	return -1;
X    }
X    u->fth = u->font->max_bounds.ascent + u->font->max_bounds.descent;
X    u->ftw = u->font->max_bounds.width;
X
X    if ((fontName = XGetDefault(u->dpy, ACM, ARG_RADAR_FONT)) == NULL) {
X	fontName = DEFAULT_RADAR_FONT;
X    }
X    if ((u->rfont = XLoadQueryFont(u->dpy, fontName)) == NULL) {
X	XCloseDisplay (u->dpy);
X	free ((char *) u);
X	ptbl[player].type = CT_FREE;
X	sprintf(err, "%s: display %s doesn't know font %s\n",
X		ACM, display, fontName);
X	write (s, err, strlen(err));
X	return -1;
X    }
X    u->rfth = u->rfont->max_bounds.ascent + u->rfont->max_bounds.descent;
X    u->rftw = u->rfont->max_bounds.width;
X
X/*
X * Select colors for the border, the window background, and the
X * foreground.  We use the default colormap to allocate the colors in.
X */
X
X    cmap = DefaultColormap(u->dpy, screen);
X
X    if (background == NULL)
X	background = DEFAULT_BACKGROUND;
X
X    if ((tempstr = XGetDefault(u->dpy, ACM, ARG_BORDER_COLOR)) == NULL)
X	tempstr = DEFAULT_BORDER;
X    if (XParseColor(u->dpy, cmap, tempstr, &color) == 0) {
X	XCloseDisplay (u->dpy);
X	free ((char *) u);
X	ptbl[player].type = CT_FREE;
X	sprintf (err, "Can't get border color %s\n", tempstr);
X	write (s, err, strlen(err));
X	return -1;
X    }
X
X    if (mono)
X	bd = BlackPixel (u->dpy, screen);
X    else {
X        if (XAllocColor(u->dpy, cmap, &color) == 0) {
X	    XCloseDisplay (u->dpy);
X	    free ((char *) u);
X	    ptbl[player].type = CT_FREE;
X	    sprintf (err, "Cannot allocate color cells\n");
X	    write (s, err, strlen(err));
X	    return -1;
X	}
X	bd = color.pixel;
X    }
X
X/*
X * Set the border width of the window, and the gap between the text
X * and the edge of the window, "pad".
X */
X
X    pad = BORDER;
X    if ((tempstr = XGetDefault(u->dpy, ACM, ARG_BORDER)) == NULL)
X	bw = 1;
X    else
X	bw = atoi(tempstr);
X
X/*
X * Deal with providing the window with an initial position & size.
X * Fill out the XSizeHints struct to inform the window manager.
X */
X
X    if (geomSpec == NULL)
X        geomSpec = XGetDefault(u->dpy, ACM, ARG_GEOMETRY);
X
X/*
X * If the defaults database doesn't contain a specification of the
X * initial size & position - fit the window to the text and locate
X * it in the center of the screen.
X */
X
X    if (geomSpec == NULL) {
X	xsh.flags = PPosition | PSize;
X	xsh.height = FS_WINDOW_HEIGHT;
X	xsh.width =  FS_WINDOW_WIDTH;
X	xsh.x = (DisplayWidth(u->dpy, screen) - xsh.width) / 2;
X	xsh.y = (DisplayHeight(u->dpy, screen) - xsh.height) / 2;
X    }
X    else {
X	int         bitmask;
X
X	bzero((char *) &xsh, sizeof(xsh));
X	bitmask = XGeometry(u->dpy, screen, geomSpec, geomSpec,
X			    bw, u->ftw, u->fth, pad, pad, &(xsh.x), &(xsh.y),
X			    &(xsh.width), &(xsh.height));
X	if (bitmask & (XValue | YValue)) {
X	    xsh.flags |= USPosition;
X	}
X	if (bitmask & (WidthValue | HeightValue)) {
X	    xsh.flags |= USSize;
X	}
X    }
X
X/*
X * Create the Window with the information in the XSizeHints, the
X * border width,  and the border & background pixels.
X */
X
X    u->win = XCreateSimpleWindow(u->dpy, DefaultRootWindow(u->dpy),
X			      xsh.x, xsh.y, xsh.width, xsh.height,
X			      bw, bd, 1);
X
X    scale = (double) xsh.width / (double) FS_WINDOW_WIDTH;
X    width = xsh.width;
X    height = xsh.height;
X
X/*
X * Create a pixmap of the engine RPM gauge and flap indicators.
X */
X
X    u->eng = XCreateBitmapFromData (u->dpy, u->win, eng_bits, eng_width,
X	eng_height);
X    u->flap[0] = XCreateBitmapFromData (u->dpy, u->win, flaps0_bits,
X	flaps0_width, flaps0_height);
X    u->flap[1] = XCreateBitmapFromData (u->dpy, u->win, flaps1_bits,
X	flaps1_width, flaps1_height);
X    u->flap[2] = XCreateBitmapFromData (u->dpy, u->win, flaps2_bits,
X	flaps2_width, flaps2_height);
X    u->flap[3] = XCreateBitmapFromData (u->dpy, u->win, flaps3_bits,
X	flaps3_width, flaps3_height);
X
X/*
X * Set the standard properties for the window managers.
X */
X
X    XSetStandardProperties(u->dpy, u->win, ACM, ACM, None, argv, argc, &xsh);
X    XSetWMHints(u->dpy, u->win, &xwmh);
X
X    xsh.width = RADAR_WINDOW_WIDTH * scale;
X    xsh.height = RADAR_WINDOW_HEIGHT * scale;
X    xsh.x = RADAR_X * scale;
X    xsh.y = RADAR_Y * scale;
X    u->rwin = XCreateWindow (u->dpy, u->win, xsh.x, xsh.y, xsh.width,
X	xsh.height, 0, CopyFromParent, CopyFromParent, CopyFromParent,
X	0, NULL);
X
X/*
X * Ensure that the window's colormap field points to the default
X * colormap,  so that the window manager knows the correct colormap to
X * use for the window.  Also,  set the window's Bit
X * Gravity to reduce Expose events.
X */
X
X    xswa.colormap = DefaultColormap(u->dpy, screen);
X    xswa.bit_gravity = NorthWestGravity;
X    XChangeWindowAttributes(u->dpy, u->win, (CWColormap | CWBitGravity), &xswa);
X
X/*
X * Create the GC for drawing the picture.
X */
X
X    gcv.font = u->font->fid;
X    curGC = XCreateGC(u->dpy, u->win, GCFont, &gcv);
X    XSelectInput(u->dpy, u->win, KeyPressMask | ButtonPressMask |
X	StructureNotifyMask | ButtonReleaseMask);
X
X/*
X *  Fill-in the viewer structure
X */
X
X    cf = &ptbl[player];
X    cf->team = player;
X    cf->vl = u;
X    strncpy (cf->name, logname, sizeof (cf->name));
X    strncpy (cf->display, display, sizeof (cf->display));
X    u->next = (viewer *) NULL;
X    u->width = VIEW_WINDOW_WIDTH * scale;
X    u->height = VIEW_WINDOW_HEIGHT * scale;
X    u->xCenter = u->width / 2;
X    u->yCenter = u->height / 2;
X
X    u->radarWidth = RADAR_WINDOW_WIDTH * scale;
X    u->radarHeight = RADAR_WINDOW_HEIGHT * scale;
X    u->gc = curGC;
X
X    u->TEWSx = TEWS_X * scale;
X    u->TEWSy = TEWS_Y * scale;
X    u->TEWSSize = TEWS_SIZE * scale;
X
X    u->v = VOpenViewport (u->dpy, screen, u->win,
X	12.0*25.4/1000.0, 0.5, scale * 0.70, u->width, u->height);
X
X    if (VBindColors (u->v, background) < 0) {
X	XCloseDisplay (u->dpy);
X	free ((char *) u);
X	ptbl[player].type = CT_FREE;
X	sprintf (err, "Error in binding colors.\n");
X	write (s, err, strlen(err));
X	return -1;
X    }
X
X/*
X *  Fill in the scale structures for the airspeed/altitude HUD scales.
X */
X
X    u->altScale.xorg = ALT_ORG_X * scale;
X    u->altScale.yorg = ALT_ORG_Y * scale;
X    u->altScale.length = ALT_LENGTH * scale;
X    u->altScale.orientation = ALT_ORIENT;
X    u->altScale.scale = ALT_SCALE / scale;
X    u->altScale.minorInterval = ALT_MIN_INTERVAL;
X    u->altScale.minorSize = ALT_MIN_SIZE * scale;
X    u->altScale.majorInterval = ALT_MAJ_INTERVAL;
X    u->altScale.majorSize = ALT_MAJ_SIZE * scale;
X    u->altScale.indexSize = ALT_INDEX_SIZE * scale;
X    u->altScale.divisor = ALT_DIVISOR;
X    u->altScale.format = ALT_FORMAT;
X
X    u->velScale.xorg = VEL_ORG_X * scale;
X    u->velScale.yorg = VEL_ORG_Y * scale;
X    u->velScale.length = VEL_LENGTH * scale;
X    u->velScale.orientation = VEL_ORIENT;
X    u->velScale.scale = VEL_SCALE / scale;
X    u->velScale.minorInterval = VEL_MIN_INTERVAL;
X    u->velScale.minorSize = VEL_MIN_SIZE * scale;
X    u->velScale.majorInterval = VEL_MAJ_INTERVAL;
X    u->velScale.majorSize = VEL_MAJ_SIZE * scale;
X    u->velScale.indexSize = VEL_INDEX_SIZE * scale;
X    u->velScale.divisor = VEL_DIVISOR;
X    u->velScale.format = VEL_FORMAT;
X
X    u->hdgScale.xorg = HDG_ORG_X * scale;
X    u->hdgScale.yorg = HDG_ORG_Y * scale;
X    u->hdgScale.length = HDG_LENGTH * scale;
X    u->hdgScale.orientation = HDG_ORIENT;
X    u->hdgScale.scale = HDG_SCALE / scale;
X    u->hdgScale.minorInterval = HDG_MIN_INTERVAL;
X    u->hdgScale.minorSize = HDG_MIN_SIZE * scale;
X    u->hdgScale.majorInterval = HDG_MAJ_INTERVAL;
X    u->hdgScale.majorSize = HDG_MAJ_SIZE * scale;
X    u->hdgScale.indexSize = HDG_INDEX_SIZE * scale;
X    u->hdgScale.divisor = HDG_DIVISOR;
X    u->hdgScale.format = HDG_FORMAT;
X									       
X/*
X * Map the window to make it visible.
X */
X
X    XMapWindow(u->dpy, u->win);
X    XMapWindow(u->dpy, u->rwin);
X    VExposeBuffer (u->v, u->gc);
X
X    whitePixel = whiteColor->index;
X    blackPixel = blackColor->index;
X    HUDPixel = HUDColor->index;
X
X    return 0;
X
X}
X
Xint killPlayer (c)
Xcraft	*c; {
X
X	viewer	*v, *vn;
X	int	i;
X
X/*
X *  Erase our radar emissions
X */
X
X	for (i=0; i<MAXPLAYERS; ++i)
X		ptbl[i].rval[c->index] = 0.0;
X
X/*
X *  Free HUD string storage
X */
X
X	if (c->leftHUD[0] != (char *) NULL)
X		for (i=0; i<3; ++i) {
X			free (c->leftHUD[i]);
X			free (c->rightHUD[i]);
X		}
X
X/*
X *  Close viewers' display
X */
X
X	for (v=c->vl; v != (viewer *) NULL;) {
X		XCloseDisplay (v->dpy);
X		vn = (viewer *) v->next;
X		free ((char *) v);
X		v = vn;
X	}
X
X	if (c->flags && FL_RECORD)
X		-- recordCount;
X
X	c->type = CT_FREE;
X	return 0;
X}
*-*-END-of-./fsim/newPlayer.c-*-*
echo x - ./fsim/missile.c
sed 's/^X//' >./fsim/missile.c <<'*-*-END-of-./fsim/missile.c-*-*'
X/*
X *	xflight : an aerial combat simulator for X
X *
X *	Written by Riley Rainey,  riley@mips.com
X *
X *	Permission to use, copy, modify and distribute (without charge) this
X *	software, documentation, images, etc. is granted, provided that this 
X *	comment and the author's name is retained.
X *
X */
X 
X#include "pm.h"
X#include <math.h>
X
Xtypedef struct _entry {
X	double	time;
X	double	min;
X	craft	*c;
X	struct	_entry *next;
X	}	entry;
X
X
Xextern craftType *lookupCraft();
Xextern int mdebug;
X
Xint	fireMissile (c)
Xcraft	*c; {
X
X	register craft	*m;
X	register int	i;
X	VPoint		s;
X
X	for ((i=0, m= &mtbl[0]); i<MAXPROJECTILES; (++i, ++m))
X		if (m->type == CT_FREE) {
X			m->type = CT_MISSILE;
X			break;
X		}
X
X	if (i == MAXPROJECTILES)
X		return -1;
X
X	m->cinfo = lookupCraft ("aim-9m");
X	m->fuel = m->cinfo->maxFuel;
X	m->curThrust = m->cinfo->maxThrust;
X	m->trihedral = c->trihedral;
X	m->Itrihedral = c->Itrihedral;
X	m->curRoll = c->curRoll;
X	m->curPitch = c->curPitch;
X	m->curHeading = c->curHeading;
X	m->Cg = c->Cg;
X	VTransform (&(c->cinfo->wStation[1]), &(c->trihedral), &s);
X	m->Sg.x = c->Sg.x + s.x;
X	m->Sg.y = c->Sg.y + s.y;
X	m->Sg.z = c->Sg.z + s.z;
X	m->armFuse = (int) (m->cinfo->armDelay / deltaT);
X	m->flags = FL_HAS_GYRO;
X
X/*
X * kludge
X */
X
X	m->curRadarTarget = c->curRadarTarget;
X
X	return 0;
X}
X
Xint	killMissile (c)
Xcraft	*c; {
X
X	c->type = CT_FREE;
X	return 0;
X}
X
Xint	lookForImpacts () {
X
X	craft	*c, *m;
X	entry	p[MAXPLAYERS], *list, *q, *r, *rprev;
X	VPoint	v, s0;
X	double	t, d;
X	int	i, j;
X
X	for (m=mtbl, i=0; i<MAXPROJECTILES; ++i, ++m) {
X
X		if (m->type != CT_MISSILE || m->armFuse > 0)
X			continue;
X
X		list = (entry *) NULL;
X		for (c=ptbl, j=0; j<MAXPLAYERS; ++j, ++c) {
X
X			if (c->type == CT_FREE)
X				continue;
X
X/*
X * Reduce the relative motion of this object to a the parametric system
X * of equations:
X *		x(t) = vx * t + s0x
X *		y(t) = vy * t + s0y
X *		z(t) = vz * t + s0z
X *
X * We can then compute the time of perigee (closest pass) along with
X * the associated minimum distance.
X */
X
X			v.x = c->Sg.x - c->prevSg.x - m->Sg.x + m->prevSg.x;
X			v.y = c->Sg.y - c->prevSg.y - m->Sg.y + m->prevSg.y;
X			v.z = c->Sg.z - c->prevSg.z - m->Sg.z + m->prevSg.z;
X			s0.x = c->prevSg.x - m->prevSg.x;
X			s0.y = c->prevSg.y - m->prevSg.y;
X			s0.z = c->prevSg.z - m->prevSg.z;
X
X/*
X * Compute time of minimum distance between the two objects (note that units
X * here are UPDATE_INTERVAL seconds).
X */
X
X			t = - (v.x * s0.x + v.y * s0.y + v.z * s0.z) /
X				(v.x * v.x + v.y * v.y + v.z * v.z);
X
X			if (mdebug)
X			printf ("perigee in %g seconds with player %d\n", t*8.0, j);
X
X/*
X *  If the closest pass occurs during this update interval, check for a hit.
X *  We'll build a linked list of all craft that this projectile may strike
X *  during this period, arranged in ascending order by time of "perigee"
X *  (closest pass).  We'll then test for strikes.  If a projectile misses
X *  the first object, then it may have struck subsequent objects in the
X *  list ...
X */
X
X/*
X *  One special case occurs when a target or missile's turn suddenly
X *  changes the perigee time from positive to negative.  If the missile
X *  is within hitting range at t=0 and the time of perigee is negative,
X *  then zap 'em.
X */
X
X			if (t < 0.0) {
X				d = sqrt (s0.x *s0.x + s0.y * s0.y +
X					s0.z * s0.z);
X				if (isMissileHit (d, c)) {
X					printf ("detected a \"curve hit\"\n");
X					t = 0.0;
X				}
X			}
X
X			if (t >= 0.0 && t <= 1.0) {
X				q = &p[i];
X				if (list == (entry *) NULL) {
X					q->next = list;
X					list = q;
X				}
X				else if (list->time > t) {
X					q->next = list;
X					list = q;
X				}
X				else {
X					for (rprev=list, r=list->next; r != (entry *) NULL;) {
X						if (r->time > t) break;
X						rprev = r;
X						r = r->next;
X					}
X					if (rprev != list) 
X						rprev->next = q;
X					q->next = r;
X				}
X				q->time = t;
X				q->c = c;
X				q->min = sqrt (pow(v.x * t + s0.x, 2.0) +
X					pow (v.y * t + s0.y, 2.0) +
X					pow (v.z * t + s0.z, 2.0) );
X					if (mdebug)
X					printf ("perigee %g feet; craft %d.\n",
X						q->min, j);
X			}
X		}
X
X/*
X *  Now look for missile hits in the list of perigees.
X */
X
X		for (r=list; r != (entry *) NULL; r=r->next)
X			if (isMissileHit (r->min, r->c)) {
X				killMissile (m);
X				killPlayer (r->c);
X				break;
X			}
X	}
X}
X
Xint isMissileHit (min, c)
Xdouble min;
Xcraft	*c; {
X
X	return (min < 50.0) ? 1 : 0;
X}
X
X#define IRScanSlope 	0.57735
X
Xint isIRVisible (c, m, t)
Xcraft *c;
XVMatrix *m;
XVPoint	*t; {
X
X	VPoint	relPos;
X
X	VTransform (&(c->Sg), m, t);
X
X	if (t->z < 0.0)
X		return 0;
X
X	relPos.x = t->x / (t->z * IRScanSlope);
X	relPos.y = t->y / (t->z * IRScanSlope);
X
X	return (sqrt(relPos.x*relPos.x + relPos.y*relPos.y) > 1.0) ? 0 : 1;
X}
X
Xint getIRTarget (c, m, t)
Xcraft *c;
XVMatrix *m;
XVPoint  *t; {
X
X	int	i, n;
X	craft	*p;
X	VPoint	tNew, tMin;
X	double	m1, min;
X
X	if (c->curRadarTarget != -1 && isIRVisible(&ptbl[c->curRadarTarget], m, t))
X		return c->curRadarTarget;
X
X/*
X *  Look for a target.  Designate the closest one as a new target.
X */
X
X	min = 1000000.0;
X	n = -1;
X	for (i=0, p=ptbl; i<MAXPLAYERS; ++i, ++p) {
X		if (p == c)
X			continue;
X		if (p->type != CT_FREE)
X		if (isIRVisible (p, m, &tNew)) {
X			m1 = mag(tNew);
X			if (m1 < min) {
X				n = i;
X				min = m1;
X				tMin = tNew;
X			}
X		}
X	}
X
X	*t = tMin;
X	return n;
X}
X
Xvoid createMissileEyeSpace (c, eyeSpace)
Xcraft	*c;
XVMatrix	*eyeSpace; {
X
X	VPoint	CntrInt, up, C1, C2;
X	VMatrix	mtx, es;
X	double	Hypotenuse, h1, SinA, CosA;
X
X/*
X *  Create an eyeSpace transformation matrix to convert from global to
X *  local coordinates.
X */
X
X	CntrInt.x = c->Sg.x + c->trihedral.m[0][0];
X	CntrInt.y = c->Sg.y + c->trihedral.m[1][0];
X	CntrInt.z = c->Sg.z + c->trihedral.m[2][0];
X
X/*
X *  If the missile has a gyroscope, then it can determine which way "down" is
X *  and, hence, compensate for gravity.  Here, we'll compensate by pointing
X *  the nose of the missile up by a maximum of 12 degrees at all times.
X */
X
X	if (c->flags & FL_HAS_GYRO)
X		if (c->curThrust > 0.0)
X			CntrInt.z += 0.208;
X		else
X			CntrInt.z += 0.30;
X
X	up.x = c->Sg.x - c->trihedral.m[0][2];
X	up.y = c->Sg.y - c->trihedral.m[1][2];
X	up.z = c->Sg.z - c->trihedral.m[2][2];
X
X	VIdentMatrix (eyeSpace);
X	eyeSpace->m[0][3] = -c->Sg.x;
X	eyeSpace->m[1][3] = -c->Sg.y;
X	eyeSpace->m[2][3] = -c->Sg.z;
X	VTransform(&CntrInt, eyeSpace, &C1);
X
X	VIdentMatrix (&mtx);
X	Hypotenuse = sqrt(C1.x * C1.x + C1.y * C1.y);
X	if (Hypotenuse > 0.0) {
X		CosA = C1.y / Hypotenuse;
X		SinA = C1.x / Hypotenuse;
X		mtx.m[0][0] = CosA;
X		mtx.m[1][0] = SinA;
X		mtx.m[0][1] = -SinA;
X		mtx.m[1][1] = CosA;
X		es = *eyeSpace;
X		VMatrixMult(&es, &mtx, eyeSpace);
X	}
X
X	VTransform(&CntrInt, eyeSpace, &C2);
X	VIdentMatrix (&mtx);
X	Hypotenuse = sqrt(C2.y * C2.y + C2.z * C2.z);
X	if (Hypotenuse > 0.0) {
X		CosA = C2.y / Hypotenuse;
X		SinA = -C2.z / Hypotenuse;
X		mtx.m[1][1] = CosA;
X		mtx.m[2][1] = SinA;
X		mtx.m[1][2] = -SinA;
X		mtx.m[2][2] = CosA;
X		es = *eyeSpace;
X		VMatrixMult(&es, &mtx, eyeSpace);
X	}
X
X        VTransform (&up, eyeSpace, &C2);
X	VIdentMatrix (&mtx);
X	h1 = sqrt (C2.y * C2.y + C2.z * C2.z);
X	Hypotenuse = sqrt(C2.x * C2.x + h1 * h1);
X	if (Hypotenuse > 0.0) {
X		CosA = h1 / Hypotenuse;
X		SinA = C2.x / Hypotenuse;
X		if (C2.z < 0.0) {
X			CosA = -CosA;
X		}
X		mtx.m[0][0] = CosA;
X		mtx.m[2][0] = SinA;
X		mtx.m[0][2] = -SinA;
X		mtx.m[2][2] = CosA;
X		es = *eyeSpace;
X		VMatrixMult(&es, &mtx, eyeSpace);
X	}
X
X	VIdentMatrix (&mtx);
X	mtx.m[1][1] = 0.0;
X	mtx.m[2][1] = 1.0;
X	mtx.m[1][2] = 1.0;
X	mtx.m[2][2] = 0.0;
X	es = *eyeSpace;
X	VMatrixMult(&es, &mtx, eyeSpace);
X
X}
X
Xvoid trackTarget (c)
Xcraft *c; {
X
X	VMatrix eyeSpace, mtx;
X	VPoint	t, t1;
X	double	v, h, m, maxTurnSlope, aMax = 30.0 * a;
X	double	deltaRoll, deltaPitch, deltaYaw;
X	double	cosR, sinR;
X
X	createMissileEyeSpace (c, &eyeSpace);
X
X/*
X *  Now let's get to target tracking;  first, if we don't already have a
X *  target designated, get one.
X */
X
X/*	if (c->armFuse > 0) {
X		t.x = 0.0;
X		t.y = 0.0;
X		t.z = 1.0;
X	}
X	else */if ((c->curRadarTarget = getIRTarget(c, &eyeSpace, &t)) == -1) {
X		if (mdebug)
X			printf ("Missile elects to self-destruct\n");
X		killMissile (c);
X		return;
X	}
X
X	t.x = t.x / t.z;
X	t.y = t.y / t.z;
X
X	h = sqrt (t.x*t.x + t.y*t.y);
X	v = mag (c->Cg);
X
X/*
X *  We'll constrain missile turns to a 20 degree/second unless it's velocity
X *  would make that greater than 30g's.
X */
X
X	if ((m=(v*v - aMax*aMax/4.0)) > 0.0)
X		maxTurnSlope = aMax / (2.0 * sqrt (m)) * deltaT;
X
X	else
X		maxTurnSlope = 0.3639 * deltaT;
X
X	if (mdebug)
X		printf ("slope = %g; maxTurnSlope = %g\n", h, maxTurnSlope);
X
X	if (h > maxTurnSlope) {
X		t.x = t.x * maxTurnSlope / h;
X		t.y = t.y * maxTurnSlope / h;
X	}
X
X        cosR = cos (c->curRoll);
X	sinR = sin (c->curRoll);
X
X	deltaRoll = 0.0;
X	deltaPitch = atan (t.y);
X	deltaYaw   = atan (t.x);
X
X/*
X *  Re-orient the velocity vector towards our new direction.
X */
X
X        VIdentMatrix (&mtx);
X	if (deltaPitch != 0.0)
X		VRotate (&mtx, YRotation, - deltaPitch);
X	if (deltaYaw != 0.0)
X		VRotate (&mtx, ZRotation, deltaYaw);
X	VTransform (&(c->Cg), &(c->Itrihedral), &t);
X	VTransform (&t, &mtx, &t1);
X	VTransform (&t1, &(c->trihedral), &(c->Cg));
X
X	if (mdebug)
X		printf ("Missile changes: pitch: %g, yaw: %g.\n",
X			RADtoDEG(deltaPitch), RADtoDEG(deltaYaw));
X
X	c->curRoll    += deltaRoll;
X	c->curHeading += sinR * deltaPitch + cosR * deltaYaw;
X	c->curPitch   += cosR * deltaPitch - sinR * deltaYaw;
X
X}
*-*-END-of-./fsim/missile.c-*-*
echo x - ./fsim/m61a1.c
sed 's/^X//' >./fsim/m61a1.c <<'*-*-END-of-./fsim/m61a1.c-*-*'
X/*
X *	xflight : an aerial combat simulator for X
X *
X *	Written by Riley Rainey,  riley@mips.com
X *
X *	Permission to use, copy, modify and distribute (without charge) this
X *	software, documentation, images, etc. is granted, provided that this 
X *	comment and the author's name is retained.
X *
X */
X 
X#include "pm.h"
X#include <stdio.h>
X#include <string.h>
X#include <math.h>
X
X#define BORE_CROSS_SIZE	7
X#define MUZZLE_VELOCITY (3.2808 * 1036.0)
X#define TRACER_MOD	10	
X#define OFFSET_ANGLE	(DEGtoRAD(3.0))		/* the gun points up at this angle */
X#define RATE_OF_FIRE	(3000.0 / 60.0)		/* rounds per second */
X#define FUZZ		(DEGtoRAD(1.0))		/* distribution due to vibration */
X
Xint select_m61a1();
Xint display_m61a1();
Xint update_m61a1();
Xint press_m61a1();
Xint release_m61a1();
Xextern craftType * lookupCraft();
X
XweaponDesc m61a1Desc = {
X	WK_M61A1,
X	select_m61a1,		/* select */
X	update_m61a1,		/* update */
X	display_m61a1,		/* display procedure */
X	press_m61a1,		/* fire */
X	release_m61a1,		/* fire button release */
X	};
X
X/*
X *  m61a1 selection function
X *
X *  A selection function normally determines whether there are any weapons
X *  of this type on-board.  If so, and the weapon system is functional
X *  (in other words, undamaged) then return 1; otherwise return 0.
X */
X
Xint select_m61a1 (c)
Xcraft *c; {
X
X	if (c->station[0].type == WK_M61A1 && c->station[0].info > 0)
X		return 1;
X	else
X		return 0;
X
X}
X
X/*
X *  m61a1 display function
X *
X *  Update the HUD display strings associated with this weapon system.
X */
X
Xint display_m61a1 (c, w, u)
Xcraft *c;
XcraftType *w;
Xviewer *u; {
X
X	char	s[16];
X	register int tx, ty, m;
X	VPoint	 tmp;
X	XSegment seg[2];
X
X	strcpy (c->leftHUD[0], "LCOS");
X	sprintf (s, "%.3d M-61A1", c->station[0].info);
X	strcpy (c->leftHUD[1], s);
X	if (c->station[0].info3)
X		strcpy (c->leftHUD[2], "FIRING");
X	else
X		strcpy (c->leftHUD[2], "");
X
X/*
X *  Draw the boresight cross
X */
X
X	m = (double) BORE_CROSS_SIZE * (double) u->width /
X		(double) VIEW_WINDOW_WIDTH + 0.5;
X
X	tx = u->xCenter;
X	ty = u->yCenter - 3 * 9;	/* kludged, for now */
X	seg[0].x1 = tx - m;
X	seg[0].x2 = tx + m;
X	seg[0].y1 = seg[0].y2 = ty;
X	seg[1].x1 = seg[1].x2 = tx;
X	seg[1].y1 = ty - m;
X	seg[1].y2 = ty + m;
X	XDrawSegments (u->dpy, u->win, u->gc, seg, 2);
X
X/*
X *  If we have a radar target designated, then draw a reticle.
X */
X/*
X	if (c->curRadarTarget >= 0) {
X		VTransform (&(ptbl[c->curRadarTarget].Sg),
X			&u->v->eyeSpace, &tmp);		
X		tx = u->v->Middl.x + tmp.x * u->v->Scale.x / tmp.z + 0.5;
X		ty = u->v->Middl.y - tmp.y * u->v->Scale.y / tmp.z + 0.5;
X	}
X*/
X}
X
Xint	press_m61a1 (c)
Xcraft	*c; {
X	c->station[0].info3 |= 1;
X	return 0;
X}
X
Xint	release_m61a1 (c)
Xcraft	*c; {
X	c->station[0].info3 &= ~1;
X	return 0;
X}
X
Xextern long random ();
X
Xint	update_m61a1 (c)
Xcraft	*c; {
X
X	craft	*m;
X	int	i;
X	VPoint	tmp, mvel;
X	int	rounds;
X	double	fuzz, fuzzAngle, phiY, phiZ, tm, mv = MUZZLE_VELOCITY;
X
X	if (c->station[0].info3 == 0)
X		return 0;
X
X/*
X *  Got any ammunition ?
X */
X
X	if (c->station[0].info <= 0)
X		return -1;
X
X/*
X *  Allocate a projectile record
X */
X
X	for ((i=0, m= &mtbl[0]); i<MAXPROJECTILES; (++i, ++m))
X		if (m->type == CT_FREE) {
X			m->type = CT_CANNON;
X			break;
X		}
X
X	if (i == MAXPROJECTILES)
X		return -1;
X
X/*
X *  Determine how far we're fuzzed off the ideal boresight.
X */
X
X	fuzz = ((double)(random() & 32767) +
X		(double)(random() & 32767)) / 32768.0 - 1.0;
X	fuzz = fuzz * FUZZ;
X	fuzzAngle = 2.0 * pi * (double)(random() & 511) / 512.0;
X
X/*
X *  Determine the initial velocity of the projectile stream.
X */
X
X	phiZ = fuzz * sin (fuzzAngle);
X	phiY = fuzz * cos (fuzzAngle);
X	tm = mv * cos (OFFSET_ANGLE + phiZ);
X
X	tmp.x = tm * cos (phiY); 
X	tmp.y = tm * sin (phiY); 
X	tmp.z = mv * sin (-OFFSET_ANGLE + phiZ);
X	VTransform (&tmp, &(c->trihedral), &mvel);
X
X	m->createTime = curTime;
X	m->Cg = c->Cg;
X	m->curRoll = c->curRoll;
X	m->curPitch = c->curPitch;
X	m->curHeading = c->curHeading;
X	m->Cg.x += mvel.x;
X	m->Cg.y += mvel.y;
X	m->Cg.z += mvel.z;
X
X/*
X *  Determine the initial position.
X */
X
X	VTransform (&(c->cinfo->wStation[0]), &(c->trihedral), &tmp);
X	m->Sg.x = c->Sg.x + tmp.x;
X	m->Sg.y = c->Sg.y + tmp.y;
X	m->Sg.z = c->Sg.z + tmp.z;
X
X/*
X *  Subtract the number of rounds fired.
X */
X
X	m->rounds = RATE_OF_FIRE * deltaT;
X	m->rounds = (m->rounds > c->station[0].info) ? c->station[0].info : m->rounds;
X	m->tracerMod = TRACER_MOD;
X	m->tracerVal = c->station[0].info2 % m->tracerMod;
X	c->station[0].info -= m->rounds;
X	c->station[0].info2 += m->rounds;
X
X	m->cinfo = lookupCraft ("m61a1 cannon");
X
X	return 0;
X
X}
X
Xextern craftType * newCraft ();
Xextern char * strdup();
X
Xint	placeCannon(c, m, poly, cnt)
Xcraft	*c;
XVMatrix	*m;
XVPolygon **poly;
Xint	*cnt; {
X
X	double	t, intervalT;
X	VPoint	v, s;
X	int	i, j, k, n;
X	VPoint	 *q, tmp;
X	VPolygon **p;
X
X/*
X *  Reduce the shell path to a set of parametric equations.
X */
X
X	v.x = c->Sg.x - c->prevSg.x;
X	v.y = c->Sg.y - c->prevSg.y;
X	v.z = c->Sg.z - c->prevSg.z;
X
X/*
X *  Now add each tracer shell to the view.
X */
X
X	intervalT = 1.0 / c->rounds;
X	for (t=intervalT*c->tracerVal; t <= 1.0; t += intervalT * TRACER_MOD) {
X		s.x = -v.x * t;
X		s.y = -v.y * t;
X		s.z = -v.z * t;
X		if (c->Sg.z + s.z > 0.0)	/* underground? don't plot it */
X			continue;
X		n = c->cinfo->object->numPolys;
X		p = c->cinfo->object->polygon;
X		j = *cnt;
X		for (i=0; i<n; ++i) {
X			poly[j] = VCopyPolygon(p[i]);
X			for ((k=0, q=poly[j]->vertex); k<poly[j]->numVtces; (++k, ++q)) {
X				VTransform(q, m, &tmp);
X				tmp.x += s.x;
X				tmp.y += s.y;
X				tmp.z += s.z;
X				*q = tmp;
X			}
X			++j;
X		}
X		*cnt = j;
X	}
X
X}
X
Xvoid initm61a1()
X{
X
X	craftType	*c;
X	FILE    	*f;
X
X	wtbl[1] = m61a1Desc;
X
X	c = newCraft();
X	c->name = strdup("m61a1 cannon");
X
X	c->placeProc = placeCannon;
X
X	f = fopen ("bullet", "r");
X	c->object = VReadObject(f);
X	fclose (f);
X
X}
X
Xint cannonCalculations (c)
Xcraft *c; {
X
X
X/*
X *  Kill projectile streams after 10.0 seconds of flight or when
X *  they strike the ground.
X */
X
X	if (curTime - c->createTime > 10.0)
X		return 1;
X
X	if (c->Sg.z > 0.0)
X		return 1;
X
X	c->prevSg = c->Sg;
X
X	c->Sg.x += c->Cg.x * deltaT;
X	c->Sg.y += c->Cg.y * deltaT;
X	c->Sg.z += c->Cg.z * deltaT + a * halfDeltaTSquared;
X
X	c->Cg.z += a * deltaT;
X	return 0;
X
X}
*-*-END-of-./fsim/m61a1.c-*-*
echo x - ./fsim/README
sed 's/^X//' >./fsim/README <<'*-*-END-of-./fsim/README-*-*'
Xacm Flight Simulator version 1.0
X
XThis software is divided into two major parts: the 3-D graphics routines
Xand the flight simulator itself.  The 3-D stuff is contained in the V
Xdirectory.  V/lib holds the library itself along with imake and make files.
XV/test contains a program that can be used to test your port of the
XV library.
X
XFsim contains the remainder of the flight simulator.  A makefile for
XMips RISC/os is provided.  The code has a Berkeley tilt to it in many
Xplaces, so people with hybrid OS's will probably want to lean that
Xdirection when selecting compiling and linking options.
X
XThe acm server, acms, must currently be started manually.  It's intended
Xthat it will eventually be managed automatically by inetd, but that's
Xnot in the code yet.  I have access to a network that includes a 16+ SPECMark
Xserver and 12 to 18 SPECMark workstations (i.e. a MIPS 3260 along with
XMIPS 2030 and Magnum workstations) (translate SPECMarks into millions of
Xinstructions per second by whatever formula you like ..).  I generally 
Xrlogin to the 3260 and start the acms process on it and leave that xterm
Xwindow hanging around;  then, from another xterm window, I'll fire off
Xthe acm command that starts my flying session.  Other players enter the
Xgame by simply firing off an "acm servername" command.
X
XI'm not saying that acm is a particularly accurate flight simulator. I'm
Xnot an aero engineer, but I did spend a fair amount of time studying
Xseveral college-level texts on the subject while I was designing this
Xsoftware.  This probably doesn't resemble real-time flight simulators
Xtoo much but, again, that's not my line of work.  Comments and
Xsuggestions to improve this software are welcome.
X
XSeveral "features" in this revision of the software:
X
X	* landing gear is ignored.  Raise it, lower it; it's
X	  not handled by the software.
X
X	* flaps can be lowered at rediculously high speeds.
X
X	* cannon fire will not hit other aircraft.  Missiles
X	  sure will, though.
X
X	* you can fly through mountains.
X
X	* engines do not flame-out.  Fly really high (and fast enough)
X	  and you can just about get into orbit.  Non-afterburning
X	  engine performance does degrade as altitude increases, but
X	  afterburner performance gives the extra kick needed to fly
X	  much higher than you should be able to.
X
X	* A hit kills you instantly.  acm does not currently have a
X	  notion of limited aircraft damage.  It may in the future.
X
X
XRiley Rainey
XOctober 1, 1990
*-*-END-of-./fsim/README-*-*
echo x - ./fsim/update.c
sed 's/^X//' >./fsim/update.c <<'*-*-END-of-./fsim/update.c-*-*'
X/*
X *	xflight : an aerial combat simulator for X
X *
X *	Written by Riley Rainey,  riley@mips.com
X *
X *	Permission to use, copy, modify and distribute (without charge) this
X *	software, documentation, images, etc. is granted, provided that this 
X *	comment and the author's name is retained.
X *
X */
X 
X#include "pm.h"
X#include <X11/Xutil.h>
X
Xextern int flightCalculations();
Xextern int missileCalculations();
Xextern void doEvents(), doViews(), flapControl();
X
Xint cur = 0;
X
Xint redraw () {
X
X	int	i, j;
X	craft	*p;
X	
X	for ((i=0, p=ptbl); i<MAXPLAYERS; (++i, ++p)) {
X		if (p->type == CT_PLANE) {
X			doEvents (p);
X			if (flightCalculations (p) == 1)
X				killPlayer (p);
X			doWeaponUpdate (p);
X			flapControl (p);
X		}
X		else if (p->type == CT_DRONE)
X			if (droneCalculations (p) == 1)
X				killPlayer (p);
X	}
X
X	for ((i=0, p=mtbl); i<MAXPROJECTILES; (++i, ++p)) {
X		if (p->type == CT_MISSILE) {
X			if (missileCalculations (p) == 1)
X				killMissile (p);
X		}
X		else if (p->type == CT_CANNON)
X			if (cannonCalculations (p) == 1)
X				killMissile (p);
X	}
X
X	lookForImpacts ();
X
X	if (cur++ % REDRAW_EVERY == 0)
X		doViews ();
X
X	curTime += deltaT;
X
X	return 0;
X
X}
*-*-END-of-./fsim/update.c-*-*
echo x - ./fsim/rwy.old
sed 's/^X//' >./fsim/rwy.old <<'*-*-END-of-./fsim/rwy.old-*-*'
XRunway
X280 69
X1 0.000000 -75.000000 0.000000
X2 12000.000000 -75.000000 0.000000
X3 12000.000000 75.000000 0.000000
X4 0.000000 75.000000 0.000000
X5 0.000000 -75.000000 0.000000
X6 12000.000000 -75.000000 0.000000
X7 12000.000000 -70.000000 0.000000
X8 0.000000 -70.000000 0.000000
X9 0.000000 75.000000 0.000000
X10 12000.000000 75.000000 0.000000
X11 12000.000000 70.000000 0.000000
X12 0.000000 70.000000 0.000000
X13 1000.000000 -66.000000 0.000000
X14 1125.000000 -66.000000 0.000000
X15 1125.000000 -36.000000 0.000000
X16 1000.000000 -36.000000 0.000000
X17 1000.000000 66.000000 0.000000
X18 1125.000000 66.000000 0.000000
X19 1125.000000 36.000000 0.000000
X20 1000.000000 36.000000 0.000000
X21 11000.000000 -66.000000 0.000000
X22 10875.000000 -66.000000 0.000000
X23 10875.000000 -36.000000 0.000000
X24 11000.000000 -36.000000 0.000000
X25 11000.000000 66.000000 0.000000
X26 10875.000000 66.000000 0.000000
X27 10875.000000 36.000000 0.000000
X28 11000.000000 36.000000 0.000000
X29 4.000000 -66.000000 0.000000
X30 129.000000 -66.000000 0.000000
X31 129.000000 -54.888889 0.000000
X32 4.000000 -54.888889 0.000000
X33 4.000000 -50.888889 0.000000
X34 129.000000 -50.888889 0.000000
X35 129.000000 -39.777779 0.000000
X36 4.000000 -39.777779 0.000000
X37 4.000000 -35.777779 0.000000
X38 129.000000 -35.777779 0.000000
X39 129.000000 -24.666666 0.000000
X40 4.000000 -24.666666 0.000000
X41 4.000000 -20.666666 0.000000
X42 129.000000 -20.666666 0.000000
X43 129.000000 -9.555555 0.000000
X44 4.000000 -9.555555 0.000000
X45 4.000000 9.555555 0.000000
X46 129.000000 9.555555 0.000000
X47 129.000000 20.666666 0.000000
X48 4.000000 20.666666 0.000000
X49 4.000000 24.666666 0.000000
X50 129.000000 24.666666 0.000000
X51 129.000000 35.777779 0.000000
X52 4.000000 35.777779 0.000000
X53 4.000000 39.777779 0.000000
X54 129.000000 39.777779 0.000000
X55 129.000000 50.888889 0.000000
X56 4.000000 50.888889 0.000000
X57 4.000000 54.888889 0.000000
X58 129.000000 54.888889 0.000000
X59 129.000000 66.000000 0.000000
X60 4.000000 66.000000 0.000000
X61 11996.000000 -66.000000 0.000000
X62 11871.000000 -66.000000 0.000000
X63 11871.000000 -54.888889 0.000000
X64 11996.000000 -54.888889 0.000000
X65 11996.000000 -50.888889 0.000000
X66 11871.000000 -50.888889 0.000000
X67 11871.000000 -39.777779 0.000000
X68 11996.000000 -39.777779 0.000000
X69 11996.000000 -35.777779 0.000000
X70 11871.000000 -35.777779 0.000000
X71 11871.000000 -24.666666 0.000000
X72 11996.000000 -24.666666 0.000000
X73 11996.000000 -20.666666 0.000000
X74 11871.000000 -20.666666 0.000000
X75 11871.000000 -9.555555 0.000000
X76 11996.000000 -9.555555 0.000000
X77 11996.000000 9.555555 0.000000
X78 11871.000000 9.555555 0.000000
X79 11871.000000 20.666666 0.000000
X80 11996.000000 20.666666 0.000000
X81 11996.000000 24.666666 0.000000
X82 11871.000000 24.666666 0.000000
X83 11871.000000 35.777779 0.000000
X84 11996.000000 35.777779 0.000000
X85 11996.000000 39.777779 0.000000
X86 11871.000000 39.777779 0.000000
X87 11871.000000 50.888889 0.000000
X88 11996.000000 50.888889 0.000000
X89 11996.000000 54.888889 0.000000
X90 11871.000000 54.888889 0.000000
X91 11871.000000 66.000000 0.000000
X92 11996.000000 66.000000 0.000000
X93 258.000000 -2.500000 0.000000
X94 383.000000 -2.500000 0.000000
X95 383.000000 2.500000 0.000000
X96 258.000000 2.500000 0.000000
X97 508.000000 -2.500000 0.000000
X98 633.000000 -2.500000 0.000000
X99 633.000000 2.500000 0.000000
X100 508.000000 2.500000 0.000000
X101 758.000000 -2.500000 0.000000
X102 883.000000 -2.500000 0.000000
X103 883.000000 2.500000 0.000000
X104 758.000000 2.500000 0.000000
X105 1008.000000 -2.500000 0.000000
X106 1133.000000 -2.500000 0.000000
X107 1133.000000 2.500000 0.000000
X108 1008.000000 2.500000 0.000000
X109 1258.000000 -2.500000 0.000000
X110 1383.000000 -2.500000 0.000000
X111 1383.000000 2.500000 0.000000
X112 1258.000000 2.500000 0.000000
X113 1508.000000 -2.500000 0.000000
X114 1633.000000 -2.500000 0.000000
X115 1633.000000 2.500000 0.000000
X116 1508.000000 2.500000 0.000000
X117 1758.000000 -2.500000 0.000000
X118 1883.000000 -2.500000 0.000000
X119 1883.000000 2.500000 0.000000
X120 1758.000000 2.500000 0.000000
X121 2008.000000 -2.500000 0.000000
X122 2133.000000 -2.500000 0.000000
X123 2133.000000 2.500000 0.000000
X124 2008.000000 2.500000 0.000000
X125 2258.000000 -2.500000 0.000000
X126 2383.000000 -2.500000 0.000000
X127 2383.000000 2.500000 0.000000
X128 2258.000000 2.500000 0.000000
X129 2508.000000 -2.500000 0.000000
X130 2633.000000 -2.500000 0.000000
X131 2633.000000 2.500000 0.000000
X132 2508.000000 2.500000 0.000000
X133 2758.000000 -2.500000 0.000000
X134 2883.000000 -2.500000 0.000000
X135 2883.000000 2.500000 0.000000
X136 2758.000000 2.500000 0.000000
X137 3008.000000 -2.500000 0.000000
X138 3133.000000 -2.500000 0.000000
X139 3133.000000 2.500000 0.000000
X140 3008.000000 2.500000 0.000000
X141 3258.000000 -2.500000 0.000000
X142 3383.000000 -2.500000 0.000000
X143 3383.000000 2.500000 0.000000
X144 3258.000000 2.500000 0.000000
X145 3508.000000 -2.500000 0.000000
X146 3633.000000 -2.500000 0.000000
X147 3633.000000 2.500000 0.000000
X148 3508.000000 2.500000 0.000000
X149 3758.000000 -2.500000 0.000000
X150 3883.000000 -2.500000 0.000000
X151 3883.000000 2.500000 0.000000
X152 3758.000000 2.500000 0.000000
X153 4008.000000 -2.500000 0.000000
X154 4133.000000 -2.500000 0.000000
X155 4133.000000 2.500000 0.000000
X156 4008.000000 2.500000 0.000000
X157 4258.000000 -2.500000 0.000000
X158 4383.000000 -2.500000 0.000000
X159 4383.000000 2.500000 0.000000
X160 4258.000000 2.500000 0.000000
X161 4508.000000 -2.500000 0.000000
X162 4633.000000 -2.500000 0.000000
X163 4633.000000 2.500000 0.000000
X164 4508.000000 2.500000 0.000000
X165 4758.000000 -2.500000 0.000000
X166 4883.000000 -2.500000 0.000000
X167 4883.000000 2.500000 0.000000
X168 4758.000000 2.500000 0.000000
X169 5008.000000 -2.500000 0.000000
X170 5133.000000 -2.500000 0.000000
X171 5133.000000 2.500000 0.000000
X172 5008.000000 2.500000 0.000000
X173 5258.000000 -2.500000 0.000000
X174 5383.000000 -2.500000 0.000000
X175 5383.000000 2.500000 0.000000
X176 5258.000000 2.500000 0.000000
X177 5508.000000 -2.500000 0.000000
X178 5633.000000 -2.500000 0.000000
X179 5633.000000 2.500000 0.000000
X180 5508.000000 2.500000 0.000000
X181 5758.000000 -2.500000 0.000000
X182 5883.000000 -2.500000 0.000000
X183 5883.000000 2.500000 0.000000
X184 5758.000000 2.500000 0.000000
X185 6008.000000 -2.500000 0.000000
X186 6133.000000 -2.500000 0.000000
X187 6133.000000 2.500000 0.000000
X188 6008.000000 2.500000 0.000000
X189 6258.000000 -2.500000 0.000000
X190 6383.000000 -2.500000 0.000000
X191 6383.000000 2.500000 0.000000
X192 6258.000000 2.500000 0.000000
X193 6508.000000 -2.500000 0.000000
X194 6633.000000 -2.500000 0.000000
X195 6633.000000 2.500000 0.000000
X196 6508.000000 2.500000 0.000000
X197 6758.000000 -2.500000 0.000000
X198 6883.000000 -2.500000 0.000000
X199 6883.000000 2.500000 0.000000
X200 6758.000000 2.500000 0.000000
X201 7008.000000 -2.500000 0.000000
X202 7133.000000 -2.500000 0.000000
X203 7133.000000 2.500000 0.000000
X204 7008.000000 2.500000 0.000000
X205 7258.000000 -2.500000 0.000000
X206 7383.000000 -2.500000 0.000000
X207 7383.000000 2.500000 0.000000
X208 7258.000000 2.500000 0.000000
X209 7508.000000 -2.500000 0.000000
X210 7633.000000 -2.500000 0.000000
X211 7633.000000 2.500000 0.000000
X212 7508.000000 2.500000 0.000000
X213 7758.000000 -2.500000 0.000000
X214 7883.000000 -2.500000 0.000000
X215 7883.000000 2.500000 0.000000
X216 7758.000000 2.500000 0.000000
X217 8008.000000 -2.500000 0.000000
X218 8133.000000 -2.500000 0.000000
X219 8133.000000 2.500000 0.000000
X220 8008.000000 2.500000 0.000000
X221 8258.000000 -2.500000 0.000000
X222 8383.000000 -2.500000 0.000000
X223 8383.000000 2.500000 0.000000
X224 8258.000000 2.500000 0.000000
X225 8508.000000 -2.500000 0.000000
X226 8633.000000 -2.500000 0.000000
X227 8633.000000 2.500000 0.000000
X228 8508.000000 2.500000 0.000000
X229 8758.000000 -2.500000 0.000000
X230 8883.000000 -2.500000 0.000000
X231 8883.000000 2.500000 0.000000
X232 8758.000000 2.500000 0.000000
X233 9008.000000 -2.500000 0.000000
X234 9133.000000 -2.500000 0.000000
X235 9133.000000 2.500000 0.000000
X236 9008.000000 2.500000 0.000000
X237 9258.000000 -2.500000 0.000000
X238 9383.000000 -2.500000 0.000000
X239 9383.000000 2.500000 0.000000
X240 9258.000000 2.500000 0.000000
X241 9508.000000 -2.500000 0.000000
X242 9633.000000 -2.500000 0.000000
X243 9633.000000 2.500000 0.000000
X244 9508.000000 2.500000 0.000000
X245 9758.000000 -2.500000 0.000000
X246 9883.000000 -2.500000 0.000000
X247 9883.000000 2.500000 0.000000
X248 9758.000000 2.500000 0.000000
X249 10008.000000 -2.500000 0.000000
X250 10133.000000 -2.500000 0.000000
X251 10133.000000 2.500000 0.000000
X252 10008.000000 2.500000 0.000000
X253 10258.000000 -2.500000 0.000000
X254 10383.000000 -2.500000 0.000000
X255 10383.000000 2.500000 0.000000
X256 10258.000000 2.500000 0.000000
X257 10508.000000 -2.500000 0.000000
X258 10633.000000 -2.500000 0.000000
X259 10633.000000 2.500000 0.000000
X260 10508.000000 2.500000 0.000000
X261 10758.000000 -2.500000 0.000000
X262 10883.000000 -2.500000 0.000000
X263 10883.000000 2.500000 0.000000
X264 10758.000000 2.500000 0.000000
X265 11008.000000 -2.500000 0.000000
X266 11133.000000 -2.500000 0.000000
X267 11133.000000 2.500000 0.000000
X268 11008.000000 2.500000 0.000000
X269 11258.000000 -2.500000 0.000000
X270 11383.000000 -2.500000 0.000000
X271 11383.000000 2.500000 0.000000
X272 11258.000000 2.500000 0.000000
X273 11508.000000 -2.500000 0.000000
X274 11633.000000 -2.500000 0.000000
X275 11633.000000 2.500000 0.000000
X276 11508.000000 2.500000 0.000000
X277 11758.000000 -2.500000 0.000000
X278 11883.000000 -2.500000 0.000000
X279 11883.000000 2.500000 0.000000
X280 11758.000000 2.500000 0.000000
X#b7b19f 4  1 2 3 4
Xwhite 4  5 6 7 8
Xwhite 4  9 10 11 12
Xwhite 4  13 14 15 16
Xwhite 4  17 18 19 20
Xwhite 4  21 22 23 24
Xwhite 4  25 26 27 28
Xwhite 4  29 30 31 32
Xwhite 4  33 34 35 36
Xwhite 4  37 38 39 40
Xwhite 4  41 42 43 44
Xwhite 4  45 46 47 48
Xwhite 4  49 50 51 52
Xwhite 4  53 54 55 56
Xwhite 4  57 58 59 60
Xwhite 4  61 62 63 64
Xwhite 4  65 66 67 68
Xwhite 4  69 70 71 72
Xwhite 4  73 74 75 76
Xwhite 4  77 78 79 80
Xwhite 4  81 82 83 84
Xwhite 4  85 86 87 88
Xwhite 4  89 90 91 92
Xwhite 4  93 94 95 96
Xwhite 4  97 98 99 100
Xwhite 4  101 102 103 104
Xwhite 4  105 106 107 108
Xwhite 4  109 110 111 112
Xwhite 4  113 114 115 116
Xwhite 4  117 118 119 120
Xwhite 4  121 122 123 124
Xwhite 4  125 126 127 128
Xwhite 4  129 130 131 132
Xwhite 4  133 134 135 136
Xwhite 4  137 138 139 140
Xwhite 4  141 142 143 144
Xwhite 4  145 146 147 148
Xwhite 4  149 150 151 152
Xwhite 4  153 154 155 156
Xwhite 4  157 158 159 160
Xwhite 4  161 162 163 164
Xwhite 4  165 166 167 168
Xwhite 4  169 170 171 172
Xwhite 4  173 174 175 176
Xwhite 4  177 178 179 180
Xwhite 4  181 182 183 184
Xwhite 4  185 186 187 188
Xwhite 4  189 190 191 192
Xwhite 4  193 194 195 196
Xwhite 4  197 198 199 200
Xwhite 4  201 202 203 204
Xwhite 4  205 206 207 208
Xwhite 4  209 210 211 212
Xwhite 4  213 214 215 216
Xwhite 4  217 218 219 220
Xwhite 4  221 222 223 224
Xwhite 4  225 226 227 228
Xwhite 4  229 230 231 232
Xwhite 4  233 234 235 236
Xwhite 4  237 238 239 240
Xwhite 4  241 242 243 244
Xwhite 4  245 246 247 248
Xwhite 4  249 250 251 252
Xwhite 4  253 254 255 256
Xwhite 4  257 258 259 260
Xwhite 4  261 262 263 264
Xwhite 4  265 266 267 268
Xwhite 4  269 270 271 272
Xwhite 4  273 274 275 276
Xwhite 4  277 278 279 280
*-*-END-of-./fsim/rwy.old-*-*
-- 
Riley Rainey			Internet: riley@mips.com
MIPS Computer Systems		Phone:    +1 214 770-7979
Dallas, Texas

dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.