#include <stdio.h>
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <graphics/sprite.h>
#include <graphics/gels.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <hardware/custom.h>
#include <hardware/cia.h>
#include <math.h>

#include "EasySound.h"  /* Declares LEFT0, LEFT1, RIGHT0, etc. */
#include "shoot.h"



struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;


struct View my_view;
struct View *my_old_view;
struct ViewPort my_view_port;
struct RasInfo my_ras_info;
struct BitMap my_bit_map;
struct RastPort my_rast_port;
struct BitMap my_bit_map2;


UWORD my_color_table[256];
UWORD level[ LEVELHEIGHTMAX ][ LEVELWIDTHMAX ];
UBYTE tiles[ TILESMAX ][ DEPTH ][ TILESHEIGHT ][ TILESWIDTH ];

extern void beak( char *);
extern void getilbm();

void clean_up();
void initstuff( void );
void loadstuff( void );
void openlibs( void );
void closelibs( void );
void drawlevel( void );
UBYTE Joystick( UBYTE );
void openstuff( void );
void tilestosecond( void );

int levelwidth;
int levelheight;
APTR DosBase;
PLANEPTR maskplane;

int docenter = 0;
int posx, posy;
UBYTE value = 0;
int dir = 0;
int aimmode = 0;
int aimposx, aimposy;
int aimdir = 0;
int aimed = 0;
int fire = 0;
int shotat = 0;
int remoove = 0;

long int gametime;

char codestr[80];
int finishx, finishy;
int startx, starty;
struct
{
	unsigned int x,y;
	long int delay;
	int foes;
} foedwell[ 50 ];
struct
{
	unsigned int x,y;
	int full;
} aid[ 20 ];
int fonum;
int aidnum;
int energy;
int lifes;

extern struct Custom custom;
struct CIA *cia = (struct CIA *) CIAAPRA;

CPTR fires = NULL;
CPTR attacks = NULL;
CPTR foedies = NULL;
CPTR steps = NULL;
CPTR shoth1 = NULL;
CPTR shoth2 = NULL;
CPTR glas = NULL;
CPTR bell = NULL;

UWORD *spritedata = NULL;

/* Vsprites */
struct VSprite head, tail, vsprite[ MAXVSPRITES ];
WORD colour_table[] = { 0x0000, 0x0ffd, 0x0fc8 };
WORD nextline[ 8 ];
WORD *lastcolor[ 8 ];
struct GelsInfo ginfo;
BOOL vsprite_on[ MAXVSPRITES ];

UWORD ship_data[70]=
{
  	0x0000, 0x0000, /* Ship 1 */

  	0x0000, 0xffff,
  	0x0f00, 0x0000,
  	0x3f00, 0x0000,
  	0x7f00, 0x0000,
  	0x0f57, 0x0000,
  	0x0f55, 0x0000,
  	0x0f57, 0x0000,
  	0x0f74, 0x0000,
  	0x0f00, 0x0000,
  	0x0000, 0xffff,
  	0x0000, 0x0000,

  	0x0000, 0x0000,
  	0xffff, 0x0000,
  	0x0000, 0x0000,
  	0x0000, 0x0000,
  	0x0000, 0x0000,
  	0x0000, 0x0000,
  	0x0000, 0x0000,
  	0x0000, 0x0000,
  	0x0000, 0x0000,
  	0x0000, 0x0000,
  	0x0000, 0x0000,
  	0x0000, 0x0000,
  	0xffff, 0x0000,
  	0x0000, 0x0000,

  	0x0000, 0x0000,
  	0xffff, 0x0000,
  	0x8421, 0x7bde,
  	0x8421, 0x7bde,
  	0x8421, 0x7bde,
  	0x8421, 0x7bde,
  	0xffff, 0x0000,


  	0x0000, 0x0000,
};



/*******************************************************/
/* 2. Declare and initialize a SimpleSprite structure: */
/*******************************************************/
struct SimpleSprite my_sprite=
{
  ship_data,   /* posctldata, pointer to the sprite data. (Frame 0) */
  33,             /* height, 12 lines tall. */
  40, 80,         /* x, y, position on the screen. */
  -1,             /* num, this field is automatically initialized when  */
                  /* you call the GetSprite() function, so we set it to */
                  /* -1 for the moment.                                 */
};

struct
{
	int used;
	int posx;
	int posy;
	int speedx, speedy;
	int owner;
	UBYTE save1[DEPTH], save2[DEPTH], save3[DEPTH], save4[DEPTH];
} shot[ SHOTSMAX ];

struct
{
	int used;
	int posx;
	int posy;
	int destx, desty;
	int angle;
	int stepdist, step;
	int shootinterv;
	int shout;
} foe[ FOESMAX ];


void openlibs( void )
{
	if( (DosBase = (APTR) OpenLibrary( "dos.library", 0 )) == NULL)
	{
		printf("ERROR: Couldn't open dos.library\n");
	}
}

void closelibs( void )
{
	CloseLibrary( DosBase );
}

void initstuff( void )
{
	levelwidth = 64;
	levelheight = 48;
}

void loadlevel( void )
{
	FILE *in;
	int filx, fily;
	unsigned char f;
	int readon;

	/*printf("Reading level data...\n");*/

	if( (in = fopen( "data/shoot_level.level", "r" )) == NULL )
	{
		printf("ERROR: Could not open shoot_level.level\n");
	}

	fonum = 0;
	aidnum = 0;

	/* Level einlesen */
	for( fily=0; fily<levelheight; fily++ )
	{
		for( filx=0; filx<levelwidth; filx++ )
		{
			f = (unsigned char) fgetc( in );

			level[ fily ][ filx ] = 0;
			if( f == '.' ) level[ fily ][ filx ] = 0;
			if( f == 44 /* Komma */ ) level[ fily ][ filx ] = 1;
			if( f == 's' ) level[ fily ][ filx ] = 2;
			if( f == 'g' ) level[ fily ][ filx ] = 3;
			if( f == 'S' ) level[ fily ][ filx ] = 4;
			if( f == 'G' ) level[ fily ][ filx ] = 5;
			if( f == 'm' ) level[ fily ][ filx ] = 6;
			if( f == 'E' ) level[ fily ][ filx ] = 7;
			if( f == 'e' ) level[ fily ][ filx ] = 8;
			if( f == 't' ) level[ fily ][ filx ] = 9;

			if( f == '+' )
			{
				level[ fily ][ filx ] = 10;
				aid[ aidnum ].x = filx;
				aid[ aidnum ].y = fily;
				aid[ aidnum ].full = 1;
				aidnum++;
			}

			if( f == 'Z' ) level[ fily ][ filx ] = 11;
			if( f == 'A' ) level[ fily ][ filx ] = 12;
			if( f == 'Q' ) level[ fily ][ filx ] = 13;
			if( f == 'K' ) level[ fily ][ filx ] = 15;
			if( f == 'Y' ) level[ fily ][ filx ] = 16;
			if( f == 'D' ) level[ fily ][ filx ] = 17;
			if( f == 'F' ) level[ fily ][ filx ] = 18;
			if( f == 'T' )
			{
				level[ fily ][ filx ] = 19;
				foedwell[ fonum ].x = filx*16+8;
				foedwell[ fonum ].y = (fily+1)*16;
				foedwell[ fonum ].delay = 0;
				foedwell[ fonum ].foes = DWELLFOES;
				fonum++;
			}
		}
		fgetc( in ); /* Return ueberspringen */
	}

	readon = 1;
	while( readon > 0 )
	{
		readon = fscanf( in, "%s", &codestr );

		if( readon > 0 )
		{
			if( strcmp( codestr, "FINISH" ) == 0 )
			{
				fscanf( in, "%d%d", &finishx, &finishy );
				/*printf("FINISH: %d %d\n", finishx, finishy );*/
			}
			else if( strcmp( codestr, "START" ) == 0 )
			{
				fscanf( in, "%d%d", &startx, &starty );
				/*printf("START: %d %d\n", startx, starty );*/
			}
			else if( strcmp( codestr, "FOEDWELL" ) == 0 )
			{
				fscanf( in, "%d%d", &foedwell[ fonum ].x, &foedwell[ fonum ].y );
				foedwell[ fonum ].delay = 0;
				foedwell[ fonum ].foes = DWELLFOES;
				/*printf("FOEDWELL: %d %d %d\n", foedwell[ fonum ].x, foedwell[ fonum ].y, fonum );*/
				fonum++;
			}
			else
			{
				readon = -1;
			}
		}
	}

	fclose( in );
}


void loadstuff( void )
{

	{
		FILE *in;
		int filx, fily;
		UBYTE r, g, b;

		/*printf("Reading colormap...\n");*/

		if( (in = fopen( "data/shoot_colormap.col", "r" )) == NULL )
		{
			printf("ERROR: Could not open shoot_colormap.col\n");
		}

		/* Header ueberspringen */
		for( filx=0; filx<48; filx++ )
		{
			fgetc( in );
		}

		/* Farben einlesen und konvertieren */
		for( fily=0; fily<COLOURS; fily++ )
		{
			r = fgetc( in );
			g = fgetc( in );
			b = fgetc( in );

			my_color_table[ fily ] = (((UWORD) r>>4)<<8) + ((g>>4)<<4) + (b>>4) ;
		}

		fclose( in );
	}


	loadlevel();


	/*printf("Reading level graphics...\n");*/
	{
		int Xpos, Ypos;
		FILE *in;
		UWORD tile;
		UWORD row;
		UWORD byte;
		UWORD index;

		UWORD manip2;
		UWORD manip;
		UBYTE schreib;

		if( (in = fopen( "data/shoot_tiles.gfx", "r" )) == NULL )
		{
			printf("ERROR: Could not open shoot_tiles.gfx\n");
		}

		for( Ypos=0; Ypos< (TILESMAX+19)/20*16; Ypos++ )
		{
			for( Xpos=0; Xpos<320; Xpos++ )
			{
				index =  (UWORD) fgetc( in );

				tile = (Ypos/16)*20 + Xpos/16;

				row = Ypos & 15;
				byte = (Xpos & 8)/8;

				manip = 1 << ( 7 - ( Xpos & 7 ) );
				manip2 = 255 ^ manip;
	
				if(tile<TILESMAX)
				{
					if( ( index & 1 ) != 0 )
					{
						tiles[ tile ][ 0 ][ row ][ byte ] |= manip;
					}
					else
					{
						tiles[ tile ][ 0 ][ row ][ byte ] &= manip2;
					}
	
					if( ( index & 2 ) != 0 )
					{
						tiles[ tile ][ 1 ][ row ][ byte ] |= manip;
					}
					else
					{
						tiles[ tile ][ 1 ][ row ][ byte ] &= manip2;
					}
	
					if( ( index & 4 ) != 0 )
					{
						tiles[ tile ][ 2 ][ row ][ byte ] |= manip;
					}
					else
					{
						tiles[ tile ][ 2 ][ row ][ byte ] &= manip2;
					}
	
					if( ( index & 8 ) != 0 )
					{
						tiles[ tile ][ 3 ][ row ][ byte ] |= manip;
					}
					else
					{
						tiles[ tile ][ 3 ][ row ][ byte ] &= manip2;
					}
	
					if( ( index & 16 ) != 0 )
					{
						tiles[ tile ][ 4 ][ row ][ byte ] |= manip;
					}
					else
					{
						tiles[ tile ][ 4 ][ row ][ byte ] &= manip2;
					}
	
					if( ( index & 32 ) != 0 )
					{
						tiles[ tile ][ 5 ][ row ][ byte ] |= manip;
					}
					else
					{
						tiles[ tile ][ 5 ][ row ][ byte ] &= manip2;
					}
	
					if( ( index & 64 ) != 0 )
					{
						tiles[ tile ][ 6 ][ row ][ byte ] |= manip;
					}
					else
					{
						tiles[ tile ][ 6 ][ row ][ byte ] &= manip2;
					}
	
					if( ( index & 128 ) != 0 )
					{
						tiles[ tile ][ 7 ][ row ][ byte ] |= manip;
					}
					else
					{
						tiles[ tile ][ 7 ][ row ][ byte ] &= manip2;
					}
				}
			}
		}
		fclose( in );
	}

	/*printf("Calculating image masks...\n");*/
	{
		int depth, image, byte, row;
		UBYTE maskbyte;

		/* Maennchen */
		for( image=0; image<16; image++ )
		{
			for( row=0; row<TILESHEIGHT; row++ )
			{
				for( byte=0; byte<TILESWIDTH; byte++ )
				{
					maskbyte = 0;
					for( depth=0; depth<DEPTH; depth++ )
					{
						maskbyte = maskbyte | tiles[ 40+image ][ depth ][ row ][ byte ];
					}
					tiles[ 56 ][ image ][ row ][ byte ] = maskbyte;
				}
			}
		}

		/* totes Maennchen */
		for( image=0; image<1; image++ )
		{
			for( row=0; row<TILESHEIGHT; row++ )
			{
				for( byte=0; byte<TILESWIDTH; byte++ )
				{
					maskbyte = 0;
					for( depth=0; depth<DEPTH; depth++ )
					{
						maskbyte = maskbyte | tiles[ 58+image ][ depth ][ row ][ byte ];
					}
					tiles[ 59 ][ image ][ row ][ byte ] = maskbyte;
				}
			}
		}

		for( image=0; image<16; image++ )
		{
			for( row=0; row<TILESHEIGHT; row++ )
			{
				for( byte=0; byte<TILESWIDTH; byte++ )
				{
					maskbyte = 0;
					for( depth=0; depth<DEPTH; depth++ )
					{
						maskbyte = maskbyte | tiles[ 60+image ][ depth ][ row ][ byte ];
					}
					tiles[ 76 ][ image ][ row ][ byte ] = maskbyte;
				}
			}
		}

	}

}

