#include "level.h"

MONSTER *new_monster( int life, int type, PHYSICS physics )
{
	static int nb = 0 ;

	MONSTER *monster = NULL ;
	Malloc( monster, MONSTER, 1 );
	__n_assert( monster, return NULL );

	memcpy( &monster -> physics, &physics, sizeof( PHYSICS ) );

	monster -> attr . life = life ;
	monster -> attr . type = type ;
	monster -> attr . xp = 0 ;
	monster -> attr . action = ACTION_MOVE ;
	switch( monster -> attr . type )
	{
		case BIGBOSS_MONSTER:
			monster -> physics . sz = 40 ;
			break;
		case AGRESSIVE_MONSTER:
			monster -> physics . sz = 20 ;
			break;
		default:
		case PASSIVE_MONSTER:
			monster -> physics . sz = 10 ;
			break;
	}
	nb ++ ;
	return monster;
}



int get_level_data( LEVEL *level, PHYSICS *physics, int mx, int my, int *x, int *y )
{
	int cellx = 0, celly = 0 ;

	cellx = ( physics -> position[ 0 ] + mx ) / level -> tilew ;
	celly = ( physics -> position[ 1 ] + my ) / level -> tileh ;

	if( cellx >= 0 && cellx < level -> w && celly >= 0 && celly < level -> h )
	{
		if( x != NULL )
			(*x) = cellx ;
		if( y != NULL )
			(*y) = celly ;

		return level -> cells[ cellx ][ celly ];
	}

	return -1000 ;
}



