home *** CD-ROM | disk | FTP | other *** search
- #include <graphics.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <conio.h>
- #include <math.h>
- #include <time.h>
- #include <ctype.h>
- #include <dos.h>
- #include <string.h>
- #include "def.h"
-
- #include "gravity.h"
-
- UBYTE bnw= FALSE ; /* global black & white flag */
-
- /************************************************************************/
- /* */
- /* This is the main routine. */
- /* Here we start the random number generator, initialize everything and */
- /* execute the main user input loop. As soon as there are less than 2 */
- /* players alive we exit to DOS. Overall, a very boring main program. */
- /* */
- /* Inputs : None */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : (BELOW ARE ALL GLOBALS, NONE USED DIRECTLY BY main() ) */
- /* maxx - Max X allowable coordinate for graphics */
- /* maxy - Max Y allowable coordiante for graphics */
- /* (Actual Max Y minus text window size) */
- /* planets - the planet array */
- /* players - the player array */
- /* */
- /* Returns : Error code (if any) */
- /* */
- /* Version : 1.00 (11/15/92) */
- /* 1.10 (11/22/92) Now supports seven players */
- /* Compass around player inputting data */
- /* Planets blow up when hit 3x */
- /* 1.20 (12/25/92) Planets blow up when hit 4x now */
- /* Planets re-appear after 3 turns */
- /* Players re-appear after 3 turns */
- /* Added opening & closing messages */
- /* Dynamic player addition/deletion added */
- /* Added (sortof) black & white support */
- /* */
- /* (c) 1992 CMI Productions */
- /* 15014 East Idaho Place */
- /* Aurora, CO 80012 */
- /* (303) 755-8006 */
- /* */
- /* Public Domain Software. You are free to distribute & */
- /* modify, as long as above copyright message trailing */
- /* program message are left intact. */
- /* */
- /************************************************************************/
- void main(int argc, char *argv[])
- {
-
- /* see if user asked for black&white mode */
- if (argc==2)
- {
- if (!stricmp(argv[1],"bw"))
- {
- bnw = TRUE ;
- }
- }
-
- /* start off randomly */
- randomize() ;
-
- /* start graphics mode, place the players & planets */
- init_screen() ;
- get_planets() ;
- get_players() ;
- paint_screen() ;
-
- /* the main input loop */
- do
- {
- /* get the users new projectile directions, abort if requested */
- if (get_inputs())
- {
- break ;
- }
-
- /* repaint the screen, erasing the old projectile paths */
- paint_screen() ;
- /* show the new projectile paths */
- show_paths() ;
- /* let people read last status message */
- delay (2000) ;
- }
- /* do this while there are at least two players */
- while (players_left() >1) ;
-
- /* state the obvious */
- msg (RED,"GAME OVER!") ;
- delay (5000) ;
-
- /* and exit */
- closegraph();
- printf("This has been yet another CMI Production.\n\n") ;
- }
-
- /************************************************************************/
- /* */
- /* This routine gets us into graphics mode and sets up the basics. */
- /* Before getting into graphics mode we register our driver and font so */
- /* those unfortunate souls withoug BC++ (and the BGI drivers) can also */
- /* play the game. This game is set up only for VGA, so it is specific- */
- /* ally requested. After getting into graphics mode we get the max */
- /* allowable coordinates, draw a border and select the font. */
- /* */
- /* Note that this routine assumes that EGAVGA.OBJ and LITT.OBJ are */
- /* being linked in at compile time! */
- /* */
- /* Inputs : None */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : maxx - playing board max x dimension */
- /* maxy - playing board max y dimension */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void init_screen (void)
- {
- WORD gdriver, gmode, errorcode;
- UBYTE i ;
-
- /* make sure we regsiter the VGA driver at compile time */
- if (registerbgidriver(EGAVGA_driver) < 0) exit(1) ;
- if (registerbgifont(small_font) < 0) exit(1) ;
-
- /* the display and mode we want */
- gdriver = VGA ;
- gmode = VGAHI ;
-
- /* initialize graphics mode */
- initgraph(&gdriver, &gmode, "");
-
- /* read result of initialization */
- errorcode = graphresult();
-
- if (errorcode != grOk) /* an error occurred */
- {
- printf("Graphics error: %s\n", grapherrormsg(errorcode));
- exit(1);
- }
-
- /* get screen limits (decrease Y for text input area) */
- maxx = getmaxx() ;
- maxy = getmaxy()-20 ;
-
- /* draw the border */
- moveto(0 ,0 ) ;
- lineto(0 ,maxy) ;
- lineto(maxx,maxy) ;
- lineto(maxx,0 ) ;
- lineto(0 ,0 ) ;
-
- settextstyle(SMALL_FONT, HORIZ_DIR, 30);
- setcolor(RED) ;
-
- for (i=0;i<5;i++)
- {
- outtextxy(150+i,100-i,"GRAVITY WARS") ;
- outtextxy(200+i,150-i,"Ver. 1.20") ;
- }
-
- settextstyle(SMALL_FONT, HORIZ_DIR, 5);
-
- }
-
- /************************************************************************/
- /* */
- /* This routine prints a message in the message area. */
- /* We first erase anything that may have been there, select the desired */
- /* color, and finally print the string. */
- /* */
- /* Inputs : color - the color to print the text */
- /* *line - the text to print */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : None */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void msg (UBYTE color,char *line)
- {
- /* fill the text rectangle area with black (erase) */
- setfillstyle (SOLID_FILL,BLACK) ;
- bar(0,maxy+1,maxx,maxy+21) ;
-
- /* select the color and print the text */
- setcolor(color) ;
- outtextxy(0,maxy,line) ;
- }
-
- /************************************************************************/
- /* */
- /* This routine creates all the planets for the game. */
- /* First we initialize all the planets and players to "dead". This is */
- /* because the create_planet routine makes sure planets don't overlap */
- /* any previously existing ones. Since these are the first planets we */
- /* must make sure planets can go anywhere. */
- /* We do this by creating a random set of specs for the planet and then */
- /* make sure they don't conflict with another already existing planet. */
- /* */
- /* Inputs : None */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : planets - planetery database array */
- /* players - player database array */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void get_planets(void)
- {
- UBYTE i ; /* general array index */
-
- /* initialize all the planets to "dead" */
- for (i=0;i<MAX_PLANETS;i++)
- {
- planets[i].outs = 1 ;
- }
-
- /* initialize all the players to "dead" */
- for (i=0;i<MAX_PLAYERS;i++)
- {
- players[i].alive = FALSE ;
- players[i].outs = 0 ;
- }
-
- /* finally create all the planets */
- for (i=0;i<MAX_PLANETS;i++)
- {
- create_planet (i) ;
- }
-
- } /* function get_planets */
-
-
- /************************************************************************/
- /* */
- /* This routine
- /* Pretty standard math here... */
- /* */
- /* Inputs : i - the planetary index to create */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : planets - planetery database array */
- /* players - player database array */
- /* */
- /* Returns : None */
- /* */
- /************************************************************************/
-
- void create_planet(UBYTE i)
- {
- UBYTE j ; /* general array index */
- UWORD lradius,ldensity,lorgx,lorgy ; /* local (temporary) planetary data */
- float lmass ; /* local planetary mass */
- UBYTE conflict ; /* planetary conflict flag */
-
- do /* until planet doesn't overlap another */
- {
- /* guess some planetary data */
- ldensity = random(4)+1 ;
-
- /* if it is a high density body, it can only be small */
- if (ldensity!=4)
- {
- lradius = random(45)+10 ;
- }
- else
- {
- lradius = 5 ;
- }
-
- /* compute the mass based on density and size */
- lmass = (lradius/2+2)*(ldensity*2-1)*10 ;
-
- /* planets are at least 5 pixels from the edge of the screen */
- lorgx = lradius+5+random(maxx-2*lradius-10) ;
- lorgy = lradius+5+random(maxy-2*lradius-10) ;
-
- /* start out with no conflicts */
- conflict = FALSE ;
-
- /* for all possible planets... */
- for(j=0;j<MAX_PLANETS;j++)
- {
- /* if the planet exists... */
- if (planets[j].outs==0)
- {
- /* planets must be at least 100 pixels apart, surface-to-surface */
- if (dist(lorgx,lorgy,planets[j].orgx,planets[j].orgy) < (lradius+planets[j].radius+100))
- {
- conflict = TRUE ;
- } /* if conflict */
- } /* for existing planets */
- } /* for all possible planets */
-
- /* for all possible players... */
- for(j=0;j<MAX_PLAYERS;j++)
- {
- /* if the playeer exists... */
- if (players[j].outs==0)
- {
- /* planets must be at least 20 pixels from nearest player */
- if (dist(lorgx,lorgy,players[j].orgx,players[j].orgy) < (lradius+20))
- {
- conflict = TRUE ;
- } /* if conflict */
- } /* for existing planets */
- } /* for all possible planets */
-
- }
- while (conflict) ;
- /* put the temporary values in the planetary data array */
- planets[i].radius = lradius ;
- planets[i].density = ldensity ;
- planets[i].orgx = lorgx ;
- planets[i].orgy = lorgy ;
- planets[i].mass = lmass ;
- planets[i].hits = 0 ;
- planets[i].outs = 0 ;
-
- } /* function create_planet */
-
- /************************************************************************/
- /* */
- /* This routine computes the distance between two points. */
- /* Pretty standard math here... */
- /* */
- /* Inputs : x1,y1 - first coordinate pair */
- /* x2,y2 - second coordinate pair */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : None */
- /* */
- /* Returns : integer distance */
- /* */
- /************************************************************************/
- UWORD dist (UWORD x1,UWORD y1,UWORD x2,UWORD y2)
- {
- float fdist ; /* floating point distance first */
- UWORD ldist ; /* integer version */
-
- /* if you don't understand this, better quit! */
- fdist = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)) ;
- ldist = fdist ;
- return (ldist) ;
- }
-
- /************************************************************************/
- /* */
- /* This routine figgers out where to put all the players. */
- /* We guess a random place for the player then make sure they are not */
- /* on top of a planet or other player. */
- /* */
- /* Inputs : None */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : players - player database array */
- /* planets - planetary database array */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void get_players(void)
- {
- UBYTE i,j,c ; /* player array database pointers */
-
- /* see how many players they want */
- msg(RED,"Welcome to GRAVITY WARS! How many players (Press 2-7)") ;
-
- /* only accept ascii '2' - '7' */
- do
- {
- c=getch() ;
- if (!c) getch() ;
- }
- while ((c<'2') || (c>'7')) ;
-
- /* for all the requested players... */
- for (i=0;i<(c-'0');i++)
- {
- create_player(i) ;
- }
-
- } /* function get_players */
-
-
- /************************************************************************/
- /* */
- /* This routine figgers out where to put a player. */
- /* We guess a random place for the player then make sure they are not */
- /* on top of a planet or other player. */
- /* */
- /* Inputs : None */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : players - player database array */
- /* planets - planetary database array */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void create_player(UBYTE i)
- {
- UBYTE j ; /* player & planet pointer */
- UBYTE conflict ; /* conflict flag */
- UWORD lorgx,lorgy ; /* temporary coordinates */
-
- /* do this until we don't have a conflict */
- do
- {
- /* guess at some coordinates */
- lorgx = 25+random(maxx-50) ;
- lorgy = 25+random(maxy-50) ;
-
- /* start out with no conflicts */
- conflict = FALSE ;
-
- /* see if ship is inside any of the planets */
- for(j=0;j<MAX_PLANETS;j++)
- {
- if (dist(lorgx,lorgy,planets[j].orgx,planets[j].orgy) < (planets[j].radius+20))
- {
- conflict = TRUE ;
- }
- }
-
- /* make sure each ship is at least 100 pixels away from all others */
- if (i!=0) /* don't check first one! */
- {
- for(j=0;j<i;j++)
- {
- if (dist(lorgx,lorgy,players[j].orgx,players[j].orgy) < 100)
- {
- conflict = TRUE ;
- } /* if too close */
- } /* for exising players */
- } /* if not 1st */
- }
- while (conflict) ;
-
- /* initialize the array database */
- players[i].speed = 0.0 ;
- players[i].angle = 0.0 ;
- players[i].alive = TRUE ;
- players[i].orgx = lorgx ;
- players[i].orgy = lorgy ;
- players[i].outs = 0 ;
-
- } /* function create_player */
-
-
- /************************************************************************/
- /* */
- /* This routine draws an "Enterprize-like" looking ship. */
- /* Nothign too sophisticated, just a bunch of brute-force drawing */
- /* commands. We select the color and draw the ship. The ship is drawn */
- /* centered around the x,y origin */
- /* */
- /* Inputs : color - color to draw the ship */
- /* x,y - where to put the ship */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : None */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void draw_ship (UWORD color,UWORD x,UWORD y)
- {
- setcolor(color) ;
- moveto (x,y) ;
-
- moverel(6,-5) ; /* the saucer */
- linerel(1,0) ;
- linerel(0,3) ;
- linerel(-1,0) ;
- moverel(-5,-2);
- linerel(11,0) ;
- linerel(0,1) ;
- linerel(-11,0);
-
- moverel(1,1) ; /* bit connecting saucer to bottom part */
- linerel(-1,3) ;
- linerel(1,0) ;
- linerel(1,-3) ;
- linerel(1,0) ;
- linerel(-1,3) ;
-
- moverel(-9,1) ; /* bottom part */
- linerel(10,0) ;
- linerel(0,1) ;
- linerel(-13,0);
- linerel(0,1) ;
- linerel(13,0) ;
-
- moverel(-9,-3); /* bit connecting bottom part to engines */
- linerel(-1,-3);
- linerel(-1,0) ;
- linerel(1,3) ;
-
- moverel(-6,-5); /* engines */
- linerel(9,0) ;
- linerel(0,1) ;
- linerel(-8,0) ;
-
- }
-
- /************************************************************************/
- /* */
- /* This routine prompts each (alive) player for new trajectories. */
- /* We go through the entire list of players, asking each one that is */
- /* still alive for a new projectile trajectory. After this questioning */
- /* we see if they want to proceed, re-enter data, or quit. */
- /* */
- /* Inputs : None */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : players - player database array */
- /* */
- /* Returns : true if they want to quit */
- /* */
- /************************************************************************/
- UBYTE get_inputs (void)
- {
- UBYTE i,c ;
- char line[80] ;
-
-
- /* until entries OK */
- do
- {
- /* for all players */
- for (i=0;i<MAX_PLAYERS;i++)
- {
- /* only if the ship is still alive do we ask */
- if (players[i].alive)
- {
- /* show them where to shoot */
- draw_compass(players[i].orgx,players[i].orgy,WHITE) ;
-
- do /* until they get it right */
- {
- /* request and get the new angle */
- sprintf (line,"Player %d, Enter angle (0-360, prev %9.4f) >",i+1,players[i].angle) ;
- msg(i+9,line) ;
- get_num(385,&(players[i].angle)) ;
- }
- while ((players[i].angle<0.0) || (players[i].angle>360.0)) ;
-
- do /* until they get it right */
- {
- /* request and get the new speed */
- sprintf (line,"Player %d, Enter speed (0-40, prev %9.4f) >",i+1,players[i].speed) ;
- msg(i+9,line) ;
- get_num(385,&(players[i].speed)) ;
- }
- while ((players[i].speed<0.0) || (players[i].speed>40.0)) ;
-
- /* erase the compas */
- draw_compass(players[i].orgx,players[i].orgy,BLACK) ;
- } /* if player is alive */
- } /* for all potential players */
-
- /* see what they want to do now */
- msg (RED,"<G>o, <R>e-enter data, <C>hange Players, or <Q>uit early") ;
- do
- {
- c=getch() ;
- if (!c) getch() ;
- c=tolower(c) ;
- }
- while ((c!='g')&&(c!='r')&&(c!='q')&&(c!='c')) ;
-
- /* if they request player change, go do it */
- if (c=='c')
- {
- change_players() ;
- /* after a change, repeat entries */
- c='r' ;
- }
-
- } /* if repeat, go over numbers again */
- while (c=='r') ;
-
- /* return quit status */
- return (c=='q') ;
- } /* function get_inputs */
-
- /************************************************************************/
- /* */
- /* This routine gets a floating point number from the user. */
- /* we are told where to print this number as we get it and inherit */
- /* whatever color is currently being used. Each time a key is pressed */
- /* we erase whatever was on the line before, add the character just */
- /* typed and print it. Only digits, periods, enter and backspace are */
- /* allowed. If the user presses enter without entering anything, we */
- /* do not alter the previous value.
- /* */
- /* Inputs : x - where in the entry line to "get" the number */
- /* */
- /* I/Os : *val - the old (and new) number */
- /* */
- /* Globals : None */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void get_num(UWORD x,float *val)
- {
- char line[20] ; /* the text number */
- UBYTE i,c ; /* pointer & character */
- float num ; /* new number */
-
- do /* until we get a valid number */
- {
-
- /* initialize the line */
- line[0]='\0' ;
- i=0 ;
-
- do /* until enter is pressed */
- {
- /* erase the old line & show current line characters */
- setfillstyle (SOLID_FILL,BLACK) ;
- bar(x,maxy+1,x+200,maxy+21) ;
- outtextxy(x,maxy,line) ;
-
- /* get a key, if extended, leave as 0 */
- c=getch() ;
- if (!c) getch() ;
-
- /* if backspace and backspacable, erase current char */
- if ((c=='\b') && (i>0))
- {
- i-- ;
- line[i] = '\0' ;
- }
-
- /* if digit or decimal, add to line */
- if ((isdigit(c) || (c=='.')) && (i<19))
- {
- line[i] = c ;
- i++ ;
- line[i] = '\0' ;
- }
-
- }
- while (c!=13) ;
- }
- /* if CR, then must be blank line or valid number */
- while ((line[0]!='\0') && (sscanf(line,"%f",&num)!=1)) ;
-
- /* if not blank line, assign new number */
- if (line[0]!='\0')
- {
- *val = num ;
- }
-
- } /* function get_num */
-
-
- /************************************************************************/
- /* */
- /* This routine
- /* */
- /* Inputs : None */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : players - global player database array */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void change_players(void)
- {
-
- UBYTE playing[MAX_PLAYERS] ;
- UBYTE i,c ;
- UBYTE mesg[100] ;
-
- /* creat a local array with players in & out */
- for (i=0;i<MAX_PLAYERS;i++)
- {
- playing[i]=((players[i].alive)||(!players[i].alive&&(players[i].outs>0))) ;
- }
-
- do /* until they press enter */
- {
- /* the basic message */
- strcpy(mesg,"Players: [1234567] Press # to add/delete, Enter to end") ;
-
- /* erase the #'s for the players not playing */
- for (i=0;i<MAX_PLAYERS;i++)
- {
- if (!playing[i])
- {
- mesg[10+i]=' ' ;
- }
- }
-
- /* write out the status message */
- msg(RED,mesg) ;
-
- /* get a char, ignore "special" chars */
- c=getch() ;
- if (!c) getch() ;
-
- /* if 1-7, invert playing status */
- if ((c>'0')&&(c<'8'))
- {
- playing[c-'1']=!playing[c-'1'] ;
- }
-
- }
- while (c!=13) ;
-
-
- for (i=0;i<MAX_PLAYERS;i++)
- {
- /* if we need to create a player... */
- if (playing[i]&&(!players[i].alive&&(players[i].outs==0)))
- {
- create_player(i) ;
- draw_ship(i+9,players[i].orgx,players[i].orgy) ;
- } /* create_player /*
-
- /* if we are killing a player... */
- if (!playing[i]&&(players[i].alive||(!players[i].alive&&(players[i].outs>0))))
- {
- players[i].alive=FALSE ;
- players[i].outs = 0 ;
- } /* kill player */
- } /* for all possible players */
-
- } /* function change_players */
-
-
- /************************************************************************/
- /* */
- /* This routine shows the torpedo path. */
- /* In the interests of speed, this is one routine with no subroutines. */
- /* We first set all the torpedos to hit, meaning they are dormant. Then */
- /* for each player that is still alive we assign the starting values */
- /* for their torpedo. These include the starting position and starting */
- /* x and y speeds. Finally we set hit to false, signifying a "live" */
- /* torpedo. Then for each dot for each torpedo we must calculate the */
- /* cumulative gravity by all the planets. The exact method of doing */
- /* this is explained quite well in the code. The total accelleration */
- /* then applies a delta to the current x and y velocities which in turn */
- /* apply delta values to the x and y coordinates. We plot the new point*/
- /* and then see if we hit anything. Three things can be hit, the */
- /* edges of the universe, a planet, or another ship. The first two just*/
- /* render the torpedo dead. The latter clearly kills an opponent (or */
- /* the originator!). This entire incremental process continues until */
- /* there are no more live torpedos. */
- /* */
- /* Inputs : None */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : players - player database array */
- /* planets - planetary database array */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void show_paths (void)
- {
- TORPEDO torps[MAX_PLAYERS] ; /* torpedo data */
- UWORD i,j,cnt ; /* general array indexes */
- float dlx,dly ;
- float dvx,dvy ; /* delta V for x and y */
- float dist,distsq ; /* planetery distance & ^2 */
-
- /* announce the race */
- msg (RED,"And they're off...") ;
-
- /* select the starting point for the projectiles */
- for (i=0;i<MAX_PLAYERS;i++)
- {
- /* assume no torpedo unless player is still alive */
- torps[i].hit = TRUE ;
- if (players[i].alive)
- {
- /* if player is alive, set up default data for torpedo */
- torps[i].x = players[i].orgx + 16*cos(players[i].angle*DEG2RAD) ;
- torps[i].y = players[i].orgy - 16*sin(players[i].angle*DEG2RAD) ;
- torps[i].vx = players[i].speed * cos(players[i].angle*DEG2RAD) ;
- torps[i].vy = -players[i].speed * sin(players[i].angle*DEG2RAD) ;
- torps[i].hit = FALSE ;
- putpixel (torps[i].x,torps[i].y,WHITE) ;
- } /* for all planets */
- } /* for all torpedos */
-
- do /* until all torpedos hit something */
- {
- /* for each possible torpedo... */
- for (i=0;i<MAX_PLAYERS;i++)
- {
- /* if it hasn't hit anything yet... */
- if (!torps[i].hit)
- {
- /* zero cumulative dv's (accellerations) */
- dvx=0.0 ;
- dvy=0.0 ;
-
- /* calculate accellaration for each planet */
- for (j=0;j<MAX_PLANETS;j++)
- {
-
- /* compute x and y distances */
- dlx = planets[j].orgx-torps[i].x ;
- dly = planets[j].orgy-torps[i].y ;
-
- /* compute absolute distance squared & distance */
- distsq = dlx*dlx+dly*dly ;
- dist = sqrt(distsq) ;
-
- /* absolute acelleration is mass/distance**2 */
- /* vectored acelleration is absolute * cos or sin */
- /* cos is dx/r, sin is dy/r, know dx,dy, & r so forget */
- /* computationally expensive cos & sine! */
- dvx += (planets[j].mass/distsq)*dlx/dist ;
- dvy += (planets[j].mass/distsq)*dly/dist ;
- } /* for all planets */
-
- /* adjust velocities by acelleration */
- torps[i].vx += dvx ;
- torps[i].vy += dvy ;
-
- /* adjust distances by velocity */
- torps[i].x += torps[i].vx/5.0 ;
- torps[i].y += torps[i].vy/5.0 ;
-
- /* draw the dot trail */
- if ((torps[i].x < maxx) && (torps[i].x > 1) &&
- (torps[i].y < maxy) && (torps[i].y > 1))
- {
- putpixel (torps[i].x,torps[i].y,WHITE) ;
- }
-
- /* see if we hit anything */
- check_bounds (&torps[i],i) ;
- check_planets(&torps[i],i) ;
- check_ships (&torps[i],i) ;
- } /* if torpedo still going */
- } /* for all torpedos */
-
- /* count how many torpedos are still going */
- cnt = 0 ;
- for (i=0;i<MAX_PLAYERS;i++)
- {
- if (!torps[i].hit)
- {
- cnt++ ;
- }
- } /* for all torpedos */
-
- delay(20) ;
-
- } /* while there are still torpedos left */
- while ((cnt >0) && !kbhit()) ;
- } /* function show_paths */
-
- /************************************************************************/
- /* */
- /* This routine figgers out how many players are still alive. */
- /* Before doing that, however, we first see if any players or planets */
- /* are due for re-encarnation. After raising any dead, we simply count */
- /* the number of players that have the alive flag set. */
- /* */
- /* Inputs : None */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : players - player database array */
- /* */
- /* Returns : Number of alive players */
- /* */
- /************************************************************************/
- UBYTE players_left(void)
- {
- UBYTE i,tot=0 ; /* counter & total */
-
- /* check all the planets */
- for (i=0;i<MAX_PLANETS;i++)
- {
- /* if it is currently dead */
- if (planets[i].hits==MAX_PLANET_HITS)
- {
- /* decrement the dead-time count */
- planets[i].outs-- ;
- /* if count expired, re-encarnate the planet */
- if (planets[i].outs==0)
- {
- create_planet(i) ;
- draw_planet(i) ;
- } /* if planet re-encarneted */
- } /* if a dead planet */
- } /* for all planets */
-
- /* check to see if any players are due for re-encarnation */
- for (i=0;i<MAX_PLAYERS;i++)
- {
- /* if the player is temporarily dead... */
- if (!players[i].alive && (players[i].outs>0))
- {
- /* decrement dead-time count */
- players[i].outs-- ;
-
- /* if count expired, re-encarnate player */
- if (players[i].outs==0)
- {
- create_player(i) ;
- draw_ship(i+9,players[i].orgx,players[i].orgy) ;
- } /* if player re-encarneted */
- } /* if player dead */
- } /* for all players */
-
- /* for all possible players */
- for (i=0;i<MAX_PLAYERS;i++)
- {
- /* if alive, increment total */
- if (players[i].alive)
- {
- tot++ ;
- }
- }
-
- /* return total */
- return (tot) ;
- } /* function players_left */
-
- /************************************************************************/
- /* */
- /* This routine paints the screen with all the planets and ships. */
- /* We simply traverse the planetary and player arrays drawing the parts.*/
- /* We take special care not to draw planets and ships that don't exist. */
- /* */
- /* Inputs : None */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : players - player database array */
- /* planets - planetary database array */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void paint_screen(void)
- {
- UBYTE i ; /* loop counter */
-
- /* first erase the old screen by painting it all black */
- setfillstyle (SOLID_FILL,BLACK) ;
- bar(1,1,maxx-1,maxy-1) ;
-
- /* for each potential planet */
- for (i=0;i<MAX_PLANETS;i++)
- {
- if (planets[i].hits <MAX_PLANET_HITS)
- {
- draw_planet(i) ;
-
- } /* if the planet exists */
- } /* for each planet */
-
- /* for each potential player... */
- for (i=0;i<MAX_PLAYERS;i++)
- {
- /* only draw them if they're still alive */
- if (players[i].alive)
- {
- draw_ship(i+9,players[i].orgx,players[i].orgy) ;
- } /* if alive */
- } /* all players */
- } /* function paint_screen */
-
-
- /************************************************************************/
- /* */
- /* This routine draws a planet. */
- /* */
- /* Inputs : None */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : planets - planetary database array */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void draw_planet(UBYTE i)
- {
-
- UWORD color ; /*planetary color */
-
- /* set the color (border & fill), & fill a planetary circle */
- switch (planets[i].density)
- {
- case 1 : color = RED ; break ;
- case 2 : color = GREEN ; break ;
- case 3 : color = BLUE ; break ;
- case 4 : color = WHITE ; break ;
- }
-
- setcolor(color) ;
- setfillstyle (SOLID_FILL,color) ;
- fillellipse(planets[i].orgx,planets[i].orgy,planets[i].radius,planets[i].radius);
-
- if (bnw)
- {
- setcolor(BLACK) ;
- switch (planets[i].density)
- {
- case 1 : outtextxy(planets[i].orgx-3,planets[i].orgy-7,"L") ; break ;
- case 2 : outtextxy(planets[i].orgx-3,planets[i].orgy-7,"M") ; break ;
- case 3 : outtextxy(planets[i].orgx-3,planets[i].orgy-7,"H") ; break ;
- case 4 : ; break ;
- }
- }
-
-
- } /* function draw_planet */
-
-
- /************************************************************************/
- /* */
- /* This routine checks to see if the projectile has gone too far. */
- /* The actual playing field is the equivilent of nine pyysical screens. */
- /* The dimesions range from -max_ to 2*max_. If we are outside this */
- /* range, we declare a "hit", calling the torpedo dead. */
- /* */
- /* Inputs : None */
- /* */
- /* I/Os : torp - torpedo data */
- /* */
- /* Globals : maxx,maxy */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void check_bounds (TORPEDO *torp, UBYTE src)
- {
- char line[80] ;
-
- /* check limits */
- if ((torp->x > maxx*2) || (torp->x < -maxx) ||
- (torp->y > maxy*2) || (torp->y < -maxy))
- {
- sprintf (line,"Player %d's torpedo left the field.",src+1) ;
- msg(src+9,line) ;
- torp->hit = TRUE ;
- }
-
- }
-
- /************************************************************************/
- /* */
- /* This routine checks to see if we hit a planet. */
- /* This is a two-step process. For each planet we first check to see */
- /* if we are within a box surrounding the planet. If we are then we do */
- /* the computationally expensive distance calculation This process */
- /* save compute time while showing trajectories. */
- /* If a missile does hit a planet we mark the event with no fanfare. */
- /* That is, unless we have hit the planet too many times. If we reach */
- /* this #defined limit, the planet blows up. The instant it blows up */
- /* it no longer has any gravitational pull. This usually messes up */
- /* any shots all the other players were working on.
- /* */
- /* Inputs : None */
- /* */
- /* I/Os : torp - torpedo data */
- /* */
- /* Globals : planets - planetary database array */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void check_planets (TORPEDO *torp, UBYTE src)
- {
- UBYTE i,j ;
- WORD lx,ly ;
- char line[80] ;
-
- lx=torp->x ;
- ly=torp->y ;
-
- for (i=0;i<MAX_PLANETS;i++)
- {
- if ((planets[i].hits <MAX_PLANET_HITS) &&
- (abs(lx-planets[i].orgx) < planets[i].radius) &&
- (abs(ly-planets[i].orgy) < planets[i].radius))
- {
- if (dist(lx,ly,planets[i].orgx,planets[i].orgy) <= planets[i].radius)
- {
- sprintf (line,"Player %d's torpedo hit a planet.",src+1) ;
- msg(src+9,line) ;
- torp->hit = TRUE ;
- planets[i].hits++ ;
- if (planets[i].hits >= MAX_PLANET_HITS)
- {
- planets[i].outs = PLANET_OUTS+1 ;
- planets[i].mass = 0.0 ;
-
- /* now explode the planet */
- setcolor(BLACK) ;
- setfillstyle (SOLID_FILL,BLACK) ;
-
- /* set of expanding filled red circles */
- for (j=2;j<planets[i].radius+1;j++)
- {
- fillellipse(planets[i].orgx,planets[i].orgy,j,j) ;
- delay (20) ;
- } /* planetary explosion loop */
- } /* if we hit a planet once too many */
- } /* if really a hit */
- } /* if torpedo inside planetary box */
- } /* for all planets */
- } /* function check planets */
-
-
- /************************************************************************/
- /* */
- /* This routine checks to see if we hit another (or our own) ship. */
- /* We check all ships, including the original one. The ship is defined */
- /* to be a boxed area 12 pixels either side of the origin and 5 pixels */
- /* up and down. If we do hit the ship we show a sortof explosion. */
- /* */
- /* Inputs : None */
- /* */
- /* I/Os : torp - torpedo data */
- /* */
- /* Globals : players - player database array */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void check_ships (TORPEDO *torp, UBYTE src)
- {
- UBYTE i ;
- WORD lx,ly ;
- char line[80] ;
-
- lx=torp->x ;
- ly=torp->y ;
-
- for (i=0;i<MAX_PLAYERS;i++)
- {
- if (players[i].alive)
- {
- if ((abs(lx-players[i].orgx) <= 12) &&
- (abs(ly-players[i].orgy) <= 5 ))
- {
- sprintf (line,"Player %d hit Player %d!",src+1,i+1) ;
- msg(src+9,line) ;
- torp->hit = TRUE ;
- explode(players[i].orgx,players[i].orgy) ;
- players[i].alive = FALSE ;
- players[i].outs = PLAYER_OUTS+1 ;
- } /* if we hit the ship */
- } /* if ship exists */
- } /* for all possible ships */
- } /* function check planets */
-
-
- /************************************************************************/
- /* */
- /* This routine draws a simple explosion. */
- /* We do this by simply drawing a series of filled circles starting with*/
- /* a radius of two to 20. We then repeat the process with "black" */
- /* circles, erasing the previous spheres. */
- /* */
- /* Inputs : x,y the place for the explosion */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : None */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
- void explode(UWORD x, UWORD y)
- {
- UWORD i ; /* counter */
-
- /* red first */
- setcolor(RED) ;
- setfillstyle (SOLID_FILL,RED) ;
-
- /* set of expanding filled red circles */
- for (i=2;i<20;i++)
- {
- fillellipse(x,y,i,i) ;
- delay (20) ;
- }
-
- /* now erase the red sphere */
- setcolor(BLACK) ;
- setfillstyle (SOLID_FILL,BLACK) ;
-
- /* set of expanding filled red circles */
- for (i=2;i<20;i++)
- {
- fillellipse(x,y,i,i) ;
- delay (20) ;
- }
- } /* function explode */
-
- /************************************************************************/
- /* */
- /* This routine draws a compass around a ship */
- /* We simply draw a circle around the ship and show the tick marks for */
- /* the important degree points. The color can be specified. */
- /* */
- /* Inputs : x,y - the place to put the compass */
- /* color - the color to draw the compass */
- /* */
- /* I/Os : None */
- /* */
- /* Globals : None */
- /* */
- /* Returns : Nothing */
- /* */
- /************************************************************************/
-
- void draw_compass(UWORD x, UWORD y, UWORD color)
- {
- UBYTE i ;
- float a ;
-
- setcolor(color) ;
- circle(x,y,25) ;
-
- for (i=0;i<12;i++)
- {
- a=i*30.0*DEG2RAD ;
- line(x+20*cos(a),y-20*sin(a),x+30*cos(a),y-30*sin(a)) ;
- }
-
- outtextxy(x+35,y-8 ,"0") ;
- outtextxy(x-7 ,y-45,"90") ;
- outtextxy(x-55,y-8 ,"180") ;
- outtextxy(x-10,y+30,"270") ;
-
- }