#include <exec/types.h>
#include <stdio.h>
#include <intuition/intuitionbase.h>
#include <libraries/diskfont.h>
#include <libraries/dos.h>

#define AB 200.0  /*Abstand Auge - Bildschirm*/
#define XX 150.0  /*Breite halber Bildschirm*/
#define YY 60.0  /*Höhe -"- */

#define B1 20 /*10*/
#define B2 12
#define B3 620 /*310*/ 
#define B4 132

/* BYTE line(Farbe,x1,y1,z1,x2,y2,z2);
   BYTE polygon(Farbe,Eckzahl,Liste); wobei float *Liste
   BYTE MausKlick()
   ToFront();
   void bridge();

   BltBitMap(&GScreen->BitMap,B1,B2,&Screen->BitMap,B1,B2,B3-B1,B4-B2,
            0xc0,0xf,areabuffer);

*/
   
extern LONG OpenLibrary();
extern struct Screen *OpenScreen();
extern float sin(),cos();
extern struct Screen *Screen, *GScreen,*GScreenB;
extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;

float eabs(x)
float x;
{ if(x<0) x*=-1.0;
  return(x);
}   

struct AreaInfo areainfo;
WORD areabuffer[250];
struct TmpRas tmp;
WORD *Raster;

#define pi2 6.28318

float tsin[360],tcos[360];

BYTE *cia=(BYTE*)0xbfe001;
BYTE MausKlick()
{  BYTE i;
   i=!((*cia)&64);
   return(i);
}

int runden(a)
float a;
{ int r;
  r=(int)a;
  if(a>0.0)
  { if( a-(float)r >= 0.5 ) return(r+1); }
  if(a<0.0)
  { if( (float)r-a >= 0.5 ) return(r-1); }
  return(r);
}


float A[4][4];    /* globale Abbildungsmatrix */
float x,y,z;    /* Position des Betrachters */
int xy,xz,yz;  /* Drehwinkel in den Ebenen 0-359 */

void MatrixBau() /*erstellt an Hand dieser Daten eine Trafo A*/
{  static float B[3][3],C[3][3],D[3][3];
   static BYTE first=1;
   int i,j,k,l;

   if(first) /* zunächst Matrizen initialisieren*/
   { for(i=0;i<3;i++)
     { for(j=0;j<i;j++)
         B[i][j]=C[i][j]=D[i][j]=0.0;
       B[i][i]=C[i][i]=D[i][i]=1.0;
       for(j=i+1;j<3;j++)
         B[i][j]=C[i][j]=D[i][j]=0.0;
       A[3][i]=0.0;
     };
     A[3][3]=1.0;
     first=0;
   }
   B[1][1]=tcos[yz]; B[1][2]=-tsin[yz];
   B[2][1]=tsin[yz]; B[2][2]=tcos[yz];
   C[0][0]=tcos[xz]; C[0][2]=-tsin[xz];
   C[2][0]=tsin[xz]; C[2][2]=tcos[xz];
   D[0][0]=tcos[xy]; D[0][1]=-tsin[xy];
   D[1][0]=tsin[xy]; D[1][1]=tcos[xy];
   /* zusammenmultiplizieren */
   for(j=0;j<3;j++)
     for(i=0;i<3;i++)
     { A[j][i]=0.0;
       for(k=0;k<3;k++)
         for(l=0;l<3;l++)
           A[j][i]+=B[j][k]*C[k][l]*D[l][i];
     }
   for(i=0;i<3;i++)
     A[i][3]=-A[i][0]*x-A[i][1]*y-A[i][2]*z;
}

/* Routine zum 3D-Clippen, Abbilden und Zeichnen einer Fläche */

BYTE innen(j,p)
int j;
float *p;
{  BYTE k;
   switch(j)
   {  case 0 : k=-YY*(*p)>=AB*(*(p+2));break;
      case 1 : k=YY*(*p)<=AB*(*(p+2)); break;
      case 2 : k=-XX*(*p)>=AB*(*(p+1));break;
      case 3 : k=XX*(*p)<=AB*(*(p+1)); break;
   }
   return(k);
}

void ToFront()
{  extern struct Screen *Screens[];
   struct Screen *merke;
   int i=0;
   while(Screens[i]) ScreenToBack(Screens[i++]);
   ScreenToBack(GScreenB);
   merke=GScreen;
   GScreen=GScreenB;
   GScreenB=merke;
}

void ScrollFront()
{  int i;
   struct Screen *merke;
   WBenchToBack();
   for(i=0;i<26;i++)
     MoveScreen(GScreenB,0,5);
   ScreenToBack(GScreenB);
   MoveScreen(GScreenB,0,-26*5);
   merke=GScreen;
   GScreen=GScreenB;
   GScreenB=merke;
}     