int test_coord( LEVEL *level, PHYSICS *physics, VECTOR3D fricton, int off_x, int off_y , PLAYER *player )
{
	int cellx = 0, celly = 0, done = 0, once = 0, has_blocked = 0 , previous_life_val = 0 ;

	if( player )
		previous_life_val = player -> attr . life ;

	/* left */
	once = 0 ;
	done = 0 ;
	do
	{
		int cellstate = get_level_data( level, physics, off_x - physics -> sz, off_y, &cellx, &celly );

		if( cellstate != -1000 )
		{
			if( cellstate > 0 && cellstate < 4 )
			{
				physics -> position[ 0 ] = physics -> position[ 0 ] + 1.0 ;
				if( !once )
				{
					if( player )
					{
						physics -> position[ 0 ] += level -> tilew ;
						player -> attr . life -= 5 ;
					}
					else
					{
						once = has_blocked = 1 ;
						physics -> speed[ 0 ] = fabs(  fabs( physics -> speed[ 0 ] ) - fabs( fricton[ 0 ] ) );
					}
				}
				done = 0 ;
			}
			else
				done = 1 ;
		}
		else
			done = 1 ;
	}
	while( !done );

	/* right */
	once = 0 ;
	done = 0 ;
	do
	{
		int cellstate = get_level_data( level, physics, off_x + physics -> sz, off_y, &cellx, &celly );

		if( cellstate != -1000 )
		{
			if( cellstate > 0 && cellstate < 4 )
			{
				physics -> position[ 0 ] = physics -> position[ 0 ] - 1.0 ;
				if( !once )
				{
					if( player )
					{
						physics -> position[ 0 ] -= level -> tilew ;
						player -> attr . life -= 5 ;
					}
					else
					{
						once = has_blocked = 1 ;
						physics -> speed[ 0 ] = - fabs(  fabs(physics -> speed[ 0 ]) -  fabs(fricton[ 0 ]) );
					}
				}
				done = 0 ;
			}
			else
				done = 1 ;
		}
		else
			done = 1 ;
	}
	while( !done );

	/* down */
	once = 0 ;
	done = 0 ;
	do
	{
		int cellstate = get_level_data( level, physics, off_x, off_y + physics -> sz, &cellx, &celly );

		if( cellstate != -1000 )
		{
			if( cellstate > 0 && cellstate < 4 )
			{
				physics -> position[ 1 ] = physics -> position[ 1 ] - 1.0 ;
				if( !once )
				{
					once = has_blocked = 1 ;
					physics -> speed[ 1 ] = -fabs( fabs( physics -> speed[ 1 ] ) - fabs(fricton[ 1 ] ) );
					physics -> can_jump = 1 ;
				}
				done = 0 ;
			}
			else
				done = 1 ;
		}
		else
			done = 1 ;
	}
	while( !done );

	/* up */
	once = 0 ;
	done = 0 ;
	do
	{
		int cellstate = get_level_data( level, physics,  off_x, off_y - physics -> sz, &cellx, &celly );

		if( cellstate != -1000 )
		{
			if( cellstate > 0 && cellstate < 4 )
			{
				physics -> position[ 1 ] = physics -> position[ 1 ] + 1.0 ;
				if( !once )
				{
					once = has_blocked = 1 ;
					if( player )
					{
						physics -> position[ 1 ] += level -> tileh ;
						player -> attr . life -= 5 ;
					}
					else
					{	
						physics -> speed[ 1 ] = fabs( fabs(physics -> speed[ 1 ] ) - fabs( fricton[ 1 ] ) );
					}
				}
				done = 0 ;
			}
			else
				done = 1 ;
		}
		else
			done = 1 ;
	}
	while( !done );

	if( !has_blocked )
	{
		physics -> can_jump = 0 ;
	}

	if( player && player -> attr . life != previous_life_val )
	{
		int px = player -> physics . position[ 0 ] ;
		int py = player -> physics . position[ 1 ] ;
		for( int it = 0 ; it < 10 ; it ++ )
		{
			PHYSICS tmp_part ;
			tmp_part . sz = 15  ;
			VECTOR3D_SET( tmp_part . speed, player -> physics . speed[ 0 ] + 100 - rand()%200 , player -> physics . speed[ 1 ] + 100 - rand()%200, 0.0  );
			VECTOR3D_SET( tmp_part . position, px, py, 0.0  );
			VECTOR3D_SET( tmp_part . acceleration, 0.0, 0.0, 0.0 );
			VECTOR3D_SET( tmp_part . orientation, 0.0, 0.0, 0.0 );
			add_particle( level -> particle_system_effects, -1, PIXEL_PART, 500 + rand()%500, 1+rand()%5, al_map_rgba( 55 + rand()%200, 0 , 0 , 255 ), tmp_part );
		}
		player -> attr . xp -=  500 ;

		if( player -> attr . xp < 0 )
		{
			player -> attr . xp = 0 ;
			if( player -> attr . level > 1 )
			{
				player -> attr . level -- ;
				player -> attr . yspeedmax = 100 * ( 1 + (player -> attr . level / 3) );
			}
		}	
	}

	return has_blocked ;
}



int animate_physics( LEVEL *level, PHYSICS *physics, VECTOR3D friction, double delta_t , PLAYER *player )
{
	VECTOR3D old_pos, new_pos, pos_delta ;

	memcpy( &old_pos, &physics -> position, sizeof( VECTOR3D ) );

	update_physics_position( physics, delta_t );

	memcpy( &new_pos, &physics -> position, sizeof( VECTOR3D ) );

	double d = distance ( old_pos, physics -> position );

	if( physics -> sz < 1 )
		physics -> sz = 1 ;

	double steps = physics -> sz ;

	if( d >= steps )
	{
		for( int it = 0 ; it < 3 ; it ++ )
			pos_delta[ it ] = ( physics -> position[ it ] - old_pos[ it ] ) / d ;

		double inc = -steps ;

		while( inc < d )
		{
			inc += steps ;
			if( inc > d )
				inc = d ;
			for( int it = 0 ; it < 3 ; it ++ )
				physics -> position[ it ] = old_pos[ it ] + pos_delta[ it ] * inc ;

			if( test_coord( level, physics, friction, 0, 0 , player ) > 0 )
				break ;
		}
	}
	else
		test_coord( level, physics, friction, 0, 0 , player );

	return TRUE ;
}