void drawlevel( void )
{
	register int levx, levy;
	register int depth, row, byte;
	register UBYTE *gfx;

	for( levy=0; levy<levelheight; levy++ )
	{
		for( levx=0; levx<levelwidth; levx++ )
		{
			for( depth=0; depth<DEPTH; depth++ )
			{
				for( row=0; row<TILESHEIGHT; row++ )
				{
					for( byte=0; byte<TILESWIDTH; byte++ )
					{
				    gfx = (UBYTE *) my_bit_map.Planes[ depth ];
						gfx = gfx + RWIDTH/8 * ( levy*TILESHEIGHT + row ) + levx*TILESWIDTH + byte;
						*gfx = tiles[ level[ levy ][ levx ] ][ depth ][ row ][ byte ];
					}
				}
			}
		}
	}

}

UBYTE Joystick( port )
UBYTE port;
{
  UBYTE data = 0;
  UWORD joy;
  
  if( port == PORT1 )
  {
    /* PORT 1 ("MOUSE PORT") */
    joy = custom.joy0dat;
    data += !( cia->ciapra & 0x0040 ) ? FIRE : 0;
  }
  else
  {
    /* PORT 2 ("JOYSTICK PORT") */
    joy = custom.joy1dat;
    data += !( cia->ciapra & 0x0080 ) ? FIRE : 0;
  }

  data += joy & 0x0002 ? RIGHT : 0;
  data += joy & 0x0200 ? LEFT : 0;
  data += (joy >> 1 ^ joy) & 0x0001 ? DOWN : 0;
  data += (joy >> 1 ^ joy) & 0x0100 ? UP : 0;

  return( data );
}

void openstuff( void )
{
  UWORD *pointer;
	int loop;

  /* Open the Intuition library: */
  IntuitionBase = (struct IntuitionBase *)
    OpenLibrary( "intuition.library", 0 );
  if( !IntuitionBase )
    clean_up( "Could NOT open the Intuition library!" );

  /* Open the Graphics library: */
  GfxBase = (struct GfxBase *)
    OpenLibrary( "graphics.library", 0 );
  if( !GfxBase )
    clean_up( "Could NOT open the Graphics library!" );


  /* Save the current View, so we can restore it later: */
  my_old_view = GfxBase->ActiView;


  /* 1. Prepare the View structure, and give it a pointer to */
  /*    the first ViewPort:                                  */
  InitView( &my_view );
  my_view.ViewPort = &my_view_port;


  /* 2. Prepare the ViewPort structure, and set some important values: */
  InitVPort( &my_view_port );
  my_view_port.DWidth = DWIDTH;        /* Set the width.                */
  my_view_port.DHeight = DHEIGHT;      /* Set the height.               */
  my_view_port.DxOffset = DXOFFSET;    /* Set the display X offset.     */
  my_view_port.DyOffset = DYOFFSET;    /* Set the display Y offset.     */
  my_view_port.RasInfo = &my_ras_info; /* Give it a pointer to RasInfo. */
  my_view_port.Modes = NULL;           /* Low resolution.               */


  /* 3. Get a colour map, link it to the ViewPort, and prepare it: */
  my_view_port.ColorMap = (struct ColorMap *) GetColorMap( COLOURS );
  if( my_view_port.ColorMap == NULL )
    clean_up( "Could NOT get a ColorMap!" );

  /* Get a pointer to the colour map: */
  pointer = (UWORD *) my_view_port.ColorMap->ColorTable;

  /* Set the colours: */
  for( loop = 0; loop < COLOURS; loop++ )
    *pointer++ = my_color_table[ loop ];


  /* 4. Prepare the BitMap: */
  InitBitMap( &my_bit_map, DEPTH, RWIDTH, RHEIGHT );

  /* Allocate memory for the Raster: */ 
  for( loop = 0; loop < DEPTH; loop++ )
  {
    my_bit_map.Planes[ loop ] = (PLANEPTR) AllocRaster( RWIDTH, RHEIGHT );
    if( my_bit_map.Planes[ loop ] == NULL )
      clean_up( "Could NOT allocate enough memory for the raster!" );

    /* Clear the display memory with help of the Blitter: */
    BltClear( my_bit_map.Planes[ loop ], RASSIZE( RWIDTH, RHEIGHT ), 0 );
  }

  
  /* 5. Prepare the RasInfo structure: */
  my_ras_info.BitMap = &my_bit_map; /* Pointer to the BitMap structure.  */
  my_ras_info.RxOffset = 0;         /* The top left corner of the Raster */
  my_ras_info.RyOffset = 0;         /* should be at the top left corner  */
                                    /* of the display.                   */
  my_ras_info.Next = NULL;          /* Single playfield - only one       */
                                    /* RasInfo structure is necessary.   */

  /* 6. Create the display: */
  MakeVPort( &my_view, &my_view_port );
  MrgCop( &my_view );


  /* 7. Prepare the RastPort, and give it a pointer to the BitMap. */
  InitRastPort( &my_rast_port );
  my_rast_port.BitMap = &my_bit_map;
}

void opensecondbitmap( void )
{
	int loop;

  /* 4. Prepare the second BitMap: */
  InitBitMap( &my_bit_map2, DEPTH2, RWIDTH2, RHEIGHT2 );

  /* Allocate memory for the Raster: */ 
  for( loop = 0; loop < DEPTH2; loop++ )
  {
    my_bit_map2.Planes[ loop ] = (PLANEPTR) AllocRaster( RWIDTH2, RHEIGHT2 );
    if( my_bit_map2.Planes[ loop ] == NULL )
      clean_up( "Could NOT allocate enough memory for the second raster!" );

    /* Clear the display memory with help of the Blitter: */
    BltClear( my_bit_map2.Planes[ loop ], RASSIZE( RWIDTH2, RHEIGHT2 ), 0 );
  }

  maskplane = (PLANEPTR) AllocRaster( RWIDTH2, RHEIGHT2 );
  if( maskplane == NULL )
    clean_up( "Could NOT allocate enough memory for the mask plane!" );

  /* Clear the display memory with help of the Blitter: */
  BltClear( maskplane, RASSIZE( RWIDTH2, RHEIGHT2 ), 0 );
}

int sintab[91] =
   {
      0,    285,   571,  857, 1142, 1427, 1712, 1996, 2280,
      2563, 2845, 3126, 3406, 3685, 3963, 4240, 4516, 4790,
      5062, 5334, 5603, 5871, 6137, 6401, 6663, 6924, 7182,
      7438, 7691, 7943, 8192, 8438, 8682, 8923, 9161, 9397,
      9630, 9860, 10086,10310,10531,10748,10963,11173,11381,
      11585,11785,11982,12175,12365,12550,12732,12910,13084,
      13254,13420,13582,13740,13894,14043,14188,14329,14466,
      14598,14725,14848,14967,15081,15190,15295,15395,15491,
      15582,15662,15749,15825,15897,15964,16025,16082,16135,
      16182,16224,16261,16294,16321,16244,16361,16374,16381,
      16384
   };
                 /* Sinustabelle, wird so berechnet:      */
                 /* sintab[x]=sin(x) * 16384 (x=1,2..,90) */
                 /* Siehe: sincos(), sin(), cos()         */

/**********************************************************/
/* Diese Funktion holt den Sinuswert aus Tabelle          */
/*--------------------------------------------------------*/
/* Eingabe-Parameter: x für sin(x)                        */
/*--------------------------------------------------------*/
/* Rückgabe-Werte: sin(x) * 16384                         */
/**********************************************************/

long sincos(x)
long x;
{
   long factor = 1;

   x %= 360;
   if (x>180)                             /* x > 180 Grad */
      {
         x -= 180;
         factor = -1;
      }
   if (x>90) x = 180 - x;
   return (sintab[x]*factor);
}