BYTE polygon(color,no,list)
BYTE color;
int no; /* color : Farbe der Fläche, no = Anzahl der Ecken (>= 3) */
float *list;   /* list = Koordinatenliste */
{  float u,*anfang,*lauf,*lp,lx,ly,lz;
   BYTE is,in;
   int nr; /*aktuelle Eckenzahl*/
   int j,i,x2d,y2d;
   static float puffer1[100],puffer2[100];

   lauf=anfang=list;
   lp=puffer1;
   for(j=0;j<4;j++)
   { nr=0;
     if(innen(j,lauf)) /* erster Punkt innen */
     { is=in=1; nr++;
       lx=*lp++=*lauf++; ly=*lp++=*lauf++; lz=*lp++=*lauf++;
     }
     else
     { is=in=0; lx=*lauf++; ly=*lauf++; lz=*lauf++; }

     for(i=1;i<no;i++) /* Alle Ecken durchgehen */
     { if(innen(j,lauf)) /* Punkt innen */
       { if(in) /*letzter war auch schon drin*/
         { nr++;
           lx=*lp++=*lauf++; ly=*lp++=*lauf++; lz=*lp++=*lauf++;
         }
         else /* letzter war nicht drin*/
         { in=1;
           /* Berechnung des Schnittpkts der Ebene mit der letzten Strecke*/
           switch(j)
           {  case 0 : u=(YY*lx+AB*lz)/((lx-(*lauf))*YY+AB*(lz-*(lauf+2)));break;
              case 1 : u=(-YY*lx+AB*lz)/(((*lauf)-lx)*YY+AB*(lz-*(lauf+2)));break;
              case 2 : u=(XX*lx+AB*ly)/((lx-(*lauf))*XX+AB*(ly-*(lauf+1)));break;
              case 3 : u=(-XX*lx+AB*ly)/((*lauf-lx)*XX+AB*(ly-*(lauf+1)));break;
           }
           nr+=2;
           *lp++=lx+u*((*lauf)  -lx);
           *lp++=ly+u*(*(lauf+1)-ly);
           *lp++=lz+u*(*(lauf+2)-lz);
           lx=*lp++=*lauf++; ly=*lp++=*lauf++; lz=*lp++=*lauf++;
         }
       }
       else
       { if(in)
         { in=0;
           switch(j)
           {  case 0 : u=(YY*lx+AB*lz)/((lx-(*lauf))*YY+AB*(lz-*(lauf+2)));break;
              case 1 : u=(-YY*lx+AB*lz)/(((*lauf)-lx)*YY+AB*(lz-*(lauf+2)));break;
              case 2 : u=(XX*lx+AB*ly)/((lx-(*lauf))*XX+AB*(ly-*(lauf+1)));break;
              case 3 : u=(-XX*lx+AB*ly)/((*lauf-lx)*XX+AB*(ly-*(lauf+1)));break;
           }
           nr++;
           *lp++=lx+u*(*lauf    -lx);
           *lp++=ly+u*(*(lauf+1)-ly);
           *lp++=lz+u*(*(lauf+2)-lz);

         }
         lx=*lauf++; ly=*lauf++; lz=*lauf++;
       }
     }
     /* Schließen des Polygons */
     if(((!in)&&is)||(in&&(!is))) /* letzter außen, erster innen oder umgk.*/
     {  switch(j)
        {  case 0 : u=(YY*lx+AB*lz)/((lx-(*anfang))*YY+AB*(lz-*(anfang+2)));break;
           case 1 : u=(-YY*lx+AB*lz)/(((*anfang)-lx)*YY+AB*(lz-*(anfang+2)));break;
           case 2 : u=(XX*lx+AB*ly)/((lx-(*anfang))*XX+AB*(ly-*(anfang+1)));break;
           case 3 : u=(-XX*lx+AB*ly)/((*anfang-lx)*XX+AB*(ly-*(anfang+1)));break;
        }
        nr++;
        *lp++=lx+u*(*anfang    -lx);  lx=*anfang;
        *lp++=ly+u*(*(anfang+1)-ly);  ly=*(anfang+1);
        *lp  =lz+u*(*(anfang+2)-lz);  lz=*(anfang+2);
     }
     if(nr<3) return(0); /* Fläche degeneriert */
     no=nr;
     if((j==0)||(j==2))
     { lauf=anfang=puffer1;
       lp=puffer2;
     }
     else
     { lauf=anfang=puffer2;
       lp=puffer1;
     }
   }

   /*jetzt ist die Fläche voll in der Sichtpyramide...*/
   InitArea(&areainfo,areabuffer,100);
   GScreen->RastPort.AreaInfo=&areainfo;
   SetAPen(&(GScreen->RastPort),color);
   lauf=puffer2;
   for(i=0;i<nr;i++)   /* zeichnen !*/
   {  if(eabs(*lauf)<0.0001)
        x2d=y2d=0;
      else
      { x2d=runden(-*(lauf+1)*AB/(*lauf));
        y2d=runden(-*(lauf+2)*AB/(*lauf));
      }
      lauf+=3;
      if(i==0)
        AreaMove(&(GScreen->RastPort),320+(x2d*2),72-y2d);
      else
        AreaDraw(&(GScreen->RastPort),320+(x2d*2),72-y2d);
   }
   AreaEnd(&(GScreen->RastPort));
   return(1);
}

