/*

InvaderCraft von J.Hertel
(C) CW-Publikationen

  "action.c"


Kompilieren mit Aztec C Version 3.20a.

Im Include-Directory muessen sich die Header-Files "invadercraft1.h" und
"invadercraft2.h" befinden!

Aufruf:  cc action -a -e400
         as action

Linken:  siehe invadercraft.c

*/

#include <exec/types.h>
#include <graphics/gfx.h>
#include <graphics/rastport.h>
#include <graphics/view.h>
#include <hardware/custom.h>
#include <hardware/cia.h>

/* Vor Compiler-Aufruf unbedingt "invadercraft1.h" und "invadercraft2.h"
in include/ - Directory kopieren! */

#include <invadercraft1.h>
#include <invadercraft2.h>

extern struct GfxBase *GfxBase;
extern struct RastPort rp,rp2,rphi;
extern struct BitMap bmhi,bm,bm2,inb,schb,misb,expb,bunb,dummyb,mistreb,
mutb,bunkerbuff[2],ab1,titelbild,bssb,bsib;
extern struct ViewPort vp,vphi;
extern struct Custom *custom;
extern struct CIA *ciaa;

extern struct liste slots[MAXVERSIONS][SLOTS];
extern UWORD color[],color1[];
extern USHORT rnd;
extern int trainer,kick,INBEWVERZ[],EIZAEMAXNORM[],MUTZAEMAX[],SCHZAEMAX[],
MISANZ[],MISZAEMAX[],MISWK[],GEZIELTEWK[],ANZPANZER[];
extern long YA1[],YA[],MITTE[],EIXD[],MUTD[],SCHD[],MISD[];

UWORD *colorp;
long KO2[2]={15L,17L},INYD[]={13L,17L},mutoff,BPRS,BPRI,GAMEOVERY;

ULONG score[MAXVERSIONS][2],hiscore[MAXVERSIONS],frei[ANZFREIPANZER+1]={

/* ab dieser Punktzahl gibt es jeweils einen Freipanzer; ANZFREIPANZER
ist die Anzahl an moeglichen Freipanzern (im Headerfile zu aendern) */

4999,9999,19999,49999,99999,199999,499999
,0xffffffff};

/* Y-Koordinaten der sensitiven Punkte der Missiles */
long misyhs[MHSANZ]={3L,8L,MKO4-1L};   /* aufsteigende Reihenfolge */

/* Aufstellung der Invaders pro Level */
int levelmin[MAXLEVEL]={1,3,5,7,9,11,13,15,17,19,21,23,24,25,25,25};
int levelh[MAXLEVEL]={4,4,5,5,5,5,6,6,6,6,6,6,6,6,6,6};
int levelb[MAXLEVEL]={7,8,8,8,9,9,9,10,10,10,10,10,10,10,10,10};
int levela[2][MAXLEVEL]={{0,0,0,1,1,2,1,1,1,2,2,2,2,2,2,2},
                         {0,1,1,2,2,2,1,2,2,3,3,4,4,4,4,4}};

int freipanz[2],invor[KO5][KO6],invor1[KO5],invor2[KO5],invor3,invaderanz,
inligre,inregre,inobgre,inungre,strigzae,eizae,eizaemax,mutzae,miszae1,
miszae1max,schzae,miszae,player,abschuss,inbewsound,ship[2],anzplay,anzplay1,
version,level[2],demo,demolevel;
long mutphase,eiphase,mutxd,inxd,inx,inphase,inphased,iny,regre,ligre,ungre,
obgre,aligre,aregre,aungre,aobgre,mutx,schx,schy,by,eix,eiy,eiligre,eiregre,
inbewsoundzae,mutbewsoundzae,eibewsoundzae,playx[2]={90,470},time;

char *txt[2]={"Player1","Player2"};
#define LEN 7L  /* Laenge der obigen Texte */

char *text[2]={"  Ready  ","Game over"};
#define LEN2 9L  /* s.o. */

struct Vorddef {
   int invor[KO5][KO6],invaderanz,inligre,inregre,inobgre,inungre;
   long inxd,inx,inphase,inphased,iny,regre,ligre,ungre,obgre;
   } vd[2];

struct schmis {
   long x,y;
   int phase;
   BYTE flag;
   } schuss,mis[MISANZMAX];

anfang()
/* einmalige Initialisierungen und Aufruf des Hauptmenues */
{
   int i,j;
   UBYTE *diskreg=0xBFD100;

   *diskreg|=0x80;   *diskreg|=0x08;   *diskreg&=0xf7; /* Disk-Motor aus */

   GAMEOVERY=MITTE[kick]+VY;
   aligre=VX; aregre=XA1+VX; aobgre=MUTKO4+MUTY+4; aungre=YA1[kick]+VY;
   eiregre=aregre-KO3+1; eiligre=aligre; eiy=aungre-KO4+1;
   by=eiy-SAY-BKO4+1; miszae1max=MKO4/MISD[version];
   BPRS=BSSWIDTH/8; BPRI=BSIWIDTH/8; BPRS+=BPRS%2; BPRI+=BPRI%2;

   sternsetz();
   for (i=0;i<3;i++)
      hiscore[i]=slots[i][0].score;
   hauptmenu();
}