int animate_level( LEVEL *level,  PLAYER *player, double delta_t )
{
	VECTOR3D friction = { 0.0, 0.0, 0.0 };
	LIST_NODE *node = NULL ;
	MONSTER *monster = NULL ;
	__n_assert( level, return FALSE );
	__n_assert( level -> monster_list, return FALSE );

	PARTICLE *ptr = NULL ;

	node = level -> particle_system_effects -> list -> start ;
	while( node )
	{
		ptr = (PARTICLE *)node -> ptr ;
		if( ptr -> lifetime != -1 )
		{
			ptr -> lifetime -= delta_t/1000.0 ;
			if( ptr -> lifetime == -1 )
				ptr -> lifetime = 0 ;
		}

		if( ptr -> lifetime > 0 || ptr -> lifetime == -1 )
		{
			animate_physics( level, &ptr -> object, friction, delta_t , NULL );
			node = node -> next ;
		}
		else
		{
			LIST_NODE *node_to_kill = node ;
			node = node -> next ;
			ptr = remove_list_node( level -> particle_system_effects -> list, node_to_kill, PARTICLE );
			Free( ptr );
		}
	}
	LIST_NODE *bnode = level -> particle_system_bullets -> list -> start ;
	while( bnode )
	{
		PARTICLE *bptr = (PARTICLE *)bnode -> ptr ;
		if( bptr )
		{
			if( bptr -> lifetime != -1 )
			{
				bptr -> lifetime -= delta_t/1000.0 ;
				if( bptr -> lifetime == -1 )
					bptr -> lifetime = 0 ;
			}

			if( bptr -> lifetime > 0 || bptr -> lifetime == -1 )
			{
				node = level -> monster_list -> start ;
				while( node )
				{
					monster= (MONSTER *)node -> ptr ;
					/*x, y, x + 2 * monster -> physics . sz, y - 2 * monster -> physics . sz,*/
					if( ( bptr -> object . position[ 0 ] - bptr -> object . sz ) > ( monster -> physics . position[ 0 ] - monster -> physics . sz ) &&
							( bptr -> object . position[ 0 ] + bptr -> object . sz ) < ( monster -> physics . position[ 0 ] + monster -> physics . sz ) &&
							( bptr -> object . position[ 1 ] - bptr -> object . sz ) > ( monster -> physics . position[ 1 ] - monster -> physics . sz ) &&
							( bptr -> object . position[ 1 ] + bptr -> object . sz ) < ( monster -> physics . position[ 1 ] + monster -> physics . sz ) )
					{
						bptr -> lifetime = 0 ;
						monster -> attr . life -= 10 ;
						int xpgain = 0 ;
						switch( monster -> attr . type )
						{
							case BIGBOSS_MONSTER:
								xpgain = 200 ;
								break;
							case AGRESSIVE_MONSTER:
								xpgain = 100 ;
								break;
							default:
							case PASSIVE_MONSTER:
								xpgain = 50 ;
								break;
						}
						(*player) . attr . xp +=  xpgain ;

						if( (*player) . attr . xp > (*player) . attr . xp_to_level )
						{
							if( (*player) . attr . level < 10 )
							{
								(*player) . attr . level ++ ;
								(*player) . attr . xp_to_level += 1000 ;
								(*player) . attr . xp  = 0 ;
								(*player) . attr . yspeedmax = 100 * ( 1 + ((*player) . attr . level / 3) );
							}
						}

						PHYSICS tmp_part ;
						tmp_part . sz = 10 ;
						for( int it = 0 ; it < 20 ; it ++ )
						{
							VECTOR3D_SET( tmp_part . speed,
									300 - rand()%600,
									300 - rand()%600,
									0.0  );
							VECTOR3D_SET( tmp_part . position, monster -> physics . position[ 0 ], monster ->  physics . position[ 1 ], 0.0  );
							VECTOR3D_SET( tmp_part . acceleration, 0.0, 0.0, 0.0 );
							VECTOR3D_SET( tmp_part . orientation, 0.0, 0.0, 0.0 );
							add_particle( level -> particle_system_effects, -1, PIXEL_PART, 100 + rand()%500, 1+rand()%3,
									al_map_rgba(   55 + rand()%200,  0, 0, 100 + rand()%155 ), tmp_part );

						}
					}
					node = node -> next ;
				}
				animate_physics( level, &bptr -> object, friction, delta_t , NULL );
				bnode = bnode -> next ;
			}
			else
			{
				LIST_NODE *node_to_kill = bnode ;
				bnode = bnode -> next ;
				ptr = remove_list_node( level -> particle_system_bullets -> list, node_to_kill, PARTICLE );
				Free( ptr );
			}
		}
	}


	node = level -> monster_list -> start ;
	while( node )
	{
		monster= (MONSTER *)node -> ptr ;
		if( monster -> attr . life <= 0 )
		{
			LIST_NODE *ntokill = node ;
			if( node -> next )
				node = node -> next ;
			else
				node = NULL ;
			MONSTER *mtokill = remove_list_node( level -> monster_list, ntokill, MONSTER );
			Free( mtokill );
		}
		else
		{


			monster -> physics . can_jump = 0 ;
			animate_physics( level, &monster -> physics, friction, delta_t , NULL );

			int cellx = 0, celly = 0 ;
			int cellstate = get_level_data( level, &monster -> physics, 0.0, 0.0, &cellx, &celly );

			if( cellstate == 1 )
				monster -> attr . life = 0 ;

			if( monster -> attr . type != PASSIVE_MONSTER && ( distance( monster -> physics . position , player -> physics . position ) < 2 * HEIGHT || monster -> physics . position[ 1 ] > player -> physics . position[ 1 ] ) )
			{
				double itx = 0, ity = 0, itz = 0, sz = 0;

				itx = monster -> physics . position[ 0 ] - (*player) . physics . position[ 0 ] ;
				ity = monster -> physics . position[ 1 ] - (*player) . physics . position[ 1 ] ;
				itz = 0 ;
				int speed_multiplicator = 3 ;
				if( monster -> attr . type == AGRESSIVE_MONSTER )
					speed_multiplicator = 6 ;
				sz = sqrt((itx * itx) + (ity * ity) + (itz * itz));
				itx /= sz ;
				ity /= sz ;
				itz /= sz ;
				itx*= ( speed_multiplicator * monster -> physics . sz );
				ity*= ( speed_multiplicator * monster -> physics . sz );
				itz*= ( speed_multiplicator * monster -> physics . sz );
				VECTOR3D_SET( monster -> physics . speed, -itx, -ity, -itz );
				VECTOR3D_SET( monster -> physics . acceleration, -itx, -ity, -itz );
			}
			node = node -> next ;
		}

	}
	return TRUE ;
}



