/*	QUADRIX
	written by Kai Karsten
		   Saalestr.7
		   3300 Braunschweig

	Compiler:	Aztec C v3.4
	Options :	cc +l -e300
			ln -lm32 -lc32
*/

#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include <fcntl.h>
#include <functions.h>
#include <exec/types.h>
#include <exec/io.h>
#include <exec/exec.h>
#include <exec/devices.h>
#include <exec/memory.h>
#include <graphics/gfx.h>
#include <graphics/rastport.h>
#include <graphics/copper.h>
#include <graphics/view.h>
#include <graphics/gels.h>
#include <graphics/regions.h>
#include <graphics/clip.h>
#include <graphics/layers.h>
#include <graphics/display.h>
#include <graphics/gfxmacros.h>
#include <graphics/gfxbase.h>
#include <devices/keyboard.h>
#include <devices/inputevent.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <libraries/mathffp.h>
#include <math.h>

#define DUAL1	0
#define DUAL2	1
#define DBUFF1	DUAL1
#define DBUFF2	DUAL2+1

struct View		View;
struct ViewPort		ViewPort;
struct RasInfo		RasInfos[3];
struct BitMap		BitMaps[3];
struct RastPort		RastPorts[3];
struct TmpRas		tmpras;
struct AreaInfo		areainfo;
struct GfxBase		*GfxBase;
struct View		*OldView;
struct cprlist		*LOF[2];
struct IntuitionBase	*IntuitionBase;
struct Window		*DummyWindow;
struct IntuiMessage	*Message;

struct NewWindow FirstNewWindow =
{
 0,0,0,0,0,1,RAWKEY|INACTIVEWINDOW|INTUITICKS,
 NOCAREREFRESH|ACTIVATE|BORDERLESS|BACKDROP,
 NULL,NULL,NULL,NULL,NULL,0,0,0,0,WBENCHSCREEN
};

extern struct ColorMap	*GetColorMap();

UWORD ColorTable[16] = {0x000,0xFFF,0x708,0x50F,
			0x483,0xFA2,0xF72,0xC00,
			0x000,0xFFF,0x708,0x50F,
			0x483,0xFA2,0xF72,0xC00};

UWORD UnvisibleImage[6] =
{
 0,0,0x0000,0x0000,0,0
};

SHORT punktdaten[9][27] =	{
	{1,1, 8,-1,-1, 1,-1, 1, 1,-1, 1},
	{2,1, 8,-2,-1, 2,-1, 2, 1,-2, 1},
	{2,1, 8,-3,-1, 3,-1, 3, 1,-3, 1},
	{2,2,16,-3, 0,-1, 0,-1,-2, 1,-2, 1, 0, 3, 0, 3, 2,-3, 2},
	{2,2,12,-3, 0, 1, 0, 1,-2, 3,-2, 3, 2,-3, 2},
	{2,2,16,-3,-2, 1,-2, 1, 0, 3, 0, 3, 2,-1, 2,-1, 0,-3, 0},
	{2,2, 8,-2,-2, 2,-2, 2, 2,-2, 2},
	{2,2,24,-3,-1,-1,-1,-1,-3, 1,-3, 1,-1, 3,-1, 3, 1, 1, 1, 1, 3,-1, 3,-1, 1,-3, 1},
	{2,2,16,-3,-2,-1,-2,-1, 0, 1, 0, 1,-2, 3,-2, 3, 2,-3, 2}
				};

SHORT cubedaten[9][11] =	{
	{1, 0, 0},
	{2,-1, 0, 1, 0},
	{3,-2, 0, 0, 0, 2, 0},
	{4,-2, 1, 0, 1, 2, 1, 0,-1},
	{4, 2,-1,-2, 1, 0, 1, 2, 1},
	{4,-2,-1, 0,-1, 0, 1, 2, 1},
	{4,-1,-1,-1, 1, 1,-1, 1, 1},
	{5, 0, 0,-2, 0, 0,-2, 2, 0, 0, 2},
	{5,-2,-1,-2, 1, 0, 1, 2, 1, 2,-1},
				};

SHORT scoredaten[9] = {10,50,100,250,200,300,150,500,400};

SHORT perspektive[13] = {10,12,14,16,18,20,23,26,30,34,39,44,51};