spiel(plr)
BYTE plr;
/* Beginn des Spiels, plr ist Nummer des Spielers (fuer Two Player Game) */
{
   int i;
   BYTE status;

/* Befindet sich das Programm im Demo-Modus (siehe menues.c), so ist die
Variable 'demo' ungleich Null (siehe menues.c) */
   if(demo==0) {
      level[0]=level[1]=0; score[version][0]=0; ship[0]=ANZPANZER[version];
      if(plr) {
          score[version][1]=0;
          ship[1]=ANZPANZER[version];
      }
      freipanz[0]=0; freipanz[1]=0;
   }
   else {
      if(demolevel==2)
         demolevel=7;
      else
         demolevel=2;
      level[0]=demolevel;
   }
   anzplay=plr; anzplay1=anzplay+1; player=0;
   setup();
   if(demo==0) {
      titrest();
      textanz(0);
   }
   player=1;
   bunker();
   storeplayer();
   setupnextplayer();
   player=0;
   storeplayer();
   setupnextplayer();
   einblenden(color,0);

   do {
      if(anzplay1==2) {
         setupnextplayer();
      }
      time=0;
  trainerlabel:
      do {
/* Alles bewegen, bis kein Invader mehr da ist, der Panzer getroffen oder
mit der linken Maustaste unterbrochen wird */
         status=inbew();
         if(status==KEINE_IN_MEHR) {
            for(i=0;i<PAUSE;i++) {
               if(status=leer()) {   /* einen Augenblick warten */
                  break;
               }
               status=KEINE_IN_MEHR;
            }
            if(status==KEINE_IN_MEHR) {
               level[player]++;        /* neue Aufstellung */
               setup();
               bunker();
            }
         }
      } while(status==KEINE_IN_MEHR);
      if(demo==0 && status!=QUIT && trainer!=0) {
         if (status==UEBERROLLT) {
            ueber();
            ausblenden(0);
            SetRast(&rp,0L);
            SetRast(&rp2,0L);
            einblenden(color,0);
            level[player]++;
            setup();
            bunker();
         }
         goto trainerlabel;
      }
      if(status==ABGESCHOSSEN) {
         if(ship[player]==0)
            status=LETZTERPANZER;
      }
      if(status==UEBERROLLT)
         ueber();
      if(status==UEBERROLLT||status==LETZTERPANZER) {
         anzplay1--;
         ausblenden(0);
         textanz(1);
         if(anzplay1) {
            player=(player+1)%2;
            titrest();
            textanz(0);
            setupnextplayer();
         }
         if(anzplay1)
            einblenden(color,0);
      }
      else if(status==ABGESCHOSSEN) {
         if(anzplay1==2) {
            storeplayer();
            player=(player+1)%2;
            ausblenden(0);
            titrest();
            textanz(0);
            einblenden(color,0);
         }
      }
      else if(status==QUIT||status==DEMO) {
         anzplay1=0;
         ausblenden(0);
      }
      else if(status==QUITDEMO) {
         anzplay1=0;
         ausblenden(0);
         return(1);
      }
   } while(anzplay1!=0);
   return(0);
}

storeplayer()

/* Zwischenspeichern der Daten eines Spielers (fuer Spiel zu zweit) */

{
   int i,j;

   vd[player].invaderanz=invaderanz; vd[player].inligre=inligre;
   vd[player].inregre=inregre;       vd[player].inobgre=inobgre;
   vd[player].inungre=inungre;       vd[player].ligre=ligre;
   vd[player].regre=regre;           vd[player].obgre=obgre;
   vd[player].ungre=ungre;           vd[player].inxd=inxd;
   vd[player].inx=inx;               vd[player].iny=iny;
   vd[player].inphase=inphase;       vd[player].inphased=inphased;
   for(i=0;i<KO5;i++)
      for(j=0;j<KO6;j++)
         vd[player].invor[i][j]=invor[i][j];

   /* Aussehen der Bunker merken */
   BltBitMap(&bm,VX,by,&bunkerbuff[player],0L,0L,XA,BKO4,0xc0L,0xffL);
}

setupnextplayer()

/* Zwischengespeicherte Daten in aktuelle Variablen uebertragen */

