////////////////////////////////////////////////////////////////////////////////
//
// File: graphics.c
//
// Description: This file contains graphics-related functions for the
//              robot competition.
//
// Author: Capt. Mike LeSauvage
//
// Revision History: 6 Mar 2006 - Created
//                  19 Jul 2006 - Major rework to change robot data from array
//                                to linked list.  LL docs found at:
//                                http://cmp.felk.cvut.cz/~matas/surrey/
//                                                             software/LL.html
//                   6 Sep 2006 - Changed DrawRobotBitmaps() to automatically
//                                center each robot based on the shield bitmap
//                                size, and the size of the robot's image.
//
////////////////////////////////////////////////////////////////////////////////
#include <math.h>                 //For cos, sin
#include "graphics.h"
#include "particles.h"

static ALLEGRO_FONT *font;
static ALLEGRO_BITMAP *temp;
static ALLEGRO_BITMAP *chargingBar;
static ALLEGRO_BITMAP *fullScreen; //Bitmap for full screen (arena/border/displays).
static ALLEGRO_BITMAP *arena; //Bitmap of just the arena (sub-bmp of fullScreen)
static ALLEGRO_BITMAP *shieldPic;     //Used for assembling shields and robot.
static ALLEGRO_BITMAP *robotImg;      //Static pic of the robot.
static ALLEGRO_BITMAP *missileImg;    //Static pic of a missile.
static ALLEGRO_BITMAP *laserImg;      //Used for temp drawing.
static ALLEGRO_BITMAP *backgroundImg; //Background interface image.
static ALLEGRO_BITMAP *sensorPic; //This image is used to draw the "large" sensor
								  //bitmap before it is cropped onto the individual
								  //sensor's bitmap.

//Internal helper prototypes
void DrawStatusText(ROBOT *robot, ALLEGRO_BITMAP *text, int destroyed);

////////////////////////////////////////////////////////////////////////////////
//
// Function: RenderScene
//
// Description: This function draws the current state of the robot competition.
//              Note that the arena is simply a sub-bitmap of the full screen.
//              This means it is quite easy to accidentally draw on the arena...
//              it won't be clipped, so the boundaries have to be right!
//
// Parameters: t_LL listOfRobots - The linked list of robots.
//             t_LL listOfDeadRobots - The linked list of dead robots.
//             message - A message to be printed in the system area.
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////
void RenderScene(t_LL listOfRobots, t_LL listOfDeadRobots, t_LL listOfWeapons,
		char *message) {
	int j, drawX, drawY, drawX2, drawY2, range;
	float angle, radians;
	ROBOT *robot;
	WEAPON *weapon;
	ALLEGRO_FONT *font = al_create_builtin_font();

	/*DRWAING THE SCREEN BITMAP*/
	al_draw_bitmap(fullScreen, 0, 0, 0);
	/*DRAWING THE BACKGROUND ARENA*/
	al_set_target_bitmap(fullScreen);
	al_draw_bitmap(backgroundImg, 0, 0, 0);
	/*DRAWING BLACK BACKGROUND FOR STATUS MESSAGE*/
	al_draw_filled_rectangle(759 + BORDER_WIDTH, BORDER_WIDTH,
		SCREEN_WIDTH - BORDER_WIDTH,
		SCREEN_HEIGHT - BORDER_WIDTH, al_map_rgb(0, 0, 0));

	/*FILLING ARENA BITMAP*/
	al_set_target_bitmap(arena);
	al_clear_to_color(
			al_map_rgb(COLOR_ARENA_RED, COLOR_ARENA_GREEN, COLOR_ARENA_BLUE));

	//Draw the sensor graphics
	ForeachLL_M(listOfRobots, robot)
	{

		for (j = 0; j < MAX_SENSORS; j++)
			if (robot->sensorArray[j].on && robot->sensorArray[j].powered)
				switch (robot->sensorArray[j].type) {
				case SENSOR_RADAR:
					drawX = robot->x * PX_PER_CM - robot->sensorArray[j].drawX;
					drawY = ARENA_HEIGHT_PX - robot->y * PX_PER_CM
							- robot->sensorArray[j].drawY;
					al_set_target_bitmap(arena);
					al_draw_bitmap(robot->sensorArray[j].image, drawX, drawY, 0);
					break;
				case SENSOR_RANGE:
					angle = -robot->sensorArray[j].angle + robot->heading;
					radians = angle * DEG_PER_RAD;
					drawX = robot->x * PX_PER_CM;
					drawY = ARENA_HEIGHT_PX - robot->y * PX_PER_CM;
					range = robot->sensorArray[j].data;
					if (range == -1)
						range = 80;
					drawX2 = drawX + cos(radians) * range * PX_PER_CM;
					drawY2 = drawY - sin(radians) * range * PX_PER_CM;
					al_set_target_bitmap(arena);
					al_draw_line(drawX, drawY, drawX2, drawY2,
							robot->color, 1);
					al_draw_filled_circle(drawX2, drawY2, 2,
							robot->color);
					break;
				case SENSOR_NONE:
				default:
					break;
				}
	}

	//Draw the robots and their related status information.
	ForeachLL_M(listOfRobots, robot)
	{
		//Draw the robot in its shield.
		drawX = robot->x * PX_PER_CM - SHIELD_BMP_SZ / 2;
		drawY = ARENA_HEIGHT_PX - robot->y * PX_PER_CM - SHIELD_BMP_SZ / 2;
		al_set_target_bitmap(arena);
		al_draw_bitmap(robot->image, drawX, drawY, 0);

	}

	//Draw robot information in the status area.
	ForeachLL_M(listOfRobots, robot)
		DrawStatusText(robot, fullScreen, 0);
	ForeachLL_M(listOfDeadRobots, robot)
		DrawStatusText(robot, fullScreen, 1);

	//Draw the weapons
	ForeachLL_M(listOfWeapons, weapon)
	{
		switch (weapon->type) {
		case WEAPON_LASER:
			drawX = weapon->x * PX_PER_CM - LASER_BMP_SZ / 2;
			drawY = ARENA_HEIGHT_PX - weapon->y * PX_PER_CM - LASER_BMP_SZ / 2;
			break;
		case WEAPON_MISSILE:
			drawX = weapon->x * PX_PER_CM - MISSILE_BMP_SZ / 2;
			drawY = ARENA_HEIGHT_PX - weapon->y * PX_PER_CM
					- MISSILE_BMP_SZ / 2;
			break;
		default:
			break;
		}

		al_set_target_bitmap(arena);
		al_draw_bitmap(weapon->image, drawX, drawY, 0);
	}

	DrawAParticles(arena);

	//Draw the system message, if any.
	al_draw_textf(font, al_map_rgb(255, 255, 255), 770, 750, 0, message);


	return;
}