BYTE line(color,x1,y1,z1,x2,y2,z2)
int color;
float x1,y1,z1,x2,y2,z2;
{  float u;
   int j,x2d,y2d;
   BYTE i1,i2;

   /* Clippen an allen Ebenen :*/

   for(j=0;j<4;j++)
   { switch(j)
     { case 0 : i1=(-YY*x1>=AB*z1); i2=(-YY*x2>=AB*z2); break;
       case 1 : i1=(YY*x1<=AB*z1);  i2=(YY*x2<=AB*z2);  break;
       case 2 : i1=(-XX*x1>=AB*y1); i2=(-XX*x2>=AB*y2); break;
       case 3 : i1=(XX*x1<=AB*y1);  i2=(XX*x2<=AB*y2);  break;
     }
     if((!i1)&&(!i2)) return(0); /*Linie außerhalb*/
     if((!i1)||(!i2)) /* nicht beide innen */
     { switch(j)
       {  case 0 : u=(YY*x1+AB*z1)/((x1-x2)*YY+AB*(z1-z2)); break;
          case 1 : u=(-YY*x1+AB*z1)/((x2-x1)*YY+AB*(z1-z2));break;
          case 2 : u=(XX*x1+AB*y1)/((x1-x2)*XX+AB*(y1-y2)); break;
          case 3 : u=(-XX*x1+AB*y1)/((x2-x1)*XX+AB*(y1-y2));break;
       }
       if((!i1)&&i2) /* erster Punkt draußen*/
       {  x1=x1+u*(x2-x1);
          y1=y1+u*(y2-y1);
          z1=z1+u*(z2-z1);
       }
       else if(i1&&(!i2)) /* zweiter Punkt draußen */
       {  x2=x1+u*(x2-x1);
          y2=y1+u*(y2-y1);
          z2=z1+u*(z2-z1);
       }
     }
   }

   /* zeichnen ! */

   SetAPen(&(GScreen->RastPort),color);
   if(eabs(x1)<0.0001)
     x2d=y2d=0;
   else
   { x2d=runden(-y1*AB/x1);
     y2d=runden(-z1*AB/x1);
   }
   Move(&(GScreen->RastPort),320+(x2d*2),72-y2d);
   if(eabs(x2)<0.0001)
     x2d=y2d=0;
   else
   { x2d=runden(-y2*AB/x2);
     y2d=runden(-z2*AB/x2);
   }
   Draw(&(GScreen->RastPort),320+(x2d*2),72-y2d);
   return(1);
}

BYTE *FilePuffer;

void OpenVGraph()
{ int i;
  extern void ex();
  
  for(i=0;i<360;i++)
  {    tsin[i]=sin(pi2*((float)i)/360.0);
       tcos[i]=cos(pi2*((float)i)/360.0);
  }

  if((Raster=(WORD*)AllocRaster(640,256))==NULL)
  {  CloseScreen(GScreenB); CloseScreen(GScreen); CloseScreen(Screen); ex(); }

  if((FilePuffer=AllocMem(40000,1))==NULL)
  {  FreeRaster(Raster,640,256); CloseScreen(GScreenB); CloseScreen(GScreen); CloseScreen(Screen);
     ex();
  }   
  GScreen->RastPort.TmpRas=(struct TmpRas *)
  InitTmpRas(&tmp,Raster,RASSIZE(640,256));
  GScreenB->RastPort.TmpRas=GScreen->RastPort.TmpRas;
  
  InitArea(&areainfo,areabuffer,100);
  GScreen->RastPort.AreaInfo=&areainfo;
  GScreenB->RastPort.AreaInfo=&areainfo; 
}

void CloseVGraph()
{  FreeRaster(Raster,640,256);
   FreeMem(FilePuffer,40000);
}