{
   int i,j;
   for(i=0;i<MISANZ[version];i++)
      mis[i].flag=0;
   schuss.flag=0; mutxd=0; schx=0; eiphase=0; eix=eiligre; eizae=0;
   eizaemax=EIZAEMAXNORM[version];   miszae=1%MISZAEMAX[version];
   schzae=2%SCHZAEMAX[version];      mutzae=3%MUTZAEMAX[version];
   strigzae=DAUERFEUERBREMSE;        inbewsound=0;

   invaderanz=vd[player].invaderanz; inligre=vd[player].inligre;
   inregre=vd[player].inregre;       inobgre=vd[player].inobgre;
   inungre=vd[player].inungre;       ligre=vd[player].ligre;
   regre=vd[player].regre;           obgre=vd[player].obgre;
   ungre=vd[player].ungre;           inxd=vd[player].inxd;
   inx=vd[player].inx;               iny=vd[player].iny;
   inphase=vd[player].inphase;       inphased=vd[player].inphased;

   for(i=0;i<KO5;i++)
      for(j=0;j<KO6;j++)
         invor[i][j]=vd[player].invor[i][j];
   /* Bunker auf urspruenglichen Zustand bringen */
   BltBitMap(&bunkerbuff[player],0L,0L,&bm,VX,by,XA,BKO4,0xc0L,0xffL);
}

textanz(flag)
BYTE flag;

/* Get Ready (flag==0) oder Game Over (flag==1) Meldung auf Lautsprecher
und Schirm geben. */

{
   int i,j;

   SetRast(&rp2,0L); SetRast(&rp,0L);
   SetAPen(&rp2,1L);
   Move(&rp2,VX+155L-5*LEN,GAMEOVERY-7L);    Text(&rp2,txt[player],LEN);
   Move(&rp2,VX+110L,GAMEOVERY+13L);         Text(&rp2,text[flag],LEN2);
   SetAPen(&rp2,2L);
   Move(&rp2,VX+155L-5*LEN+1L,GAMEOVERY-7L); Text(&rp2,txt[player],LEN);
   Move(&rp2,VX+110L+1L,GAMEOVERY+13L);      Text(&rp2,text[flag],LEN2);
   sound(11+flag,0,2-player);
   einblenden(color1,0);
   for(i=0;i<50;i++) {
      SetRGB4(&vp,10L,(long)(i%5+5),(long)((i+3)%5+5),(long)((i+6)%6+5));
      sound(13+flag,(2*flag-1)*i*5,player+1); /* zus. Soundeffekt */
      sync();
   }
   if(flag) {
      ausblenden(0);
      eintrag(score[version][player]);
      ausblenden(0);
      interaus();
   }
   else
      ausblenden(0);
   SetAPen(&rp2,0L); SetAPen(&rp,0L);
   SetRast(&rp2,0L); SetRast(&rp,0L);
}

ueber()

/* Schirm flimmern lassen, wenn Invaders Panzer ueberrollen */

{
   int i,j;

   sound(3,0,3);
   SetRast(&rp,0L); SetRast(&rp2,0L);
   for(i=0;i<61;i++) {
      SetRGB4(&vphi,0L,(long)(i%16),(long)((i+3)%5),(long)((i+6)%3));
      SetRGB4(&vp,0L,(long)(i%16),(long)((i+3)%5),(long)((i+6)%3));
      sync();
   }
}

setup()

/* Invaders neu aufstellen, einige Variablen initialisieren */

{
   int i,j;
   invaderanz=0;

   if(level[player]>=MAXLEVEL)
      level[player]=MAXLEVEL-1;
   for(i=0;i<KO5;i++)
      for(j=0;j<KO6;j++)
         invor[i][j]=0;
   for(i=0;i<levelb[level[player]];i++)
      for(j=0;j<levelh[level[player]];j++) {
         invor[i][j]=levelmin[level[player]]+j;
         invaderanz++;
      }
   inphase=0; inxd=1; inphased=1; inligre=0; inregre=KO5-1; inobgre=0;
   inungre=KO6-1;
   fingre();
   obgre=aobgre-inobgre*KO2[kick]+(ungre-aobgre+inobgre*KO2[kick])%INYD[kick];
   inx=ligre; iny=obgre+INYD[kick]*levela[kick][level[player]];
}

titrest()

/* Status-Balken am oberen Bildschirmrand restaurieren */

{
   SetRast(&rphi,0L);
   SetAPen(&rphi,1L);
   titrest1(player);
   if(anzplay) {
      SetAPen(&rphi,2L);
      titrest1((player+1)%2);
   }
   SetAPen(&rphi,3L);
   if(anzplay) {
      ausdruck(300L,hiscore[version]);
      Move(&rphi,270L,8L);
   }
   else  {
      ausdruck(530L,hiscore[version]);
      Move(&rphi,500L,8L);
   }
   Text(&rphi,"Hi",2L);
}

titrest1(plyr)
int plyr;

/* Punkte und Anzahl an Panzern (Ships) ausgeben*/

{
   Move(&rphi,playx[plyr]-80L,8L);   Text(&rphi,txt[plyr],LEN);
   ausdruck(playx[plyr],score[version][plyr]);
   Move(&rphi,playx[plyr]+70L,8L);   Text(&rphi,"Ships",5L);
   shipanz(playx[plyr],ship[plyr]);
}

