/**\file RazorCrest.c
 *
 *  RazorCrest Main File
 *
 *\author Castagnier Mickaël
 *
 *\version 1.0
 *
 *\date 15/12/2019
 */


#include "nilorea/n_common.h"
#include "nilorea/n_particles.h"
#include "nilorea/n_anim.h"
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_ttf.h>
#include "level.h"

ALLEGRO_DISPLAY *display  = NULL ;

/******************************************************************************
 *                           VARIOUS DECLARATIONS                             *
 ******************************************************************************/

int		DONE = 0,                    /* Flag to check if we are always running */
		getoptret = 0,				  /* launch parameter check */
		log_level = LOG_ERR ;			 /* default LOG_LEVEL */

ALLEGRO_BITMAP *scr_buf       = NULL ;

ALLEGRO_TIMER *fps_timer = NULL ;
ALLEGRO_TIMER *logic_timer = NULL ;
LIST *active_object = NULL ;                      /* list of active objects */

LEVEL *level = NULL ;

int main( int argc, char *argv[] )
{
	srand(time(NULL));
	/*
	 * INITIALISATION
	 */
	set_log_level( LOG_NOTICE );

	N_STR *log_file = NULL ;
	nstrprintf( log_file, "%s.log", argv[ 0 ] ) ;
	/*set_log_file( _nstr( log_file ) );*/
	free_nstr( &log_file );

	n_log( LOG_NOTICE, "%s is starting ...", argv[ 0 ] );

	/* allegro 5 + addons loading */
	if (!al_init())
	{
		n_abort("Could not init Allegro.\n");
	}
	if (!al_install_audio())
	{
		n_abort("Unable to initialize audio addon\n");
	}
	if (!al_init_acodec_addon())
	{
		n_abort("Unable to initialize acoded addon\n");
	}
	if (!al_init_image_addon())
	{
		n_abort("Unable to initialize image addon\n");
	}
	if (!al_init_primitives_addon() )
	{
		n_abort("Unable to initialize primitives addon\n");
	}
	if( !al_init_font_addon() )
	{
		n_abort("Unable to initialize font addon\n");
	}
	if( !al_init_ttf_addon() )
	{
		n_abort("Unable to initialize ttf_font addon\n");
	}
	if( !al_install_keyboard() )
	{
		n_abort("Unable to initialize keyboard handler\n");
	}
	if( !al_install_mouse())
	{
		n_abort("Unable to initialize mouse handler\n");
	}
	ALLEGRO_EVENT_QUEUE *event_queue = NULL;

	event_queue = al_create_event_queue();
	if(!event_queue)
	{
		fprintf(stderr, "failed to create event_queue!\n");
		al_destroy_display(display);
		return -1;
	}
	char ver_str[ 128 ] = "" ;

	while( ( getoptret = getopt( argc, argv, "hvV:L:" ) ) != EOF )
	{
		switch( getoptret )
		{
			case 'h':
				n_log( LOG_NOTICE, "\n    %s -h help -v version -V DEBUGLEVEL (NOLOG,VERBOSE,NOTICE,ERROR,DEBUG)\n", argv[ 0 ] );
				exit( TRUE );
			case 'v':
				sprintf( ver_str, "%s %s", __DATE__, __TIME__ );
				exit( TRUE );
				break ;
			case 'V':
				if( !strncmp( "NOTICE", optarg, 6 ) )
				{
					log_level = LOG_INFO ;
				}
				else
				{
					if(  !strncmp( "VERBOSE", optarg, 7 ) )
					{
						log_level = LOG_NOTICE ;
					}
					else
					{
						if(  !strncmp( "ERROR", optarg, 5 ) )
						{
							log_level = LOG_ERR ;
						}
						else
						{
							if(  !strncmp( "DEBUG", optarg, 5 ) )
							{
								log_level = LOG_DEBUG ;
							}
							else
							{
								n_log( LOG_ERR, "%s is not a valid log level\n", optarg );
								exit( FALSE );
							}
						}
					}
				}
				n_log( LOG_NOTICE, "LOG LEVEL UP TO: %d\n", log_level );
				set_log_level( log_level );
				break;
			case 'L' :
				n_log( LOG_NOTICE, "LOG FILE: %s\n", optarg );
				set_log_file( optarg );
				break ;
			case '?' :
				{
					switch( optopt )
					{
						case 'V' :
							n_log( LOG_ERR, "\nPlease specify a log level after -V. \nAvailable values: NOLOG,VERBOSE,NOTICE,ERROR,DEBUG\n\n" );
							break;
						case 'L' :
							n_log( LOG_ERR, "\nPlease specify a log file after -L\n" );
						default:
							break;
					}
				}
				__attribute__ ((fallthrough));
			default:
				n_log( LOG_ERR, "\n    %s -h help -v version -V DEBUGLEVEL (NOLOG,VERBOSE,NOTICE,ERROR,DEBUG) -L logfile\n", argv[ 0 ] );
				exit( FALSE );
		}
	}

	fps_timer = al_create_timer( 1.0/60.0 );
	logic_timer = al_create_timer( 1.0/60.0 );

	al_set_new_display_flags( ALLEGRO_OPENGL|ALLEGRO_WINDOWED );
	display = al_create_display( WIDTH, HEIGHT );
	if( !display )
	{
		n_abort("Unable to create display\n");
	}
	al_set_window_title( display, "RazorCrest" );

	al_set_new_bitmap_flags( ALLEGRO_VIDEO_BITMAP );

	ALLEGRO_FONT *font = al_load_font( "DATA/2Dumb.ttf", 18, 0 );


	double delta_time = 1000000.0/50.0 ;


	PLAYER player ;

	player . attr . level = 1 ;
	player . attr . cur_level = 1 ;
	al_register_event_source(event_queue, al_get_display_event_source(display));
	al_start_timer( fps_timer );
	al_start_timer( logic_timer );
	al_register_event_source(event_queue, al_get_timer_event_source(fps_timer));
	al_register_event_source(event_queue, al_get_timer_event_source(logic_timer));

	al_register_event_source(event_queue, al_get_keyboard_event_source());
	al_register_event_source(event_queue, al_get_mouse_event_source());

	ALLEGRO_BITMAP *scrbuf = al_create_bitmap( WIDTH, HEIGHT );

	al_hide_mouse_cursor(display);

	/* each level */
	do
	{
		DONE = 0 ;
		active_object = new_generic_list( -1 );

		LEVEL *level = NULL ;
		N_STR *level_string = NULL ;
		nstrprintf( level_string , "DATA/Levels/level%d.txt" , player . attr . cur_level );
		level = load_level( _nstr( level_string ) , "DATA/Levels/level1_ressources.txt", WIDTH, HEIGHT );
		free_nstr( &level_string );

		VECTOR3D_SET( player . physics . position, level -> startx, level -> starty, 0.0 );
		VECTOR3D_SET( player . physics . speed,  0.0, 0.0, 0.0  );
		VECTOR3D_SET( player . physics . acceleration, 0.0, 0.0, 0.0 );
		VECTOR3D_SET( player . physics . orientation, 0.0, 0.0, 0.0 );

		player . physics . can_jump = 0, player . physics . sz = 3 ;
		player . attr . action = 0 ;
		player . attr . move = 0 ;
		player . attr . life = 100 ;
		player . attr . xp = 0 ;
		player . attr . xp_to_level = player. attr . cur_level * 1000 ;
		player . attr . direction = 0 ;
		player . attr . xspeedmax = 200 ;
		player . attr . xspeedinc = 5 ;
		player . attr . yspeedmax = 100 * ( 1 + (player . attr . level / 3) );
		player . attr . yspeedinc = 5 ;

		double shoot_rate_time = 0 ;

		enum APP_KEYS
		{
			KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ESC, KEY_SPACE, KEY_CTRL
		};
		int key[ 7 ] = {false,false,false,false,false,false,false};
		VECTOR3D old_pos ;
		VECTOR3D friction = { 100.0, 0.0, 0.0 };


		int mx = 0, my = 0, mouse_b1 = 0, mouse_b2 = 0 ;
		int do_draw = 0, do_logic = 0 , press_up_message = 1 ;

		al_set_mouse_xy( display , WIDTH / 2 , (HEIGHT / 2) - 100 );

		al_flush_event_queue( event_queue );
		do
		{
			ALLEGRO_EVENT ev ;

			al_wait_for_event(event_queue, &ev);

			if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
			{
				switch(ev.keyboard.keycode)
				{
					case ALLEGRO_KEY_UP:
						key[KEY_UP] = 1;
						break;
					case ALLEGRO_KEY_DOWN:
						key[KEY_DOWN] = 1;
						break;
					case ALLEGRO_KEY_LEFT:
						key[KEY_LEFT] = 1;
						break;
					case ALLEGRO_KEY_RIGHT:
						key[KEY_RIGHT] = 1;
						break;
					case ALLEGRO_KEY_ESCAPE:
						key[KEY_ESC] = 1 ;
						break;
					case ALLEGRO_KEY_SPACE:
						key[KEY_SPACE] = 1 ;
						break;
					case ALLEGRO_KEY_LCTRL:
					case ALLEGRO_KEY_RCTRL:
						key[KEY_CTRL] = 1 ;
					default:
						break;
				}
			}
			else if(ev.type == ALLEGRO_EVENT_KEY_UP)
			{
				switch(ev.keyboard.keycode)
				{
					case ALLEGRO_KEY_UP:
						key[KEY_UP] = 0;
						break;
					case ALLEGRO_KEY_DOWN:
						key[KEY_DOWN] = 0;
						break;
					case ALLEGRO_KEY_LEFT:
						key[KEY_LEFT] = 0;
						break;
					case ALLEGRO_KEY_RIGHT:
						key[KEY_RIGHT] =0;
						break;
					case ALLEGRO_KEY_ESCAPE:
						key[KEY_ESC] = 0 ;
						break;
					case ALLEGRO_KEY_SPACE:
						key[KEY_SPACE] = 0 ;
						break;
					case ALLEGRO_KEY_LCTRL:
					case ALLEGRO_KEY_RCTRL:
						key[KEY_CTRL] = 0 ;
					default:
						break;
				}
			}
			else if( ev.type == ALLEGRO_EVENT_TIMER )
			{
				if( al_get_timer_event_source( fps_timer ) == ev.any.source )
				{
					do_draw = 1 ;
				}
				else if( al_get_timer_event_source( logic_timer ) == ev.any.source )
				{
					do_logic = 1;
				}
			}
			else if( ev.type == ALLEGRO_EVENT_MOUSE_AXES )
			{
				mx = ev.mouse.x;
				my = ev.mouse.y;
			}
			else if( ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN )
			{
				if( ev.mouse.button == 1 )
					mouse_b1 = 1 ;
				if( ev.mouse.button == 2 )
					mouse_b2 = 1 ;
			}
			else if( ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP )
			{
				if( ev.mouse.button == 1 )
					mouse_b1 = 0 ;
				if( ev.mouse.button == 2 )
					mouse_b2 = 0 ;
			}


			/* Processing inputs */
			int mouse_button = -1 ;
			if( mouse_b1==1 )
				mouse_button = 1 ;
			if( mouse_b2==1 )
				mouse_button = 2 ;

			player . attr . move = 0 ;

			if( key[ KEY_UP ] )
			{
				VECTOR3D_SET( player . physics . speed, player . physics . speed[ 0 ], player . physics . speed[ 1 ] - player . attr . yspeedinc, player . physics . speed[ 2 ] );
				if( player . physics . speed[ 1 ] < -player . attr . yspeedmax )
					player . physics . speed[ 1 ] = -player . attr . yspeedmax ;

				player . physics . can_jump = 0 ;
				player . attr . move = 1 ;
			}
			else
			{
				if( player . physics . speed[ 1 ] < 0.0 )
				{
					player . physics . speed[ 1 ] = player . physics . speed[ 1 ] + friction[ 1 ] * delta_time / 1000000.0 ;
					if( player . physics . speed[ 1 ] > 0.0 )
						player . physics . speed[ 1 ] = 0.0 ;
				}
			}


			if( key[ KEY_DOWN ] && player . physics . speed[ 1 ] != 0 )
			{
				VECTOR3D_SET( player . physics . speed, player . physics . speed[ 0 ], player . physics . speed[ 1 ] + player . attr . yspeedinc, player . physics . speed[ 2 ] );
				if( player . physics . speed[ 1 ] > player . attr . yspeedmax )
					player . physics . speed[ 1 ] = player . attr . yspeedmax ;
				player . physics . can_jump = 0 ;
				player . attr . move = 1 ;
			}
			else
			{
				if( player . physics . speed[ 1 ] > 0.0 )
				{
					player . physics . speed[ 1 ] = player . physics . speed[ 1 ] - friction[ 1 ] * delta_time / 1000000.0 ;
					if( player . physics . speed[ 1 ] < 0.0 )
						player . physics . speed[ 1 ] = 0.0 ;
				}
			}

			if( key[ KEY_LEFT ] && player . physics . speed[ 1 ] != 0 )
			{
				VECTOR3D_SET( player . physics . speed, player . physics . speed[ 0 ] - player . attr . xspeedinc, player . physics . speed[ 1 ], player . physics . speed[ 2 ] );
				if( player . physics . speed[ 0 ] < -player . attr . xspeedmax )
					player . physics . speed[ 0 ] = -player . attr . xspeedmax ;
				player . attr . direction = 1 ;
				player . attr . move = 1 ;
			}
			else
			{
				if( player . physics . speed[ 0 ] < 0.0 )
				{
					player . physics . speed[ 0 ] = player . physics . speed[ 0 ] + friction[ 0 ] * delta_time / 1000000.0 ;
					if( player . physics . speed[ 0 ] > 0.0 )
						player . physics . speed[ 0 ] = 0.0 ;
				}
			}


			if( key[ KEY_RIGHT ] && player . physics . speed[ 1 ] != 0 )
			{
				VECTOR3D_SET( player . physics . speed, player . physics . speed[ 0 ] + player . attr . xspeedinc, player . physics . speed[ 1 ], player . physics . speed[ 2 ] );
				if( player . physics . speed[ 0 ] > player . attr . xspeedmax )
					player . physics . speed[ 0 ] = player . attr . xspeedmax ;
				player . attr . direction = 1 ;
				player . attr . move = 1 ;
			}
			else
			{
				if( player . physics . speed[ 0 ] > 0.0 )
				{
					player . physics . speed[ 0 ] = player . physics . speed[ 0 ] - friction[ 0 ] * delta_time / 1000000.0 ;
					if( player . physics . speed[ 0 ] < 0.0 )
						player . physics . speed[ 0 ] = 0.0 ;
				}
			}


			if( key[KEY_CTRL ]  || mouse_button == 1 )
			{
				if( player . attr . action == 0 )
					player . attr . action = 2 ;

				if( player . attr . action == 3 )
				{
					if( shoot_rate_time > ( ( 11 - player . attr . level ) * 50000 ) )
					{
						player . attr . action = 2 ;
						shoot_rate_time -= ( ( 11 - player . attr . level ) * 50000 )  ;
					}
				}
			}
			else
			{
				shoot_rate_time = 0 ;
				player . attr . action = 0 ;
			}

			if( player . physics . speed[ 1 ] != 0 )
			{
				if(  player . physics . speed[ 1 ] > -50 )
				{
					player . physics . speed[ 1 ] = -50 ;
				}
				press_up_message = 0 ;
			}
			else
			{
				press_up_message = 1 ;
			}

			if( do_logic == 1 )
			{
				shoot_rate_time += delta_time ;
				if( fabs( player . physics . speed[ 0 ] ) < 0.5 )
					player . physics . speed[ 0 ] = 0.0 ;

				memcpy( &old_pos, &player . physics . position, sizeof( VECTOR3D ) );

				animate_physics( level, &player . physics, friction, delta_time , &player );

				animate_level( level, &player, delta_time );

				/* add particles to player position  */
				if( ( player . attr . move != 0 || player . physics . can_jump == 0 ) || player . attr . action == 2 )
				{

					PHYSICS tmp_part ;
					tmp_part . sz = 10 ;
					for( int it = 0 ; it < fabs( player . physics . speed[ 1 ] / 50 ) ; it ++ )
					{
						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, player . physics . position[ 0 ], player . 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(   0 ,  0 , 55 + rand()%200, 10 + rand()%245 ), tmp_part );

					}

					if( player . attr . action == 2 )
					{
						player . attr . action = 3 ;

						double itx = 0, ity = 0, itz = 0, sz = 0;

						itx = (double)(mx - level -> native_w / 2  ) - level -> tilew / 2 ;
						ity = (double)(my - level -> native_h / 2  ) - level -> tileh / 2 ;
						itz = 0 ;
						sz = sqrt((itx * itx) + (ity * ity) + (itz * itz));
						itx /= sz ;
						ity /= sz ;
						itz /= sz ;

						for( int it = 0  ; it <= (1 + (player . attr . level / 3) ) ; it ++ )
						{
							double speed_mult = 500 +rand()%100 ;
							double accuity = rand()%( 10* (11 - player . attr . level) );
							VECTOR3D_SET( tmp_part . speed, accuity + player . physics . speed[ 0 ] + itx * speed_mult, accuity + player . physics . speed[ 1 ] + ity * speed_mult, player . physics . speed[ 2 ] + itz * speed_mult );
							VECTOR3D_SET( tmp_part . position, player . physics . position[ 0 ], player . 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 );
							//int bw_color =  10 + rand()%200 ;
							//add_particle( level -> particle_system_bullets, -1, PIXEL_PART, 2000, 5 + rand()%player.attr.level,  al_map_rgba(  bw_color, bw_color, bw_color, 255 - bw_color  ), tmp_part );
							add_particle( level -> particle_system_bullets, -1, PIXEL_PART, 2000, 5 + rand()%player.attr.level,  al_map_rgb( 0 , 0 , 150 + rand()%100 ), tmp_part );

						}

					}

					list_foreach( node, level -> monster_list )
					{
						MONSTER *npc = (MONSTER *)node -> ptr ;
						int px = player . physics . position[ 0 ] ;
						int py = player . physics . position[ 1 ] ;
						int npx = npc -> physics . position[0];
						int npy = npc -> physics . position[1];

						if( npx >= px - 32 && npx <= px + 32 && npy >= py - 32 && npy <= py + 32 )
						{
							int loss = 0 ;
							switch( npc -> attr . type )
							{
								case BIGBOSS_MONSTER:
									loss = 15 ;
									break;
								case AGRESSIVE_MONSTER:
									loss = 7 ;
									break;
								default:
								case PASSIVE_MONSTER:
									loss = 3 ;
									break;
							}


							player . attr . life -=  loss ;
							npc -> attr . life = 0 ;
							if( player . attr . life < 0 )
							{
								player . attr . life  = 0 ;
								DONE = 2 ;
							}
							
							player . attr . xp -=  10 * npc -> physics . sz ;
							if( player . attr . xp < 0 )
							{
								player . attr . xp = 0 ;
								if( player . attr . level > 1 )
								{
									player . attr . level -- ;
								}
							}	

							npx =  player . physics . position[ 0 ] ;
							npy =  player . physics . position[ 1 ] ;
							for( int it = 0 ; it < 2 * loss; 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_rgb( 255 - (255 * player . attr . life ) / 100 , (255 * player . attr . life) / 100 , 0 ) , tmp_part );
										//al_map_rgba( 55 + rand()%200, 0 , 0 , 255 ), tmp_part );
							}
						}
					}
				}

				int cellx = player . physics . position[ 0 ] / level -> tilew ;
				int celly = player . physics . position[ 1 ] / level -> tileh ;
				if( cellx >= 0 && cellx < level -> w && celly >= 0 && celly < level -> h )
				{
					/* cell containing an exit */
					if( level -> cells[ cellx ][ celly ] == EXIT_CELL )
						DONE = 1 ;
				}
				do_logic = 0 ;
			}

			if( do_draw == 1 )
			{
				al_set_target_bitmap( scrbuf );
				al_clear_to_color( al_map_rgba( 0, 0, 0, 255 ) );

				draw_level( level, player . physics . position[ 0 ], player . physics . position[ 1 ], WIDTH, HEIGHT );

				int tmp_x = WIDTH / 2 ;
				int tmp_y = HEIGHT / 2 ;
				al_draw_filled_triangle( tmp_x - 32 , tmp_y + 32 - player . physics . speed[ 0 ] / 15 ,
					                 tmp_x + 32 , tmp_y + 32 + player . physics . speed[ 0 ] / 15 , 
							 tmp_x + player . physics . speed[ 0 ] / 10 , tmp_y - 32 - fabs( player . physics . speed[ 1 ] / 15 ) , 
							 al_map_rgb( 255 - (255 * player . attr . life ) / 100 , (255 * player . attr . life) / 100 , 0 ) );

				al_acknowledge_resize( display );
				int w = al_get_display_width(  display );
				int h = al_get_display_height( display );

				al_set_target_bitmap( al_get_backbuffer( display ) );

				al_clear_to_color( al_map_rgba( 0, 0, 0, 255 ) );
				al_draw_bitmap( scrbuf, w/2 - al_get_bitmap_width( scrbuf ) /2, h/2 - al_get_bitmap_height( scrbuf ) / 2, 0 );

				/* mouse pointer */
				al_draw_line( mx - 10, my, mx + 10, my, al_map_rgb( 255, 255, 255 ), 2 );
				al_draw_line( mx, my + 10, mx, my - 10, al_map_rgb( 255, 255, 255 ), 2 );
				al_draw_circle( mx, my , 5 , al_map_rgb( 255, 255, 255 ), 2 );

				/* speed meter */
				al_draw_filled_rectangle( 20, h/2, 25, h/2 + player . physics . speed[ 1 ], al_map_rgba( 255, 255, 255, 255 ) );
				al_draw_rectangle( 20, h/2, 25, h/2 - player . attr . yspeedmax , al_map_rgba( 255, 255, 255, 255 ) , 1 );
				al_draw_filled_rectangle( w/2, h -20, w/2 + player . physics . speed[ 0 ], h-25, al_map_rgba( 255, 255, 255, 255 ) );

				/* draw press up message */
				if( press_up_message )
				{
					static int color = 100 ;
					al_draw_text( font, al_map_rgb( color, 0, 0 ), WIDTH / 2 , HEIGHT / 2       , ALLEGRO_ALIGN_CENTRE , "*** PRESS UP TO START ***" );
					al_draw_text( font, al_map_rgb( color, 0, 0 ), WIDTH / 2 , HEIGHT / 2 + 100 , ALLEGRO_ALIGN_CENTRE , "*** DO NOT WAIT FOR VIRUS !! ***" );
					color += 2 ;
					if( color > 255 )
						color = 100 ;
				}

				N_STR *nstr = NULL ;
				nstrprintf( nstr, "Life: %d %% exp: %d level: %d", player . attr . life , player . attr . xp , player . attr . level );
				al_draw_text( font, al_map_rgb( 255, 0, 0 ), 20, HEIGHT - 20, 0, _nstr( nstr ) );
				free_nstr( &nstr );

				al_flip_display();
				do_draw = 0 ;
			}

		}
		while( !key[KEY_ESC] && !DONE && player . attr . life > 0 );

		N_STR *playerstr = new_nstr( 100 );
		N_STR *levelstr = new_nstr( 100 );
		nstrprintf( playerstr, "Player power level %d, XP %d" , player . attr . level , player . attr . xp );
		if( DONE == 1 )
		{
			nstrprintf( levelstr, "You won level %d !" , player . attr . cur_level );
			al_show_native_message_box(  al_get_current_display(), " " ,  _nstr( levelstr ) , _nstr( playerstr ), NULL, 0  );
			player . attr . cur_level ++ ;
		}
		else
		{
			nstrprintf( levelstr, "You LOST at level %d !" , player . attr . level );
			al_show_native_message_box(  al_get_current_display(), _nstr( levelstr ) , _nstr( playerstr ) , "Game Over", NULL, 0  );
		}
		free_nstr( &playerstr );
		free_nstr( &levelstr );

		/******************************************************************************
		 *                             EXITING                                        *
		 ******************************************************************************/

		list_destroy( &active_object );


	}while( player . attr . life > 0 && player . attr . cur_level < 4 && DONE );


	if( player . attr . life > 0 && player . attr . cur_level > 3 )
	{
		N_STR *playerstr = new_nstr( 100 );
		nstrprintf( playerstr, "Player power level %d, XP %d" , player . attr . level , player . attr . xp );
		al_show_native_message_box(  al_get_current_display(), "" , "YOU WON THE GAME !!" , _nstr( playerstr ) , NULL, 0  );
		free_nstr( &playerstr );
	}


	return 0;

}



int choose_level()
{
	return TRUE ;
}