void tilestosecond( void )
{
	int levx;
	int depth, row, byte;
	UBYTE *gfx;

	/*printf("Preparing level graphics...\n");*/

	/* Maennchen kopieren */
	for( levx=0; levx<16; levx++ )
	{
		for( depth=0; depth<DEPTH; depth++ )
		{
			for( row=0; row<TILESHEIGHT; row++ )
			{
				for( byte=0; byte<TILESWIDTH; byte++ )
				{
			    gfx = (UBYTE *) my_bit_map2.Planes[ depth ];
					gfx = gfx + RWIDTH2/8*row + levx*TILESWIDTH + byte;

					*gfx = tiles[ 40+levx ][ depth ][ row ][ byte ];
				}
			}
		}
	}

	/* Maennchen Maske kopieren */
	for( levx=0; levx<16; levx++ )
	{
		for( row=0; row<TILESHEIGHT; row++ )
		{
			for( byte=0; byte<TILESWIDTH; byte++ )
			{
		    gfx = (UBYTE *) maskplane;
				gfx = gfx + RWIDTH2/8*row + levx*TILESWIDTH + byte;

				*gfx = tiles[ 56 ][ levx ][ row ][ byte ];
			}
		}
	}

	/* totes Maennchen kopieren */
	for( levx=18; levx<19; levx++ )
	{
		for( depth=0; depth<DEPTH; depth++ )
		{
			for( row=0; row<TILESHEIGHT; row++ )
			{
				for( byte=0; byte<TILESWIDTH; byte++ )
				{
			    gfx = (UBYTE *) my_bit_map2.Planes[ depth ];
					gfx = gfx + RWIDTH2/8*row + levx*TILESWIDTH + byte;

					*gfx = tiles[ 40+levx ][ depth ][ row ][ byte ];
				}
			}
		}
	}

	/* totes Maennchen Maske kopieren */
	for( levx=0; levx<1; levx++ )
	{
		for( row=0; row<TILESHEIGHT; row++ )
		{
			for( byte=0; byte<TILESWIDTH; byte++ )
			{
		    gfx = (UBYTE *) maskplane;
				gfx = gfx + RWIDTH2/8*row + (levx+18)*TILESWIDTH + byte;

				*gfx = tiles[ 59 ][ levx ][ row ][ byte ];
			}
		}
	}


	/* Aimring kopieren */
	for( levx=0; levx<16; levx++ )
	{
		for( depth=0; depth<DEPTH; depth++ )
		{
			for( row=0; row<TILESHEIGHT; row++ )
			{
				for( byte=0; byte<TILESWIDTH; byte++ )
				{
			    gfx = (UBYTE *) my_bit_map2.Planes[ depth ];
					gfx = gfx + RWIDTH2/8*(16+row) + levx*TILESWIDTH + byte;

					*gfx = tiles[ 60+levx ][ depth ][ row ][ byte ];
				}
			}
		}
	}

	/* Aimring Maske kopieren */
	for( levx=0; levx<16; levx++ )
	{
		for( row=0; row<TILESHEIGHT; row++ )
		{
			for( byte=0; byte<TILESWIDTH; byte++ )
			{
		    gfx = (UBYTE *) maskplane;
				gfx = gfx + RWIDTH2/8*(16+row) + levx*TILESWIDTH + byte;

				*gfx = tiles[ 76 ][ levx ][ row ][ byte ];
			}
		}
	}

}

void initshots( void )
{
	int sht;

	for( sht=0; sht<SHOTSMAX; sht++ )
	{
		shot[ sht ].used = 0;
	}
}

void initfoes( void )
{
	int sht;

	for( sht=0; sht<SHOTSMAX; sht++ )
	{
		foe[ sht ].used = 0;
	}
}

void cleanandmoveshots( void )
{
	int sht;
	int offset;
	int depth;
	UBYTE *data;
	int boden;
	int fo;

	for( sht=0; sht<SHOTSMAX; sht++ )
	{
		if( shot[ sht ].used == 1 )
		{
			/* Neu geschaffener Schuß; ist noch nicht gezeichnet; und muss also
					auch nicht beseitigt werden */
			shot[ sht ].used = 2;
		}
		else if( shot[ sht ].used == 2 )
		{
			/* Regulaerer Schuß oder sterbender Schuß */
			offset = RWIDTH/8 * (shot[ sht ].posy/16) + shot[ sht ].posx/16/8;
			for( depth=0; depth<DEPTH; depth++ )
			{
				data = (UBYTE *) my_bit_map.Planes[ depth ] + offset;
				*data 							= shot[ sht ].save1[depth];
				*(data+1) 					= shot[ sht ].save2[depth];
				*(data+RWIDTH/8) 		= shot[ sht ].save3[depth];
				*(data+RWIDTH/8+1) 	= shot[ sht ].save4[depth];
			}

			/* Bewegen */
			shot[ sht ].posx += shot[ sht ].speedx;
			shot[ sht ].posy += shot[ sht ].speedy;

			/* Testen, ob der Schuss anstoesst */
			/* X_Richtung */
			boden = level[ shot[ sht ].posy/16/TILESHEIGHT ][ shot[ sht ].posx/16/(TILESWIDTH*8) ];
			if( boden >= BODEN )
			{
				/* Es ist ein Hindernis da */
				shot[ sht ].used = 0;
				if( ( (shot[ sht ].posy/16) & (TILESHEIGHT-1) ) > TILESHEIGHT-3 )
				{
					if( boden == 18 ) /* glas */
					{
						/* Schuss kommt von unten */
						if( ( (shot[ sht ].posx/16) & (TILESWIDTH*8-1) ) >= 2 )
						{
							if( ( (shot[ sht ].posx/16) & (TILESWIDTH*8-1) ) < (TILESWIDTH*8-1) )
							{
								/* Glas bricht */
						    BltBitMap(
						      &my_bit_map2, /* Source                 */
						      2*16, 						/* Position, source. */
						      16, 					/*          - " -         */
						      &my_bit_map, /* Destination.           */
							    (shot[ sht ].posx/16) & 0xfff0 , 						/* Position, destin. */
							    (shot[ sht ].posy/16) & 0xfff0,					 	/*          - " -         */
						      TILESWIDTH*8, TILESHEIGHT,      /* Width and height.      */
						      0xC0,        /* Normal copy.           */
						      0xFF,        /* All bitplanes.         */
						      NULL );      /* No temporary storage.  */

								level[ shot[ sht ].posy/16/TILESHEIGHT ][ shot[ sht ].posx/16/(TILESWIDTH*8) ] = 14;
								PlaySound( glas, MAXVOLUME/2, LEFT0, NORMALRATE, 1 );
							}
							else
							{
								boden = 0;
							}
						}
						else
						{
							boden = 0;
						}
					}
					if( boden != 18 )
					{
					  SetAPen( &my_rast_port, 1 );
						WritePixel( &my_rast_port, shot[ sht ].posx/16, shot[ sht ].posy/16 - rand()%2 - 1 );
					}
				}
				else
				{
					PlaySound( shoth1, MAXVOLUME/2, RIGHT0, NORMALRATE, 1 );
				}
			}

			/* Testen, ob der Schuss jemanden trifft */
			if( ( abs( shot[ sht ].posx - posx ) <= 48 ) && ( abs( shot[ sht ].posy - posy ) <= 48 ) )
			{
				if( energy > 0 )
				{
					if( shot[ sht ].owner != 100 )
					{
						shotat = 1;
						shot[ sht ].used = 0;
					}
				}
			}
			for( fo=0; fo<FOESMAX; fo++ )
			{
				if( ( abs( shot[ sht ].posx - foe[ fo ].posx ) <= 64 ) && ( abs( shot[ sht ].posy - foe[ fo ].posy ) <= 64 ) )
				{
					if( (shot[ sht ].owner == 100/*!= fo*/) && (foe[ fo ].used == 2 /*!= 0*/) )
					{
						foe[ fo ].used = 3;
						shot[ sht ].used = 0;
					}
				}
			}

			if( shot[ sht ].posx/16 < 0 )
			{
				shot[ sht ].used = 0;
			}
			if( shot[ sht ].posx/16 > RWIDTH - SHOTWIDTH )
			{
				shot[ sht ].used = 0;
			}
			if( shot[ sht ].posy/16 < 0 )
			{
				shot[ sht ].used = 0;
			}
			if( shot[ sht ].posy/16 > RHEIGHT - SHOTHEIGHT -1 ) /* -1, damit ein schuss in der rechten unteren ecke nicht zum absturz fuehrt*/
			{
				shot[ sht ].used = 0;
			}
		}
	}
}
 
void drawshots( void )
{
	int sht;
	int offset;
	int depth;
	UBYTE *data;

  SetAPen( &my_rast_port, 1 );

	for( sht=SHOTSMAX-1; sht>=0; sht-- )
	{
		if( shot[ sht ].used == 2 )
		{
			/* Regulaerer Schuß  */
			offset = RWIDTH/8 * (shot[ sht ].posy/16) + shot[ sht ].posx/16/8;
			for( depth=0; depth<DEPTH; depth++ )
			{
				data = (UBYTE *) my_bit_map.Planes[ depth ] + offset;
				shot[ sht ].save1[depth] = *data;
				shot[ sht ].save2[depth] = *(data+1);
				shot[ sht ].save3[depth] = *(data+RWIDTH/8);
				shot[ sht ].save4[depth] = *(data+RWIDTH/8+1);
			}

			WritePixel( &my_rast_port, shot[ sht ].posx/16, shot[ sht ].posy/16 );
			WritePixel( &my_rast_port, shot[ sht ].posx/16+1, shot[ sht ].posy/16 );
			WritePixel( &my_rast_port, shot[ sht ].posx/16, shot[ sht ].posy/16+1 );
			WritePixel( &my_rast_port, shot[ sht ].posx/16+1, shot[ sht ].posy/16+1 );
		}
	}
}


void launchshot( sposx, sposy, speedx, speedy, owner )
int sposx, sposy, speedx, speedy, owner;
{
	int sht;

	for( sht=0; sht<SHOTSMAX; sht++ )
	{
		if( shot[ sht ].used == 0 )
		{
			shot[ sht ].used = 1;
			shot[ sht ].posx = sposx;
			shot[ sht ].posy = sposy;
			shot[ sht ].speedx = speedx;
			shot[ sht ].speedy = speedy;
			shot[ sht ].owner = owner;

		  if( fires )
			{
				if( owner == 100 )
				{
				  StopSound( LEFT1 );
					PlaySound( fires, MAXVOLUME, LEFT1, NORMALRATE, 1 );
				}
				else
				{
				  StopSound( LEFT1 );
					PlaySound( fires, MAXVOLUME/2, LEFT1, NORMALRATE, 1 );
				}
			}

			sht = SHOTSMAX;
		}
	}
}

void walk( void )
{
	int posneux, posneuy;
	int boden;

	if( energy > 0 )
	{
		if( aimmode == 0 )
		{
			posneux = posx;
			posneuy = posy;
	
			/* Nur laufen, wenn nicht im aimmode */
	    if( value & DOWN )
			{
				posneuy += PLSPEED;
				dir = 4;
			}
	    if( value & UP )
			{
				posneuy -= PLSPEED;
				dir = 0;
			}
	    if( value & RIGHT )
			{
				posneux += PLSPEED;
		
				dir = 2;
		
				if( value & UP )
				{
					posneux = posneux - PLSPEED + PLSPEED7;
					posneuy = posneuy + PLSPEED - PLSPEED7;
					dir = 1;
				}
				if( value & DOWN )
				{
					posneux = posneux - PLSPEED + PLSPEED7;
					posneuy = posneuy - PLSPEED + PLSPEED7;
					dir = 3;
				}
			}
	    if( value & LEFT )
			{
				posneux -= PLSPEED;
		
				dir = 6;
		
				if( value & UP )
				{
					posneux = posneux + PLSPEED - PLSPEED7;
					posneuy = posneuy + PLSPEED - PLSPEED7;
					dir = 7;
				}
				if( value & DOWN )
				{
					posneux = posneux + PLSPEED - PLSPEED7;
					posneuy = posneuy - PLSPEED + PLSPEED7;
					dir = 5;
				}
			}
	
			/* Testen, ob der Spieler in die gewuenschte Richtung laufen kann */
			/* X_Richtung */
			boden = level[ posy/16/TILESHEIGHT ][ posneux/16/(TILESWIDTH*8) ];
			if( boden >= BODEN )
			{
				/* Es ist ein Hindernis da */
				posneux = posx;				
			}
			/* Y_Richtung */
			boden = level[ posneuy/16/TILESHEIGHT ][ posx/16/(TILESWIDTH*8) ];
			if( boden >= BODEN )
			{
				/* Es ist ein Hindernis da */
				posneuy = posy;
			}
		
			posx = posneux;
			posy = posneuy;
		
			if( posx/16 < TILESWIDTH*8/2 )
			{
				posx = 16*TILESWIDTH*8/2;
			}
			if( posx/16 >= RWIDTH - TILESWIDTH*8/2 )
			{
				posx = 16*(RWIDTH - TILESWIDTH*8/2);
			}
			if( posy/16 < TILESHEIGHT/2 )
			{
				posy = 16*TILESHEIGHT/2;
			}
			if( posy/16 >= RHEIGHT - TILESHEIGHT/2 )
			{
				posy = 16*(RHEIGHT - TILESHEIGHT/2);
			}
		}
	}
	else
	{
		/* Image fuer totes maennchen */
		dir = 9;
	}
}