LEVEL *load_level( char *file, char *resfile, int w, int h )
{
	FILE *in = NULL ;
	LEVEL *lvl = NULL ;

	MONSTER *monster = NULL ;

	in = fopen( file, "r" );
	if( !in )
	{
		n_log( LOG_ERR, "%s not found", file );
		return NULL ;
	}

	Malloc( lvl, LEVEL, 1 );
	__n_assert( lvl, return NULL );

	char *str = NULL ;
	Malloc( str, char, 1024 );
	__n_assert( str, return NULL );

	fgets( str, 1024, in );
	sscanf( str, "%d %d %d %d %d %d %d", &lvl -> w, &lvl -> h, &lvl -> m1, &lvl -> m2 , &lvl -> m3 , &lvl -> tilew, &lvl -> tileh );

	for( int it = 0 ; it < 4 ; it ++ )
	{
		char tmpstr[ 1024 ] = "" ;
		fscanf( in, "%s", tmpstr );
		n_log( LOG_DEBUG, "loading tile bmp %s", tmpstr );
		lvl -> tiles[ it ] = al_load_bitmap( tmpstr );
	}

	n_log( LOG_DEBUG, "Level parameters: %d %d %d %d %d %d %d", lvl -> w, lvl -> h, lvl -> m1 , lvl -> m2 , lvl -> m3 , lvl -> tilew, lvl -> tileh );
	n_log( LOG_DEBUG, "Loading ressources from config %s", resfile );

	init_particle_system( &lvl -> particle_system_bullets, 5000, 0, 0, 0, 100 );
	init_particle_system( &lvl -> particle_system_effects, 5000, 0, 0, 0, 100 );

	lvl -> cells = (int **)calloc( lvl -> w, sizeof( void * ) );
	for( int x = 0 ; x < lvl -> w ; x ++ )
	{
		lvl -> cells[ x ] = (int *)calloc( lvl -> h, sizeof( void * ) );
	}
	for( int x = 0 ; x < lvl -> w ; x ++ )
		for( int y = 0 ;  y < lvl -> h ; y ++ )
			lvl -> cells[ x ][ y ] = 1 + rand()%3 ;

	lvl -> monster_list = new_generic_list( -1 );

	/* starting pos */
	n_log( LOG_DEBUG , "Screen dimensions for level: %d / %d" , w , h );
	lvl -> startx = (lvl -> w * lvl -> tilew) / 2 ;
	lvl -> starty = (lvl -> h * lvl -> tileh) - (h / 2 ) - 2 * lvl -> tileh - 1;

	int nb_crawlers = lvl -> w / 5 ;
	int crawlers[ nb_crawlers ] ;
	for( int it = 0 ; it < nb_crawlers ; it ++ )
	{
		crawlers[ it ] = 2 + rand()%(lvl -> w - 2);
	}

	/* Now draw a level */
	for( int y = 0 ; y < lvl -> h - 1 ; y ++ )
	{
		for( int it = 0 ; it < nb_crawlers ; it ++ )
		{
			crawlers[ it ] = crawlers[ it ] + 2 - rand()%5 ;
			if( crawlers[ it ] < 1 )
				crawlers[ it ] = 1 ;
			if( crawlers[ it ] > lvl -> w - 2 )
				crawlers[ it ] = lvl -> w - 2 ;
			for( int y_it = y - 2 ; y_it < y + 2 ; y_it ++ )
			{
				for( int x_it = crawlers[ it ] - 2 ; x_it < crawlers[ it ] + 2 ; x_it ++ )
				{
					if( x_it > 1 && x_it < lvl -> w -1 && y_it >= 0 && y_it < lvl -> h - 2 )
						lvl -> cells[ x_it ][ y_it ] = 0 ;
				}
			}
		}
	}

	// placing end of level 
	for( int it = 0 ; it < lvl -> w ; it ++ )
	{
		lvl -> cells[ it ][ 0 ] = EXIT_CELL ;
	}

	// placing end of level 
	for( int ity = lvl->h - 30 ; ity < lvl->h ; ity ++ )
	{
		for( int itx = ((lvl->w/2)-5) ; itx < ((lvl->w/2)+5) ; itx ++ )
		{
			lvl -> cells[ itx ][ ity ] = 0 ;
		}
	}

	//placing passive monsters 
	for( int it = 0 ; it < lvl -> m1 ; it ++ )
	{
		int x = 0 , y = 0 ;
		while( lvl -> cells[ x ][ y ] != 0 )
		{
			x = 1 + rand()%( lvl -> w - 1 );
			y = 1 + rand()%( lvl -> h - (  h / lvl -> tileh ) );
		}
		PHYSICS mpos ;
		mpos . can_jump = 1 ;
		double vx = 100-rand()%200 ;
		double vy = 100-rand()%200 ;
		VECTOR3D_SET( mpos . position, ( x * lvl -> tilew ) + lvl -> tilew / 2.0, y * lvl -> tileh - lvl -> tileh / 2.0, 0.0 );
		VECTOR3D_SET( mpos . speed, vx, vy, 0.0 );
		VECTOR3D_SET( mpos . acceleration, 0.0, 0.0, 0.0 );
		VECTOR3D_SET( mpos . orientation, 0.0, 0.0, 0.0 );
		monster = new_monster( 20 , PASSIVE_MONSTER , mpos );
		if( monster )
			list_push( lvl -> monster_list, monster, NULL );
	}
	//placing aggressive monsters 
	for( int it = 0 ; it < lvl -> m2 ; it ++ )
	{
		int x = 0 , y = 0 ;
		while( lvl -> cells[ x ][ y ] != 0 )
		{
			x = 1 + rand()%( lvl -> w - 1 );
			y = 1 + rand()%( lvl -> h - ( ( 2 * h ) / lvl -> tileh ) );
		}
		PHYSICS mpos ;
		mpos . can_jump = 1 ;
		double vx = 100-rand()%200 ;
		double vy = 100-rand()%200 ;
		VECTOR3D_SET( mpos . position, ( x * lvl -> tilew ) + lvl -> tilew / 2.0, y * lvl -> tileh - lvl -> tileh / 2.0, 0.0 );
		VECTOR3D_SET( mpos . speed, vx, vy, 0.0 );
		VECTOR3D_SET( mpos . acceleration, 0.0, 0.0, 0.0 );
		VECTOR3D_SET( mpos . orientation, 0.0, 0.0, 0.0 );
		monster = new_monster( 30 , AGRESSIVE_MONSTER , mpos );
		if( monster )
			list_push( lvl -> monster_list, monster, NULL );
	}
	//placing big boss monsters 
	for( int it = 0 ; it < lvl -> m3 ; it ++ )
	{
		int x = 0 , y = 0 ;
		while( lvl -> cells[ x ][ y ] != 0 )
		{
			x = 1 + rand()%( lvl -> w - 1 );
			y = 1 + rand()%( lvl -> h - ( (3 * h) / lvl -> tileh ) );
		}
		PHYSICS mpos ;
		mpos . can_jump = 1 ;
		double vx = 150-rand()%300 ;
		double vy = 150-rand()%300 ;
		VECTOR3D_SET( mpos . position, ( x * lvl -> tilew ) + lvl -> tilew / 2.0, y * lvl -> tileh - lvl -> tileh / 2.0, 0.0 );
		VECTOR3D_SET( mpos . speed, vx, vy, 0.0 );
		VECTOR3D_SET( mpos . acceleration, 0.0, 0.0, 0.0 );
		VECTOR3D_SET( mpos . orientation, 0.0, 0.0, 0.0 );
		monster = new_monster( 50 , BIGBOSS_MONSTER , mpos );
		if( monster )
			list_push( lvl -> monster_list, monster, NULL );
	}

	lvl -> native_w = w ;
	lvl -> native_h = h ;

	n_log( LOG_INFO, "Level %s loaded", file );

	return lvl ;
}