bunker()

/* Bunker (neue) auf Schirm bringen */

{
   long k;
   for(k=0;k<BANZ;k++)
      BltBitMap(&bunb,BOFF1,BOFF2,&bm,k*BKO1+BX,by,BKO3,BKO4,0xc0L,0xffL);
}

punktezaehlung()

/* Evtl. Freipanzer vergeben und Hiscore aktualisieren */

{
   SetAPen(&rphi,1L);
   ausdruck(playx[player],score[version][player]);
   if(score[version][player]>frei[freipanz[player]]) {
      freipanz[player]++; ship[player]++;
      shipanz(playx[player],ship[player]);
   }
   if(score[version][player]>hiscore[version]) {
      hiscore[version]=score[version][player];
      SetAPen(&rphi,3L);
      if(anzplay)
         ausdruck(300L,hiscore[version]);
      else
         ausdruck(530L,hiscore[version]);
   }
}

ausdruck(x,z)
long x,z;

/* Ausdruck der Punkte z auf Status-Balken (x-Koordinate=x) */

{
   char str[6];
   int i;
   for(i=5;i>=0;i--) {
      str[i]= z % 10 + 48;
      z/=10;
   }
   Move(&rphi,x,8L); Text(&rphi,str,6L);
}

shipanz(x,s)
long x;
BYTE s;

/* Ausdruck der Anzahl an Panzern s auf Status-Balken (x-Koordinate=x) */

{
   char str[2];

   str[1]=s%10+48; s/=10; str[0]=s%10+48;
   Move(&rphi,130L+x,8L); Text(&rphi,str,2L);
}

strig()

/* Feuerknopf-Abfrage und Verlangsamung bei dauerndem Druck auf Knopf */

{

   if(ciaa->ciapra & 0x80 && demo==0) {
      strigzae=0;
      return(0);
   }
   else {
      if(strigzae) {
         strigzae--;
         return(0);
      }
      else {
         strigzae=DAUERFEUERBREMSE;
         return(1);
      }
   }

}

eibew()

/* Panzer bewegen (Joystick oder, im Demo-Modus, zufaellig) */

{
   BYTE flg=0;
   static BYTE demorichtung=1;

   if(eiphase<0) {
      /* Panzer explodiert */
      BltBitMap(&expb,OFF1,(-eiphase-1)*EXPHEIGHT+OFF2,&bm,eix,eiy,KO3,KO4,
       0xc0L,0xffL);
      --eiphase;
      if(eiphase==-EXPPHASEN-1) {
         abschuss=1; eiphase=0; eix=eiligre; eizaemax=EIZAEMAXNORM[version];
      }
   }
   else {
      if(demo==0) {
         if(custom->joy1dat&0x200) {         /* Joystick bewegt Panzer */
            if(eix-EIXD[version]>=eiligre) {
               eix-=EIXD[version]; eiphase=++eiphase%PHASEN; flg=1;
            }
         }
         else if (custom->joy1dat & 2) {
            if (eix+EIXD[version]<=eiregre) {
               eix+=EIXD[version]; eiphase=(eiphase+PHASEN-1) % PHASEN;
               flg=1;
            }
         }
      }
      else {                      /*  Demo-Modus: Zufall bewegt Panzer */
         rnd1();
         if(rnd>61000L) {
            rnd1();
            if(rnd>55000L)
               demorichtung=inxd;
            else {
               rnd1();
               demorichtung=3L*rnd/0x10000L-1;
            }
         }
         if(demorichtung==-1) {
            if(eix-EIXD[version]>=eiligre) {
               eix-=EIXD[version]; eiphase=++eiphase%PHASEN; flg=1;
            }
            else
               demorichtung=-demorichtung;
         }
         else if (demorichtung==1) {
            if (eix+EIXD[version]<=eiregre) {
               eix+=EIXD[version]; eiphase=(eiphase+PHASEN-1) % PHASEN;
               flg=1;
            }
            else
               demorichtung=-demorichtung;
         }
      }
      if(flg)                    /* Panzer bewegt: flg!=0 */
         if(eiphase==0) {
            if(eibewsoundzae==0) {
               sound(2,0,3);
               eibewsoundzae=EIBEWSOUNDZAEMAX;
            }
            eibewsoundzae--;
         }
      else
         eibewsoundzae==0;
      BltBitMap(&inb,INEX*(INA-1)+OFF1,eiphase*INEY+OFF2,&bm,eix,eiy,KO3,KO4,0xc0L,0xffL);
   }
}

schbew()

/* Schuss bewegen und Abfrage auf Treffer */