////////////////////////////////////////////////////////////////////////////////
//
// Function: DrawSensorBitmaps
//
// Description: For sensors that have a corresponding image, this function
//              draws that image.
//              Images are drawn as they will appear on the screen.  This
//              means that y values are inverted because y increases from top
//              to bottom on a bitmap.
//              Angles are correct as sensor angles are given relative to the
//              robot's heading, but width values must be subtracted as
//              angles increase counterclockwise in "math" headings vs "compass"
//              headings.
//
// Note: There is the opportunity to optimize this function by drawing the
//       sensor bitmap only when it is on and powered (as is the case with the
//       RenderScene and UpdateSensorData functions.)  However, when done this
//       way the robot may turn its radar on AFTER this function is called,
//       which results in the older sensor graphic appearing on the screen for
//       one frame.
//
// Assumption: Currently, this function assumes that the max radar width
//             is 45 deg.  The assumption solves some problems related to
//             fitting the radar into a 200x200 pixel box.  The sensor graphic
//             would not fit in this box if much larger than 45deg.  Also,
//             the 45deg has been used in handing the special case of the
//             radar pointing left/right or up/down (see in-line docs).
//
// Parameters: t_LL listOfRobots - The linked list of robots.
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////
void DrawSensorBitmaps(t_LL listOfRobots) {
	double startAngle, endAngle, oppositeAngle, radians, radiansL1, radiansL2;
	int j, x, y, x1, x2, y1, y2, range;
	int xMin, yMin, left, top;
	ROBOT *robot;

	ForeachLL_M(listOfRobots, robot)
	{
		for (j = 0; j < MAX_SENSORS; j++)

			switch (robot->sensorArray[j].type) {
			case SENSOR_RADAR:
				//The algorithm for drawing the radar bitmap is:
				//1: Clear the bitmap to transparent.
				//2: Draw a colored circle to the radar range.
				//3: Draw lines in transparency bounding the arc on either side
				//4: Directly opposite to the arc, 10 pixels out, fill the remainder
				//   of the circle with the transparent color.
				//5: Now the job is to copy just the sensor graphic to the bitmap
				//   associated with the radar.
				//6: Find the three x,y points that define the arc and find the min
				//   and max each of x/y.
				//7: Min/max doesn't work if the arc is pointing with its curve left/
				//   right or up/down because the curve is further away than any of
				//   the defining arc points. To compensate, do a test to see if the
				//   round part of the arc is left/right or up/down, and if so,
				//   bound the box so the arc fits.
				//8: Pick x/y points for the final image for where the sensor should
				//   be drawn.  Sadly, although there is math behind it, due to
				//   rounding of odd pixels, the value had to be adjusted with +1
				//   with no proof...just empirical tests.

//				clearBitmap(temp);		//1

//				range = robot->sensorArray[j].range * PX_PER_CM;
//
//				startAngle = -robot->sensorArray[j].angle + robot->heading;
//				endAngle = startAngle - robot->sensorArray[j].width;
//				oppositeAngle = startAngle - robot->sensorArray[j].width / 2
//						+ 180;
//				al_set_target_bitmap(sensorPic);
////				al_draw_filled_circle(al_get_bitmap_width(sensorPic) / 2,		//***************************************************
////						al_get_bitmap_height(sensorPic) / 2,   				//2
////						range, robot->color);
//
//				radiansL1 = startAngle * DEG_PER_RAD;
//				x1 = RADAR_WRKIMG_PX / 2 * cos(radiansL1);
//				y1 = RADAR_WRKIMG_PX / 2 * sin(radiansL1);
//				al_set_target_bitmap(sensorPic);							//3a
//				al_draw_line(al_get_bitmap_width(sensorPic) / 2,
//						al_get_bitmap_height(sensorPic) / 2,
//						al_get_bitmap_width(sensorPic) / 2 + x1,
//						al_get_bitmap_height(sensorPic) / 2 - y1,
//						al_map_rgb(COLOR_TRANS_RED, COLOR_TRANS_GREEN,
//								COLOR_TRANS_BLUE), 1);
//				radiansL2 = endAngle * DEG_PER_RAD;
//				x2 = RADAR_WRKIMG_PX / 2 * cos(radiansL2);
//				y2 = RADAR_WRKIMG_PX / 2 * sin(radiansL2);
//				al_set_target_bitmap(sensorPic);
//				al_draw_line(al_get_bitmap_width(sensorPic) / 2,
//						al_get_bitmap_height(sensorPic) / 2,         	 //3b
//						al_get_bitmap_width(sensorPic) / 2 + x2,
//						al_get_bitmap_height(sensorPic) / 2 - y2,
//						al_map_rgb(COLOR_TRANS_RED, COLOR_TRANS_GREEN,
//								COLOR_TRANS_BLUE), 1);
//
//				radians = oppositeAngle * DEG_PER_RAD;
//				x = 10 * cos(radians);
//				y = 10 * sin(radians);
//				floodfill(sensorPic, al_get_bitmap_width(sensorPic) / 2 + x,                   //4
//						al_get_bitmap_height(sensorPic) / 2 - y, al_map_rgb(COLOR_TRANS_RED, COLOR_TRANS_GREEN,
//								COLOR_TRANS_BLUE));
//
//				//OK, now the *big* bitmap is drawn.  Now we just have to take the
//				//section we need and copy it to the radar sensor's bitmap.        //5
//				x1 = RADAR_WRKIMG_PX / 2 + range * cos(radiansL1);           //6
//				y1 = RADAR_WRKIMG_PX / 2 - range * sin(radiansL1);
//				x2 = RADAR_WRKIMG_PX / 2 + range * cos(radiansL2);
//				y2 = RADAR_WRKIMG_PX / 2 - range * sin(radiansL2);
//
//				xMin = al_get_bitmap_width(sensorPic) / 2;                   //6
//				if (x1 < xMin)
//					xMin = x1;
//				if (x2 < xMin)
//					xMin = x2;
//
//				yMin = al_get_bitmap_height(sensorPic) / 2;                  //6
//				if (y1 < yMin)
//					yMin = y1;
//				if (y2 < yMin)
//					yMin = y2;
//
//				while (startAngle < 0)                    //Due to earlier calc,
//					startAngle += 360;               //startAngle could be -ve.
//
//				if (startAngle > 180 && startAngle < 225)                    //7
//					left = 1;
//				else
//					left = xMin + 1;
//
//				if (startAngle > 90 && startAngle < 135)                     //7
//					top = 1;
//				else
//					top = yMin + 1;
//
//				al_set_target_bitmap(robot->sensorArray[j].image);
//				al_draw_bitmap_region(sensorPic, left, top, RADAR_IMAGE_PX,
//				RADAR_IMAGE_PX, 0, 0, 0);
//
//				robot->sensorArray[j].drawX = RADAR_IMAGE_PX - left + 1;
//				;                //8
//				robot->sensorArray[j].drawY = RADAR_IMAGE_PX - top + 1;

				break;
			case SENSOR_RANGE:
				break;
			case SENSOR_NONE:
			default:
				break;
			}
	}

}