int draw_level( LEVEL *lvl, int px, int py, int w, int h )
{
	int startx =  ( px - w / 2 ) / lvl -> tilew ;
	int starty =  ( py - h / 2 ) / lvl -> tileh ;
	int endx = 1 + w / lvl -> tilew ;
	int endy = 1 + h / lvl -> tileh ;

	int mx = 0, my = 0 ;

	mx = ( px - w / 2 ) - lvl -> tilew * startx ;
	my = ( py - h / 2 ) - lvl -> tileh * starty ;


	double xmin = 0.0, ymin = 0.0, xmax = 0.0, ymax = 0.0 ;
	for( int x = 0 ; x <= endx ; x ++ )
	{
		for( int y = 0 ; y <= endy ; y ++ )
		{
			int x1 = x * lvl -> tilew - mx ;
			int y1 = y * lvl -> tileh - my ;

			int x2 = x1 + lvl -> tilew ;
			int y2 = y1 + lvl -> tileh ;

			if( x1 < xmin )
				xmin = x1 ;
			if( x2 < xmin )
				xmin = x2 ;
			if( y1 < ymin )
				ymin = y1 ;
			if( y2 < ymin )
				ymin = y2 ;
			if( x1 > xmax )
				xmax = x1 ;
			if( x2 > xmax )
				xmax = x2 ;
			if( y1 > ymax )
				ymax = y1 ;
			if( y2 > ymax )
				ymax = y2 ;


			int px = x + startx ;
			int py = y + starty ;

			if( px >= 0 && py >= 0 && px < lvl -> w && py < lvl -> h )
			{
				if( lvl -> cells[ px ][ py ] > 0 )
				{
					ALLEGRO_BITMAP *bmp = lvl -> tiles[ lvl -> cells[ px ][ py ] - 1 ];
					if( bmp )
					{
						int w = al_get_bitmap_width( bmp );
						int h = al_get_bitmap_height( bmp );

						al_draw_bitmap( bmp, x1 + (lvl -> tilew / 2) - w / 2, y1 - h + lvl -> tileh, 0 );
					}
					else
					{
						al_draw_filled_rectangle( x1, y1, x2, y2, al_map_rgb( 255, 255, 255 ) );
					}
				}
			}
		}
	}

	LIST_NODE *node = NULL ;
	node = lvl -> monster_list -> start ;
	int it = 0 ;
	ALLEGRO_COLOR passive_color = al_map_rgb( 0, 255, 0 );
	ALLEGRO_COLOR aggressive_color = al_map_rgb( 255, 255, 0 );
	ALLEGRO_COLOR bigboss_color = al_map_rgb( 255, 0, 0 );
	while( node )
	{
		MONSTER *monster = node -> ptr ;
		if( monster )
		{
			double x = w / 2 + monster -> physics . position[ 0 ] - px ;
			double y = h / 2 + monster -> physics . position[ 1 ] - py ;
			switch( monster -> attr . type )
			{
				case BIGBOSS_MONSTER:
					al_draw_circle( x, y, monster -> physics . sz, bigboss_color , 1 );
					al_draw_line( x - monster -> physics . sz - 10 , y -  monster -> physics . sz -10 ,  x + monster -> physics . sz + 10 , y +  monster -> physics . sz + 10 , bigboss_color , 1 );
					al_draw_line( x - monster -> physics . sz - 10 , y +  monster -> physics . sz + 10 ,  x + monster -> physics . sz + 10 , y -  monster -> physics . sz - 10 , bigboss_color , 1 );
					al_draw_line( x , y -  monster -> physics . sz - 10 ,  x , y +  monster -> physics . sz + 10 , bigboss_color , 1 );
					al_draw_line( x - monster -> physics . sz - 10 , y ,  x + monster -> physics . sz + 10 , y , bigboss_color , 1 );
					break;
				case AGRESSIVE_MONSTER:
					al_draw_circle( x, y, monster -> physics . sz, aggressive_color , 1 );
					al_draw_line( x - monster -> physics . sz - 10 , y -  monster -> physics . sz -10 ,  x + monster -> physics . sz + 10 , y +  monster -> physics . sz + 10 , aggressive_color , 1 );
					al_draw_line( x - monster -> physics . sz - 10 , y +  monster -> physics . sz  + 10 , x + monster -> physics . sz + 10 , y -  monster -> physics . sz - 10 , aggressive_color , 1 );
					al_draw_line( x , y -  monster -> physics . sz -10 ,  x , y +  monster -> physics . sz + 10 , aggressive_color , 1 );
					al_draw_line( x - monster -> physics . sz - 10 , y ,  x + monster -> physics . sz + 10 , y , aggressive_color , 1 );
					break;
				default:
				case PASSIVE_MONSTER:
					al_draw_circle( x, y, monster -> physics . sz, passive_color , 1 );
					al_draw_line( x - monster -> physics . sz - 10 , y -  monster -> physics . sz -10 ,  x + monster -> physics . sz + 10 , y +  monster -> physics . sz + 10 , passive_color , 1 );
					al_draw_line( x - monster -> physics . sz - 10 , y +  monster -> physics . sz + 10 ,  x + monster -> physics . sz + 10 , y -  monster -> physics . sz - 10 , passive_color , 1 );
					al_draw_line( x , y -  monster -> physics . sz -10 ,  x , y +  monster -> physics . sz + 10 , passive_color , 1 );
					al_draw_line( x - monster -> physics . sz - 10 , y ,  x + monster -> physics . sz + 10 , y , passive_color , 1 );
					break;
			}
		}
		node = node -> next ;
		it ++ ;
	}

	draw_particle( lvl -> particle_system_effects, px - w / 2, py - h / 2, w, h, 50 );
	draw_particle( lvl -> particle_system_bullets, px - w / 2, py - h / 2, w, h, 50 );

	return TRUE ;
}