{
   int xz=0,yz=0;
   short farbe;
   long i;

   if(schuss.flag) {          /* immer nur ein Schuss unterwegs */
      if(schuss.y<=VY-SKO4) { /* Schuss nicht mehr sichtbar */
         schuss.flag=0;
         /* Zeit-Dummys: */
         farbe=ReadPixel(&rp,13L,13L);
         BltBitMap(&schb,SOFF1,SOFF2,&dummyb,0L,0L,SKO3,SKO4,0xc0L,0xffL);
         for(i=0;i<50;i++) ;
      }
      else {
         BltBitMap(&schb,SOFF1,schuss.phase*SCHHEIGHT+SOFF2,&bm2,schuss.x,
          schuss.y,SKO3,SKO4,0xc0L,0xffL);
         if(schuss.y>=VY) {
            if(farbe=ReadPixel(&rp,schuss.x+SHS,schuss.y)) {
               /* Treffer */
               xz=(schuss.x+SHS-inx)/KO1; yz=(schuss.y-iny)/KO2[kick];
               if(farbe==7) {             /* Bunker hat Farbe 7 */
                  sound(7,0,1);           /* Bunkertreffer */
                  BltPattern(&rp,bssb.Planes[0],schuss.x+SHS-BSHS,
                   schuss.y-BSSHEIGHT+SCHD[version],
                   schuss.x+SHS-BSHS+BSSWIDTH-1L,schuss.y+SCHD[version]-1L,
                   BPRS);                 /* Bunker beschaedigen */
                  schuss.flag=0;
                  RectFill(&rp2,schuss.x,schuss.y,schuss.x+SKO3-1L,
                   schuss.y+SKO4-1L);
               }
               else if(schuss.y<MUTY+MUTKO4) {
                  if(mutphase>=0) {       /* Mutterschiff-Treffer */
                     sound(9,0,3);
                     mutphase=-1;
                     RectFill(&rp2,schuss.x,schuss.y,schuss.x+SKO3-1L,
                      schuss.y+SKO4-1L);
                     schuss.flag=0;
                     if(demo==0) {
                        rnd1();
                        score[version][player]+=(mutoff/MUTWIDTH)*
                         (MUTPUNKTE+MUTPUNKTERND*(long)rnd/65536L);
                        punktezaehlung();
                     }
                  }
               }
               else if(invor[xz][yz]>0) {
                  sound(5,0,1);           /* Invader getroffen */
                  if(demo==0) {
                     score[version][player]+=10*invor[xz][yz];
                     punktezaehlung();
                  }
                  invor[xz][yz]=-1;
                  schuss.flag=0;
                  rnd1();
                  RectFill(&rp2,schuss.x,schuss.y,schuss.x+SKO3-1L,
                   schuss.y+SKO4-1L);
               }
            }
         }
         else {
            /* Zeit-Dummy: */
            farbe=ReadPixel(&rp,0L,0L);
         }
         schuss.y-=SCHD[version];
         schuss.phase=++schuss.phase%SCHPHASEN;
      }
   }
   else {                              /* kein Schuss unterwegs */
      if(strig() && eiphase>=0) {
         schuss.y=eiy-SAY;             /* Schuss abgefeuert */
         schuss.x=eix+SAX;
         schuss.phase=0;
         schuss.flag=1;
         sound(0,0,4);
      }

      /* Zeit-Dummys: */
      farbe=ReadPixel(&rp,13L,13L);
      BltBitMap(&schb,SOFF1,SOFF2,&dummyb,0L,0L,SKO3,SKO4,0xc0L,0xffL);
      for(i=0;i<20;i++) ;
   }
}

misbew()

/* Bewegen der Missiles */