/* Brücken - Bild */
float Seile[29][4] =
 { { -10000.0,-15000.0, -60000.0, 35000.0 },
   { -65000.0, 35000.0, -75000.0, 20000.0 },
   { -75000.0,  20000.0, -85000.0,  5000.0 },
   { -85000.0,  5000.0, -95000.0, -5000.0 },
   { -95000.0, -5000.0, -105000.0, -10000.0 },
   { -105000.0, -10000.0, -125000.0, -10000.0 },
   { -125000.0, -10000.0, -135000.0, -5000.0 },
   { -135000.0, -5000.0, -145000.0,  5000.0 },
   { -145000.0, 5000.0, -155000.0, 20000.0 },
   { -155000.0, 20000.0, -165000.0, 35000.0 },
   { -170000.0, 35000.0, -220000.0, -15000.0 },
   { -20000.0, -15000.0, -20000.0, -5000.0 },
   { -30000.0, -15000.0, -30000.0, 5000.0 },
   { -40000.0, -15000.0, -40000.0, 15000.0 },
   { -50000.0, -15000.0, -50000.0, 25000.0 },
   { -75000.0, -15000.0, -75000.0, 20000.0 },
   { -85000.0, -15000.0, -85000.0, 5000.0 },
   { -95000.0, -15000.0, -95000.0, -5000.0 },
   { -105000.0, -15000.0, -105000.0, -10000.0 },
   { -115000.0, -15000.0, -115000.0, -10000.0 },
   { -125000.0, -15000.0, -125000.0, -10000.0 },
   { -135000.0, -15000.0, -135000.0, -5000.0 },
   { -145000.0, -15000.0, -145000.0, 5000.0 },
   { -155000.0, -15000.0, -155000.0, 20000.0 },
   { -180000.0, -15000.0, -180000.0, 25000.0 },
   { -190000.0, -15000.0, -190000.0, 15000.0 },
   { -200000.0, -15000.0, -200000.0, 5000.0 },
   { -210000.0, -15000.0, -210000.0, -5000.0 },
   { -20000.0,  -13500.0, -210000.0, -13500.0}};

int Hausfarben[5][6]={{2,3,4, 5,5, 2},
                      {12,11,12, 5,5,7},
                      {12,3,4, 5,5, 12},
                      {11,3,4, 5,5, 11},
                      {7,11,12, 5,5, 7}};
   
float Strassen[2][12]={{10000.0,-80.0,-50.0,
                       10000.0,20.0,-50.0,
                       -1700.0,20.0,-50.0,
                       -1700.0,-80.0,-50.0 },
                      {-1700.0,-400.0,-50.0,
                       -1700.0,400.0,-50.0,
                       -2000.0,400.0,-50.0,
                       -2000.0,-400.0,-50.0}}; 

float dorf[7][6][15];                       
float Haus[6][15]={{ 100.0,-150.0,-50.0,
                    100.0, 150.0,-50.0,
                    100.0, 150.0, 120.0,
                    100.0,-150.0, 120.0, 0.0,0.0,0.0 },
                  { 100.0, 150.0,-50.0,
                   -100.0, 150.0,-50.0,
                   -100.0, 150.0, 120.0,
                    0.0  , 150.0, 200.0,
                    100.0, 150.0, 120.0 },
                  {-100.0,-150.0,-50.0,
                    100.0,-150.0,-50.0,
                    100.0,-150.0, 120.0,
                    0.0,  -150.0, 200.0,
                   -100.0,-150.0, 120.0 },
                  { 100.0,-150.0, 120.0,
                    100.0, 150.0, 120.0,
                    0.0,   150.0, 200.0,
                    0.0,  -150.0, 200.0, 0.0,0.0,0.0 },
                  {-100.0, 150.0, 120.0,
                   -100.0,-150.0, 120.0,
                    0.0,  -150.0, 200.0,
                    0.0,   150.0, 200.0, 0.0,0.0,0.0 },
                  {-100.0, 150.0, -50.0,
                   -100.0,-150.0, -50.0,
                   -100.0,-150.0, 120.0,
                   -100.0, 150.0, 120.0, 0.0,0.0,0.0 }};
                          