void screenscrolling( void )
{
	int delx, dely;
	int spdx, spdy;

	delx = posx/16 - DWIDTH/2  -  my_ras_info.RxOffset;
	dely = posy/16 - DHEIGHT/2  -  my_ras_info.RyOffset;

	/* Wenn das Maennchen den Rand bis auf ein drittel erreicht hat,
			den Bildschirm neu zentrieren */
	if( abs( delx ) > DWIDTH/6 )
	{
		docenter |= 4;
	}
	if( abs( dely ) > DHEIGHT/7 )
	{
		docenter |= 2;
	}

	if( docenter != 0 )
	{
		spdx = 0;
		if( (docenter & 4) != 0 )
		{
			if( delx > 0 ) spdx = SCROLLSPEED;
			if( delx < 0 ) spdx = -SCROLLSPEED;
			spdx *= (PLSPEED+SCROLLSPEED-1)/SCROLLSPEED;
		}

		spdy = 0;
		if( (docenter & 2) != 0 )
		{
			if( dely > 0 ) spdy = SCROLLSPEED;
			if( dely < 0 ) spdy = -SCROLLSPEED;
			spdy *= (PLSPEED+SCROLLSPEED-1)/SCROLLSPEED;
		}

		if( (spdx != 0) || (spdy != 0) )
		{
	    my_ras_info.RxOffset += spdx/16;
	    my_ras_info.RyOffset += spdy/16;

	    /* Have we reached the left side? */
	    if( my_ras_info.RxOffset < 0 )
			{
				my_ras_info.RxOffset = 0;
			}
	
	    /* Have we reached the right (Raster width - Display width) side? */
	    if( my_ras_info.RxOffset >= RWIDTH - DWIDTH )
			{
				my_ras_info.RxOffset = RWIDTH - DWIDTH;
			}
	
	    /* Have we reached the top side? */
	    if( my_ras_info.RyOffset < 0 )
			{
				my_ras_info.RyOffset = 0;
			}
	
	    /* Have we reached the bottom (Raster height - Display height) side? */
  	  if( my_ras_info.RyOffset >= RHEIGHT - DHEIGHT )
  	  {	
  	  	my_ras_info.RyOffset = RHEIGHT - DHEIGHT;
  	  }
		}

		if( spdx == 0 ) docenter &= 255-4;
		if( spdy == 0 ) docenter &= 255-2;
	}
}

void shoot( void )
{
	if( energy > 0 )
	{
	  value = Joystick( PORT2 );
	    
	  if( value & FIRE )
		{
			int xoff, yoff;
	
			if( !((value & RIGHT) || (value & LEFT) || (value & UP) || (value & DOWN)) ) 
			{
				/* Wenn Feuer im Stillstand gedrueckt wird, aimmode einschalten */
				if( aimmode == 0 )
				{
					aimed = 0;
				}
				aimmode = 1;
			}
			else
			{
				if( fire == 0 )
				{
					launchshot( posx, posy, sincos( dir*45 ) * SHOTSPEED / 16384, -sincos( dir*45+90 ) * SHOTSPEED / 16384, 100);
				}
			}
	
			fire = 1;
	
			if( aimmode == 1 )
			{
				/* Nur zielen, wenn aimmode == 1 */
		    if( value & RIGHT )
				{
					aimdir += AIMSPEED;
					while( aimdir >= 360 ) aimdir -= 360;
					aimed = 1;
				}
		    if( value & LEFT )
				{
					aimdir -= AIMSPEED;
					while( aimdir < 0 ) aimdir += 360;
					aimed = 1;
				}
		
				xoff = sincos( aimdir ) * AIMLENGTH / 16384;
				yoff = sincos( aimdir+90 ) * AIMLENGTH / 16384;
	
				aimposx = posx/16 + xoff - TILESWIDTH*8/2;
				aimposy = posy/16 - yoff - TILESHEIGHT/2;
		
				if( aimposx < 0 )
				{
					aimposx = 0;
				}
				if( aimposx > RWIDTH - TILESWIDTH*8 )
				{
					aimposx = RWIDTH - TILESWIDTH*8;
				}
				if( aimposy < 0 )
				{
					aimposy = 0;
				}
				if( aimposy > RHEIGHT - TILESHEIGHT )
				{
					aimposy = RHEIGHT - TILESHEIGHT;
				}
	
				/* Maennchen in Richtung des Zielens drehen */
				dir = 0;
				if( aimdir < 23 )
				{
					dir = 0;
				}	
				else if( aimdir < 68 )
				{
					dir = 1;
				}	
				else if( aimdir < 113 )
				{
					dir = 2;
				}	
				else if( aimdir < 158 )
				{
					dir = 3;
				}	
				else if( aimdir < 203 )
				{
					dir = 4;
				}	
				else if( aimdir < 248 )
				{
					dir = 5;
				}	
				else if( aimdir < 293 )
				{
					dir = 6;
				}	
				else if( aimdir < 338 )
				{
					dir = 7;
				}	
	
			}
	
		}
		else
		{
			if( fire == 1 )
			{
				/* Feuer wird gerade losgelassen. */
				if( (aimmode == 1) && (aimed == 0) )
				{
					/* Der Spieler hat im Stand Fire gedrueck, aber nicht ge-
							aimt. Also Standschuss */
					launchshot( posx, posy, sincos( aimdir ) * SHOTSPEED / 16384, -sincos( aimdir+90 ) * SHOTSPEED / 16384, 100 );
				}
				fire = 0;
				/* aimmode ausschalten */
				aimmode = 0;
			}
		}
	}
}

void drehfoe( fo )
int fo;
{
	foe[ fo ].angle += (rand() % 45) - 23;
	while( foe[ fo ].angle >= 360 ) foe[ fo ].angle -= 360;
	while( foe[ fo ].angle < 0 ) foe[ fo ].angle += 360;
}

void drehfoe2( fo )
int fo;
{
	foe[ fo ].angle += 97;
	while( foe[ fo ].angle >= 360 ) foe[ fo ].angle -= 360;
	while( foe[ fo ].angle < 0 ) foe[ fo ].angle += 360;
}

void cleanandmovefoes( void )
{
	int fo;
	int offset;
	int depth;
	UBYTE *data;
	int boden;
	int delx, dely;
	int foneux, foneuy;

	for( fo=FOESMAX-1; fo>=0; fo-- )
	{
		if( foe[ fo ].used == 0 )
		{
			foe[ fo ].used = 1;
			foe[ fo ].posx = rand() % (16*RWIDTH);
			foe[ fo ].posy = rand() % (16*RHEIGHT);
			foe[ fo ].angle = rand() % 360;
		}

		if( foe[ fo ].used == 1 )
		{
			/* Neu geschaffener Foe; ist noch nicht gezeichnet; und muss also
					auch nicht beseitigt werden */
			foe[ fo ].used = 2;
		}
		else if( foe[ fo ].used == 2 )
		{
			/* Regulaerer Foe */
	    BltBitMap(
	      &my_bit_map2, /* Source                 */
	      fo*16, 						/* Position, source. */
	      128, 					/*          - " -         */
	      &my_bit_map, /* Destination.           */
		    foe[ fo ].posx/16-TILESWIDTH*8/2, 						/* Position, destin. */
		    foe[ fo ].posy/16-TILESHEIGHT/2,					 	/*          - " -         */
	      TILESWIDTH*8, TILESHEIGHT,      /* Width and height.      */
	      0xC0,        /* Normal copy.           */
	      0xFF,        /* All bitplanes.         */
	      NULL );      /* No temporary storage.  */

			/* Bewegen */
			delx = sincos( foe[ fo ].angle ) * SPEED / 16384;
			dely = -sincos( foe[ fo ].angle+90 ) * SPEED / 16384;

			foneux = foe[ fo ].posx + delx;
			foneuy = foe[ fo ].posy + dely;
			
			/* Testen, ob der Foe anstoesst */
			boden = level[ foneuy/16/TILESHEIGHT ][ foneux/16/(TILESWIDTH*8) ];
			if( boden >= BODEN )
			{
				/* Es ist ein Hindernis da */
				drehfoe( fo );
				foneux = foe[ fo ].posx;
				foneuy = foe[ fo ].posy;
			}

			foe[ fo ].posx = foneux;
			foe[ fo ].posy = foneuy;

			if( foe[ fo ].posx/16 < TILESWIDTH*8/2 )
			{
				foe[ fo ].posx = 16*TILESWIDTH*8/2;
				drehfoe2( fo );
			}
			if( foe[ fo ].posx/16 >= RWIDTH - TILESWIDTH*8/2 )
			{
				foe[ fo ].posx = 16*(RWIDTH - TILESWIDTH*8/2);
				drehfoe2( fo );
			}
			if( foe[ fo ].posy/16 < TILESHEIGHT/2 )
			{
				foe[ fo ].posy = 16*TILESHEIGHT/2;
				drehfoe2( fo );
			}
			if( foe[ fo ].posy/16 >= RHEIGHT - TILESHEIGHT/2 )
			{
				foe[ fo ].posy = 16*(RHEIGHT - TILESHEIGHT/2);
				drehfoe2( fo );
			}

		}
	}
}