{
   int xz,yz,i,k,farbe1,farbe2,flg;
   long zwx1,zwx2,yko;

   miszae1 = ++miszae1 % miszae1max;
   if(miszae1==0) {
      /* Ein Invader darf nur dann schiessen, wenn ueber ihm keiner ist;
      mit invor1 und invor2 werden die Indices, mit invor3 die Anzahl
      der Kandidaten, die fuer den Start eines Misiles in Frage kommen,
      gespeichert*/
      invor3=0;
      for(xz=inligre;xz<=inregre;xz++) {
         for(yz=inungre;yz>=inobgre;yz--) {
            if(invor[xz][yz]>0) {
               break;
            }
         }
         if(yz>=inobgre) {
            invor1[xz]=yz; invor2[invor3]=xz; invor3++;
         }
         else {
            invor1[xz]=-1;
         }
      }
   }
   for(i=0;i<MISANZ[version];i++) {    /* MISANZ ist max. Missile-Anzahl */
      if(mis[i].y>=YA[kick]+VY) {
         mis[i].flag=0;                /* Missile am Rand verschwunden */
      }
      if(mis[i].flag) {                /* Missile unterwegs */
         BltBitMap(&misb,MOFF1,MOFF2+mis[i].phase*MISHEIGHT,&bm2,mis[i].x,
          mis[i].y,MKO3,MKO4,0xc0L,0xffL);
         zwx1=mis[i].x+MHS-MHSDX; zwx2=mis[i].x+MHS+MHSDX; flg=0;
         for(k=0;k<MHSANZ;k++) {       /* Sensitive Punkte der Missiles
                                          auf Kollision abfragen */
            farbe1=ReadPixel(&rp,zwx1,mis[i].y+misyhs[k]);
            farbe2=ReadPixel(&rp,zwx2,mis[i].y+misyhs[k]);
            if(farbe1==7||farbe2==7) {
               flg=7; yko=misyhs[k];   /* Bunkertreffer */
               break;                  /* oberster Wert zaehlt */
            }
            else if(farbe1||farbe2) {  /* Panzertreffer */
               flg=1; yko=misyhs[k];   /* unterster Wert zaehlt*/
            }
         }
         if(flg) {                     /* Treffer  */
            if(flg==7) {               /* Bunker hat Prioritaet ueber
                                          Panzertreffer */
               sound(7,0,1);
               mis[i].flag=0;
               BltPattern(&rp,bsib.Planes[0],mis[i].x+MHS-BIHS,
                mis[i].y-MISD[version]+1L+yko,mis[i].x+MHS-BIHS+BSIWIDTH-1L,
                mis[i].y-MISD[version]+BSIHEIGHT+yko,BPRI);
               RectFill(&rp2,mis[i].x,mis[i].y,mis[i].x+MKO3-1L,
                mis[i].y+MKO4-1L);
            }
            /* Abfrage nur um auszuschliessen, dass ein Invader sich selbst
               abschiesst (beim Herabsetzen des Invaderblocks am Rand) */
            else if(mis[i].y+yko>=eiy && eiphase>=0) {
               sound(1,0,4);           /* Panzertreffer */
               mis[i].flag=0;
               RectFill(&rp2,mis[i].x,mis[i].y,mis[i].x+MKO3-1L,
                mis[i].y+MKO4-1L);
               if(demo==0 && trainer==0)
                  --ship[player];
               SetAPen(&rphi,1L);
               shipanz(playx[player],ship[player]);
               eiphase=-1; eizaemax=STRAFE;
               eibew();
            }
         }
         mis[i].y+=MISD[version]; mis[i].phase=++mis[i].phase%MISPHASEN;
      }
      else {
         rnd1();                        /* zufaellig Missile starten */
         if(rnd<=MISWK[version] && miszae1==0 && invor3!=0) {
            rnd1();                     /* Zufall entscheidet ueber
                                           gezielten Angriff auf Panzer */
            if(rnd<=GEZIELTEWK[version]) {
               xz=(eix+SAX+SHS-inx)/KO1;
               if(xz<inligre)
                  xz=inligre;
               else if(xz>inregre)
                  xz=inregre;
            }
            else {
               rnd1();
               xz=invor2[(long)rnd*invor3/65536L]; /* kein gezielter
                                                      Schuss */
            }
            if((yz=invor1[xz])!=-1) {   /* Missile nur ausloesen,
                                           wenn Invader auch vorhanden */
               sound(4,0,2);
               mis[i].y=KO2[kick]*yz+iny+MAY; mis[i].x=KO1*xz+inx+MAX;
               mis[i].phase=0;                mis[i].flag=1;
            }
         }
         /* Zeit-Dummy */
         for(k=0;k<2*MISANZ[version];k++)
            farbe1=ReadPixel(&rp,0L,0L);
         BltBitMap(&misb,MOFF1,MOFF2,&dummyb,0L,0L,MKO3,MKO4,0xc0L,0xffL);
      }
   }
}    

mistre()

/* Treffer von Schuss auf Missile, kurze Explosion einblenden */

{
   int i,k=0;
   long yko=0;

   for(i=0;i<MISANZ[version];i++) {
      if(mis[i].flag && yko<mis[i].y && mis[i].x+MHS-MHSDX<=schuss.x+SHS &&
       schuss.x+SHS<=mis[i].x+MHS+MHSDX) {
         if(schuss.flag && schuss.y+SCHD[version]<=mis[i].y-MISD[version]+
          misyhs[MHSANZ-1]) {
            yko=mis[i].y; k=i+1;
         }
      }
   }
   if(schx) {
      RectFill(&rp2,schx,schy,MTKO3+schx,MTKO4+schy);
      schx=0;
   }
   if(k) {
      sound(8,0,2);
      k--; mis[k].flag=0;
      RectFill(&rp2,mis[k].x,mis[k].y,mis[k].x+MKO3-1L,mis[k].y+MKO4-1L);
      RectFill(&rp2,schuss.x,schuss.y,schuss.x+SKO3-1L,schuss.y+SKO4-1L);
      schuss.flag=0; schx=schuss.x+SHS-MTHSX; schy=schuss.y-MTHSY;
      BltBitMap(&mistreb,MTOFF1,MTOFF2,&bm2,schx,schy,MTKO3,MTKO4,0xc0L,
       0xffL);
   }
}

mutbew()

/* Mutterschiff bewegen */