UWORD BUFF[2]={DBUFF1,DBUFF2};

PLANEPTR mem;
LONG timer,intervall,planes,bricks,score,pause,sec,micsec;
WORD areabuffer[250];
UWORD koordx[6][6][13];
UWORD koordy[6][6][13];
BOOL  cube[5][5][12],draw,gameover,fillkoerper,exitgame,trig1=0,trig2=0;
SHORT p[2][2][24][3],liniendaten[9][73],plane[12];
SHORT xort,yort,zort,panz,lanz,canz,nummer,maxheight;
DOUBLE ran();

ClearKoerperData()
{
 SHORT i,j;

 for(i=0;i<24;i++)
  for(j=0;j<3;j++)
    p[0][0][i][j]=p[0][1][i][j]=p[1][0][i][j]=p[1][1][i][j]=0;
}

ClearCubesData()
{
 SHORT i,j,k;

 timer=maxheight=planes=score=0;
 bricks=1;
 intervall = pause = 50;
 gameover = draw = FALSE;

 for(i=0;i<5;i++)
  for(j=0;j<5;j++)
   for(k=0;k<12;k++)
    cube[i][j][k]=FALSE;
 for(i=0;i<12;i++)
  plane[i]=0;
}

ReadKoerperData()
{
 SHORT i;

 xort=punktdaten[nummer][0]+4;
 yort=punktdaten[nummer][1]+4;
 zort=23;
 panz=punktdaten[nummer][2];
 lanz=liniendaten[nummer][0];
 canz=cubedaten[nummer][0];
 for(i=0;i<panz;i+=2)
 {
  p[0][trig2][i][0]=p[0][trig2][i+1][0]=punktdaten[nummer][i+3];
  p[0][trig2][i][1]=p[0][trig2][i+1][1]=punktdaten[nummer][i+4];
  p[0][trig2][i][2]=-1;
  p[0][trig2][i+1][2]=1;
  p[1][trig2][i>>1][0]=cubedaten[nummer][i+1];
  p[1][trig2][i>>1][1]=cubedaten[nummer][i+2];
  p[1][trig2][i>>1][2]=0;
 }
}

RotateKoerper(achse,rchtg)
SHORT achse,rchtg;
{
 BOOL MoveDown = FALSE;
 SHORT i,x,y,z,px,py,pz,cx,cy,cz;

 draw = TRUE;
 for(i=0;i<panz;i++)
 {
  px=p[0][trig2][i][0];
  py=p[0][trig2][i][1];
  pz=p[0][trig2][i][2];
  cx=p[1][trig2][i][0];
  cy=p[1][trig2][i][1];
  cz=p[1][trig2][i][2];

  switch(achse)
  {
   case 1:
	p[0][trig2^1][i][0]=px;			/* x-Achse */
	p[0][trig2^1][i][1]=rchtg*pz;
	p[0][trig2^1][i][2]=-rchtg*py; 
	p[1][trig2^1][i][0]=cx;
	p[1][trig2^1][i][1]=rchtg*cz;
	p[1][trig2^1][i][2]=-rchtg*cy; 
	break;
   case 2:
	p[0][trig2^1][i][0]=rchtg*pz;		/* y-Achse */
	p[0][trig2^1][i][1]=py;
	p[0][trig2^1][i][2]=-rchtg*px;
	p[1][trig2^1][i][0]=rchtg*cz;
	p[1][trig2^1][i][1]=cy;
	p[1][trig2^1][i][2]=-rchtg*cx; 
	break;
   case 3:
	p[0][trig2^1][i][0]=rchtg*py;		/* z-Achse */
	p[0][trig2^1][i][1]=-rchtg*px;
	p[0][trig2^1][i][2]=pz;
	p[1][trig2^1][i][0]=rchtg*cy;
	p[1][trig2^1][i][1]=-rchtg*cx;
	p[1][trig2^1][i][2]=cz; 
	break;   
  }
  if(i<canz)
  {
   x=(xort+p[1][trig2^1][i][0]-1)>>1;
   y=(yort+p[1][trig2^1][i][1]-1)>>1;
   z=(zort+p[1][trig2^1][i][2]-1)>>1;
   if(x<0) xort+=2;
   if(x>4) xort-=2;
   if(y<0) yort+=2;
   if(y>4) yort-=2;
   if(z>11)
   {
    if(fillkoerper == FALSE)	MoveDown = TRUE;
    else			return;
   }
   if(x>=0 && x<=4 && y>=0 && y<=4 && z<=11) 
    if(cube[x][y][z] == TRUE) return;
  }
 }
 trig2^=1;
 if(MoveDown == TRUE)
 {
  zort-=2;
  MoveKoerper(0,0);
 }
}

