|
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 ; }