float Flaechen[17][12] =
               { {  2000000.0, -1000000.0, -25000.0,
                   -2000000.0,-1000000.0, -25000.0,
                   -2000000.0, 1000000.0, -25000.0,
                    2000000.0,  1000000.0, -25000.0 },
                 { -200000.0, -1000000.0, -25000.0,
                   -9000.0, -1000000.0, -25000.0,
                   -9000.0,  1000000.0, -25000.0,
                   -200000.0,  1000000.0, -25000.0 },
                 {  2000000.0, -3000000.0, -25000.0,
                   -2000000.0,-3000000.0, -25000.0,
                   -2000000.0,-500000.0, -25000.0,
                    2000000.0,-500000.0, -25000.0 },
                 /* hintere Türme */
                 { -165000.0, -12000.0, -25000.0,
                   -165000.0, -12000.0, 35000.0,
                   -165000.0, -10000.0, 35000.0,
                   -165000.0, -10000.0, -25000.0 },
                 { -165000.0, -10000.0, -25000.0,
                   -170000.0, -10000.0, -25000.0,
                   -170000.0, -10000.0, 35000.0,
                   -165000.0, -10000.0, 35000.0 },

                 { -165000.0, 12000.0, -25000.0,
                   -165000.0, 12000.0, 35000.0,
                   -165000.0, 10000.0, 35000.0,
                   -165000.0, 10000.0, -25000.0 },
                 { -165000.0, 10000.0, -25000.0,
                   -170000.0, 10000.0, -25000.0,
                   -170000.0, 10000.0, 35000.0,
                   -165000.0, 10000.0, 35000.0 },

                 { -165500.0, 10000.0, 20000.0,
                   -165500.0,-10000.0, 20000.0,
                   -165500.0,-10000.0, 30000.0,
                   -165500.0, 10000.0, 30000.0 },

                 /* vordere Türme */
                 { -60000.0, -12000.0, -25000.0,
                   -60000.0, -12000.0, 35000.0,
                   -60000.0, -10000.0, 35000.0,
                   -60000.0, -10000.0, -25000.0 },
                 { -60000.0, -10000.0, -25000.0,
                   -65000.0, -10000.0, -25000.0,
                   -65000.0, -10000.0, 35000.0,
                   -60000.0, -10000.0, 35000.0 },

                 { -60000.0, 12000.0, -25000.0,
                   -60000.0, 12000.0, 35000.0,
                   -60000.0, 10000.0, 35000.0,
                   -60000.0, 10000.0, -25000.0 },
                 { -60000.0, 10000.0, -25000.0,
                   -65000.0, 10000.0, -25000.0,
                   -65000.0, 10000.0, 35000.0,
                   -60000.0, 10000.0, 35000.0 },

                 { -62500.0, 10000.0, 20000.0,
                   -62500.0,-10000.0, 20000.0,
                   -62500.0,-10000.0, 30000.0,
                   -62500.0, 10000.0, 30000.0 },
                 /*Straße*/
                 {-1500000.0 ,10000.0,-15000.0,
                   1500000.0,10000.0,-15000.0,
                   1500000.0,-10000.0, -15000.0,
                  -1500000.0,-10000.0, -15000.0 },
                 {-1500000.0,10000.0,-15000.0,
                   1500000.0,10000.0,-15000.0,
                   1500000.0,9500.0, -15000.0,
                  -1500000.0,9500.0, -15000.0 },
                 {-1500000.0,-10000.0,-15000.0,
                   1500000.0,-10000.0,-15000.0,
                   1500000.0,-9500.0, -15000.0,
                  -1500000.0,-9500.0, -15000.0 },
                 {-1500000.0,-250.0, -15000.0,
                   1500000.0,-250.0, -15000.0,
                   1500000.0, 250.0, -15000.0,
                  -1500000.0, 250.0, -15000.0 }};
  
int Farben[]= { 8,9,9, 6,7,6,7,6,6,7,6,7,6,4,5,5,5 };

void mamu(u,v,anz)
float *u,*v;
int anz;
{  int i;
   for(i=0;i<anz;i++)
   {  *u++=A[0][0]**v+A[0][1]**(v+1)+A[0][2]**(v+2)+A[0][3];
      *u++=A[1][0]**v+A[1][1]**(v+1)+A[1][2]**(v+2)+A[1][3];
      *u++=A[2][0]**v+A[2][1]**(v+1)+A[2][2]**(v+2)+A[2][3];
      v+=3;
   }
}
void translation(u,anz,x,y,z)
float *u,x,y,z;
int anz;
{ int i;
  for(i=0;i<anz;i++)
  { (*u++)+=x; (*u++)+=y; (*u++)+=z; }
}   

BYTE sichtbar(u)
float *u;
{ float x1,y1,z1,x2,y2,z2,vx,vy,vz;
  
  x1=*u-*(u+3); y1=*(u+1)-*(u+4); z1=*(u+2)-*(u+5);
  x2=*(u+3)-*(u+6); y2=*(u+4)-*(u+7); z2=*(u+5)-*(u+8);
  /*Vektorprodukt :*/
  vx=y1*z2-y2*z1; vy=z1*x2-x1*z2; vz=x1*y2-x2*y1;
  /*Skalarprodukt :*/
  if(vx*(*(u+3))+vy*(*(u+4))+vz*(*(u+5))>0.0) /*sichtbar*/
    return(0);
  else return(1);
}    
      
void PrintBridge(Typ)
BYTE Typ; /* steuert die Reihenfolge der Flächen*/
{ int i,j;
  float S=10000.0;
  float x1,x2,y1,y2,z1,z2;
  float *u,*v;
  static float Puffer[12];

  SetAPen(&GScreen->RastPort,10);
  RectFill(&GScreen->RastPort,B1,B2,B3,B4);
  

  for(j=0;j<17;j++)
  { if((!Typ)||((j!=3)&&(j!=4)&&(j!=8)&&(j!=9)))
    { if(Typ||(j!=2))
      { u=Puffer; v=Flaechen[j];
        mamu(u,v,4);
        polygon(Farben[j],4,Puffer);
      }
    }  
  }
  if(Typ)
  { for(i=0;i<3;i++)
    { if(i<2) j=3+i; else j=6+i;
      u=Puffer; v=Flaechen[j];
      mamu(u,v,4);
      polygon(Farben[j],4,Puffer);
    }  
  }
  for(j=0;j<2;j++)
  { for(i=0;i<29;i++) /*alle Seile durchgehen*/
    {  x1=A[0][0]*Seile[i][0]+A[0][1]*S+A[0][2]*Seile[i][1]+A[0][3];
       y1=A[1][0]*Seile[i][0]+A[1][1]*S+A[1][2]*Seile[i][1]+A[1][3];
       z1=A[2][0]*Seile[i][0]+A[2][1]*S+A[2][2]*Seile[i][1]+A[2][3];

       x2=A[0][0]*Seile[i][2]+A[0][1]*S+A[0][2]*Seile[i][3]+A[0][3];
       y2=A[1][0]*Seile[i][2]+A[1][1]*S+A[1][2]*Seile[i][3]+A[1][3];
       z2=A[2][0]*Seile[i][2]+A[2][1]*S+A[2][2]*Seile[i][3]+A[2][3];
       line(6,x1,y1,z1,x2,y2,z2);
    }
    S=-10000.0;
  }
}