MoveKoerper(xmove,ymove)
SHORT xmove,ymove;
{
 SHORT i,j,x,y,z;
 BOOL cubenotfree;

 draw = TRUE;
 for(i=1;i>=0;i--)
 {
  fillkoerper=cubenotfree=FALSE;
  for(j=0;j<canz;j++)
  {
   x=(xort+i*xmove+p[1][trig2][j][0]-1)>>1;
   y=(yort+i*ymove+p[1][trig2][j][1]-1)>>1;
   z=(zort+p[1][trig2][j][2]-1)>>1;
   if(x<0 || x>4 || y<0 || y>4 || cube[x][y][z]==TRUE ) cubenotfree = TRUE;
   if(z==0 || cube[x][y][z-1]==TRUE) fillkoerper = TRUE;
  }
  if(!cubenotfree) return i*2;
 }
}

DrawKoerper()
{
 SHORT i,p1,p2,kx1[36],ky1[36],kz1[36],kx2[36],ky2[36],kz2[36];

 for(i=0;i<lanz;i++)
 {
  p1=liniendaten[nummer][(i<<1)+1]-1;
  p2=liniendaten[nummer][(i<<1)+2]-1;
  kx1[i]=(p[0][trig2][p1][0]+xort)>>1;
  ky1[i]=(p[0][trig2][p1][1]+yort)>>1;
  kz1[i]=(p[0][trig2][p1][2]+zort)>>1;
  kx2[i]=(p[0][trig2][p2][0]+xort)>>1;
  ky2[i]=(p[0][trig2][p2][1]+yort)>>1;
  kz2[i]=(p[0][trig2][p2][2]+zort)>>1;
  Move(&RastPorts[BUFF[trig1]],koordx[kx1[i]][ky1[i]][kz1[i]],koordy[kx1[i]][ky1[i]][kz1[i]]);
  Draw(&RastPorts[BUFF[trig1]],koordx[kx2[i]][ky2[i]][kz2[i]],koordy[kx2[i]][ky2[i]][kz2[i]]);
 }
 SwitchScreen(&View);
 draw = FALSE;
}

ChooseNewKoerper()
{
 nummer = (int)(ran()*9);
 ClearKoerperData();
 ReadKoerperData();
 MoveKoerper(0,0);
 DrawKoerper();
}

FillKoerper()
{
 SHORT i,x,y,z,zmax=0,zmin=11;

 for(i=0;i<canz;i++)
 {
  x=(xort+p[1][trig2][i][0]-1)>>1;
  y=(yort+p[1][trig2][i][1]-1)>>1;
  z=(zort+p[1][trig2][i][2]-1)>>1;
  plane[z]++;
  cube[x][y][z]=TRUE;
  if(z>zmax) zmax=z;
  if(z<zmin) zmin=z;
 }
 if(zmax>maxheight) maxheight=zmax;
 DrawCubes(zmin,maxheight);
 for(i=11;i>=0;i--)
  if(plane[i] == 25) KillPlane(i);
 WriteNumber(++bricks,225,2);
 WriteNumber(score+=scoredaten[nummer],75,5);
 intervall = pause;
}