void movefoes( void )
{
	int fo;
	int offset;
	int depth;
	UBYTE *data;
	int boden;
	int delx, dely;
	int foneux, foneuy;
	int fodir;
	int shoot;
	int sdelx, sdely, sdist;
	int free;

	for( fo=FOESMAX-1; fo>=0; fo-- )
	{
		if( foe[ fo ].used == 0 )
		{
	    vsprite[ fo ].X = 0;
	    vsprite[ fo ].Y = SDUMPY;

			free = rand() % fonum;

			foe[ fo ].posx = foedwell[ free ].x*16;
			foe[ fo ].posy = foedwell[ free ].y*16;
			if( (abs( foe[ fo ].posx - posx ) < FOEDOORX) && (abs( foe[ fo ].posy - posy ) < FOEDOORY) )
			{
				if( foedwell[ free ].foes > 0 )
				{
					if( (gametime - DWELLDELAY) >= foedwell[ free ].delay )
					{
						foedwell[ free ].delay = gametime;
						foedwell[ free ].foes--;

						foe[ fo ].used = 1;
						foe[ fo ].angle = rand() % 360;
						foe[ fo ].stepdist = STEP;
						foe[ fo ].step = 0;
						foe[ fo ].shootinterv = FOEINTERV;
						foe[ fo ].shout = 0;
					}
				}
			}
		}

		if( foe[ fo ].used == 1 )
		{
			/* Neu geschaffener Foe; ist noch nicht gezeichnet; und muss also
					auch nicht beseitigt werden */
			foe[ fo ].used = 2;
		}
		else if( foe[ fo ].used == 2 )
		{
			/* Regulaerer Foe */

			shoot = 0;
			if( foe[ fo ].shootinterv < FOESHAT )
			{
				/* Der Foe kann schiessen */
				if( (abs( foe[ fo ].posx - posx ) < FOEDIST) && (abs( foe[ fo ].posy - posy ) < FOEDIST) )
				{
					/* Der Foe ist nahe genug dran */
					if( foe[ fo ].shootinterv <= 0 )
					{
						foe[ fo ].shootinterv = FOEINTERV;
						sdelx = posx-foe[ fo ].posx;
						sdely = posy-foe[ fo ].posy;
						if( ( sdelx>=0 ) && (sdely<0 ) )
						{
							foe[ fo ].angle = 180 / 3.141592 * atan( (float) sdelx / (float) (-sdely) );
						}
						if( ( sdelx>0 ) && (sdely>=0 ) )
						{
							foe[ fo ].angle = -180 / 3.141592 * atan( (float) (-sdely) / (float) (sdelx) ) + 90;
						}
						if( ( sdelx<=0 ) && (sdely>0 ) )
						{
							foe[ fo ].angle = 180 / 3.141592 * atan( (float) sdelx / (float) (-sdely) ) + 180;
						}
						if( ( sdelx<0 ) && (sdely<0 ) )
						{
							foe[ fo ].angle = -180 / 3.141592 * atan( (float) (-sdely) / (float) (sdelx) ) + 270;
						}

						while( foe[ fo ].angle<0 ) foe[ fo ].angle += 360;

						/* Pruefen, ob der Weg frei ist */
						for( free=1; free<8; free++ )
						{
							if( level[ (foe[ fo ].posy+sdely/free)/16/TILESHEIGHT ][ (foe[ fo ].posx+sdelx/free)/16/(TILESWIDTH*8) ] >= BODEN )
							{
								free = 1000;
							}
						}
						if( free<1000 )
						{
							launchshot( foe[ fo ].posx, foe[ fo ].posy, sincos( foe[ fo ].angle ) * FSHOTSPEED / 16384, -sincos( foe[ fo ].angle+90 ) * FSHOTSPEED / 16384, fo );
						}
						shoot=2;
					}
					else
					{
						if( foe[ fo ].shout!=1 )
						{
							PlaySound( attacks, MAXVOLUME/2, LEFT0, NORMALRATE, 1 );
						}
						foe[ fo ].shout = 1;
						shoot=1;
						foe[ fo ].shootinterv--;
					}
				}
				else
				{
					foe[ fo ].shootinterv--;
					foe[ fo ].shout = 0;
				}
			}
			else
			{
				foe[ fo ].shootinterv--;
			}


			if( shoot == 1 )
			{
				foneux = foe[ fo ].posx;
				foneuy = foe[ fo ].posy;
			}
			else
			{
				/* Bewegen */

				delx = sincos( foe[ fo ].angle ) * SPEED / 16384;
				dely = -sincos( foe[ fo ].angle+90 ) * SPEED / 16384;
	
				foneux = foe[ fo ].posx + delx;
				foneuy = foe[ fo ].posy + dely;
			}
				
			/* Testen, ob der Foe zu weit weggelaufen ist */
			if( (abs( foe[ fo ].posx - posx ) > FOEVANISH) || (abs( foe[ fo ].posy - posy ) > FOEVANISH) )
			{
				/* Foe verschwindet */
				foe[ fo ].used = 0;
			}

			/* Testen, ob der Foe anstoesst */
			boden = level[ foneuy/16/TILESHEIGHT ][ foneux/16/(TILESWIDTH*8) ];
			if( boden >= BODEN )
			{
				/* Es ist ein Hindernis da */
				drehfoe( fo );
				foneux = foe[ fo ].posx;
				foneuy = foe[ fo ].posy;
			}
			else
			{
				/* Fuesse bewegen */
				if( (foe[ fo ].posx != foneux) || (foe[ fo ].posy != foneuy) )
				{
					foe[ fo ].stepdist -= SPEED;
					if( foe[ fo ].stepdist < 0 )
					{
						foe[ fo ].stepdist += STEP;
						foe[ fo ].step++;
					}
				}
			}
	
			foe[ fo ].posx = foneux;
			foe[ fo ].posy = foneuy;

			if( foe[ fo ].posx/16 < TILESWIDTH*8/2 )
			{
				foe[ fo ].posx = 16*TILESWIDTH*8/2;
				drehfoe2( fo );
			}
			if( foe[ fo ].posx/16 >= RWIDTH - TILESWIDTH*8/2 )
			{
				foe[ fo ].posx = 16*(RWIDTH - TILESWIDTH*8/2);
				drehfoe2( fo );
			}
			if( foe[ fo ].posy/16 < TILESHEIGHT/2 )
			{
				foe[ fo ].posy = 16*TILESHEIGHT/2;
				drehfoe2( fo );
			}
			if( foe[ fo ].posy/16 >= RHEIGHT - TILESHEIGHT/2 )
			{
				foe[ fo ].posy = 16*(RHEIGHT - TILESHEIGHT/2);
				drehfoe2( fo );
			}

			/* Sprite positionieren */
		  if( (foe[ fo ].posx/16 >= my_ras_info.RxOffset - 8) &&
					(foe[ fo ].posx/16 < my_ras_info.RxOffset + DWIDTH + 8) &&
					(foe[ fo ].posy/16 >= my_ras_info.RyOffset - SFOEHEIGHT/2) &&
					(foe[ fo ].posy/16 < my_ras_info.RyOffset + DHEIGHT + SFOEHEIGHT/2) )
			{
		    vsprite[ fo ].X = foe[ fo ].posx/16-8 - my_ras_info.RxOffset;
		    vsprite[ fo ].Y = foe[ fo ].posy/16-SFOEHEIGHT/2 -my_ras_info.RyOffset;

				fodir = foe[ fo ].angle + 22;
				while( fodir>=360 ) fodir -= 360;
				fodir = fodir/45;
			  vsprite[ fo ].ImageData = (UWORD *) (spritedata + 40 * (fodir*2 + (foe[ fo ].step&1) ));
			}
			else
			{
		    vsprite[ fo ].X = 0;
		    vsprite[ fo ].Y = SDUMPY;
			}
		}
		else if( foe[ fo ].used == 3 )
		{
			/* Erschossener foe */
			/* Blutfleck malen */

		  BltMaskBitMapRastPort(
		    &my_bit_map2, 	/* Source                 */
		    16, 16,    			/* Position, source.      */
		    &my_rast_port, /* Destination.           */
		    foe[ fo ].posx/16-TILESWIDTH*8/2, 						/* Position, destination. */
		    foe[ fo ].posy/16-TILESHEIGHT/2,					 	/*          - " -         */
		    TILESWIDTH*8, TILESHEIGHT,      /* Width and height.      */
		    0xe0,        	/* Normal copy.           */
				maskplane );	/* Maske */

			PlaySound( foedies, MAXVOLUME/2, RIGHT0, NORMALRATE, 1 );

		  vsprite[ fo ].ImageData = (UWORD *) (spritedata + 40 * 18 );
			foe[ fo ].shootinterv = FOEBLEIBT;
			foe[ fo ].used = 4;
		}
		else if( foe[ fo ].used == 4 )
		{
			/* toter foe */
			foe[ fo ].shootinterv--;
			if( foe[ fo ].shootinterv<0 )
			{
				foe[ fo ].used = 0;
			}
			else
			{
			/* Sprite positionieren */
			  if( (foe[ fo ].posx/16 >= my_ras_info.RxOffset - 8) &&
						(foe[ fo ].posx/16 < my_ras_info.RxOffset + DWIDTH + 8) &&
						(foe[ fo ].posy/16 >= my_ras_info.RyOffset - SFOEHEIGHT/2) &&
						(foe[ fo ].posy/16 < my_ras_info.RyOffset + DHEIGHT + SFOEHEIGHT/2) )
				{
			    vsprite[ fo ].X = foe[ fo ].posx/16-8 - my_ras_info.RxOffset;
			    vsprite[ fo ].Y = foe[ fo ].posy/16-SFOEHEIGHT/2 -my_ras_info.RyOffset;
				  vsprite[ fo ].ImageData = (UWORD *) (spritedata + 40 * 18 );
				}
				else
				{
			    vsprite[ fo ].X = 0;
			    vsprite[ fo ].Y = SDUMPY;
				}
			}
		}
	}
}

void drawfoes( void )
{
	int fo;
	int offset;
	int depth;
	UBYTE *data;

  SetAPen( &my_rast_port, 1 );

	for( fo=0; fo<FOESMAX; fo++ )
	{
		if( foe[ fo ].used == 2 )
		{
			/* Regulaerer Foe */
	    BltBitMap(
	      &my_bit_map, /* Source                 */
		    foe[ fo ].posx/16-TILESWIDTH*8/2, 						/* Position, source. */
		    foe[ fo ].posy/16-TILESWIDTH*8/2,					 	/*          - " -         */
	      &my_bit_map2, /* Destination.           */
	      fo*16, 						/* Position, destination. */
	      128, 					/*          - " -         */
	      TILESWIDTH*8, TILESHEIGHT,      /* Width and height.      */
	      0xC0,        /* Normal copy.           */
	      0xFF,        /* All bitplanes.         */
	      NULL );      /* No temporary storage.  */

		  BltMaskBitMapRastPort(
		    &my_bit_map2, 	/* Source                 */
		    0, 0,    			/* Position, source.      */
		    &my_rast_port, /* Destination.           */
		    foe[ fo ].posx/16-TILESWIDTH*8/2, 						/* Position, destination. */
		    foe[ fo ].posy/16-TILESHEIGHT/2,					 	/*          - " -         */
		    TILESWIDTH*8, TILESHEIGHT,      /* Width and height.      */
		    0xe0,        	/* Normal copy.           */
				maskplane );	/* Maske */

		}
	}
}

void createsprites( void )
{
	int a, sprit;
	UBYTE *wo;

  spritedata = (UWORD *) AllocMem( 2000, MEMF_CHIP|MEMF_CLEAR );
	if( spritedata == NULL ) clean_up( "ERROR: Couldn't allocate sprite memory\n");

	/* Maennchen in Sprite umwandeln */
	for( sprit=0; sprit<19; sprit++ )
	{
		wo = (UBYTE *) (spritedata + 40 * sprit);

		for( a=5; a<12; a++ )
		{
			*wo++=(UBYTE) tiles[ 40+sprit ][ 0 ][ a ][ 0 ];
			*wo++=(UBYTE) tiles[ 40+sprit ][ 0 ][ a ][ 1 ];
			*wo++=(UBYTE) tiles[ 40+sprit ][ 1 ][ a ][ 0 ];
			*wo++=(UBYTE) tiles[ 40+sprit ][ 1 ][ a ][ 1 ];
		}
		*wo++=0;
		*wo++=0;
	}
}

void initsprites( void )
{
  /* 6. Initialize the GelsInfo structure: */

  /* All sprites except the first two may be used to draw */
  /* the VSprites: ( 11111100 = 0xFC )                    */
  ginfo.sprRsrvd = 0xFF;
  /* If we do not exclude the first two sprites, the mouse */
  /* pointer's colours may be affected.                    */


  /* Give the GelsInfo structure some memory: */
  ginfo.nextLine = &nextline[0];
  ginfo.lastColor = &lastcolor[0];


  /* Give the Rastport a pointer to the GelsInfo structure: */
  my_rast_port.GelsInfo = &ginfo;

  
  /* Give the GelsInfo structure to the system: */
  InitGels( &head, &tail, &ginfo );


  /* 7. Initialize the VSprite structure: */

	{
		int loop;

	  for( loop = 0; loop < MAXVSPRITES; loop++ )
	  {
		  vsprite[ loop ].Flags = VSPRITE; /* It is a VSprite.            */
		  vsprite[ loop ].X = 0;           /* X position.                 */
		  vsprite[ loop ].Y = SDUMPY;           /* Y position.                 */
		  vsprite[ loop ].Height = 6;     /* 16 lines tall.              */
		  vsprite[ loop ].Width = 2;       /* Two bytes (16 pixels) wide. */
		  vsprite[ loop ].Depth = 2;       /* Two bitplanes, 4 colours.   */


		  /* Pointer to the sprite data: */
		  vsprite[ loop ].ImageData = spritedata;

		  /* Pointer to the colour table: */
		  vsprite[ loop ].SprColors = colour_table;

		  /* 8. Add the VSprites to the VSprite list: */
		  AddVSprite( &vsprite[ loop ], &my_rast_port );

		  /* The VSprite is in the list. */
		  vsprite_on[ loop ] = TRUE;

		}
		vsprite[ MAXVSPRITES-1 ].Flags |= (MUSTDRAW & VSOVERFLOW);
	}
}