{
   if(mutxd) {
      if(mutphase<0)
         /* Explosion des Mutterschiffs*/
         BltBitMap(&mutb,MUTOFF1+mutoff,(-mutphase+MUTPHASEN-1)*MUTHEIGHT+
          MUTOFF2,&bm,mutx,MUTY,MUTKO3,MUTKO4,0xc0L,0xffL);
      else {
         BltBitMap(&mutb,MUTOFF1+mutoff,mutphase*MUTHEIGHT+MUTOFF2,&bm,mutx,
          MUTY,MUTKO3,MUTKO4,0xc0L,0xffL);
         if(mutphase==0) {
            if(mutbewsoundzae==0) {
               sound(10,0,3);
               mutbewsoundzae=MUTBEWSOUNDZAEMAX;
            }
            mutbewsoundzae--;
         }
      }
      mutx+=mutxd;
      if(mutxd<0) {
         if(mutx<=VX-MUTKO3)
            mutxd=0;
         else {
            if(mutphase<0)
               if(mutphase==-MUTEXPPHASEN)
                  mutxd=0;
               else
                  --mutphase;
            else
               mutphase=++mutphase%MUTPHASEN;
         }
      }
      else {
         if (mutx>=XA+VX)
            mutxd=0;          /* am Rand verschwunden */
         else {
            if(mutphase<0)
               if(mutphase==-MUTEXPPHASEN)
                  mutxd=0;
               else
                  --mutphase;
            else
               mutphase=(mutphase+MUTPHASEN-1) % MUTPHASEN;
         }
      }
   }
   else {
      rnd1();                 /* kein Mutterschiff unterwegs */
      if(rnd<=MUTWK) {        /* Zufall entscheidet ueber neues Schiff */
         mutbewsoundzae=0;
         if(rnd%2==0) {
            mutxd=MUTD[version]; mutx=VX-MUTKO3;
         }
         else {
            mutxd=-MUTD[version]; mutx=XA+VX;
         }
         mutphase=0;
         rnd1();
         mutoff=MUTWIDTH*(MUTANZ*rnd/0x10000L);
      }
      /* Dummy */
      BltBitMap(&mutb,MUTOFF1+mutoff,mutphase*MUTHEIGHT+MUTOFF2,
       &dummyb,0L,0L,MUTKO3,MUTKO4,0xc0L,0xffL);
   }
}

fingre()

/* Findet die Grenzen des Invaderblocks, damit sich die Invaders stets bis
zum Rand bewegen, auch wenn mehrere bereits abgeschossen sind. */

{
   int i;

   for(i=inligre;i<inregre;i++)
      if(fingre1(i))
         break;
   inligre=i;
   for(i=inregre;i>inligre;i--)
      if(fingre1(i))
         break;
   inregre=i;
   for(i=inobgre;i<inungre;i++)
      if(fingre2(i))
         break;
   inobgre=i;
   for(i=inungre;i>inobgre;i--)
      if(fingre2(i))
         break;
   inungre=i;
   ligre=aligre-inligre*KO1; regre=aregre-inregre*KO1-KO3+1L;
   ungre=by+BKO4-inungre*KO2[kick]-KO4;
}

fingre1(i)
int i;
{
   int j;

   for(j=inobgre;j<=inungre;j++)
      if(invor[i][j])
         return(1);
   return(0);
}

fingre2(j)
int j;
{
   int i;

   for(i=inligre;i<=inregre;i++)
      if(invor[i][j])
         return(1);
   return(0);
}

inbew()

/* Bewegung der Invaders und Steuerung des Gesamtablaufs */