float pos[][2]={{-2400.0,0.0},{-900.0,-250.0},{-1200.0,200.0},
                {-1900.0,-800.0},{-2000.0,800.0}};
                  
int wink[]={20,0,85,  45,320};
void PrintD(Winkel,px,py)
int Winkel;
float px,py;
{ int j,i,k;
  float *u,*v,m;
  static float Puffer[15];
  static int fertig=0;
  static int sort[7],dis[7];

  SetAPen(&GScreen->RastPort,9);
  RectFill(&GScreen->RastPort,B1,B2,B3,B2+(B4-B2)/3);
  SetAPen(&GScreen->RastPort,10);
  RectFill(&GScreen->RastPort,B1,B2+(B4-B2)/3,B3,B2+(B4-B2)/2);

  SetAPen(&GScreen->RastPort,8);
  RectFill(&GScreen->RastPort,B1,B2+(B4-B2)/2,B3,B2+2*(B4-B2)/3);
  SetAPen(&GScreen->RastPort,13);
  RectFill(&GScreen->RastPort,B1,B2+2*(B4-B2)/3,B3,B4);

  /*gege. Anlegen der Häuser*/  
  if(!fertig)
  for(i=0;i<5;i++)
  { xy=wink[i]; xz=yz=0; x=y=z=0.0;
    MatrixBau();
    for(j=0;j<6;j++)
    { u=dorf[i][j]; v=Haus[j];
      if((j==1)||(j==2))
      { mamu(u,v,5);
        translation(dorf[i][j],5,pos[i][0],pos[i][1],0.0); 
      }
      else
      { mamu(u,v,4);
        translation(dorf[i][j],4,pos[i][0],pos[i][1],0.0); 
      }     
    }
  }   
  fertig=1;
  /* Bild auswählen */
  xz=yz=0; xy=Winkel; x=px;y=py;z=0.0;
  /* sortieren der Häuser nach Entfernung */
  for(i=0;i<5;i++) 
  { sort[i]=i;
    dis[i]=eabs(pos[sort[i]][0]-x)+eabs(pos[sort[i]][1]-y);
  }
  for(i=0;i<6;i++)
  { for(j=i+1;j<7;j++)
    { if(dis[j]>dis[i])
      { m=dis[j]; dis[j]=dis[i]; dis[i]=m;
        k=sort[i]; sort[i]=sort[j]; sort[j]=k;
      }
    }
  }           
  /* zeichnen des Dorfes :*/
  MatrixBau();
  for(i=0;i<2;i++)
  {  u=Puffer; v=Strassen[i];
     mamu(u,v,4);
     polygon(6,4,Puffer);
  } 
  for(i=0;i<5;i++) /* 5 Häuser*/
  { for(j=0;j<6;j++)
    {  u=Puffer; v=dorf[sort[i]][j];
       if((j==1)||(j==2))
       { mamu(u,v,5);
         if(sichtbar(Puffer))
            polygon(Hausfarben[sort[i]][j],5,Puffer);
       }
       else
       { mamu(u,v,4);
         if(sichtbar(Puffer))
         polygon(Hausfarben[sort[i]][j],4,Puffer);
       }
     }
  }   
  ToFront();
}
void turn(w1,w2,xa,ya)
int w1,w2;
float xa,ya;
{  int i;
   i=w2;
   /* Hier von w2 nach w1, beides Vielfache von 30 !, drehen*/
   if(w2!=w1)
   { if((w2>w1)&&(w2-w1<=180)) /*abziehen bis w1*/
     {  do 
        { i-=30;
          PrintD(i,xa,ya);
        }while(i>w1);
     }
     else if(w2>w1)
     {  do
        { i+=30; i=i%360;
          PrintD(i,xa,ya);
        }while(i!=w1);             
     }
     else if(w1-w2<=180)
     {  do 
        { i+=30;
          PrintD(i,xa,ya);
        }while(i<w1);
     }
     else
     {  do
        { i-=30; if(i<0) i+=360;
          PrintD(i,xa,ya);
        }while(i!=w1);
     }
   }
}            