DrawCubes(von,bis)
SHORT von,bis;
{
 SHORT color,i,j,k;

 for(i=von;i<bis+1;i++)
 {
  color = (i>5) ? (i-4) : (i+2);
  SetAPen(&RastPorts[DUAL2],color);
  for(j=0;j<5;j++)
   for(k=0;k<5;k++)
    if(cube[j][k][i] == TRUE)
    {
     if(j>2 && cube[j-1][k][i] == FALSE)
     {
      AreaMove(&RastPorts[DUAL2],koordx[j][k][i+1],koordy[j][k][i+1]);
      AreaDraw(&RastPorts[DUAL2],koordx[j][k+1][i+1],koordy[j][k+1][i+1]);
      AreaDraw(&RastPorts[DUAL2],koordx[j][k+1][i],koordy[j][k+1][i]);
      AreaDraw(&RastPorts[DUAL2],koordx[j][k][i],koordy[j][k][i]);
      AreaEnd(&RastPorts[DUAL2]);
     }
     if(k>2 && cube[j][k-1][i] == FALSE)
     {
      AreaMove(&RastPorts[DUAL2],koordx[j][k][i+1],koordy[j][k][i+1]);
      AreaDraw(&RastPorts[DUAL2],koordx[j+1][k][i+1],koordy[j+1][k][i+1]);
      AreaDraw(&RastPorts[DUAL2],koordx[j+1][k][i],koordy[j+1][k][i]);
      AreaDraw(&RastPorts[DUAL2],koordx[j][k][i],koordy[j][k][i]);
      AreaEnd(&RastPorts[DUAL2]);
     }
     if(j<2 && cube[j+1][k][i] == FALSE)
     {
      AreaMove(&RastPorts[DUAL2],koordx[j+1][k][i+1],koordy[j+1][k][i+1]);
      AreaDraw(&RastPorts[DUAL2],koordx[j+1][k+1][i+1],koordy[j+1][k+1][i+1]);
      AreaDraw(&RastPorts[DUAL2],koordx[j+1][k+1][i],koordy[j+1][k+1][i]);
      AreaDraw(&RastPorts[DUAL2],koordx[j+1][k][i],koordy[j+1][k][i]);
      AreaEnd(&RastPorts[DUAL2]);
     }
     if(k<2 && cube[j][k+1][i] == FALSE)
     {
      AreaMove(&RastPorts[DUAL2],koordx[j][k+1][i+1],koordy[j][k+1][i+1]);
      AreaDraw(&RastPorts[DUAL2],koordx[j+1][k+1][i+1],koordy[j+1][k+1][i+1]);
      AreaDraw(&RastPorts[DUAL2],koordx[j+1][k+1][i],koordy[j+1][k+1][i]);
      AreaDraw(&RastPorts[DUAL2],koordx[j][k+1][i],koordy[j][k+1][i]);
      AreaEnd(&RastPorts[DUAL2]);
     }
    }
  for(j=0;j<5;j++)
   for(k=0;k<5;k++)
    if(cube[j][k][i] == TRUE) 
     RectFill(&RastPorts[DUAL2],koordx[j][k][i+1],koordy[j][k][i+1],koordx[j+1][k+1][i+1],koordy[j+1][k+1][i+1]);
 }
 SwitchScreen(&View);
}

KillPlane(nr)
SHORT nr;
{
 SHORT i,j,k;

 if(nr<11)
  for(i=nr+1;i<12;i++)
  {
   plane[i-1]=plane[i];
   for(j=0;j<5;j++)
    for(k=0;k<5;k++)
     cube[j][k][i-1]=cube[j][k][i];
  }
 plane[11]=0;
 for(i=0;i<5;i++)
  for(j=0;j<5;j++)
   cube[i][j][11] = FALSE;
 Delay(30L);
 WriteNumber(++planes,175,7);
 WriteNumber(score+=1000,75,5);
 DrawBackground();
 DrawCubes(0,10);
}

DrawBackground()
{
 SHORT i;

 SetAPen(&RastPorts[DUAL2],0);
 RectFill(&RastPorts[DUAL2],0,0,255,255);
 SetAPen(&RastPorts[DUAL2],1);
 SetDrPt(&RastPorts[DUAL2],0x8888);
 for(i=0;i<5;i++)
 {
  Move(&RastPorts[DUAL2],0,i*51);
  Draw(&RastPorts[DUAL2],127-25,127-25+i*10);
  Draw(&RastPorts[DUAL2],127+25,127-25+i*10);
  Draw(&RastPorts[DUAL2],254,i*51);
  Move(&RastPorts[DUAL2],i*51,0);
  Draw(&RastPorts[DUAL2],127-25+i*10,127-25);
  Draw(&RastPorts[DUAL2],127-25+i*10,127+25);
  Draw(&RastPorts[DUAL2],i*51,254);
 }
 Move(&RastPorts[DUAL2],127+25,127+25);
 Draw(&RastPorts[DUAL2],254,254);
 for(i=0;i<13;i++)
  DrawSquare(perspektive[i]*5);
 SetDrPt(&RastPorts[DUAL2],0xFFFF);
 SetOPen(&RastPorts[DUAL2],0);
}