/* Pointers to the three sound effects: */
CPTR explosion;
CPTR background;


/* Declare the functions in this module: */
void free_memory();
void pause();

void sound( void )
{
	printf("\nE A S Y - S O U N D\n");
	printf("Amiga C Club (ACC)\nAnders Bjerin\nTulevagen 22\n");
	printf("181 41  LIDINGO\nSWEDEN\n\n");
  printf("1. Prepare the sound Fire.snd\n");
	fires = PrepareSound( "Fire.snd" );
  if( !fires )
	  free_memory( "Could not prepare the sound effect!" );

  printf("   Prepare the sound Explosion.snd\n");
	explosion = PrepareSound( "Explosion.snd" );
  if( !explosion )
	  free_memory( "Could not prepare the sound effect!" );

  printf("   Prepare the sound Background.snd\n");
	background = PrepareSound( "Background.snd" );
  if( !background )
	  free_memory( "Could not prepare the sound effect!" );



  printf("2. Play the sound\n");

  /* Start with some atmospheric background sounds: */
  PlaySound( background, MAXVOLUME/2, LEFT0, NORMALRATE, NONSTOP );
  PlaySound( background, MAXVOLUME/2, RIGHT0, NORMALRATE, NONSTOP );
	pause( 5000 );

  PlaySound( fires, MAXVOLUME, LEFT1, NORMALRATE, 2 );
  pause( 4000 );

  PlaySound( explosion, MAXVOLUME, RIGHT1, NORMALRATE, 2 );
  pause( 10000 );



  printf("3. Stop the audio channels\n");
  StopSound( LEFT0 );
  StopSound( LEFT1 );
  StopSound( RIGHT0 );
  StopSound( RIGHT1 );


  printf("4. Remove the sound effects\n");
  free_memory( "THE END" );
}


void free_memory( message )
STRPTR message;
{
	printf("%s\n\n", message );

  /* It is not dangerous to try to remove a sound that has not been     */
	/* prepared. We can therefore try to remove all sounds, even if some  */
	/* have not been initialized. (However, all channels that are playing */
	/* the sound must have been stopped before you may remove the sound!  */
  RemoveSound( fires );
  RemoveSound( explosion );
  RemoveSound( background );

  exit();
}


void pause( time )
int time;
{
	int loop;
	for( loop=0; loop < time*100; loop++ )
	  ;
}



/* Returns all allocated resources: */
void clean_up( message )
STRPTR message;
{
  int loop;

  /* Free automatically allocated display structures: */
  FreeVPortCopLists( &my_view_port );
  FreeCprList( my_view.LOFCprList );
  
  if( spritedata ) FreeMem( spritedata, 2000 );

  /* Deallocate the display memory, BitPlane for BitPlane: */
  for( loop = 0; loop < DEPTH; loop++ )
    if( my_bit_map.Planes[ loop ] )
      FreeRaster( my_bit_map.Planes[ loop ], RWIDTH, RHEIGHT );

  /* Deallocate the second display memory, BitPlane for BitPlane: */
  for( loop = 0; loop < DEPTH2; loop++ )
    if( my_bit_map2.Planes[ loop ] )
      FreeRaster( my_bit_map2.Planes[ loop ], RWIDTH2, RHEIGHT2 );

  if( maskplane )
    FreeRaster( maskplane, RWIDTH2, RHEIGHT2 );

  /* Deallocate the ColorMap: */
  if( my_view_port.ColorMap ) FreeColorMap( my_view_port.ColorMap );

  /* Close the Graphics library: */
  if( GfxBase ) CloseLibrary( GfxBase );

  /* Close the Intuition library: */
  if( IntuitionBase ) CloseLibrary( IntuitionBase );

  /* Print the message and leave: */
  /*printf( "%s\n", message ); */
  exit( 0 );
}

void energybar( void )
{
	UWORD *wo;
	int heit, divide;

	divide = energy * 10 / ENERGY;
	wo = (UWORD *) (maskplane+RWIDTH2/8*140 + 14*4);
	for( heit=0; heit<10; heit++ )
	{
		wo++;
		if( (10-heit) <= divide )
		{
			*wo++ = 0xffff;
		}
		else
		{
			*wo++ = 0x0000;
		}
	}
}

void clrrast( void )
{
	int loop;

  for( loop = 0; loop < DEPTH; loop++ )
  {
    /* Clear the display memory with help of the Blitter: */
    BltClear( my_bit_map.Planes[ loop ], RASSIZE( RWIDTH, RHEIGHT ), 0 );
  }
}


void title( void )
{
	int mesn;

	mesn = 0;

	while( (! ( Joystick( PORT2 ) & FIRE )) && (! ( Joystick( PORT1 ) & FIRE )) )
	{

		{
			char *text;
			char text2[80];
			int wart;
	
			text = "'EM ALL UP";
			SetAPen( &my_rast_port, 5 );
			Move( &my_rast_port, 224, 134 );
			Text( &my_rast_port, text, strlen( text ) );
	
			SetAPen( &my_rast_port, 0 );
			SetBPen( &my_rast_port, 0 );
			SetDrMd( &my_rast_port, JAM1 );
			RectFill( &my_rast_port, 186, 147, 319, 168 );
	
			SetAPen( &my_rast_port, 4 );
	
			if( mesn == 0 )
			{
				sprintf( text2, "SHOOT EM ALL UP" );
				Move( &my_rast_port, 186, 153 );
				Text( &my_rast_port, text2, strlen( text2 ) );
	
				sprintf( text2, "'96 Thomas Lange" );
				Move( &my_rast_port, 186, 166 );
				Text( &my_rast_port, text2, strlen( text2 ) );
			}
	
			if( mesn == 1 )
			{
				sprintf( text2, " CREDITS: " );
				Move( &my_rast_port, 186, 153 );
				Text( &my_rast_port, text2, strlen( text2 ) );
	
				sprintf( text2, " " );
				Move( &my_rast_port, 186, 166 );
				Text( &my_rast_port, text2, strlen( text2 ) );
			}
	
			if( mesn == 2 )
			{
				sprintf( text2, "Code & GFX:" );
				Move( &my_rast_port, 186, 153 );
				Text( &my_rast_port, text2, strlen( text2 ) );
	
				sprintf( text2, "Thomas Lange" );
				Move( &my_rast_port, 186, 166 );
				Text( &my_rast_port, text2, strlen( text2 ) );
			}
	
			if( mesn == 3 )
			{
				sprintf( text2, "Music: boner.mod" );
				Move( &my_rast_port, 186, 153 );
				Text( &my_rast_port, text2, strlen( text2 ) );
	
				sprintf( text2, "by Jon Pickard" );
				Move( &my_rast_port, 186, 166 );
				Text( &my_rast_port, text2, strlen( text2 ) );
			}
	
			if( mesn == 4 )
			{
				sprintf( text2, "and marky.mod by" );
				Move( &my_rast_port, 186, 153 );
				Text( &my_rast_port, text2, strlen( text2 ) );
	
				sprintf( text2, "Black Shadow" );
				Move( &my_rast_port, 186, 166 );
				Text( &my_rast_port, text2, strlen( text2 ) );
			}
	
			if( mesn == 5 )
			{
				sprintf( text2, "Both taken from" );
				Move( &my_rast_port, 186, 153 );
				Text( &my_rast_port, text2, strlen( text2 ) );
	
				sprintf( text2, "AMINET" );
				Move( &my_rast_port, 186, 166 );
				Text( &my_rast_port, text2, strlen( text2 ) );
			}
	
			if( mesn == 6 )
			{
				sprintf( text2, "Read the docs" );
				Move( &my_rast_port, 186, 153 );
				Text( &my_rast_port, text2, strlen( text2 ) );
	
				sprintf( text2, "for more info" );
				Move( &my_rast_port, 186, 166 );
				Text( &my_rast_port, text2, strlen( text2 ) );
			}
	
			if( mesn == 7 )
			{
				sprintf( text2, "on this thrashy" );
				Move( &my_rast_port, 186, 153 );
				Text( &my_rast_port, text2, strlen( text2 ) );
	
				sprintf( text2, "hack. LMB=EXIT" );
				Move( &my_rast_port, 186, 166 );
				Text( &my_rast_port, text2, strlen( text2 ) );
			}
	
			mesn++;
			if( mesn > 8 ) mesn=0;
			wart = 0;
	
			while( (!( Joystick( PORT2 ) & FIRE )) && (wart<33) && (!( Joystick( PORT1 ) & FIRE )) )
			{
				Delay( 5 );
				wart ++;
			}

		}
	}
}

void intro( void )
{
	clrrast();
  my_ras_info.RxOffset = 400;
  my_ras_info.RyOffset = 0;
  MakeVPort( &my_view, &my_view_port );
  MrgCop( &my_view );
  LoadView( &my_view );

	Execute( "simpleplay >nil: data/shoot_title.mod", NULL, NULL );
	getilbm();

  my_ras_info.RxOffset = 0;
  my_ras_info.RyOffset = 0;
  MakeVPort( &my_view, &my_view_port );
  MrgCop( &my_view );
  LoadView( &my_view );

	title();

	{
		UWORD *pointer;
		int loop;

	  /* Get a pointer to the colour map: */
	  pointer = (UWORD *) my_view_port.ColorMap->ColorTable;

	  /* Set the colours: */
	  for( loop = 0; loop < COLOURS; loop++ )
	    *pointer++ = 0;
	}
  MakeVPort( &my_view, &my_view_port );
  MrgCop( &my_view );
  LoadView( &my_view );

	Execute( "simpleplay >nil: -stop", NULL, NULL );
}