////////////////////////////////////////////////////////////////////////////////
//
// Function: DrawRobotBitmaps
//
// Description: This function draws the shield outline and robot on the robot's
//              image bitmap.  A temporary image is used to draw the shield
//              and robot before the final product is drawn, rotated, onto the
//              robot's bitmap.  The robot bitmap is drawn centered onto
//              the shield image, which is then drawn centered on the robot's
//              image (the one in its structure).
//
// Parameters: t_LL listOfRobots - The linked list of robots.
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////
void DrawRobotBitmaps(t_LL listOfRobots) {
	float shieldCenterX, shieldCenterY;
	float drawAngle, modifier;
	ROBOT *robot;
	ALLEGRO_BITMAP *robotGraphic;
	ALLEGRO_BITMAP *temp;




	ForeachLL_M(listOfRobots, robot)
	{
		temp = al_create_bitmap(SHIELD_BMP_SZ, SHIELD_BMP_SZ);

		clearBitmap(temp);
		clearBitmap(robot->image);

		shieldCenterX = al_get_bitmap_width(temp) / 2; //All robot's shields are same size,
		shieldCenterY = al_get_bitmap_height(temp) / 2; //so calculate center point here.

		drawAngle = 90 - robot->heading;  //Convert "math" angle to screen "heading"
		if (drawAngle < 0)                //angle as rotate_sprite is in compass
			drawAngle = drawAngle + 360;  //coords and make positive.
		drawAngle = drawAngle * DEG_PER_RAD; //Convert from degrees to radian.


		modifier = robot->shields / MAX_SHIELD_ENERGY;

		if (robot->graphic != NULL)
			robotGraphic = robot->graphic;
		else
			robotGraphic = robotImg;

		al_set_target_bitmap(temp);
		al_draw_bitmap(robotGraphic, al_get_bitmap_width(robot->image) / 2 - al_get_bitmap_width(robotGraphic) / 2,
				al_get_bitmap_height(robot->image) / 2 - al_get_bitmap_height(robotGraphic) / 2, 0);
		al_set_target_bitmap(robot->image);
		al_draw_rotated_bitmap(temp, shieldCenterX, shieldCenterY, SHIELD_BMP_SZ / 2, SHIELD_BMP_SZ / 2,
				drawAngle, 0);
		al_draw_tinted_bitmap(robot->shield, al_map_rgba_f(1 * modifier, 1 * modifier, 1 * modifier, modifier), 0, 0, 0);
	}

	al_destroy_bitmap(temp);
}