int mWinkel=0;

void umrunden(typ)
BYTE typ;
{ int Winkel=270,w2=0,i;
  for(i=0;i<24;i++)
  {  if(typ) {Winkel+=15; Winkel%=360; w2-=15; if(w2<0) w2+=360;}
     else {Winkel-=15; if(Winkel<0) Winkel+=360; w2+=15; w2%=360;}
     PrintD(w2,-2000.0*tsin[Winkel]-2000.0,2000.0*tcos[Winkel]);
  }
  mWinkel=0;
}

void haufa()
{  extern int TIME;
   int i=1;
   if((TIME>=35)&&(TIME<=80)) i=3;
  
  SetAPen(&GScreen->RastPort,0);
  RectFill(&GScreen->RastPort,0,B2,639,B4);
  SetRGB4(&GScreen->ViewPort,4,10/i,9/i,9/i);
  SetRGB4(&GScreen->ViewPort,5,15/i,2/i,2/i);
  SetRGB4(&GScreen->ViewPort,6,6/i,6/i,5/i);
  SetRGB4(&GScreen->ViewPort,7,15/i,12/i,12/i);
  SetRGB4(&GScreen->ViewPort,8,2/i,10/i,3/i);
  SetRGB4(&GScreen->ViewPort,9,3/i,14/i,15/i);
  SetRGB4(&GScreen->ViewPort,10,3/i,15/i,15/i);
  SetRGB4(&GScreen->ViewPort,11,9/i,9/i,9/i);
  SetRGB4(&GScreen->ViewPort,12,12/i,12/i,12/i);
  SetRGB4(&GScreen->ViewPort,13,2/i,9/i,3/i);
  SetRGB4(&GScreen->ViewPort,2,12/i,11/i,11/i);
  SetRGB4(&GScreen->ViewPort,3,14/i,11/i,11/i);
}                          
     
void PrintDorf(alt,neu)
int alt,neu;
{ static float xalt=0.0,yalt=0.0; 
  switch(neu)
  { case 24 : if(alt==25) {turn(180,mWinkel,xalt,yalt); 
                           mWinkel=180;  
                           PrintD(180,0.0,0.0);
                          }
                    else { haufa();
                           mWinkel=0; PrintD(0,0.0,0.0);
                           haufa();
                         }
              xalt=yalt=0.0;              
              break;
    case 25 : if(alt==26) {turn(180,mWinkel,xalt,yalt); 
                           mWinkel=180;  
                           PrintD(180,-1000.0,0.0);
                           xalt=-1000.0;
                          }
              else if(alt==24) { turn(0,mWinkel,xalt,yalt);
                           mWinkel=0; PrintD(0,-800.0,0.0);
                           xalt=-800.0;
                          }
              else { haufa();
                     mWinkel=0; PrintD(0,-800.0,0.0);
                     haufa(); xalt=-800.0;
                   }

              yalt=0.0;              
              break;
    case 26 : if(alt==27) {turn(180,mWinkel,xalt,yalt); 
                           mWinkel=180;  
                           PrintD(180,-1300.0,0.0);
                           xalt=-1300.0;
                          }
              else if(alt==25) { turn(0,mWinkel,xalt,yalt);
                           mWinkel=0; PrintD(0,-1100.0,0.0);
                           xalt=-1100.0;
                         }
              else { haufa();
                     mWinkel=0; PrintD(0,-1100.0,0.0);
                     haufa(); xalt=-1100.0;
                   }
          
               yalt=0.0;
               break;
     case 27 : if(alt==26) {turn(0,mWinkel,xalt,yalt);
                            mWinkel=0;
                            PrintD(0,-1800.0,0.0);
                           }
               else if(alt==29) {turn(270,mWinkel,xalt,yalt);
                            mWinkel=270;
                            PrintD(270,-1800.0,0.0);
                            turn(330,mWinkel,-1800.0,0.0);
                            mWinkel=330;
                           }
               else if(alt==28) {turn(90,mWinkel,xalt,yalt);
                            mWinkel=90;
                            PrintD(90,-1800.0,0.0);
                            turn(30,mWinkel,-1800.0,0.0);
                            mWinkel=30;
                           } 
               else { haufa();
                      mWinkel=0; PrintD(0,-1800.0,0.0);
                      haufa();
                    }
                                    
               xalt=-1800.0; yalt=0.0;
               break;    
     case 28 : if(alt==27)
               { turn(270,mWinkel,xalt,yalt);    
                 mWinkel=270;
                 PrintD(270,-1800.0,-200.0);
               }
               else { haufa();
                      mWinkel=270; PrintD(270,-1800.0,-200.0);
                      haufa();
                    }

               xalt=-1800.0; yalt=-200.0;
               break;            
     case 29 : if(alt==27)
               { turn(90,mWinkel,xalt,yalt);
                 mWinkel=90;
                 PrintD(90,-1800.0,200.0);
               }
               else  { haufa();
                       mWinkel=90; PrintD(90,-1800.0,200.0);
                       haufa();
                     }
  
               xalt=-1800.0; yalt=200.0;
               break;
  }
} 
/*---------------------------------------------------------------------*/
void farbbri()
{  extern int TIME;
   int i=1;
   if((TIME>=35)&&(TIME<=80)) i=3;
   SetRGB4(&GScreen->ViewPort,4,4/i,4/i,4/i);
   SetRGB4(&GScreen->ViewPort,5,13/i,13/i,0);
   SetRGB4(&GScreen->ViewPort,6,12/i,6/i,2/i);
   SetRGB4(&GScreen->ViewPort,7,13/i,6/i,2/i);
   SetRGB4(&GScreen->ViewPort,8,2/i,10/i,3/i);
   SetRGB4(&GScreen->ViewPort,9,1/i,8/i,15/i);
   SetRGB4(&GScreen->ViewPort,10,3/i,15/i,15/i);
   SetRGB4(&GScreen->ViewPort,11,9/i,9/i,9/i);
   SetRGB4(&GScreen->ViewPort,12,12/i,12/i,12/i);
   SetRGB4(&GScreen->ViewPort,13,9/i,9/i,2/i);
   SetRGB4(&GScreen->ViewPort,2,10/i,12/i,15/i);
   SetRGB4(&GScreen->ViewPort,3,6/i,6/i,6/i);
   SetAPen(&GScreen->RastPort,0);
   RectFill(&GScreen->RastPort,0,B2,639,B4);

}
void Night() 
{  SetRGB4(&GScreen->ViewPort,3,2,2,3);
   SetAPen(&GScreen->RastPort,3);
   RectFill(&GScreen->RastPort,0,B2,639,B4);

   ToFront(); 
}
     