DrawScoreBoard()
{
 SetAPen(&RastPorts[DUAL2],3);
 RectFill(&RastPorts[DUAL2],258,0,319,254);
 SetAPen(&RastPorts[DUAL2],0);
 RectFill(&RastPorts[DUAL2],260,2,317,252);
 WriteText("Quadrix",6,260,20);
 WriteText("score",4,268,60);
 WriteNumber(score,75,5);
 WriteText("delay",4,268,110);
 WriteNumber(pause*2,125,6);
 WriteText("planes",4,264,160);
 WriteNumber(planes,175,7);
 WriteText("bricks",4,264,210);
 WriteNumber(bricks,225,2);
}

GameOver(delay)
LONG delay;
{
 gameover = TRUE;
 Delay(delay);
 SetAPen(&RastPorts[DUAL2],3);
 RectFill(&RastPorts[DUAL2],10,50,245,205);
 SetAPen(&RastPorts[DUAL2],0);
 RectFill(&RastPorts[DUAL2],13,53,242,202);
 WriteText("Quadrix",6,103,70);
 WriteText("© 1990 by K.Karsten",7,50,85);
 WriteText("ESC         = Ende",4,20,110);
 WriteText("SPACE       = Start",4,20,130);
 WriteText("CURSORKEYS  = Move Object",4,20,150);
 WriteText("NUMERIC PAD = Rotate Object",4,20,170);
 WriteText("ENTER       = Drop Object",4,20,190);
}

WriteText(text,color,x,y)
SHORT color,x,y;
TEXT text[];
{
 SHORT len;

 len=strlen(&text[0]);
 SetAPen(&RastPorts[DUAL2],1);
 SetDrMd(&RastPorts[DUAL2],JAM2);
 Move(&RastPorts[DUAL2],x,y);
 Text(&RastPorts[DUAL2],&text[0],len);
 SetAPen(&RastPorts[DUAL2],color);
 SetDrMd(&RastPorts[DUAL2],JAM1);
 Move(&RastPorts[DUAL2],x+1,y+1);
 Text(&RastPorts[DUAL2],&text[0],len);
}

WriteNumber(num,y,color)
SHORT y,color;
LONG num;
{
 SHORT len;
 TEXT zahl[8];

 ItoA(num,zahl);
 WriteText(&zahl[0],color,264,y);
}

ItoA(n,s)
register LONG n;
register TEXT *s;
{
 register SHORT i;

 for(i=0;i<6;i++)
  s[i]='0';
 i=0;
 do
  s[i++] = n % 10 +'0';
 while(n /= 10);
 s[6] = '\0';
 Reverse(s);
}

Reverse(s)
register TEXT *s;
{
 register SHORT c,i,j;

 for(i=0,j=strlen(s)-1;i<j;i++,j--)
 {
  c=s[i];
  s[i]=s[j];
  s[j]=c;
 }
}

DrawSquare(a)
SHORT a;
{
 a>>=1;
 Move(&RastPorts[DUAL2],127-a,127-a);
 Draw(&RastPorts[DUAL2],127+a,127-a);
 Draw(&RastPorts[DUAL2],127+a,127+a);
 Draw(&RastPorts[DUAL2],127-a,127+a);
 Draw(&RastPorts[DUAL2],127-a,127-a); 
}

SwitchScreen(View)
struct View *View;
{
 View->LOFCprList = LOF[trig1];
 trig1^=1;
 SetRast (&RastPorts[BUFF[trig1]],0);
 LoadView(View);
 WaitTOF();
}