////////////////////////////////////////////////////////////////////////////////
//
// Function: DrawWeaponBitmaps
//
// Description: This function draws the image of the weapon for the direction
//              it will be travelling.
//
// Parameters: WEAPON *weapon - A pointer to the weapon being drawn.
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////
void DrawWeaponBitmap(WEAPON *weapon) {
	float drawAngle;

	drawAngle = 90 - weapon->heading; //Convert "math" angle to screen "heading"
	if (drawAngle < 0)                   //angle as rotate_sprite is in compass
		drawAngle = drawAngle + 360;        //coords and make positive.
	drawAngle = drawAngle * DEG_PER_RAD;  //Convert from 0->255 for rotate_sprite.

	switch (weapon->type) {
	case WEAPON_LASER:
		clearBitmap(laserImg);
		clearBitmap(weapon->image);
		al_set_target_bitmap(laserImg);
		al_draw_rectangle(4, 2, 6, 8, al_map_rgb(255, 0, 0), 10);
		al_draw_line(5, 1, 5, 9, al_map_rgb(255, 0, 0), 1);
		al_set_target_bitmap(weapon->image);
		al_draw_bitmap(laserImg, 0, 0, 0);
		break;
	case WEAPON_MISSILE:
		clearBitmap(weapon->image);
		al_set_target_bitmap(weapon->image);
		al_draw_rotated_bitmap(missileImg, al_get_bitmap_width(missileImg) / 2,
				al_get_bitmap_height(missileImg) / 2, MISSILE_X_OFFSET,
				MISSILE_Y_OFFSET, drawAngle, 0);
		break;
	default:
		break;
	}
}