{
   int i,xv,yv,flag=0;

   eibewsoundzae=0; abschuss=0;
   if(invaderanz==0)      /* Alle schon abgeschossen ? */
      if(demo==0)
         return(KEINE_IN_MEHR);
      else
         return(DEMO);
label:
   for(yv=inobgre;yv<=inungre;yv++) {      /* Alle Invaders bewegen */
      for(xv=inligre;xv<=inregre;xv++) {
         if(invor[xv][yv]) {
            if(invor[xv][yv]>0) {
               BltBitMap(&inb,INEX*(invor[xv][yv]-1)+OFF1,inphase*INEY+OFF2,
                &bm,KO1*xv+inx,KO2[kick]*yv+iny,KO3,KO4,0xc0L,0xffL);
            }
            else {
               /* explodierende Invader */
               BltBitMap(&expb,OFF1,(-invor[xv][yv]-1)*EXPHEIGHT+OFF2,&bm,
                KO1*xv+inx,KO2[kick]*yv+iny,KO3,KO4,0xc0L,0xffL);
               if(invor[xv][yv]==-EXPPHASEN) {
                  invaderanz--; invor[xv][yv]=0;
                  if(invaderanz==0) {
                     if(demo==0)
                        flag=KEINE_IN_MEHR;
                     else
                        flag=DEMO;
                     break;
                  }
                  else
                     fingre();
               }
               else
                  --invor[xv][yv];
            }
            /* Da die Geschwindigkeit der Schuesse, Missiles, usw.
               konstant sein sollen, wird nach jeder Bewegung eines
               Invaders restbew() aufgerufen */
            if(flag=restbew()) {
               break;            /* Panzer getroffen */
            }
         }
      }
      if(flag)
         break;
   }
   if(flag)
      return(flag);
   flag=0;
   for(i=0;i<INBEWVERZ[version];i++) {
   /* damit der letzte Invader etwas gebremst wird */
      if(flag=leer()) {
         break;
      }
   }
   if(inbewsoundzae==0) {
      inbewsound=(inbewsound+1)%3;
      sound(6,inbewsound*30,2);
      inbewsoundzae=INBEWSOUNDZAEMAX;
   }
   inbewsoundzae--; inphase+=inphased;
   if(inphase>0) {
      if(inphase==PHASEN) {
         inphase=0;
      }
   }
   else {
      if(inphase==-1) {
         inphase=PHASEN-1;
      }
   }
   inx+=inxd;
   if ( (inx>regre) || (inx<ligre) ) {
      inxd=-inxd; inx+=inxd; inphased=-inphased;
      RectFill(&rp,inligre*KO1+inx,inobgre*KO2[kick]+iny,
       inregre*KO1+inx+KO3-1L,inungre*KO2[kick]+iny+KO4-1L);
      if(kick || iny+2*INYD[kick] <= ungre)
         RectFill(&rp,VX,inungre*KO2[kick]+KO4+iny,VX+XA,
          iny+INYD[kick]+inungre*KO2[kick]+KO4-1L);
      else
         RectFill(&rp,VX,inungre*KO2[kick]+KO4+iny,VX+XA,
          iny+INYD[kick]+inungre*KO2[kick]+KO4+2L);
      iny+=INYD[kick];
      if (iny>ungre)      /* Invaders schon zu tief ? */
         if(demo==0)
            return(UEBERROLLT);
         else
            return(DEMO);
   }
   if(flag)
      return(flag);
   goto label;
}

restbew()

/* Alles ausser Invaders bewegen, Abfrage der Maustaste (Pause)
Wenn Panzer abgeschossen oder Spiel unterbrochen wurde gibt restbew() einen
entsprechenden Wert zurueck */

{
   int item=1;

   if(demo) {
      time++;
      if(time==DEMOTIME)
         return(DEMO);
      if((ciaa->ciapra & 0x80)==0) {
         while((ciaa->ciapra & 0x80)==0) ;
         return(QUITDEMO);
      }
   }
   if((ciaa->ciapra & 0x40)==0) {      /* Mit linker Maustaste Pause */
      while((ciaa->ciapra & 0x40)==0) ;
      if(demo==0) {
         SetRast(&rphi,3L);
         SetAPen(&rphi,2L); SetBPen(&rphi,3L);
         Move(&rphi,215L,8L); Text(&rphi,"Pause - use joystick !",22L);
         pausanz(0);
         SetAPen(&rphi,1L);
         pausanz(1);
         while(ciaa->ciapra&0x80) {
            if(custom->joy1dat&0x200)
               item=0;
            else if(custom->joy1dat&2)
               item=1;
            SetAPen(&rphi,1L); pausanz(item);
            SetAPen(&rphi,2L); pausanz((item+1)%2);
         }
         while((ciaa->ciapra&0x80)==0) ;
         SetBPen(&rphi,0L);
         titrest();
         if(item==0)
            return(QUIT);
      }
      else {
         return(QUITDEMO);
      }
   }
  /* Die Zaehler (Endung 'zae') sind fuer die Geschwindigkeiten
     verantwortlich */
   mutzae++;
   if(mutzae==MUTZAEMAX[version]) {
      mutzae=0;
      mutbew();
   }
   eizae++;
   if (eizae==eizaemax) {
      eizae=0;
      eibew();
   }
   schzae++;
   if (schzae==SCHZAEMAX[version]) {
      schzae=0;
      schbew();
      mistre();
   }
   miszae++;
   if (miszae==MISZAEMAX[version]) {
      miszae=0;
      misbew();
   }
   if(abschuss) {
      if(demo==0)
         return(ABGESCHOSSEN);
      else
         return(DEMO);
   }
   else
      return(0);
}

leer()

/* Zeitdummy */

{
   /* Zeit-Dummy: */
   BltBitMap(&inb,OFF1,OFF2,&dummyb,0L,0L,KO3,KO4,0xc0L,0xffL);

   return(restbew());
}

pausanz(item)
BYTE item;

/* Pause im Status-Balken anzeigen */

{
   if(item) {
      Move(&rphi,510L,8L); Text(&rphi,"Back to game",12L);
   }
   else {
      Move(&rphi,10L,8L); Text(&rphi,"Quit",4L);
   }
}