void bridge(typ)
BYTE typ;
{  float f=100000.0;
   int i;

   farbbri();
  
   if(typ!=2)
   { xy=10; xz=yz=1;
     x=f;y=0.0;z=5.0;
   }
   else { xy=5; xz=0; yz=0; x=-220000.0; y=0.0; z=5.0; }   
   if(typ==3) { y=-250000.0; x+=80000.0; }
   if(typ==4) { y=-500000.0; x+=80000.0; }
   if((typ>=1)&&(typ<5))
   { MatrixBau();
     if(typ==1) PrintBridge(0);
     else PrintBridge(1);
     ToFront();
   }
   if(typ==0)
   {  for(i=0;i<8;i++)
      {  f-=40000.0;
         x=f; MatrixBau(); PrintBridge(0); ToFront();
         if(i==0) farbbri();  
      }
   }   
   if(typ==5)
   {  f=-220000.0;
      for(i=0;i<8;i++)
      {  f+=40000.0;
         x=f; MatrixBau(); PrintBridge(0); ToFront();
         if(i==0) farbbri();
      }
   }   
   
}   

UBYTE *PicTab[20];
/* Bilder nachladen : */
extern UBYTE *Bilder1,*Bilder2;
void ReadPics()
{ UBYTE *z;
  int i,j;
  ULONG filehandle=0L;
  char txt[10];
  z=Bilder1;
  for(i=0;(i<18)&&Bilder1;i++) /* bis jetzt 16 Bilder */
  {  sprintf(txt,"Pic%d",i);
     filehandle=Open(txt,MODE_OLDFILE);
     if(filehandle) 
     { j=Read(filehandle,z,20000);
       PicTab[i]=z;
       z+=j+2;
       Close(filehandle);
     }
     else
     {  FreeMem(Bilder1,100000L); FreeMem(Bilder2,100000L);
        Bilder1=0;
     }       
     if(i==9) z=Bilder2;
  }   
}   

void load(nr)
int nr;
{  ULONG filehandle=0L;
   UBYTE *z1,*z;
   UBYTE code;
   int i,j,k,l;
   char txt[10];
   
   if(Bilder1) 
     z=PicTab[nr];  
   else
   { sprintf(txt,"Pic%d",nr); 
     filehandle=Open(txt,MODE_OLDFILE);
     if(filehandle)
     {  /*zeilenweise speichern*/
        z=FilePuffer;
        Read(filehandle,z,20000);
        Close(filehandle);
     }     
     else return;
   }     
   for(l=0;l<4;l++)
   { i=0; 
     z1=(UBYTE*)(GScreen->BitMap.Planes[l])+12*80; /*12*80*/
     code=*z++;
     while(i<9680)
     { if(*z==code) { z++; k=*z++; for(j=0;j<k;j++) *z1++=*z; z++; i+=k; }
       else { *z1++=*z++; i++; }
     }    
   }    
   for(i=2;i<14;i++)
   { z+=2; j=*z++; k=(*z)>>4; l=(*z++)&0xf;
     SetRGB4(&GScreen->ViewPort,i,j,k,l);
   } 
   ToFront();
 
}