////////////////////////////////////////////////////////////////////////////////
//
// Function: ClearRobotGraphics
//
// Description: This function erases the robot bitmap and all sensor bitmaps
//              to the transparent color.
//
// Parameters: ROBOT *robot - A pointer to the robot to clear.
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////
void ClearRobotGraphics(ROBOT *robot) {
	int i;

	al_destroy_bitmap(robot->image);
	for (i = 0; i < MAX_SENSORS; i++) {
		if (robot->sensorArray[i].image != NULL) {
			al_destroy_bitmap(robot->sensorArray[i].image);
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
//
// Function: InitGraphics
//
// Description:
//
// Parameters:
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////
void InitGraphics() {

	//Set up the for full screen graphics.  Give warning on error and exit.

	/*Will probably be remove since we don't draw sprite anymore*/
//	set_trans_blender(0, 0, 0, 60);   //Set transparency level for drawing
	//transparent sprites.
	//Perform loading of specific resources to the competition.
	fullScreen = al_create_bitmap(SCREEN_WIDTH, SCREEN_HEIGHT);
	arena = al_create_sub_bitmap(fullScreen, 9, 9, ARENA_WIDTH_PX,
	ARENA_HEIGHT_PX);
	shieldPic = al_create_bitmap(SHIELD_BMP_SZ, SHIELD_BMP_SZ);
	al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
	sensorPic = al_create_bitmap(RADAR_WRKIMG_PX, RADAR_WRKIMG_PX);
	al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
	robotImg = al_load_bitmap(IMG_ROBOT);
	al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
	al_convert_mask_to_alpha(robotImg, al_map_rgb(COLOR_TRANS_RED, COLOR_TRANS_GREEN, COLOR_TRANS_BLUE));
	missileImg = al_load_bitmap(IMG_MISSILE);
	al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
	al_convert_mask_to_alpha(missileImg, al_map_rgb(COLOR_TRANS_RED, COLOR_TRANS_GREEN, COLOR_TRANS_BLUE));
	laserImg = al_create_bitmap(LASER_BMP_SZ, LASER_BMP_SZ);
	al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
	backgroundImg = al_load_bitmap(IMG_UI);
	chargingBar = al_load_bitmap(CHARGE_BAR);
	temp = al_create_bitmap(RADAR_IMAGE_PX, RADAR_IMAGE_PX);
	font = al_create_builtin_font();
	if (fullScreen == NULL || arena == NULL || shieldPic == NULL
			|| sensorPic == NULL || robotImg == NULL || missileImg == NULL
			|| laserImg == NULL || backgroundImg == NULL || chargingBar == NULL
			|| temp == NULL)
		AbortOnError(
				"InitGraphics() failed to create/load required resources.\n"
						"Program will exit.");
	InitParticleSystem(COLOR_ARENA_RED, COLOR_ARENA_GREEN, COLOR_ARENA_BLUE);
}

////////////////////////////////////////////////////////////////////////////////
//
// Function: DeInitGraphics
//
// Description:
//
// Parameters:
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////
void DeInitGraphics() {
	DeleteAllParticles();            //If any particles exist, free them!
	al_destroy_bitmap(arena);      //Delete arena bitmap before fullScreen as it
	al_destroy_bitmap(fullScreen);      //is really a sub-bitmap of fullScreen.
	al_destroy_bitmap(robotImg);
	al_destroy_bitmap(missileImg);
	al_destroy_bitmap(laserImg);
	al_destroy_bitmap(shieldPic);
	al_destroy_bitmap(sensorPic);
	al_destroy_bitmap(backgroundImg);
	al_destroy_bitmap(chargingBar);
	al_destroy_bitmap(temp);
	al_destroy_font(font);
}

////////////////////////////////////////////////////////////////////////////////
//
// Function: DrawStatusText
//
// Description: This internal helper is used for drawing the information about
//              each robot in the status area.  Sadly, it is a poorly-documented
//              mess as it was quickly implemented before the 2007 competition.
//              However, what it is doing is simply converting the generator,
//              shield, missile, and laser systems to bar graphs that fade
//              from green to red.
//
// Parameters: ROBOT *robot - The robot to draw information about.
//             BITMAP *text - The statues area of the screen to drawn on.
//             int destroyed - 0 if robot is destroyed, 1 if still fighting.
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////
void DrawStatusText(ROBOT *robot, ALLEGRO_BITMAP *text, int destroyed) {
	int i, j, k, count = 0, offset = 180;
	int tx = 850, ty, bx = 855, by; //text and bar values.
	ALLEGRO_COLOR white = al_map_rgb(255, 255, 255);
	char msg[STATUS_CHAR_COLS + 1];                  //Extra for null character.

	i = robot->number;
	al_set_target_bitmap(text);
	al_draw_textf(font, robot->color, 770, 20 + offset * i, 0, "%s",
			robot->name);

	if (destroyed) {
		al_set_target_bitmap(text);
		al_draw_textf(font, robot->color, 820, 40 + offset * i, -1,
				"DESTROYED!!!");
	} else {
		//Output Generator Status
		ty = 45;
		by = 43;
		al_set_target_bitmap(text);
		al_draw_bitmap(chargingBar, bx - 2, by + offset * i - 1, 0);
		al_draw_filled_rectangle(bx - 1 + 150 - (150.0 *(1- (float) robot->generatorStructure / (float) MAX_GENERATOR_STRUCTURE)), by + offset * i, bx - 1 + 150, by + 10 + offset * i, al_map_rgb(0, 0, 0));
		al_set_target_bitmap(text);
		al_draw_textf(font, robot->color, tx, ty + offset * i,
				ALLEGRO_ALIGN_RIGHT, "Generator:");
		al_set_target_bitmap(text);
		al_draw_textf(font, white, tx + 18, ty + offset * i, -1, "%d",
				robot->generatorStructure);

		//Output Shield Status
		ty = 65;
		by = 63;
		al_set_target_bitmap(text);
		al_draw_bitmap(chargingBar, bx - 2, by + offset * i - 1, 0);
		al_draw_filled_rectangle(bx - 1 + 150 - (150.0 *(1- robot->shields / (float) MAX_SHIELD_ENERGY)), by + offset * i, bx - 1 + 150, by + 10 + offset * i, al_map_rgb(0, 0, 0));
		al_set_target_bitmap(text);
		al_draw_textf(font, robot->color, tx, ty + offset * i,
				ALLEGRO_ALIGN_RIGHT, "Shield:");
		al_draw_textf(font, white, tx + 6, ty + offset * i, 0, "%.2f",
				robot->shields);

		//Output Missile Status
		ty = 85;
		by = 83;
		al_set_target_bitmap(text);
		al_draw_bitmap(chargingBar, bx - 2, by + offset * i - 1, 0);
		al_draw_filled_rectangle(bx - 1 + 150 - (150.0 *(1- robot->weaponArray[MISSILE_PORT].chargeEnergy / (float) MAX_MISSILE_ENERGY)), by + offset * i, bx - 1 + 150, by + 10 + offset * i, al_map_rgb(0, 0, 0));
		al_set_target_bitmap(text);
		al_draw_textf(font, robot->color, tx, ty + offset * i,
				ALLEGRO_ALIGN_RIGHT, "Missiles:");
		al_draw_textf(font, white, tx + 6, ty + offset * i, 0, "%.2f",
				robot->weaponArray[MISSILE_PORT].chargeEnergy);

		//Output Laser Status
		ty = 105;
		by = 103;
		al_set_target_bitmap(text);
		al_draw_bitmap(chargingBar, bx - 2, by + offset * i - 1, 0);
		al_draw_filled_rectangle(bx - 1 + 150 - (150.0 *(1- robot->weaponArray[LASER_PORT].chargeEnergy / (float) MAX_LASER_ENERGY)), by + offset * i, bx - 1 + 150, by + 10 + offset * i, al_map_rgb(0, 0, 0));
		al_set_target_bitmap(text);
		al_draw_textf(font, robot->color, tx, ty + offset * i,
				ALLEGRO_ALIGN_RIGHT, "Lasers:");
		al_draw_textf(font, white, tx + 6, ty + offset * i, 0, "%.2f",
				robot->weaponArray[LASER_PORT].chargeEnergy);

		//Output user's text message.
		for (j = 0; j < STATUS_CHAR_ROWS; j++) {
			for (k = 0; k < STATUS_CHAR_COLS; k++) {
				msg[k] = robot->statusMessage[count++];
				msg[k + 1] = '*';
				if (msg[k] == '\0' || msg[k] == '\n')
					break;
			}
			if (msg[k] == '\0') {
				al_set_target_bitmap(text);
				al_draw_textf(font, robot->color, 770, 135 + offset * i + 10 * j, 0, msg);
				break;
			} else if (msg[k] == '\n')
				msg[k] = '\0';
			else
				msg[k] = '\0';
			al_set_target_bitmap(text);
			al_draw_textf(font, robot->color, 770, 135 + offset * i + 10 * j, 0, msg);
		}
	}
	al_set_target_bitmap(text);
	al_draw_line(770, 30 + offset * i, 970, 30 + offset * i, robot->color, 0);
}

////////////////////////////////////////////////////////////////////////////////
//
// Function: _ffill
//
// Description: This function is changing the color of a pixel if the pixel
//				is of the desired color. Then it does the same for
//				the surrounding pixel.
//
// Parameters: ALLEGRO_BITMAP *bmp - The bitmap on which we want to change the color.
//             int x, int y - the position (x, y) of the pixel to scan.
//             ALLEGRO_COLOR fillcolor - The color we want the pixel to be.
//			   ALLEGRO_COLOR old - The color we want to be changed.
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////

void _ffill(ALLEGRO_BITMAP *bmp, int x, int y, ALLEGRO_COLOR fillcolor, ALLEGRO_COLOR old) {
	ALLEGRO_COLOR cmpColor = al_get_pixel(bmp, x, y);
    if(memcmp(&cmpColor, &old, sizeof(ALLEGRO_COLOR)))
    {
	    al_set_target_bitmap(bmp);
	    al_draw_pixel(x, y, fillcolor);
	    _ffill(bmp, x+1, y, fillcolor, old);
	    _ffill(bmp, x-1, y, fillcolor, old);
	    _ffill(bmp, x, y+1, fillcolor, old);
	    _ffill(bmp, x, y-1, fillcolor, old);
    }
 }

////////////////////////////////////////////////////////////////////////////////
//
// Function: floodfill
//
// Description: This function is changing the color of all
//				pixel adjacent to the original pixel.
//
// Parameters: ALLEGRO_BITMAP *bmp - The bitmap on which we want to change the color.
//             int x, int y - the position (x, y) of the pixel to scan.
//             ALLEGRO_COLOR fillcolor - The color we want the pixel to be.
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////

void floodfill(ALLEGRO_BITMAP *bmp, int x, int y, ALLEGRO_COLOR fillcolor) {
     ALLEGRO_COLOR oldcolor;
     oldcolor = al_get_pixel(bmp,x,y);
     _ffill(bmp,x,y,fillcolor,oldcolor);
 }


////////////////////////////////////////////////////////////////////////////////
//
// Function: loadShield
//
// Description: This function load the shield of each robot on a bitmap
//				to accelerate the rendering process while the game is running.
//
// Parameters: t_LL listOfRobots - A list of all robot structure.
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////
void loadShield(t_LL listOfRobots) {

	ROBOT *robot;
	ALLEGRO_BITMAP *temp;
	int i;
	int robotX, robotY;
	float alpha = 0.3;

	ForeachLL_M(listOfRobots, robot){

		robotX = al_get_bitmap_width(robot->image);
		robotY = al_get_bitmap_height(robot->image);

		temp = al_create_bitmap(robotX, robotY);
		al_set_target_bitmap(temp);
		al_clear_to_color(al_map_rgb(255, 0, 255));
		al_convert_mask_to_alpha(temp, al_map_rgb(255, 0, 255));

		for(i = 0; i < SHIELD_THICK_PX; i++){
				al_set_target_bitmap(temp);
				al_draw_filled_circle(robotX / 2, robotY / 2, robotX/ 2 - 4 + i, robot->color);
				al_set_target_bitmap(robot->shield);
				al_draw_tinted_bitmap(temp, al_map_rgba_f(1 * alpha * (i * 0.6), 1 * alpha * (i * 0.6), 1 * alpha * (i * 0.6), alpha), 0, 0, 0);
			}
		al_set_target_bitmap(robot->shield);
		al_draw_filled_circle(robotX / 2, robotY / 2, robotX/ 2 - SHIELD_THICK_PX, al_map_rgb(255, 0, 255));
		al_convert_mask_to_alpha(robot->shield, al_map_rgb(255, 0, 255));
	}

	al_destroy_bitmap(temp);
}

////////////////////////////////////////////////////////////////////////////////
//
// Function: loadRhield
//
// Description: This function load the radar of each robot on a bitmap
//				to accelerate the rendering process while the game is running.
//
// Parameters: t_LL listOfRobots - A list of all robot structure.
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////
void loadRadar(t_LL listOfRobots) {

	ROBOT *robot;
	ALLEGRO_BITMAP *temp = al_create_bitmap(RADAR_IMAGE_PX, RADAR_IMAGE_PX);
	int j;
	float x1, x2, x3, x4, y1, y2, y3, y4, radius, rad, alpha;

	alpha = 0.6;

	ForeachLL_M(listOfRobots, robot){

		for (j = 0; j < MAX_SENSORS; j++) {

			if (robot->sensorArray[j].type == SENSOR_RADAR) {

				rad = robot->sensorArray[j].angle * PI / 180;

					//Radius of the circle
					radius = robot->sensorArray[j].width / 2;
					//Middle of the bitmap
					x1 = 200 / 2;
					y1 = 200 / 2;
					//Middle of the circle
					x2 = x1;
					y2 = y1 - robot->sensorArray[j].range + radius;
					//Left vertex
					x3 = x2 - radius;
					y3 = y2;
					//Right vertex
					x4 = x2 + radius;
					y4 = y2;

					al_set_target_bitmap(temp);
					al_draw_filled_circle(x2, y2, radius, al_map_rgb(255, 255, 255));
					al_draw_filled_rectangle(0, y2, 200, 200, al_map_rgb(255, 0, 255));
					al_draw_filled_triangle(x1, y1, x2, y2, x3, y3, al_map_rgb(255, 255, 255));
					al_draw_filled_triangle(x1, y1, x2, y2, x4, y4, al_map_rgb(255, 255, 255));
					al_convert_mask_to_alpha(temp, al_map_rgb(255, 0, 255));
					al_set_target_bitmap(robot->sensorArray[j].image);
					al_draw_tinted_rotated_bitmap(temp, al_map_rgba_f(alpha, alpha, alpha, alpha), 100, 100, 100, 100, rad, 0);

			}
		}

	}

	al_destroy_bitmap(temp);
}
////////////////////////////////////////////////////////////////////////////////
//
// Function: clearBitmap
//
// Description: This function clear a bitmap.
//
// Parameters: ALLEGRO_BITMAP *bitmap - The bitmap to be cleared.
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////
void clearBitmap(ALLEGRO_BITMAP *bitmap){

	al_set_target_bitmap(bitmap);
	al_clear_to_color(al_map_rgb(255, 0, 255));
	al_convert_mask_to_alpha(bitmap, al_map_rgb(255, 0, 255));

}
//void DrawText(ROBOT *robot, BITMAP *text, int destroyed)
//{
//  int i, j, k, count=0, offset=180;
//  char msg[STATUS_CHAR_COLS+1];            //Extra for null character.
//
//  i=robot->number;
//  textprintf_ex(text, font, 770, 20+offset*i, robot->color, -1, "%s", robot->name);
//
//  if(destroyed)
//    textprintf_ex(text, font, 800, 40+offset*i, robot->color, -1, "DESTROYED!!!");
//  else
//  {
//    textprintf_ex(text, font, 770, 35+offset*i, robot->color, -1, "Speeds: %d, %d", robot->leftTreadSpeed, robot->rightTreadSpeed);
//    textprintf_ex(text, font, 770, 45+offset*i, robot->color, -1, "Shield Capacitor: %.2f", robot->shields);
//    textprintf_ex(text, font, 770, 55+offset*i, robot->color, -1, "Shield Recharge Rate: %d", robot->shieldChargeRate);
//    textprintf_ex(text, font, 770, 65+offset*i, robot->color, -1, "Missile Energy: %.2f", robot->weaponArray[MISSILE_PORT].chargeEnergy);
//    textprintf_ex(text, font, 770, 75+offset*i, robot->color, -1, "Missile Recharge Rate: %d", robot->weaponArray[MISSILE_PORT].chargeRate);
//    textprintf_ex(text, font, 770, 85+offset*i, robot->color, -1, "Laser Energy: %.2f", robot->weaponArray[LASER_PORT].chargeEnergy);
//    textprintf_ex(text, font, 770, 95+offset*i, robot->color, -1, "Laser Recharge Rate: %d", robot->weaponArray[LASER_PORT].chargeRate);
//    textprintf_ex(text, font, 770, 105+offset*i, robot->color, -1, "Bump Status: %d", robot->bumped);
//    textprintf_ex(text, font, 770, 115+offset*i, robot->color, -1, "Generator Structure: %d", robot->generatorStructure);
//
//    for(j=0; j<STATUS_CHAR_ROWS; j++)
//    {
//      for(k=0; k<STATUS_CHAR_COLS; k++)
//      {
//        msg[k]=robot->statusMessage[count++];
//        msg[k+1]='*';
//        if(msg[k]=='\0' || msg[k]=='\n')
//          break;
//      }
//      if(msg[k] == '\0')
//      {
//        textprintf_ex(text, font, 770, 135+offset*i+10*j, robot->color, -1, msg);
//        break;
//      }
//      else if(msg[k] == '\n')
//        msg[k]='\0';
//      else
//        msg[k]='\0';
//      textprintf_ex(text, font, 770, 135+offset*i+10*j, robot->color, -1, msg);
//    }
//  }
//    fastline(text, 770, 30+offset*i, 970, 30+offset*i, robot->color);
//}