InitKoord()
{
 SHORT a,b,c,i,j,k;

 for(i=0;i<13;i++)
 {
  a=perspektive[i]*5;
  for(j=0;j<6;j++)
  {
   b=127-a/2+j*(a/5);
   for(k=0;k<6;k++)
   {
    c=127-a/2+k*(a/5);
    koordx[j][k][i]=b;
    koordy[j][k][i]=c;
   }
  }
 }
}

InitLinienDaten()
{
 SHORT i,j,anz;

 for(i=0;i<9;i++)
 {
  anz=punktdaten[i][2];
  liniendaten[i][0] = anz/2*3;
  for(j=1;j < anz+1;j++)
   liniendaten[i][j]=j;
  for(j=0;j < anz;j+=2)
  {
   liniendaten[i][j+anz+1]=j+1;
   liniendaten[i][j+anz+2]=j+3;
   liniendaten[i][j+anz*2+1]=j+2;
   liniendaten[i][j+anz*2+2]=j+4;
  }
  liniendaten[i][anz*2]=1;
  liniendaten[i][anz*3]=2;
 }
}

InitDisplay()
{
 SHORT i,j;

 if ((!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",0))) ||
     (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",0))) ||
     (!(DummyWindow = (struct Window *) OpenWindow(&FirstNewWindow))))
      FreeMemory2();

 OldView = GfxBase -> ActiView;
 InitView(&View);
 InitVPort(&ViewPort);
 View.ViewPort	= &ViewPort;
 InitBitMap(&BitMaps[DUAL1],3,320,256);
 InitBitMap(&BitMaps[DUAL2],3,320,256);
 InitBitMap(&BitMaps[DBUFF2],3,320,256);
 for(i=0;i<3;i++)
 {
  RasInfos[i].BitMap 	= &BitMaps[i];
  RasInfos[i].RxOffset	= 0;
  RasInfos[i].RyOffset	= 0;
  RasInfos[i].Next	= NULL;
 }
 ViewPort.DxOffset	= 0;
 ViewPort.DyOffset	= 0;
 ViewPort.DWidth	= 320;
 ViewPort.DHeight	= 256;
 ViewPort.RasInfo	= &RasInfos[DUAL1];
 ViewPort.Modes		= DUALPF;
 ViewPort.Next		= NULL;
 if(!(ViewPort.ColorMap=GetColorMap(16))) FreeMemory2();
 RasInfos[DUAL1].Next	= &RasInfos[DUAL2];
 LoadRGB4(&ViewPort,&ColorTable[0],16);
 for(i=0;i<3;i++)
 {
  if((!(BitMaps[0].Planes[i]=(PLANEPTR)AllocRaster(320,256))) ||
     (!(BitMaps[1].Planes[i]=(PLANEPTR)AllocRaster(320,256))) ||
     (!(BitMaps[2].Planes[i]=(PLANEPTR)AllocRaster(320,256))))
      FreeMemory2();

  BltClear((UBYTE *)BitMaps[0].Planes[i],RASSIZE(320,256),0);
  BltClear((UBYTE *)BitMaps[1].Planes[i],RASSIZE(320,256),0);
  BltClear((UBYTE *)BitMaps[2].Planes[i],RASSIZE(320,256),0);
 }
 if(!(mem=(PLANEPTR)AllocRaster(320,256))) FreeMemory2();
 BltClear((UBYTE *)mem,RASSIZE(320,256),0);
 InitTmpRas(&tmpras,mem,RASSIZE(320,256));
 for(i=0;i<3;i++)
 {
  InitRastPort(&RastPorts[i]);
  RastPorts[i].BitMap	= &BitMaps[i];
  RastPorts[i].AreaInfo	= &areainfo;
  RastPorts[i].TmpRas	= &tmpras; 
 }
 MakeVPort(&View,&ViewPort);
 MrgCop(&View);
 LOF[0] = View.LOFCprList;
 ViewPort.RasInfo	= &RasInfos[DBUFF2];
 RasInfos[DBUFF2].Next	= &RasInfos[DUAL2];
 View.LOFCprList = NULL;
 View.SHFCprList = NULL;
 MakeVPort(&View,&ViewPort);
 MrgCop(&View);
 LOF[1] = View.LOFCprList;
 InitArea(&areainfo,areabuffer,100);
 SetPointer(IntuitionBase->ActiveWindow,&UnvisibleImage[0],1,15,0,0);
 SetAPen(&RastPorts[BUFF[0]],1);
 SetAPen(&RastPorts[BUFF[1]],1);
}

FreeMemory1()
{
 FreeVPortCopLists(&ViewPort);
 FreeCprList(LOF[0]);
 FreeCprList(LOF[1]);
 FreeMemory2();
}

FreeMemory2()
{
 SHORT i;

 ClearPointer(IntuitionBase->ActiveWindow);

 for(i=0;i<3;i++)
 {
  if(BitMaps[DUAL1].Planes[i]) FreeRaster(BitMaps[DUAL1].Planes[i],320,256);
  if(BitMaps[DUAL2].Planes[i]) FreeRaster(BitMaps[DUAL2].Planes[i],320,256);
  if(BitMaps[DBUFF2].Planes[i])FreeRaster(BitMaps[DBUFF2].Planes[i],320,256);
 }
 if (mem)		FreeRaster(mem,320,256);
 if (ViewPort.ColorMap)	FreeColorMap(ViewPort.ColorMap);
 if (DummyWindow)	CloseWindow(DummyWindow);
 if (IntuitionBase)	CloseLibrary(IntuitionBase);
 if (GfxBase)		CloseLibrary(GfxBase);
}

main()
{
 USHORT Code;
 ULONG MessageClass,s,ms;
 struct Message *GetMsg();
 
 exitgame = FALSE;

 InitKoord();
 InitLinienDaten();
 ClearCubesData();
 InitDisplay();
 DrawBackground();
 DrawScoreBoard();
 SwitchScreen(&View);
 GameOver(0L);

 while(!exitgame)
 {
  if(!(Message=(struct IntuiMessage *) GetMsg(DummyWindow->UserPort)))
  {
   Wait(1L<<DummyWindow->UserPort->mp_SigBit);
   continue;
  }
  MessageClass=Message->Class;
  Code=Message->Code;
  ReplyMsg(Message);
  switch(MessageClass)
  {
   case	RAWKEY:
	if(!gameover)
        {
	 switch(Code)
	 {
	  case	0x43:
		intervall=0;
		break;
	  case	0x4f:
		xort-=MoveKoerper(-2, 0);
		break;
	  case	0x4c:
		yort-=MoveKoerper( 0,-2);
		break;
	  case	0x4d:
		yort+=MoveKoerper( 0, 2);
		break;
	  case	0x4e:
		xort+=MoveKoerper( 2, 0);
		break;
	  case	0x1e:
		RotateKoerper( 1, 1);
		break;
	  case	0x3e:
		RotateKoerper( 1,-1);
		break;
	  case	0x2f:
		RotateKoerper( 2, 1);
		break;
	  case	0x2d:
		RotateKoerper( 2,-1);
		break;
	  case	0x1d:
		RotateKoerper( 3, 1);
		break;
	  case	0x3f:
		RotateKoerper( 3,-1);
		break;
	 }
	 if(draw) DrawKoerper();
        }
        else
        {
         switch(Code)
         {
          case	0x45:
		exitgame = TRUE;
		break;
	  case  0x40:
		gameover = FALSE;
		ClearCubesData();
		DrawBackground();
		DrawScoreBoard();
		ChooseNewKoerper();
                CurrentTime(&sec,&micsec);
		break;
         }
        }
	break;

   case INACTIVEWINDOW:
	ActivateWindow(DummyWindow);
	break;

   case INTUITICKS:
        if(!gameover)
        {
         CurrentTime(&s,&ms);
         if((s-sec) > 45 && pause > 5)
         {
          sec = s;
          pause = pause-(pause/10)-1;
          if(intervall) intervall = pause;
          WriteNumber(pause*2,125,6);
         }
	 timer++;
	 if(timer >= intervall)
	 {
	  if(fillkoerper == TRUE) 
	  {
	   FillKoerper();
	   if(zort == 23)	GameOver(200L);
	   else			ChooseNewKoerper();
	  }
	  else 
	  {
	   zort-=2;
	   MoveKoerper(0,0);
	   DrawKoerper();
	  }
	  timer=0;
	 }
        }
        else
         ran();
	break;
  } 
 }
 LoadView(OldView);
 FreeMemory1();
}
