|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T a
Length: 36644 (0x8f24)
Types: TextFile
Names: »ast_main.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/Sun/Asteroids/ast_main.c«
/* ast_main.c
*
* The game of Asteroids.
* Written by Rich Burridge - SUN Microsystems Australia (Melbourne).
*
* Version 3.0. - April 1987.
*
* No responsibility is taken for any errors or inaccuracies inherent
* either to the comments or the code of this program, but if reported
* to me then an attempt will be made to fix them.
*/
#include <stdio.h>
#include <strings.h>
#include <sys/fcntl.h>
#include "bltstuff.h"
#include "asteroids.h"
#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <signal.h>
Canvas canvas ;
Frame base_frame ;
Pixfont *pf ;
Pixwin *pw ;
extern etext() ;
Notify_value main_loop() ;
void event_proc() ;
short ast_image[] = {
#include "asteroids.icon"
} ;
DEFINE_ICON_FROM_IMAGE(ast_icon,ast_image) ;
short testarea[(BSIZE+1)*4*BYTESPERWORD] ;
mpr_static(test_pr,512,4,1,testarea) ;
short wrkarea[50*48*BYTESPERWORD] ;
mpr_static(wrk_pr,768,50,1,wrkarea) ;
struct timeb tlast,tnew,tstartflash,tlastflash ;
struct ainfo
{
struct ainfo *next ;
int x,y,dx,dy,xp,yp,sx,sy,wx,wy ;
int sizex,sizey,offx,offy,typ ;
} ;
struct hscore highscore[MAXHS] ;
int key_stations[3] = {21, 22, 23} ; /* Station values for function keys R1-R3. */
char old_key_vals[3][MAXLINE] ; /* Function key string values to save. */
char new_key_vals[3][MAXLINE] = /* Function key values used by asteroids. */
{
"g", /* Motor on - Function key R1. */
"s", /* Motor off - Function key R2. */
"t" /* Hyperspace/teleport - Function key R3. */
} ;
char path[MAXLINE] ; /* Full path to the asteroids files. */
char progname[MAXLINE] ; /* Name of this program. */
char thisscore[MAXLINE] ; /* User name for new highscore. */
char titlestring[MAXLINE] ; /* Displayed titleline for this program. */
int c ; /* Value returned by event_proc. */
int canvasfd ; /* File descriptor for canvas subwindow. */
int canvasflags ; /* Used to setup no delay for canvas. */
int csi,csj ; /* Used to put the new highscore value. */
int height ; /* Height of the asteroids window. */
int givehelp ; /* Set to 0, indicates no initial help. */
int orgx ; /* X origin of the asteroids window. */
int orgy ; /* Y origin of the asteroids window. */
int scorei ; /* Number of characters in highscore user name. */
int state = 0 ; /* Current button state. */
int width ; /* Width of the asteroids window. */
int xmax,xmin,ymax,ymin,mindimension ;
int score = 0 ;
int scorethistank = 0 ;
int enkey = 01652 ; /* ENCODE key used in highscore file. */
int addbonus = 0 ;
int bonus ; /* what bonus do we give for each set of asteroids */
int bonusship = 10000 ; /* new ship every bonusship points. */
int flashbonus = 0 ; /* flag for when to flash message. */
int bonusshown = 0 ;
int motoron ;
int fuel = FULLTANK ; /* Amount of spaceship fuel left. */
int fuelxoffset ; /* Start of fuel display bar. */
int fuelmaxlength ; /* Maximum length of fuel bar. */
int fuellength ; /* Current length of fuel bar. */
int progstate ; /* State machine for main loop. */
int savedstate ; /* State machine value after Ctrl S. */
char bonusstr[80] ;
struct ainfo *freeap,*bplist,*waitlist,*aplist ;
int basestatus ;
int ax,ay,bx,by,bdx,bdy,bxp,byp,bxpd,bypd ;
int nummove,swcount,ssector,scount ;
int basecount,t3count,t1count,waitcount,rr,dummy ;
int keys = 0 ;
extern int sfunc ; /* Rasterop code used by WRITELN. */
char *malloc() ;
extern int rint() ;
checkscore()
{
char buffer[MAXLINE] ;
SCHRFUNC(RRPL) ;
csi = MAXHS - 1 ;
while ((score > highscore[csi].score) && (csi >= 0)) csi-- ;
if (++csi < MAXHS)
{
clear_screen() ;
SPRINTF(buffer,"Congratulations, you have one of the top %d scores\n",MAXHS) ;
WRITELN(100,140,buffer) ;
WRITELN(100,200,"Please enter your name : ") ;
scorei = 0 ;
c = 0 ;
thisscore[scorei] = '_' ;
thisscore[scorei+1] = '\0' ;
WRITELN(370,200,thisscore) ;
progstate = NEXTLINE ;
}
else progstate = DOEND ;
}
showhighscore()
{
char buffer[MAXLINE] ;
int i ;
clear_screen() ;
write_bold(220,200,"High Scores") ;
SCHRFUNC(ROR) ;
WRITELN(220,201,"___________") ;
WRITELN(200,300," Score Name") ;
WRITELN(200,301," _____ ____") ;
SCHRFUNC(RRPL) ;
for (i = 0; i < MAXHS; i++)
{
SPRINTF(buffer,"%6d %s",highscore[i].score,highscore[i].who) ;
WRITELN(200,330+i*30,buffer) ;
}
SPRINTF(buffer,"Your score was %d",score) ;
WRITELN(220,500,buffer) ;
WRITELN(5,height-40,"Type RETURN to quit") ;
progstate = SCORE ;
}
gethighscore()
{
int hsfile,i ;
struct hscore nullscore ;
char highscname[MAXLINE] ; /* Full path name of the high score file. */
SPRINTF(highscname,"%sasteroids.hs",path) ;
if ((hsfile = open(highscname,2)) == -1)
{
if ((hsfile = creat(highscname,0777)) == -1)
{
PRINTF("\nunable to create highscore file.\n") ;
exit(1) ;
}
nullscore.score = 0 ; /* file should be open. */
STRCPY(nullscore.who," ") ;
for (i = 0; i < MAXHS; i++)
{
puths(hsfile,&nullscore) ;
STRCPY(highscore[i].who," ") ;
highscore[i].score = 0 ;
}
}
else
for (i = 0; i < MAXHS; i++) geths(hsfile,&highscore[i]) ;
CLOSE(hsfile) ;
}
puthighscore()
{
int hsfile,i ;
char highscname[MAXLINE] ; /* Full path name of the high score file. */
SPRINTF(highscname,"%sasteroids.hs",path) ;
if ((hsfile = open(highscname,1)) == -1)
PRINTF("Unable to open highscore file.\n") ;
else
{
for (i = 0; i < MAXHS; i++) puths(hsfile,&highscore[i]) ;
CLOSE(hsfile) ;
}
}
puths(where,record) /* put one hscore record out. */
struct hscore *record ;
int where ;
{
char buffer[32],valuestr[7] ;
int i,value ;
for (i = 0; i < 16; i++) buffer[i] = record->who[i] ^ enkey ;
value = record->score ;
SPRINTF(valuestr,"%d",value) ;
for (i = 0; i < 7; i++) buffer[i+16] = valuestr[i] ^ enkey ;
WRITE(where,buffer,23) ;
}
geths(where,record) /* get one hscore record in. */
struct hscore *record ;
int where ;
{
char buffer[32],valuestr[7] ;
int i ;
i = read(where,buffer,23) ;
for (i = 0; i < 16; i++) record->who[i] = buffer[i] ^ enkey ;
for (i = 0; i < 7; i++) valuestr[i] = buffer[i+16] ^ enkey ;
record->score = atoi(valuestr) ;
}
init()
{
int i,j ;
NICE(-20) ; /* High priority activity this game !!! */
gethighscore() ;
BLT_MEM(&wrk_pr,0,0,768,50,RXOR,&wrk_pr,0,0) ; /* Clear work area. */
rr = 1234 ;
LINE(&wrk_pr,128,25,128,40,RSET) ; /* BIG asteroid. */
LINE(&wrk_pr,128,40,147,49,RSET) ;
LINE(&wrk_pr,147,49,160,49,RSET) ;
LINE(&wrk_pr,160,49,173,47,RSET) ;
LINE(&wrk_pr,173,47,177,35,RSET) ;
LINE(&wrk_pr,177,35,177,19,RSET) ;
LINE(&wrk_pr,177,19,174,8,RSET) ;
LINE(&wrk_pr,174,8,168,3,RSET) ;
LINE(&wrk_pr,168,3,150,0,RSET) ;
LINE(&wrk_pr,150,0,144,2,RSET) ;
LINE(&wrk_pr,144,2,135,15,RSET) ;
LINE(&wrk_pr,135,15,128,25,RSET) ;
for (i = 1; i <= 48; i++)
{
j = 128 ;
while (BITSET(j,i,48,wrkarea) == 0) j++ ;
do
j++ ;
while (BITSET(j,i,48,wrkarea) != 0) ;
while (BITSET(j,i,48,wrkarea) == 0)
{
if (rint(j-128) < 6) SETON(j,i,48,wrkarea) ;
else SETOFF(j,i,48,wrkarea) ;
j++ ;
}
}
LINE(&wrk_pr,192,10,192,20,RSET) ; /* MEDIUM asteroid. */
LINE(&wrk_pr,192,20,201,29,RSET) ;
LINE(&wrk_pr,201,29,214,29,RSET) ;
LINE(&wrk_pr,214,29,221,17,RSET) ;
LINE(&wrk_pr,221,17,221,08,RSET) ;
LINE(&wrk_pr,221,08,209, 0,RSET) ;
LINE(&wrk_pr,209, 0,200, 0,RSET) ;
LINE(&wrk_pr,200, 0,192,10,RSET) ;
for (i = 1; i <= 28; i++)
{
j = 192 ;
while (BITSET(j,i,48,wrkarea) == 0) j++ ;
do
j++ ;
while (BITSET(j,i,48,wrkarea) != 0) ;
while (BITSET(j,i,48,wrkarea) == 0)
{
if (rint(j-192) < 5) SETON(j,i,48,wrkarea) ;
else SETOFF(j,i,48,wrkarea) ;
j++ ;
}
}
LINE(&wrk_pr,261, 0,270, 0,RSET) ; /* SMALL asteroid. */
LINE(&wrk_pr,270, 0,270, 9,RSET) ;
LINE(&wrk_pr,270, 9,263,14,RSET) ;
LINE(&wrk_pr,263,14,256,14,RSET) ;
LINE(&wrk_pr,256,14,256, 8,RSET) ;
LINE(&wrk_pr,256, 8,261, 0,RSET) ;
for (i = 1; i <= 13; i++)
{
j = 256 ;
while (BITSET(j,i,48,wrkarea) == 0) j++ ;
do
j++ ;
while (BITSET(j,i,48,wrkarea) != 0) ;
while (BITSET(j,i,48,wrkarea) == 0)
{
if (rint(j-256) < 4) SETON(j,i,48,wrkarea) ;
else SETOFF(j,i,48,wrkarea) ;
j++ ;
}
}
for (i = 0; i <= 3; i++) /* spaceship */
BLT_MEM(&wrk_pr,320+20-i/2,i+10,i+10,1,RXNOR,&wrk_pr,320+20-i/2,i+10) ;
for (i = 4; i <= 15; i++)
{
BLT_MEM(&wrk_pr,320+20-i/2,i+10,4,1,RXNOR,&wrk_pr,320+20-i/2,i+10) ;
BLT_MEM(&wrk_pr,320+26+(i+1)/2,i+10,4,1,RXNOR,&wrk_pr,320+26+(i+1)/2,i+10) ;
}
BLT_MEM(&wrk_pr,320,26,50,4,RXNOR,&wrk_pr,320,26) ;
for (i = 0; i <= 3; i++)
BLT_MEM(&wrk_pr,320+15-i/2,49-i,i+20,1,RXNOR,&wrk_pr,320+15-i/2,49-i) ;
for (i = 4; i <= 19; i++)
{
BLT_MEM(&wrk_pr,320+15-i/2,49-i,4,1,RXNOR,&wrk_pr,320+15-i/2,49-i) ;
BLT_MEM(&wrk_pr,320+31+(i+1)/2,49-i,4,1,RXNOR,&wrk_pr,320+31+(i+1)/2,49-i) ;
}
BLT_MEM(&wrk_pr,320+18,0,3,3,RXNOR,&wrk_pr,320+18,0) ;
BLT_MEM(&wrk_pr,320+30,0,3,3,RXNOR,&wrk_pr,320+30,0) ;
LINE(&wrk_pr,320+19,2,320+24,9,RSET) ;
LINE(&wrk_pr,320+31,2,320+26,9,RSET) ;
BLT_MEM(&wrk_pr,256,16,3,3,RXNOR,&wrk_pr,256,16) ; /* Missiles. */
aplist = NULL ;
bplist = NULL ;
freeap = NULL ;
waitlist = NULL ;
waitcount = rint(100) ;
xmax = width - 4 ;
xmin = 4 ;
ymax = height - 4 - FONT_HEIGHT ;
ymin = 4 + FONT_HEIGHT ;
mindimension = (height < width) ? height : width ;
/* Calculate bonus payments, smaller window = LARGER bonus. */
bonus = 80 - ((mindimension / 100) * 10) ;
BLT_SCRN(0,0,width,height,RXOR) ;
/* Screen black except the border. */
FPRINTF(stderr,"%d %d %d %d\n",xmin,ymin,xmax-xmin+1,ymax-ymin+1) ;
BLT_SCRN(xmin,ymin,xmax-xmin+1,ymax-ymin+1,RXNOR) ;
SCHRFUNC(RRPL) ;
WRITELN(xmin+2,height-5,"Fuel : ") ;
FPRINTF(stderr,"%d %d\n",xmin+2,height-5) ;
fuelxoffset = xmin+58 ;
fuelmaxlength = (xmax-xmin) - fuelxoffset ;
fuellength = fuelmaxlength ;
BLT_SCRN(fuelxoffset,height-FONT_HEIGHT,fuellength,FONT_HEIGHT-2,RXNOR) ;
addscore(0) ;
}
cleara(a)
struct ainfo *a ;
{
if (a->sizex > 0 && a->sizey > 0)
BLT_MEM_TO_SCRN(a->x+a->offx,a->y+a->offy,a->sizex,a->sizey,RXOR,
&wrk_pr,a->wx+a->offx,a->wy+a->offy) ;
}
updatea(a)
struct ainfo *a ;
{
int res,dx,dy ;
int sizex,sizey,offx,offy ;
res = 1 ;
a->dx += a->xp*nummove ;
dx = a->dx / AFACTOR ;
a->dy += a->yp*nummove ;
dy = a->dy / AFACTOR ;
if (dx || dy)
{
sizex = a->sx ;
sizey = a->sy ;
offx = 0 ;
offy = 0 ;
a->x += dx ;
a->y += dy ;
if (a->x < xmin)
{
offx = xmin - a->x ;
sizex -= offx ;
}
else if (a->x > xmax - a->sx) sizex = xmax - a->x + 1 ;
if (a->y < ymin)
{
offy = ymin - a->y ;
sizey -= offy ;
}
else if (a->y > ymax - a->sy) sizey = ymax - a->y + 1 ;
if (sizex > 0 && sizey > 0)
BLT_MEM_TO_SCRN(a->x+offx,a->y+offy,sizex,sizey,RXOR,
&wrk_pr,a->wx+offx,a->wy+offy) ;
else res = 0 ;
if (a->sizex > 0 && a->sizey > 0)
BLT_MEM_TO_SCRN(a->x-dx+a->offx,a->y-dy+a->offy,a->sizex,a->sizey,RXOR,
&wrk_pr,a->wx+a->offx,a->wy+a->offy) ;
a->sizex = sizex ;
a->sizey = sizey ;
a->offx = offx ;
a->offy = offy ;
a->dx -= AFACTOR * dx ;
a->dy -= AFACTOR * dy ;
}
return(res) ;
}
starta(plist,typ,x,y,xp,yp)
struct ainfo **plist ;
int typ,x,y,xp,yp ;
{
struct ainfo *newap ;
if (freeap == NULL)
newap = (struct ainfo *) malloc(sizeof(struct ainfo)) ;
else
{
newap = freeap ;
freeap = freeap->next ;
}
newap->next = *plist ;
*plist = newap ;
newap->typ = typ ;
newap->x = x ;
newap->dx = 0 ;
newap->xp = xp ;
newap->y = y ;
newap->dy = 0 ;
newap->yp = yp ;
switch (typ)
{
case 0 : newap->sx = 3 ;
newap->sy = 3 ;
newap->wx = 256 ;
newap->wy = 16 ;
break ;
case 1 : newap->sx = 50 ;
newap->sy = 50 ;
newap->wx = 128 ;
newap->wy = 0 ;
break ;
case 2 : newap->sx = 30 ;
newap->sy = 30 ;
newap->wx = 192 ;
newap->wy = 0 ;
break ;
case 3 : newap->sx = 15 ;
newap->sy = 15 ;
newap->wx = 256 ;
newap->wy = 0 ;
break ;
case 5 : newap->sx = 50 ;
newap->sy = 50 ;
newap->wx = 320 ;
newap->wy = 0 ;
break ;
}
if (x == xmin) newap->x = xmin - newap->sx + 1 ;
if (y == ymin) newap->y = ymin - newap->sy + 1 ;
newap->sizex = 0 ; /* initialise value while off screen. */
if (*plist != waitlist)
if (updatea(newap)) /* do nothing */ ;
}
updatelist(plist)
struct ainfo **plist ;
{
struct ainfo *owner,*this,*del ;
int nx,ny,s ;
owner = NULL ;
this = *plist ;
while (this != NULL)
{
if (updatea(this))
{
if (this->typ >= 5)
{
if (scount > 0) scount -= nummove ;
else
{
scount = 100 / this->typ ;
scount += rint(scount) ;
ny = rint(71) ;
if (ny > 40) nx = 140 - ny ;
else nx = 100 ;
switch (ssector)
{
case 1 : s = nx ;
nx = ny ;
ny = s ;
break ;
case 2 : s = nx ;
nx = (-ny) ;
ny = s ;
break ;
case 3 : nx = (-nx) ;
break ;
case 4 : nx = (-nx) ;
ny = (-ny) ;
break ;
case 5 : s = (-nx) ;
nx = (-ny) ;
ny = s ;
break ;
case 6 : s = (-nx) ;
nx = ny ;
ny = s ;
break ;
case 7 : ny = (-ny) ;
break ;
}
ssector = (ssector + 1) % 8 ;
starta(plist,0,this->x+20,this->y+20,3*nx,3*ny) ;
if (owner == NULL) owner = *plist ;
}
this->typ += 1 ;
}
owner = this ;
this = this->next ;
}
else if ((this->typ == 1 || this->typ == 2 || this->typ == 3)
&& basestatus == BACTIVE)
{
if (this->xp > 0)
{
if (this->x >= xmax) this->x = xmin - this->sx + 1 ;
}
else if (this->x <= xmin - this->sx + 1) this->x = xmax ;
if (this->yp > 0)
{
if (this->y >= ymax) this->y = ymin - this->sy + 1 ;
}
else if (this->y <= ymin - this->sy + 1) this->y = ymax ;
cleara(this) ;
}
else
{
del = this ;
this = this->next ;
if (owner == NULL) *plist = this ;
else owner->next = this ;
if ((del->typ == 1 || del->typ == 2 || del->typ == 3)
&& basestatus != BIDLE)
{
del->next = waitlist ;
waitlist = del ;
}
else
{
del->next = freeap ;
freeap = del ;
}
}
}
}
nextangle(cw,x,y,newx,newy)
int cw,x,y,*newx,*newy ;
{
int inc ;
if (cw) inc = 1 ;
else inc = -1 ;
*newx = x ;
*newy = y ;
if (x + ((y > 0) == cw) > 40) *newy = y - inc ;
if (x - ((y < 0) == cw) < -40) *newy = y + inc ;
if (y + ((x < 0) == cw) > 40) *newx = x + inc ;
if (y - ((x > 0) == cw) < -40) *newx = x - inc ;
}
diff()
{
if (fuel <= 0) return(0) ;
if (state == LEFTDOWN)
{
fuel -= 1 ;
return(MAXDIFF) ;
}
else if (state == RIGHTDOWN)
{
fuel -= 1 ;
return(-MAXDIFF) ;
}
else return(0) ;
}
drawbase(x,y)
int x,y ;
{
int t1,t2,i,dbmin,dbmax,ax,ay,bx,by,cx,cy,dx,dy ;
BLT_MEM(&wrk_pr,0,0,64,BSIZE,RXOR,&wrk_pr,0,0) ; /* clear work area. */
ax = (14 * x + 50) / 100 + BHEIGHT ;
ay = (14 * y + 50) / 100 + BHEIGHT ;
cx = (-(5 * x + 50)) / 100 + BHEIGHT ;
cy = (-(5 * y + 50)) / 100 + BHEIGHT ;
t1 = (-10 * x) ;
t2 = 6 * y ;
bx = (t1 - t2 + 50) / 100 + BHEIGHT ;
dx = (t1 + t2 + 50) / 100 + BHEIGHT ;
t1 = (-10 * y) ;
t2 = 6 * x ;
by = (t1 + t2 + 50) / 100 + BHEIGHT ;
dy = (t1 - t2 + 50) / 100 + BHEIGHT ;
LINE(&wrk_pr,ax,ay,bx,by,RSET) ;
LINE(&wrk_pr,bx,by,cx,cy,RSET) ;
LINE(&wrk_pr,cx,cy,dx,dy,RSET) ;
LINE(&wrk_pr,dx,dy,ax,ay,RSET) ;
if (abs(x) > abs(y))
{
if (ay > by)
{
dbmax = ay ;
dbmin = by ;
}
else
{
dbmax = by ;
dbmin = ay ;
} ;
if (dy > dbmax) dbmax = dy ;
if (dy < dbmin) dbmin = dy ;
for (i = dbmin+1; i <= (dbmax-1); i++)
{
t1 = 0 ;
while (BITSET(t1,i,48,wrkarea) == 0) t1++ ;
t2 = BSIZE - 1 ;
while (BITSET(t2,i,48,wrkarea) == 0) t2-- ;
BLT_MEM(&wrk_pr,t1,i,t2-t1,1,RXNOR,&wrk_pr,t1,i) ;
}
}
else
{
if (ax > bx)
{
dbmax = ax ;
dbmin = bx ;
}
else
{
dbmax = bx ;
dbmin = ax ;
} ;
if (dx > dbmax) dbmax = dx ;
if (dx < dbmin) dbmin = dx ;
for (i = dbmin+1; i <= (dbmax-1); i++)
{
t1 = 0 ;
while (BITSET(i,t1,48,wrkarea) == 0) t1++ ;
t2 = BSIZE - 1 ;
while (BITSET(i,t2,48,wrkarea) == 0) t2-- ;
BLT_MEM(&wrk_pr,i,t1,1,t2-t1,RXNOR,&wrk_pr,i,t1) ;
}
}
}
renewbase(dx,dy)
int dx,dy ;
{
BLT_MEM_TO_SCRN(bx+dx-BHEIGHT,by+dy-BHEIGHT,BSIZE,BSIZE,RXOR,&wrk_pr,0,0) ;
BLT_MEM_TO_SCRN(bx-BHEIGHT,by-BHEIGHT,BSIZE,BSIZE,RXOR,&wrk_pr,64,0) ;
bx = bx + dx ;
by = by + dy ;
BLT_MEM(&wrk_pr,64,0,64,BSIZE,RRPL,&wrk_pr,0,0) ;
}
startlist()
{
int i,ss,nx ;
struct ainfo *ap ;
t1count = 0 ;
t3count = 0 ;
if (waitlist != NULL)
{
ap = waitlist ;
while (ap->next != NULL) ap = ap->next ;
ap->next = freeap ;
freeap = waitlist ;
waitlist = NULL ;
}
for (i = 1; i <= 6; i++)
{
ss = (xmax - xmin) / 2 - 50 ;
ss = xmin + rint(ss-150) + rint(ss+150) + 50 ;
nx = rint(23) + rint(59) - 40 ;
switch (rint(12) / 3)
{
case 0 : starta(&waitlist,1,xmin,ss,100,nx) ;
break ;
case 1 : starta(&waitlist,1,xmax,ss,-100,nx) ;
break ;
case 2 : starta(&waitlist,1,ss,ymin,nx,100) ;
break ;
case 3 : starta(&waitlist,1,ss,ymax,nx,-100) ;
break ;
}
}
if (addbonus)
{
SPRINTF(bonusstr," ** Bonus : %3d ** ",bonus*10) ;
startflashbonus() ;
addscore(bonus) ;
}
else addbonus = 1 ; /* don't add bonus at start. */
}
matchlist(plist,test,tx,ty)
struct ainfo **plist,*test ;
int tx,ty ;
{
struct ainfo *owner,*this ;
int nx,ny,s ;
owner = NULL ;
this = *plist ;
while (this != NULL)
{
if (this != test)
{
if ((tx >= this->x) && (tx < this->x + this->sx)
&& (ty >= this->y)
&& (ty < this->y + this->sy))
if (BITSET(tx - this->x + this->wx,ty - this->y + this->wy,48,wrkarea) != 0)
{
cleara(this) ;
addscore(this->typ) ;
if ((scorethistank - REFUEL) >= 0)
{
fuel = FULLTANK ; /* refuel */
scorethistank = 0 ;
}
if ((this->typ == 1) || (this->typ == 2))
{
nx = (rint(42) + 1) / 2 ;
if (nx > 12) ny = 42 - nx ;
else ny = 30 ;
switch (rint(4))
{
case 1 : ny = (-ny) ;
break ;
case 2 : s = nx ;
nx = ny ;
ny = s ;
break ;
case 3 : s = nx ;
nx = ny ;
ny = (-s) ;
break ;
}
if (this->typ == 1) s = 10 ;
else s = 8 ;
starta(plist,this->typ+1,this->x+s,this->y+s,this->xp+nx,this->yp+ny) ;
starta(plist,this->typ+1,this->x+s,this->y+s,this->xp-nx,this->yp-ny) ;
if (owner == NULL) owner = (*plist)->next ;
if (this->typ == 1)
{
t1count++ ;
if (t1count == 6)
{
if (rint(2) == 0)
starta(&waitlist,5,xmin,ymin+1,100,0) ;
else starta(&waitlist,5,xmax,ymin+1,-100,0) ;
scount = 10 ;
ssector = rint(7) ;
}
}
}
else if (this->typ == 3)
{
t3count++ ;
if (t3count == 24) startlist() ;
} ;
if (owner == NULL) *plist = this->next ;
else owner->next = this->next ;
this->next = freeap ;
freeap = this ;
return(1) ;
}
}
owner = this ;
this = this->next ;
}
return(0) ;
}
checkhit()
{
struct ainfo *owner,*this,*del ;
int i,x,y ;
owner = NULL ;
this = bplist ;
while (this != NULL)
{
BLT_MEM(&test_pr,0,0,64,3,RXOR,&test_pr,0,0) ;
BLT_SCRN_TO_MEM(&test_pr,0,0,3,3,RRPL,this->x,this->y) ;
y = -1 ;
for (i = 0; i <= 2; i++)
if (testarea[i*4] != 0) y = i ; /* this checks to see if row <> zeros */
if (y < 0)
{
owner = this ;
this = this->next ;
}
else
{
x = 0 ;
while (BITSET(x,y,4,testarea) == 0) x++ ;
x += this->x ;
y += this->y ;
cleara(this) ;
if (!matchlist(&aplist,(struct ainfo *) NULL,x,y))
if (!matchlist(&bplist,this,x,y)) /* do nothing */ ;
del = this ;
this = this->next ;
if (owner == NULL) bplist = this ;
else
{
if (owner->next == del) owner->next = this ;
else if (bplist == del) bplist = this ;
else
{
owner = bplist ;
while (owner->next != del) owner = owner->next ;
owner->next = this ;
}
}
del->next = freeap ;
freeap = del ;
}
}
}
disintgt(gone)
int *gone ;
{
int x,y,xx,yy,countdown,gotone ;
x = 0 ;
y = 0 ;
gotone = 0 ;
countdown = rint(3) ;
SETOFF(BHEIGHT,BHEIGHT,48,wrkarea) ;
do
{
if (x > y)
if (x > (-y)) y-- ;
else x-- ;
else if (x < (-y)) y++ ;
else x++ ;
if (BITSET(x + BHEIGHT,y + BHEIGHT,48,wrkarea) != 0)
{
gotone = 1 ;
if (countdown > 0) countdown-- ;
else
{
countdown = 5 ;
xx = x ;
yy = y ;
if (abs(x) >= abs(y)) xx = xx - (2 * (x > 0) - 1) ;
if (abs(x) <= abs(y)) yy = yy - (2 * (y > 0) - 1) ;
SETOFF(x+BHEIGHT,y+BHEIGHT,48,wrkarea) ;
SETON(xx+BHEIGHT,yy+BHEIGHT,48,wrkarea) ;
}
}
}
while (x + y != BHEIGHT + BHEIGHT) ;
*gone = !gotone ;
}
updatebase()
{
int count,d,dd,dx,dy,i,j,newx,newy ;
int changed,gone ;
struct ainfo *ap ;
switch (basestatus)
{
case BWAITING : if ((aplist == NULL) && (bplist == NULL))
{
bx = (xmin + xmax + 1) / 2 ;
by = (ymin + ymax + 1) / 2 ;
ax = 100 ;
ay = 0 ;
bxp = 0 ;
byp = 0 ;
bdx = 0 ;
bdy = 0 ;
bxpd = 0 ;
bypd = 0 ;
motoron = 0 ;
drawbase(ax,ay) ;
renewbase(0,0) ;
swcount = 0 ;
basestatus = BACTIVE ;
}
break ;
case BACTIVE : if (waitlist != NULL)
if (waitcount > 0) waitcount-- ;
else
{
ap = waitlist ;
waitlist = ap->next ;
ap->next = aplist ;
aplist = ap ;
waitcount = rint(rint(20) * 10 + 10) + 10 ;
}
d = diff() ;
changed = 0 ;
count = nummove + nummove ;
while ((d != 0) && (count > 0))
{
nextangle((d > 0),ax,ay,&newx,&newy) ;
dd = diff() ;
if ((dd == 0) || ((d > 0) == (dd > 0)) || (abs(dd) < abs(d)))
{
ax = newx ;
ay = newy ;
changed = 1 ;
}
if ((d > 0) != (dd > 0)) d = 0 ;
else d = dd ;
count-- ;
}
if (changed) drawbase(ax,ay) ;
for (count = 1; count <= nummove; count++)
{
if (motoron)
{
fuel -= 10 ; /* burn some fuel. */
if (fuel <= 0)
{
fuel = 0 ;
motoron = 0 ;
}
bxpd += ax ;
bypd += ay ;
dx = bxpd / BFACTOR ;
dy = bypd / BFACTOR ;
bxp += dx ;
byp += dy ;
bxpd -= dx * BFACTOR ;
bypd -= dy * BFACTOR ;
}
bdx += bxp ;
bdy += byp ;
}
dx = bdx / BFACTOR ;
dy = bdy / BFACTOR ;
bdx -= dx * BFACTOR ;
bdy -= dy * BFACTOR ;
if (changed || (dx != 0) || (dy != 0)) renewbase(dx,dy) ;
BLT_MEM(&test_pr,0,0,64,BSIZE,RRPL,&wrk_pr,64,0) ;
BLT_SCRN_TO_MEM(&test_pr,0,0,BSIZE,BSIZE,RXNOR,
bx-BHEIGHT,by-BHEIGHT) ;
i = 0 ;
do
if ((testarea[i*4] == 0) && /* Is row = zero? */
(testarea[i*4+1] == 0) &&
(testarea[i*4+2] == 0) &&
(testarea[i*4+3] == 0)) i++ ;
else
{
j = 0 ;
while (BITSET(j,i,4,testarea) == 0) j++ ;
i += bx - BHEIGHT ;
j += by - BHEIGHT ;
if (!matchlist(&aplist,(struct ainfo *) NULL,j,i))
if (!matchlist(&bplist,(struct ainfo *) NULL,j,i)) ;
basestatus = BDYING ;
return ;
}
while (i != BSIZE) ;
if (c == BUTMIDDLE)
{
if (swcount > 0) swcount -= nummove ;
else
{
swcount = 20 ;
starta(&bplist,0,bx-1+(17*ax)/100,by-1+(17*ay)/100,ax*5,ay*5) ;
}
c = 0 ;
}
else swcount = 0 ;
break ;
case BDYING : disintgt(&gone) ;
renewbase(0,0) ;
if (gone)
{
state = 0 ; /* Clear previous button state. */
basecount-- ;
addscore(0) ; /* Correct number of ships left. */
if (basecount == 0) basestatus = BIDLE ;
else
{
basestatus = BWAITING ;
scorethistank = 0 ;
fuel = FULLTANK ;
}
}
break ;
}
}
checkkey()
{
int nx,ny,ss ;
if (keys)
{
keys = 0 ;
switch (c)
{
case K_QUIT : progstate = EXPIRED ;
break ;
case K_GO : motoron = ((basestatus == BACTIVE) && (fuel > 0)) ;
break ;
case K_STOP : motoron = 0 ;
break ;
case K_TELEPORT: if (basestatus == BACTIVE)
if (fuel >= (FULLTANK / 5))
{
fuel -= (FULLTANK / 5) ; /* 20% loss each hyperspace. */
ss = (xmax - xmin) / 2 - BSIZE ;
nx = xmin + BHEIGHT + rint(ss-50) + rint(ss+50) ;
ny = ymin + BHEIGHT + rint(ss-50) + rint(ss+50) ;
if (nx < xmin + BHEIGHT) nx = xmin + BHEIGHT ;
else if (nx > xmax - BHEIGHT) nx = xmax - BHEIGHT ;
if (ny < ymin + BHEIGHT) ny = ymin + BHEIGHT ;
else if (ny > ymax - BHEIGHT) ny = ymax - BHEIGHT ;
renewbase(nx-bx,ny-by) ;
}
break ;
}
}
}
numticks(to,from)
struct timeb *to,*from ;
{
return(((to->time - from->time) * 1000 + (to->millitm - from->millitm)) / 16) ;
}
main(argc,argv)
int argc ;
char *argv[] ;
{
get_options(argc,argv) ; /* Get users command line options. */
function_keys(KEY_SET) ; /* Set asteroid commands function keys. */
base_frame = window_create(NULL, FRAME,
FRAME_LABEL, titlestring,
FRAME_ICON, &ast_icon,
WIN_X, orgx,
WIN_Y, orgy,
WIN_WIDTH, width,
WIN_HEIGHT, height,
FRAME_ARGS, argc, argv,
0) ;
width = width - 10 ;
height = height - 25 ;
canvas = window_create(base_frame, CANVAS,
CANVAS_RETAINED, TRUE,
CANVAS_FAST_MONO, TRUE,
WIN_EVENT_PROC, event_proc,
0) ;
window_set(canvas, WIN_CONSUME_KBD_EVENTS, WIN_ASCII_EVENTS, 0) ;
window_set(canvas, WIN_CONSUME_KBD_EVENTS, WIN_LEFT_KEYS, 0) ;
pf = pf_default() ;
pw = canvas_pixwin(canvas) ;
/* Set up no delay for events within the canvas. */
canvasfd = (int) window_get(canvas,WIN_FD) ;
canvasflags = fcntl(canvasfd,F_GETFL,0) ;
canvasflags |= FNDELAY ;
FCNTL(canvasfd,F_SETFL,canvasflags) ;
sfunc = PIX_SRC ; /* Used by WRITELN. */
iocursormode(OFFCURSOR) ;
progstate = HELP ;
(void) notify_set_itimer_func(base_frame, main_loop, ITIMER_REAL,
&NOTIFY_POLLING_ITIMER, ((struct itimerval *) 0)) ;
window_main_loop(base_frame) ;
exit(0) ;
}
/*ARGSUSED*/
void
event_proc(window,event,arg)
Window *window ;
Event *event ;
caddr_t arg ;
{
if (event_is_button(event))
{
switch (event_id(event))
{
case MS_LEFT : if (event_is_down(event)) c = LEFTDOWN ;
else c = LEFTUP ;
break ;
case MS_MIDDLE : if (event_is_down(event)) c = BUTMIDDLE ;
break ;
case MS_RIGHT : if (event_is_down(event)) c = RIGHTDOWN ;
else c = RIGHTUP ;
}
}
else if (event_is_ascii(event)) c = event_id(event) ;
if (c == CTRLS)
{
if (progstate != CTRLSHIT) savedstate = progstate ;
progstate = CTRLSHIT ;
return ;
}
else if (c == CTRLQ)
{
progstate = savedstate ;
return ;
}
else if (c > RIGHTDOWN) keys = 1 ;
if (c == LEFTDOWN || c == RIGHTDOWN || c == LEFTUP || c == RIGHTUP) state = c ;
}
/*ARGSUSED*/
static Notify_value
main_loop(client, itimer_type)
Notify_client client ;
int itimer_type ;
{
switch (progstate)
{
case HELP : clear_screen() ; /* Clear the asteroids window. */
if (givehelp) do_help_screen() ; /* Output help screen. */
progstate = GETRET ;
break ;
case GETRET : if (c == RETURN) progstate = STARTUP ;
break ;
case STARTUP : clear_screen() ; /* White background, before inversion. */
basecount = 3 ;
init() ;
startlist() ;
basestatus = BWAITING ;
ftime(&tlast) ;
nummove = 1 ;
progstate = UPDATE ;
break ;
case UPDATE : update() ;
break ;
case EXPIRED : function_keys(KEY_RESET) ;
BLT_SCRN(0,0,width,height,RXOR) ;
checkscore() ;
case NEXTLINE : getnewscore(365,200) ;
break ;
case DOEND : showhighscore() ;
break ;
case SCORE : if (c == RETURN) exit(0) ;
break ;
case CTRLSHIT : break ;
}
}
update()
{
updatelist(&aplist) ;
updatelist(&bplist) ;
updatebase() ;
checkhit() ;
checkkey() ;
showfuel() ;
if (flashbonus) doflashbonus() ;
do
{
dummy = rint(2) ;
ftime(&tnew) ;
}
while (tnew.millitm == tlast.millitm) ;
nummove = numticks(&tnew,&tlast) ;
if (nummove > 20) nummove = 20 ;
tlast.time = tnew.time ;
tlast.millitm = tnew.millitm ;
if ((basestatus == BIDLE) && (aplist == NULL) && (bplist == NULL))
progstate = EXPIRED ;
}