void showmessage( number )
int number;
{
	struct View my_view3;
	struct View *my_old_view3;
	struct ViewPort my_view_port3;
	struct RasInfo my_ras_info3;
	struct BitMap my_bit_map3;
	struct RastPort my_rast_port3;


	UWORD my_color_table3[] =
	{
	  0x000, /* Colour 0, Black       */
	  0xfff, /* Colour 1, Red         */
	  0xa00, /* Colour 2, Light red   */
	  0x080, /* Colour 3, Green       */
	  0x0F0, /* Colour 4, Light green */
	  0x008, /* Colour 5, Blue        */
	  0x00F, /* Colour 6, Light Blue  */
	  0xFFF, /* Colour 7, White       */
	};

	UWORD *pointer3;
	int loop3;
  
	if( number != 5 )
	{
		Execute( "simpleplay >nil: data/shoot_message.mod", NULL, NULL );
	}

  my_old_view3 = GfxBase->ActiView;

  InitView( &my_view3 );
  my_view3.ViewPort = &my_view_port3;

  InitVPort( &my_view_port3 );
  my_view_port3.DWidth = WIDTH3;         /* Set the width.                */
  my_view_port3.DHeight = HEIGHT3;       /* Set the height.               */
  my_view_port3.RasInfo = &my_ras_info3; /* Give it a pointer to RasInfo. */
  my_view_port3.Modes = 0;          /* High resolution.              */


  /* 3. Get a colour map, link it to the ViewPort, and prepare it: */
  my_view_port3.ColorMap = (struct ColorMap *) GetColorMap( COLOURS3 );
  if( my_view_port3.ColorMap == NULL )
    printf( "Could NOT get a ColorMap!\n" );

  /* Get a pointer to the colour map: */
  pointer3 = (UWORD *) my_view_port3.ColorMap->ColorTable;

  /* Set the colours: */
  for( loop3 = 0; loop3 < COLOURS3; loop3++ )
    *pointer3++ = my_color_table3[ loop3 ];


  /* 4. Prepare the BitMap: */
  InitBitMap( &my_bit_map3, DEPTH3, WIDTH3, HEIGHT3 );

  /* Allocate memory for the Raster: */ 
  for( loop3 = 0; loop3 < DEPTH3; loop3++ )
  {
    my_bit_map3.Planes[ loop3 ] = (PLANEPTR) AllocRaster( WIDTH3, HEIGHT3 );
    if( my_bit_map3.Planes[ loop3 ] == NULL )
      printf( "Could NOT allocate enough memory for the raster!\n" );

    /* Clear the display memory with help of the Blitter: */
    BltClear( my_bit_map3.Planes[ loop3 ], RASSIZE( WIDTH3, HEIGHT3 ), 0 );
  }

  
  /* 5. Prepare the RasInfo structure: */
  my_ras_info3.BitMap = &my_bit_map3; /* Pointer to the BitMap structure.  */
  my_ras_info3.RxOffset = 0;         /* The top left corner of the Raster */
  my_ras_info3.RyOffset = 0;         /* should be at the top left corner  */
                                    /* of the display.                   */
  my_ras_info3.Next = NULL;          /* Single playfield - only one       */
                                    /* RasInfo structure is necessary.   */

  /* 6. Create the display: */
  MakeVPort( &my_view3, &my_view_port3 );
  MrgCop( &my_view3 );


  /* 7. Prepare the RastPort, and give it a pointer to the BitMap. */
  InitRastPort( &my_rast_port3 );
  my_rast_port3.BitMap = &my_bit_map3;
  

  /* 8. Show the new View: */
  LoadView( &my_view3 );


  /* Set the draw mode to JAM1. FgPen's colour will be used. */
  SetDrMd( &my_rast_port3, JAM1 );

	if( number == 1 )
	{
		char *text;
		char text2[80];
		text = "You blew it!";
		SetAPen( &my_rast_port3, 1 );
		Move( &my_rast_port3, WIDTH3/2-TextLength( &my_rast_port3, text, strlen( text ) )/2, 100 );
		Text( &my_rast_port3, text, strlen( text ) );
		sprintf( text2, "Lifes left: %d", lifes );
		Move( &my_rast_port3, WIDTH3/2-TextLength( &my_rast_port3, text2, strlen( text2 ) )/2, 115 );
		Text( &my_rast_port3, text2, strlen( text2 ) );
		SetAPen( &my_rast_port3, 2 );
		sprintf( text2, "Try again brave soldier" );
		Move( &my_rast_port3, WIDTH3/2-TextLength( &my_rast_port3, text2, strlen( text2 ) )/2, 130 );
		Text( &my_rast_port3, text2, strlen( text2 ) );
	}

	if( number == 2 )
	{
		char *text;
		char text2[80];
		text = "You blew it!";
		SetAPen( &my_rast_port3, 1 );
		Move( &my_rast_port3, WIDTH3/2-TextLength( &my_rast_port3, text, strlen( text ) )/2, 100 );
		Text( &my_rast_port3, text, strlen( text ) );
		sprintf( text2, "This is your last chance" );
		Move( &my_rast_port3, WIDTH3/2-TextLength( &my_rast_port3, text2, strlen( text2 ) )/2, 115 );
		Text( &my_rast_port3, text2, strlen( text2 ) );
		SetAPen( &my_rast_port3, 2 );
		sprintf( text2, "Go for it!" );
		Move( &my_rast_port3, WIDTH3/2-TextLength( &my_rast_port3, text2, strlen( text2 ) )/2, 130 );
		Text( &my_rast_port3, text2, strlen( text2 ) );
	}

	if( number == 3 )
	{
		char *text;
		char text2[80];
		text = "You blew it!";
		SetAPen( &my_rast_port3, 1 );
		Move( &my_rast_port3, WIDTH3/2-TextLength( &my_rast_port3, text, strlen( text ) )/2, 100 );
		Text( &my_rast_port3, text, strlen( text ) );
		SetAPen( &my_rast_port3, 2 );
		sprintf( text2, "GAME OVER" );
		Move( &my_rast_port3, WIDTH3/2-TextLength( &my_rast_port3, text2, strlen( text2 ) )/2, 130 );
		Text( &my_rast_port3, text2, strlen( text2 ) );
	}

	if( number == 4 )
	{
		char *text;
		char text2[80];
		text = "You did it!";
		SetAPen( &my_rast_port3, 1 );
		Move( &my_rast_port3, WIDTH3/2-TextLength( &my_rast_port3, text, strlen( text ) )/2, 100 );
		Text( &my_rast_port3, text, strlen( text ) );
		sprintf( text2, "Blow those wimps away" );
		Move( &my_rast_port3, WIDTH3/2-TextLength( &my_rast_port3, text2, strlen( text2 ) )/2, 115 );
		Text( &my_rast_port3, text2, strlen( text2 ) );
		SetAPen( &my_rast_port3, 2 );
		sprintf( text2, "Go for it!" );
		Move( &my_rast_port3, WIDTH3/2-TextLength( &my_rast_port3, text2, strlen( text2 ) )/2, 130 );
		Text( &my_rast_port3, text2, strlen( text2 ) );
	}

	if( number == 5 )
	{
		char *text;
		char text2[80];
		text = "Entering";
		SetAPen( &my_rast_port3, 1 );
		Move( &my_rast_port3, WIDTH3/2-TextLength( &my_rast_port3, text, strlen( text ) )/2, 100 );
		Text( &my_rast_port3, text, strlen( text ) );
		sprintf( text2, "Terrorist Camp" );
		Move( &my_rast_port3, WIDTH3/2-TextLength( &my_rast_port3, text2, strlen( text2 ) )/2, 115 );
		Text( &my_rast_port3, text2, strlen( text2 ) );
		SetAPen( &my_rast_port3, 2 );
		sprintf( text2, "Prepare To Defend Your Honor!" );
		Move( &my_rast_port3, WIDTH3/2-TextLength( &my_rast_port3, text2, strlen( text2 ) )/2, 130 );
		Text( &my_rast_port3, text2, strlen( text2 ) );
	}

	{
		int wait;

		wait = MESSAGEWAIT;
		while( wait>0 )
		{
		  value = Joystick( PORT2 );
	    
		  if( value & FIRE )
			{
				wait = -1;
			}

			WaitBOVP( &my_view_port3 );
			WaitTOF();
			wait--;
		}
	}

	Execute( "simpleplay >nil: -stop", NULL, NULL );

/*  StopSound( LEFT1 );
  StopSound( RIGHT1 );*/

  /* 9. Restore the old View: */
  LoadView( my_old_view3 );


  /* Free automatically allocated display structures: */
  FreeVPortCopLists( &my_view_port3 );
  FreeCprList( my_view3.LOFCprList );
  
  /* Deallocate the display memory, BitPlane for BitPlane: */
  for( loop3 = 0; loop3 < DEPTH3; loop3++ )
    if( my_bit_map3.Planes[ loop3 ] )
      FreeRaster( my_bit_map3.Planes[ loop3 ], WIDTH3, HEIGHT3 );

  /* Deallocate the ColorMap: */
  if( my_view_port3.ColorMap ) FreeColorMap( my_view_port3.ColorMap );

}

void dwellreset( void )
{
	int a;

	for( a=0; a<fonum; a++ )
	{
		foedwell[ a ].delay = 0;
	}
}

void game( void )
{
  SHORT deltaX;
  SHORT deltaY;

	unsigned int restartx, restarty;

	Execute( "simpleplay >nil: data/shoot_message.mod", NULL, NULL );

	loadlevel();
	drawlevel();

	initshots();
	initfoes();

	{
		UWORD *pointer;
		int loop;

	  /* Get a pointer to the colour map: */
	  pointer = (UWORD *) my_view_port.ColorMap->ColorTable;

	  /* Set the colours: */
	  for( loop = 0; loop < COLOURS; loop++ )
	    *pointer++ = my_color_table[ loop ];
	}
  MakeVPort( &my_view, &my_view_port );
  MrgCop( &my_view );
  LoadView( &my_view );

	showmessage( 5 );

	restartx = startx*16*16 + 8*16;
	restarty = starty*16*16 + 8*16;

	lifes = LIFES;

	while( lifes > 0 )
	{

	  if( GetSprite( &my_sprite, 2 ) != 2 )
			printf("ERROR: Couldn't get sprite\n");
	
	  /* Move the sprite: */
	  MoveSprite( 0, &my_sprite, 6, 6 );
	
		initsprites();
	
		/*		Delay( 5 );
		Disable();*/
	
		{
			int posaltx, posalty;
			int aimposaltx, aimposalty;
			int quit = 0;
			int step = 0;
			int stepdist;
			int dist;
	
			posx = restartx;
			posy = restarty;

			initfoes();
	
			aimposx = -1;
			aimposy = 0;
	
			stepdist = STEP;
	
			remoove = 0;

			shotat = 0;

			gametime = 0;
			dwellreset();
	
	    BltBitMap(
	      &my_bit_map, /* Source                 */
		    posx/16-TILESWIDTH*8/2, 						/* Position, source. */
		    posy/16-TILESWIDTH*8/2,					 	/*          - " -         */
	      &my_bit_map2, /* Destination.           */
	      0, 						/* Position, destination. */
	      112, 					/*          - " -         */
	      TILESWIDTH*8, TILESHEIGHT,      /* Width and height.      */
	      0xC0,        /* Normal copy.           */
	      0xFF,        /* All bitplanes.         */
	      NULL );      /* No temporary storage.  */
	
			energy = ENERGY;
			energybar();

	    my_ras_info.RxOffset = posx/16 - DWIDTH/2;
	    my_ras_info.RyOffset = posy/16 - DHEIGHT/2;

	    /* Have we reached the left side? */
	    if( my_ras_info.RxOffset < 0 )
			{
				my_ras_info.RxOffset = 0;
			}
	
	    /* Have we reached the right (Raster width - Display width) side? */
	    if( my_ras_info.RxOffset >= RWIDTH - DWIDTH )
			{
				my_ras_info.RxOffset = RWIDTH - DWIDTH;
			}
	
	    /* Have we reached the top side? */
	    if( my_ras_info.RyOffset < 0 )
			{
				my_ras_info.RyOffset = 0;
			}
	
	    /* Have we reached the bottom (Raster height - Display height) side? */
  	  if( my_ras_info.RyOffset >= RHEIGHT - DHEIGHT )
  	  {	
  	  	my_ras_info.RyOffset = RHEIGHT - DHEIGHT;
  	  }
	
			while( quit == 0 )
			{
				int vbeam;
				int lop;

				deltaX = deltaY = 0;
	
				posaltx = posx;
				posalty = posy;
	
				aimposaltx = aimposx;
				aimposalty = aimposy;
	
				rand();
	
				/* LMB = verlassen abfragen */
		    value = Joystick( PORT1 );
	
		    if( value & FIRE )
				{
					quit = 1;
					lifes = 0;
					energy = 0;
				}
	
				shoot();		/* Joystick auf Feuer abfragen und diverse Schussmodi
												ausfuehren */
				walk();			/* Joystick auf Bewegung abfragen und maennchen rumlaufen lassen */

				screenscrolling();
	
				/* Quadrat der zurueckgelegten Entfernung */
				dist = (posx-posaltx) * (posx-posaltx) + (posy-posalty) * (posy-posalty);
				if( dist>0 )
				{
					stepdist = stepdist - SPEED;
					while( stepdist<0 )
					{
						stepdist += STEP;
						step++;
						PlaySound( steps, MAXVOLUME/8, RIGHT1, NORMALRATE, 1 );
					}
				}
				else
				{
					stepdist = STEP;
				}
				if( energy <= 0 ) step = 0;
	
				/* Bitmap wiederherstellen */
	
				cleanandmoveshots();
	
				/*cleanandmovefoes();*/
				movefoes();
	
				/* Aimring */
				if( ((aimmode == 1) && (aimposaltx != -1)) || ( (aimmode==0) && (aimposaltx != -1) ) )
				{
			    BltBitMap(
			      &my_bit_map2, /* Source                 */
			      16, 						/* Position, source. */
			      112, 					/*          - " -         */
			      &my_bit_map, /* Destination.           */
				    aimposaltx, 						/* Position, destin. */
				    aimposalty,					 	/*          - " -         */
			      TILESWIDTH*8, TILESHEIGHT,      /* Width and height.      */
			      0xC0,        /* Normal copy.           */
			      0xFF,        /* All bitplanes.         */
			      NULL );      /* No temporary storage.  */
	
					/* Wenn der aimmode ausgeschaltet wurde und dieses schon das
							letzte refreshen der bitmap war, dann dieses abschalten */
					if( aimmode == 0 ) aimposx = -1;
				}
	
				/* Maennchen */
				if( 1==2 )
				{
		    BltBitMap(
		      &my_bit_map2, /* Source                 */
		      0, 						/* Position, source. */
		      112, 					/*          - " -         */
		      &my_bit_map, /* Destination.           */
			    posaltx/16-TILESWIDTH*8/2, 						/* Position, destin. */
			    posalty/16-TILESWIDTH*8/2,					 	/*          - " -         */
		      TILESWIDTH*8, TILESHEIGHT,      /* Width and height.      */
		      0xC0,        /* Normal copy.           */
		      0xFF,        /* All bitplanes.         */
		      NULL );      /* No temporary storage.  */
				}
	
	
				/* Blutfleck */
				if( shotat == 1 )
				{
				  SetAPen( &my_rast_port, ROT );
					WritePixel( &my_rast_port, posx/16, posy/16 );
					WritePixel( &my_rast_port, posx/16+1, posy/16 );
					WritePixel( &my_rast_port, posx/16+1, posy/16+1 );
					PlaySound( foedies, MAXVOLUME, RIGHT0, NORMALRATE, 1 );
					energy--;

					energybar();

					if( energy <= 0 )
					{
						/* Blutfleck malen */
					  BltMaskBitMapRastPort(
					    &my_bit_map2, 	/* Source                 */
					    16, 16,    			/* Position, source.      */
					    &my_rast_port, /* Destination.           */
					    posx/16-TILESWIDTH*8/2, 						/* Position, destination. */
					    posy/16-TILESHEIGHT/2,					 	/*          - " -         */
					    TILESWIDTH*8, TILESHEIGHT,      /* Width and height.      */
					    0xe0,        	/* Normal copy.           */
							maskplane );	/* Maske */

					}
					shotat = 0;
				}
	
				if( energy <= 0 )
				{
					if( energy-- < -DEAD )
					{
						UWORD *wo;
						int heit;

						/* Neues Leben */
						quit = 1;
						lifes--;

						wo = (UWORD *) (maskplane+RWIDTH2/8*140 + 28*4);

						for( heit=0; heit<4; heit++ )
						{
							if( lifes==3 )
							{
								*wo++ = 0x8421;
								*wo++ = 0x7bde;
							}
							if( lifes==2 )
							{
								*wo++ = 0x8421;
								*wo++ = 0x7bc0;
							}
							if( lifes==1 )
							{
								*wo++ = 0x8421;
								*wo++ = 0x7800;
							}
							if( lifes==0 )
							{
								*wo++ = 0x8421;
								*wo++ = 0x0000;
							}
						}

						remoove = 1;
					}
				}
	
				/* Bitmap zwischenspeichern */
				/* und Bitmap beschreiben */
	
				/* Maennchen */

		    vsprite[ MAXVSPRITES-1 ].X = posx/16-8 - my_ras_info.RxOffset;
		    vsprite[ MAXVSPRITES-1 ].Y = posy/16-SFOEHEIGHT/2 -my_ras_info.RyOffset;

			  vsprite[ MAXVSPRITES-1 ].ImageData = (UWORD *) (spritedata + 40 * (dir*2 + (step&1)) );

				if( remoove == 1 )
				{
			    vsprite[ MAXVSPRITES-1 ].X = 0;
			    vsprite[ MAXVSPRITES-1 ].Y = SDUMPY;
				}

				if( 1==2 )
				{
		    BltBitMap(
		      &my_bit_map, /* Source                 */
			    posx/16-TILESWIDTH*8/2, 						/* Position, source. */
			    posy/16-TILESWIDTH*8/2,					 	/*          - " -         */
		      &my_bit_map2, /* Destination.           */
		      0, 						/* Position, destination. */
		      112, 					/*          - " -         */
		      TILESWIDTH*8, TILESHEIGHT,      /* Width and height.      */
		      0xC0,        /* Normal copy.           */
		      0xFF,        /* All bitplanes.         */
		      NULL );      /* No temporary storage.  */
	
				if( remoove != 1 )
				{
				  BltMaskBitMapRastPort(
				    &my_bit_map2, 	/* Source                 */
				    16*(dir*2+(step&1)), 0,    			/* Position, source.      */
				    &my_rast_port, /* Destination.           */
				    posx/16-TILESWIDTH*8/2, 						/* Position, destination. */
				    posy/16-TILESWIDTH*8/2,					 	/*          - " -         */
				    TILESWIDTH*8, TILESHEIGHT,      /* Width and height.      */
				    0xe0,        	/* Normal copy.           */
						maskplane );	/* Maske */
				}
				}
	
				/* Aimring */
				if( aimmode == 1 )
				{
				  BltBitMap(
				    &my_bit_map, 	/* Source                 */
				    aimposx,
						aimposy,    			/* Position, source.      */
				    &my_bit_map2, /* Destination.           */
				    16, 						/* Position, destination. */
				    112,					 	/*          - " -         */
				    TILESWIDTH*8, TILESHEIGHT,      /* Width and height.      */
			      0xC0,        /* Normal copy.           */
			      0xFF,        /* All bitplanes.         */
			      NULL );      /* No temporary storage.  */
	
					if( remoove != 1 )
					{
					  BltMaskBitMapRastPort(
					    &my_bit_map2, 	/* Source                 */
					    0, 16,    			/* Position, source.      */
					    &my_rast_port, /* Destination.           */
					    aimposx, 						/* Position, destination. */
					    aimposy,					 	/*          - " -         */
					    TILESWIDTH*8, TILESHEIGHT,      /* Width and height.      */
					    0xe0,        	/* Normal copy.           */
							maskplane );	/* Maske */
					}
				}
	
				/*drawfoes();*/
	
				drawshots();

				if( (gametime % KILLBACK) == 0 )
				{
					restartx = posx;
					restarty = posy;
				}
				gametime++;
	
		    /* Recalculate the display instructions: (If you change any values */
		    /* in the display structures the Amiga have to recalculate the     */
		    /* entire display instructions. You must therefore call all three  */
		    /* display functions: MakeVPort(), MrgCop() and LoadView().)       */
			  SortGList( &my_rast_port );
			  DrawGList( &my_rast_port, &my_view_port );
		    MakeVPort( &my_view, &my_view_port );
		    MrgCop( &my_view );
		    LoadView( &my_view );
				vbeam = VBeamPos();
				if( (vbeam < 290) && (vbeam > 120) )
				{
					WaitBOVP( &my_view_port );
				}
	
				if( (posx/256 == finishx) && (posy/256 == finishy) )
				{
					/* Ziel erreicht */
					lifes = -10;
					remoove = 1;
					energy = -DEAD-10;
				}

				lop = gametime % aidnum;

				if( (posx/256 == aid[ lop ].x) && (posy/256 == aid[ lop ].y) )
				{
					if( aid[ lop ].full == 1 )
					{
						aid[ lop ].full = 0;
						PlaySound( bell, MAXVOLUME, LEFT0, NORMALRATE, 1 );
						energy = ENERGY;
						energybar();
					}
				}
		  }

		}

		{
			int loop;
	
		  for( loop = 0; loop < MAXVSPRITES; loop++ )
		  {
			  if( vsprite_on[ loop ] )
			    RemVSprite( &vsprite[ loop ] );
			}
		}

	  if( my_sprite.num != (UWORD) -1 )
	    FreeSprite( my_sprite.num );

		/* Zwischenbildschirm zeigen */
		if( lifes>1 )
		{
			showmessage( 1 );
		}
		if( lifes==1 )
		{
			showmessage( 2 );
		}
		if( lifes==0 )
		{
			showmessage( 3 );
		}
		if( lifes<0 )
		{
			showmessage( 4 );
		}



		/*Enable();*/
	}
}

int main( void )
{
	int leave;

	srand( 100 );

	openlibs();
	initstuff();
	loadstuff();  

	openstuff();
	opensecondbitmap();
  tilestosecond();

	Execute( "assign >nil: libs: libs add", NULL, NULL );
	Execute( "changetaskpri >nil: 1", NULL, NULL );

	createsprites();

	attacks = PrepareSound( "data/shoot_attack.sfx" );
	foedies = PrepareSound( "data/shoot_foedie.sfx" );
	steps = PrepareSound( "data/shoot_step.sfx" );
	fires = PrepareSound( "data/shoot_shot.sfx" );
	shoth1 = PrepareSound( "data/shoot_shoth1.sfx" );
	shoth2 = PrepareSound( "data/shoot_shoth2.sfx" );
	glas = PrepareSound( "data/shoot_glas.sfx" );
	bell = PrepareSound( "data/shoot_bell.sfx" );

	my_sprite.posctldata = (UWORD *) (maskplane+RWIDTH2/8*140);
	{
		int a;
		UWORD *wo;

		wo = (UWORD *) (maskplane+RWIDTH2/8*140);

		for( a=0; a<70; a++ )
		{
			*wo++=ship_data[a];
		}
	}


	leave = 0;

	while( leave == 0 )
	{
		intro();

		if( (( Joystick( PORT1 ) & FIRE )) )
		{
			leave = 1;
		}

		if( leave == 0 )
		{
			game();
		}
	}


  StopSound( LEFT0 );
  StopSound( LEFT1 );
  StopSound( RIGHT0 );
  StopSound( RIGHT1 );
  RemoveSound( steps );
  RemoveSound( foedies );
  RemoveSound( attacks );
  RemoveSound( fires );
  RemoveSound( shoth1 );
  RemoveSound( shoth2 );
  RemoveSound( glas );
  RemoveSound( bell );

  /* 9. Restore the old View: */
  LoadView( my_old_view );

	if( lifes <= -10 )
	{
		/*printf("You did it!\n");*/
	}
	else
	{
		/*printf("You blew it!\n");*/
	}

  /* Free all allocated resources and leave. */
	closelibs();
  clean_up( "THE END" );
	return( 0 );
}

