
#include "aicpu.h"
#include <math.h>
#include "framedata.h"
#include "job.h"

#include <iostream>
#include "aimath.h"
#include "mdefs.h"


#define SHOTSPEEDAST 7.77
#define SHOTSPEEDUFO 8.4

bool AICpu::Shot = false;
bool AICpu::Hyper = false;

AICpu::AICpu(QObject *parent):
	QObject(parent),n(0)
{

}

AICpu::~AICpu()
{
}
	




// Drehe auf den Winkel aus Options::Angle
bool AICpu::applyAngle1(double angle, bool correction)
{

	
	FrameData *data = ai->getLast();
	QPair<int, double> anglePair = ai->getShootAngle(n);
	
	double shipAngle = anglePair.second;
	//double sollAngle = (double)Options::Angle;
	double diffAngle = angle - shipAngle;

	// Normalisieren
	if(diffAngle >= 180.0)
	{
		diffAngle = diffAngle - 360.0;
	}
	else if(diffAngle <= -180.0)
	{
		diffAngle = diffAngle + 360.0;
	}

	// Schwellwert
	if (abs(diffAngle) >= 2.5 && data->shipData.visible)
	{
		// Richtungsentscheidung
		if (diffAngle < 0.0)
		{
				ai->actionRight(true);
				n--;
				return false;
		} 
		else if (diffAngle > 0.0)
		{
				ai->actionLeft(true);
				n++;
				return false;
		}
		else
		{
			ai->clearActions();
			return true;
		}
	}
	else
	{
		if(!correction)
		{
			return true;
		}
		// Prüfen ob Winkel passt und gegebenfalls korrigieren
		static int nError = 0;
		if(floor(data->shipData.angle) != anglePair.first)
		{
			nError++;
			if(nError > 6)
			{
				qDebug()<<"XXXXXXXXXXXXXXXXXXXXXXXXXXXX";
				qDebug()<<"Offset Erkannt Index: " << n;
				qDebug()<<"Winkelpaar: "<< anglePair;
				qDebug()<<"Ausgelesener Winkel: "<<floor(data->shipData.angle);
				qDebug()<<"Moegliche Indices: "<<ai->getIndizes(floor(data->shipData.angle));
				
				QList<unsigned char> indices = ai->getIndizes(floor(data->shipData.angle));
				unsigned char correctionFactor  = 0;
				int dif = 256;
				for(int i=0; i< indices.size(); i++)
				{
					int c=abs(indices[i]-n);
					if(c<dif)
					{
						dif = c;
						correctionFactor = indices[i];
					}
				}
				qDebug()<<"Gefundene Korrektur: "<<correctionFactor;
				qDebug()<<" ";
				nError = 0;
				// Nur korrigieren wenn der Fehler nicht zu Groß ist 
				if(abs(n - correctionFactor) < 40)
				{
					n = correctionFactor;
				}
				// Hier ist alles kapput
				else
				{
					qDebug() << "error offset cannot be corrected";
				}
				return false;
			}
			return true;
		}
		else
		{
			nError = 0;
			return true;
		}
		

	}


}


bool AICpu::applyAngle(double angle, bool correction)
{
	FrameData *data = ai->getLast();
	QPair<int, double> anglePair = ai->getShootAngle(n);
	QPair<int, double> leftAnglePair = ai->getShootAngle(n+1);
	QPair<int, double> rightAnglePair = ai->getShootAngle(n-1);
	
	double shipAngle = anglePair.second;
	double leftShipAngle = leftAnglePair.second;
	double rightShipAngle = rightAnglePair.second;
	
	double diffAngle = abs(angle - shipAngle);
	if(diffAngle > 180.0)
	{
		diffAngle = 360.0 - diffAngle;
	}
	
	double leftDiffAngle = abs(angle - leftShipAngle);
	if(leftDiffAngle > 180.0)
	{
		leftDiffAngle = 360.0 - leftDiffAngle;
	}
	
	double rightDiffAngle = abs(angle - rightShipAngle);
	if(rightDiffAngle > 180.0)
	{
		rightDiffAngle = 360.0 - rightDiffAngle;
	}

	double min = qMin(leftDiffAngle, rightDiffAngle);
	min = qMin(diffAngle, min);

	static unsigned char nLast = 0;
	if(min == leftDiffAngle)
	{
		ai->actionLeft(true);
		nLast = n;
		n++;
		return false;
	}
	else if (min == rightDiffAngle)
	{
		ai->actionRight(true);
		nLast = n;
		n--;
		return false;
	}
	else
	{
		if(!correction)
		{
			return true;
		}
		// Prüfen ob Winkel passt und gegebenfalls korrigieren
		static int nError = 0;

		if(floor(data->shipData.angle) != anglePair.first && floor(data->shipData.angle) != ai->getShootAngle(nLast).first)
		{
			nError++;
			if(nError > 0)
			{
				//qDebug()<<"XXXXXXXXXXXXXXXXXXXXXXXXXXXX";
				//qDebug()<<"Offset Erkannt Index: " << n;
				//qDebug()<<"Winkelpaar: "<< anglePair;
				//qDebug()<<"Ausgelesener Winkel: "<<floor(data->shipData.angle);
				//qDebug()<<"Moegliche Indices: "<<ai->getIndizes(floor(data->shipData.angle));
				
				QList<unsigned char> indices = ai->getIndizes(floor(data->shipData.angle));
				unsigned char correctionFactor  = 0;
				int dif = 256;
				for(int i=0; i< indices.size(); i++)
				{
					int c=abs(indices[i]-n);
					if(c<dif)
					{
						dif = c;
						correctionFactor = indices[i];
					}
				}
				//qDebug()<<"Gefundene Korrektur: "<<correctionFactor;
				//qDebug()<<" ";
				nError = 0;
				// Nur korrigieren wenn der Fehler nicht zu Groß ist 
				if(abs(n - correctionFactor) < 40)
				{
					n = correctionFactor;
				}
				// Hier ist alles kapput
				else
				{
					//qDebug() << "error offset cannot be corrected";
				}
				return false;
			}
			return true;
		}
		else
		{
			nError = 0;
			return true;
		}
		

	}

}

bool AICpu::checkAngle(double angle)
{
	FrameData *data = ai->getLast();
	QPair<int, double> anglePair = ai->getShootAngle(n);
	QPair<int, double> leftAnglePair = ai->getShootAngle(n+1);
	QPair<int, double> rightAnglePair = ai->getShootAngle(n-1);
	
	double shipAngle = anglePair.second;
	double leftShipAngle = leftAnglePair.second;
	double rightShipAngle = rightAnglePair.second;
	
	double diffAngle = abs(angle - shipAngle);
	if(diffAngle > 180.0)
	{
		diffAngle = 360.0 - diffAngle;
	}
	
	double leftDiffAngle = abs(angle - leftShipAngle);
	if(leftDiffAngle > 180.0)
	{
		leftDiffAngle = 360.0 - leftDiffAngle;
	}
	
	double rightDiffAngle = abs(angle - rightShipAngle);
	if(rightDiffAngle > 180.0)
	{
		rightDiffAngle = 360.0 - rightDiffAngle;
	}

	double min = qMin(leftDiffAngle, rightDiffAngle);
	min = qMin(diffAngle, min);

	if(diffAngle == min)
	{
		return true;
	}
	else
	{
		return false;
	}

}

void AICpu::fire(Target *target, bool once)
{
	// Feuern wenn Winkel erreicht
	ai->clearActions();



	// Winkeldiffernz zwischen <Ist> und <Soll> ermitteln 
	QPair<int, double> anglePair = ai->getShootAngle(n);
	double diffAngle = abs(target->angAstF - anglePair.second);
	if(diffAngle > 180.0)
	{
		diffAngle = 360.0 -diffAngle;
	}

	// Nur schiesen, wenn getroffen werden kann
	double dist = abs(target->distTarget * atan((PI / 180) * diffAngle));
	if(dist > 10.0 && target->type == MovingObject::Asteroid && target->size == Target::Small)
	{
		target->miss = true;
		return;
	}
	
	// Nur maximal jedes zweitemal schießen
	if(!Shot)
	{
		int shots = ai->getLast()->shotDataList.size();
		if(shots >= 4)
		{
			return;
		}
		
		ai->actionFire(true);
		// Falls mehrfachschiessen erlaubt
		if(!once)
		{
			target->forget(4-shots);
		}
		else
		{
			target->forget(1);
		}
	}


	
}

//void AICpu::generateDistanceData()
//{
//	FrameData *data = ai->getLast();
//	QList<Target*> targetList = data->targetList;
//	QPointF shipPos = data->shipData.position;
//	
//	double shotSpeed;
//	double time;
//	double dist;
//
//	double preDistInZeit;
//	QPointF preAstInZeit;
//	QPointF preShipInZeit;
//	QPointF preDPosAS;
//
//	QPointF vDist;
//	QPointF vecShipAst;
//	QPointF vecAstSpeed;
//	QPointF	radVec;
//
//	double astSpeed;
//	
//	QPointF absRadVec;
////	QPointF astInZeit;
////	QPointF shipInZeit;
//	QPointF dPosAS;
//
//	for(int i = 0; i < targetList.size(); i++)
//	{
//		vDist = targetList[i]->position - shipPos;
//		dist = sqrt(vDist.x() * vDist.x() + vDist.y() * vDist.y());
//		double distPixel = abs(vDist.x() + vDist.y());
//		targetList[i]->vTarget = vDist / dist;
//		targetList[i]->distTarget = dist;
//		
//		vecAstSpeed = targetList[i]->vVec;
//		astSpeed = targetList[i]->velocity;
//
//		time = distPixel / SHOTSPEEDAST; // + abs((angAst - angShip) / 96);
//
//		// PosAst in Zeit bestimmen mit SpeedAst und Zeit für drehung Ship
//		//preAstInZeit = targetList[i]->position + targetList[i]->vVec * targetList[i]->velocity * time;
//		//preShipInZeit = shipPos + data->shipData.vVec * data->shipData.velocity * time;
//		//preDPosAS = (preShipInZeit - preAstInZeit);
//		//preDistInZeit = sqrt(preDPosAS.x() * preDPosAS.x() + preDPosAS.y() * preDPosAS.y());
//
//		// Radiale Geschwindigekeit
//		vecShipAst = targetList[i]->position / dist; //preDistInZeit;
//
//		// Projektion
//		targetList[i]->radVec = ((vecShipAst.x() * vecAstSpeed.x() + vecShipAst.y() * vecAstSpeed.y()) / 
//			(vecAstSpeed.x() * vecAstSpeed.x() + vecAstSpeed.y() * vecAstSpeed.y())) * vecAstSpeed;
//		
//		// Absolute Projektion
//		// absRadVec = targetList[i]->radVec * targetList[i]->radSpeed;
//		
//		// Komponete in Richtung Ship (invertiert mit -1 * ) um selektion im findJob2 zu vereinfachen
//		targetList[i]->radSpeed = -1 * ((vecShipAst.x() * vecAstSpeed.x() * astSpeed + vecShipAst.y() * vecAstSpeed.y() * astSpeed) / 
//			sqrt((double)(vecAstSpeed.x() * vecAstSpeed.x() * astSpeed * astSpeed + vecAstSpeed.y() * vecAstSpeed.y() * astSpeed * astSpeed)));
//
//		//double angAst = double(qRound(((180.0 / PI) * acos(vDist.x() / dist)))) + 180;
//		// Zeit für schuss von aktShip zu aktAst
//		//if (targetList[i]->radSpeed < 0.0) 
//		//{
//		//	shotSpeed = 8.5;
//		//}
//		//else
//		//{
//		//	shotSpeed = 8.22;
//		//}
//
//		time = distPixel / SHOTSPEEDAST; // + abs((angAst - angShip) / 96);
//		
//		//PosAst in Zeit bestimmen mit SpeedAst und Zeit für drehung Ship
//		targetList[i]->astInZeit = targetList[i]->position + targetList[i]->vVec * targetList[i]->velocity * time;
//		targetList[i]->shipInZeit = shipPos + data->shipData.vVec * data->shipData.velocity * time;
//		dPosAS = (targetList[i]->shipInZeit - targetList[i]->astInZeit);
//		//targetList[i]->distInZeit = dPosAS.x() + dPosAS.y();
//		targetList[i]->distInZeit = sqrt(dPosAS.x() * dPosAS.x() + dPosAS.y() * dPosAS.y());
//	
//		//neuen Winkel zw ship und ast bestimmen
//		double angAstInTime = double(qRound(((180.0 / PI) * acos(dPosAS.x() / targetList[i]->distInZeit)))) + 180.0;
//			
//		if(angAstInTime > 360)
//			{
//				targetList[i]->dAngInZeit = abs(angAstInTime - 360.0 - data->shipData.angle);
//			}
//
//		if(dPosAS.y() < 0.0)
//			{
//				targetList[i]->dAngInZeit = abs(360.0 - angAstInTime - data->shipData.angle); 
//			}	
//	}
//}

void AICpu::generateDistanceData2()
{
	FrameData *data = ai->getLast();
	QList<Target*> targetList = data->targetList;

	// ShipDaten
	QPointF shipPos = data->shipData.heading;
	QPointF shipVec = data->shipData.heading;
	QPointF shipHead = data->shipData.heading;

	double shotSpeed = 8.0;
	double shipSpeed = data->shipData.velocity;

	double shipSpeed2 = Power(shipSpeed, 2);
	double shipVecx2 = Power(shipVec.x(), 2);
	double shipVecy2 = Power(shipVec.y(), 2);
	double shotSpeed2 = Power(shotSpeed, 2);
	double shipHeadx2 = Power(shipHead.x(), 2);
	double shipHeady2 = Power(shipHead.y(), 2);

	for(int i = 0; i < targetList.size(); i++)
	{
		if(!targetList[i]->hasSpeed)
		{
			targetList[i]->inRange = false;
			continue;
		}
		//AstDaten
		QPointF astPos = targetList[i]->position;
		QPointF astVec = targetList[i]->vVec;
		double astSpeed = targetList[i]->velocity;
		
		// DatenAllgemein
		QPointF distSAVec = shipPos - astPos;
		QPointF distHAVec = shipHead - astPos;
	
		double distSAreal = sqrt(distSAVec.x() * distSAVec.x() + distSAVec.y() * distSAVec.y());
		
		targetList[i]->vTarget = distSAVec;
		targetList[i]->distTarget = distSAreal;
	
		double time = 0.0;

		double astSpeed2 = Power(astSpeed, 2);
		double astVecx2 = Power(astVec.x(), 2);
		double astVecy2 = Power(astVec.y(),2);

		double time3= -((astPos.x()*astSpeed*astVec.x())/(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 
           2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + 
		   shipSpeed2*shipVecy2 - shotSpeed2)) - (astPos.y()*astSpeed*astVec.y())/(astSpeed2*astVecx2 + 
		   astSpeed2*astVecy2 - 2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 
		   2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) + 
		   (astSpeed*astVec.x()*shipHead.x())/(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 
		   2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + 
		   shipSpeed2*shipVecy2 - shotSpeed2) + (astSpeed*astVec.y()*shipHead.y())/(astSpeed2*astVecx2 + 
		   astSpeed2*astVecy2 - 2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 
		   2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) + 
		   (astPos.x()*shipSpeed*shipVec.x())/(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 
		   2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + 
           shipSpeed2*shipVecy2 - shotSpeed2) - (shipHead.x()*shipSpeed*shipVec.x())/(astSpeed2*astVecx2 + 
		   astSpeed2*astVecy2 - 2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 
		   2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) + 
		   (astPos.y()*shipSpeed*shipVec.y())/(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 
		   2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + 
           shipSpeed2*shipVecy2 - shotSpeed2) - (shipHead.y()*shipSpeed*shipVec.y())/(astSpeed2*astVecx2 + 
		   astSpeed2*astVecy2 - 2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 
		   2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) - 
		   Sqrt(Power(2*astPos.x()*astSpeed*astVec.x() + 2*astPos.y()*astSpeed*astVec.y() - 2*astSpeed*astVec.x()*shipHead.x() - 
		   2*astSpeed*astVec.y()*shipHead.y() - 2*astPos.x()*shipSpeed*shipVec.x() + 2*shipHead.x()*shipSpeed*shipVec.x() - 2*astPos.y()*shipSpeed*shipVec.y() + 
		   2*shipHead.y()*shipSpeed*shipVec.y(),2) - 4*(Power(astPos.x(),2) + Power(astPos.y(),2) - 2*astPos.x()*shipHead.x() + shipHeadx2 - 
		   2*astPos.y()*shipHead.y() + shipHeady2)*(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 
           2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + 
		   shipSpeed2*shipVecy2 - shotSpeed2))/(2.*(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 
           2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + 
		   shipSpeed2*shipVecy2 - shotSpeed2));
		
		/*long double time4 = -((astPos.x()*astSpeed*astVec.x())/(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 
           2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + 
		   shipSpeed2*shipVecy2 - shotSpeed2)) - (astPos.y()*astSpeed*astVec.y())/(astSpeed2*astVecx2 + 
		   astSpeed2*astVecy2 - 2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 
		   2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) + 
		   (astSpeed*astVec.x()*shipHead.x())/(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + 
           shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) + 
           (astSpeed*astVec.y()*shipHead.y())/(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + 
           shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) + 
           (astPos.x()*shipSpeed*shipVec.x())/(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + 
           shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) - 
           (shipHead.x()*shipSpeed*shipVec.x())/(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + 
           shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) + 
           (astPos.y()*shipSpeed*shipVec.y())/(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + 
           shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) - 
           (shipHead.y()*shipSpeed*shipVec.y())/(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + 
           shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) + 
           Sqrt(Power(2*astPos.x()*astSpeed*astVec.x() + 2*astPos.y()*astSpeed*astVec.y() - 2*astSpeed*astVec.x()*shipHead.x() - 2*astSpeed*astVec.y()*shipHead.y() - 
		   2*astPos.x()*shipSpeed*shipVec.x() + 2*shipHead.x()*shipSpeed*shipVec.x() - 2*astPos.y()*shipSpeed*shipVec.y() + 2*shipHead.y()*shipSpeed*shipVec.y(),2) - 
           4*(Power(astPos.x(),2) + Power(astPos.y(),2) - 2*astPos.x()*shipHead.x() + shipHeadx2 - 2*astPos.y()*shipHead.y() + 
		   shipHeady2)*(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + 
		   shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - 
		   shotSpeed2))/(2.*(astSpeed2*astVecx2 + astSpeed2*astVecy2 - 2*astSpeed*astVec.x()*shipSpeed*shipVec.x() + 
		   shipSpeed2*shipVecx2 - 2*astSpeed*astVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2));*/

				//if(time3 < 0.0)
				//{
				//	time = abs(time4);
				//}
				//else
				//{
					time = abs(time3);
				//}

		QPointF astVecCalc = astPos + astVec * time * astSpeed;
		QPointF shipVecCalc = shipHead + shipVec * time * shipSpeed;
		
		//// X-Anpassung
		//if(astVecCalc.x() > 499.0)
		//{
		//	astVecCalc.setX(astVecCalc.x() - 1024.0);
		//}
		//else if(astVecCalc.x() < -524.0)
		//{
		//	astVecCalc.setX(astVecCalc.x() + 1024.0);
		//}
		// Y-Anpassung
		if(astVecCalc.y() > 371.0)
		{
			astVecCalc.setY(astVecCalc.y() - 768.0);
		}
		else if(astVecCalc.y() < -396.0)
		{
			astVecCalc.setY(astVecCalc.y() + 768.0);
		}

		QPointF SAvecF = (astVecCalc - shipVecCalc);
		double distF = dist(astVecCalc, shipVecCalc);

		double radSpeed = (astVecCalc.x() * shipVecCalc.x()  + astVecCalc.y() * shipVecCalc.y()) / distF;

		double angAstInTime = double(((180.0 / Pi) * acos(SAvecF.x() / distF)));
		
		if(SAvecF.y() < 0.0)
			{
				angAstInTime = 360.0 - angAstInTime; 
			}

		targetList[i]->timeToDeath = time;
		targetList[i]->angAstF = angAstInTime;
		targetList[i]->dAngSAF = abs(angAstInTime - data->shipData.angle);
		
		if (distF > 477.0 && targetList.size() > 5)
		{
			targetList[i]->inRange = false;
		}
		else
		{
			targetList[i]->inRange = true;
		}
		targetList[i]->shootAngle = targetList[i]->angAstF;
		targetList[i]->timeToKill = targetList[i]->timeToDeath;

		double shipAngle = ai->getShootAngle(n).second;
		double diffAngle = angAstInTime - shipAngle;
		if(diffAngle >= 180.0)
		{
			diffAngle = diffAngle - 360.0;
		}
		else if(diffAngle <= -180.0)
		{
			diffAngle = diffAngle + 360.0;
		}

		double altSelect = time / 70.0 + abs(diffAngle) / 180.0;

		targetList[i]->selectionValue = abs(diffAngle) / 180.0;
	}
}

#define VS 8.0   // Schussgeschwindigkeit
#define OK 19.2  // Offset Kannone
void AICpu::generateDistanceData3()
{
	FrameData *data = ai->getLast();
	QList<Target*> targetList = data->targetList;

	for(int i = 0; i < targetList.size(); i++)
	{
		// Fall keine Geschwindigkeitswerte bekannt sind gehts gleich weiter
		if(!targetList[i]->hasSpeed)
		{
			continue;
		}
		// Lösen der quadratischen Gleichung
		QPointF pT = targetList[i]->position;
		QPointF vT = targetList[i]->velocity * targetList[i]->vVec; 
		double a = vT.x() * vT.x() + vT.y() * vT.y() - VS * VS;
		double b = 2 * (pT.x() * vT.x() + pT.y() * vT.y())- (2 * VS * OK);
		double c = pT.x() * pT.x() + pT.y() * pT.y() - (OK * OK);

		bool solution;
		double time;
		QPair<double, double> times = AIMath::SolveQuad(a,b,c,solution);
		
		// Kleinstes Positives Ergebniss wählen
		if(!solution || (times.first < 0.0 && times.second < 0.0))
		{
			return;
		}
		if(times.first > 0.0 && times.second > 0.0)
		{
			time = qMin(times.first, times.second);
		}
		else
		{
			time = qMax(times.first, times.second);
		}

		// Berechnung des Drehwinkels
		QPointF hitPoint = pT + time * vT;
		double lenght = sqrt(hitPoint.x() * hitPoint.x() + hitPoint.y() * hitPoint.y());
		hitPoint = hitPoint / lenght;
		double hitAngle = (180.0 / PI) * acos(hitPoint.x());
		if(hitPoint.y() < 0)
		{
			hitAngle = 360.0 - hitAngle;
		}
		targetList[i]->inRange = true;
		targetList[i]->shootAngle = hitAngle;
		targetList[i]->angAstF = hitAngle;
		targetList[i]->timeToKill = time;
		targetList[i]->timeToDeath = time;

		// Berechnung des Selektins-Wertes
		double shipAngle = ai->getShootAngle(n).second;
		double diffAngle = hitAngle - shipAngle;
		if(diffAngle >= 180.0)
		{
			diffAngle = diffAngle - 360.0;
		}
		else if(diffAngle <= -180.0)
		{
			diffAngle = diffAngle + 360.0;
		}
		targetList[i]->selectionValue = abs(diffAngle);
	}

}

double AICpu::dist(QPointF ship, QPointF target)
{
	QPointF delta = (ship - target);
	double distance = sqrt((double)(delta.x() * delta.x() + delta.y() * delta.y()));

	return distance;
}
// Ziel KI

void AICpu::aimBot2()
{
	
	Job *job = ai->getJob();
	
	
	if(!job)
	{
		return;
	}
	
	if(job->target)
	{
		if(job->thread)
		{
			FrameData *data = ai->getLast();
			QList<Target*> tList = data->targetList;
			for(int i = 0; i < tList.size(); i++)
			{
				if(checkAngle(tList[i]->angAstF))
				{
					fire(tList[i], true);
				}

			}

		}
		if(applyAngle(job->target->angAstF))
		{
			fire(job->target);
		}
	}
}


void AICpu::escape()
{
	
	FrameData *data = ai->getLast();
	QList<AsteroidData*> threadList = data->threadList;
	bool escape = false;

	if(data->deadlyFire)
	{
		escape = true;
	}

	
	for(int i = 0; i < threadList.size(); i++)
	{
		double dist = 0.0;
		switch(threadList[i]->size)
		{
			case Target::Small:
				dist = 30.0;
				break;
			case Target::Medium:
				dist = 40.0;
				break;
			case Target::Big:
				dist = 60.0;
				break;
			default:
				break;
		}
		if(threadList[i]->distTarget < dist)
		{
			escape = true;
		}
	}

	if(escape && !Hyper)
	{
		if(ai->getActionPacket().data()[6] & AICore::ACTION_LEFT)
		{
			n--;
		}
		else if(ai->getActionPacket().data()[6] & AICore::ACTION_RIGHT)
		{
			n++;
		}
		ai->clearActions();
		ai->actionHyperspace(true);
	}
}

void AICpu::checkThread1()
{
	FrameData *data = ai->getLast();
	// Wenn kein Schiff dann macht alles keinen Sinn
	if(!data->shipData.visible)
	{
		return;
	}
	QList<AsteroidData*> aList = data->asteroidDataList;

	// Ziel: Ermitteln einer Kollision, indedm der minimale Abstand zweier
	// 3D Geraden (Schif und Asteroid) berechnet wird. Dabei ist die Zeit die Z-Koordinate.

	// Schiff Gerade: (0 0 0) + a * (vSX vSY 1)
	// Asteroid Gerade (targetDist) + a * (vAX vAY 1)

	// Richtungsvektor Schiff
	QPointF vShip = data->shipData.velocity * data->shipData.vVec;

	Vector3 dirShip = Vector3(vShip, 1.0);

	// Für alle Asteroide Prüfen
	for(int i = 0; i < aList.size(); i++)
	{
		// Wenn keine Geschwindigkeut vorliegt gehts gleich weiter
		if(!aList[i]->hasSpeed)
		{
			continue;
		}

		// Richtungsvektor Asteroid
		QPointF vAsteroid = aList[i]->velocity * aList[i]->vVec;
		Vector3 dirAsteroid = Vector3(vAsteroid, 1.0);

		// Normale einer Ebene in der die Schiffsbewgung verläuft, 
		// und die parallel zur Asteroidenbewegung ist.
		Vector3 planeNorm = dirShip.vectorProduct(dirAsteroid);
		// Sicherstellen das die Z-Komponente positiv ist, da die Zeit
		// nicht rückwerts verläuft ;-)
		if(planeNorm.z < 0.0)
		{
			planeNorm = -1.0 * planeNorm;
		}
		planeNorm.normalize();

		// Einsetzen der Asteroiden Position (Aufpunkt der Geraden) in die Normalform 
		// der Ebene (a *x + b * y + c * z = 0) ergiebt den minimalen Abstabd der Geraden.
		// Wobei die Asteroiden Positio im Bezug auf das Schiff angegeben wird 
		// (Vektor vom Schiff zum Asteroiden)
		Vector3 asteroidPos = Vector3(aList[i]->distTarget * aList[i]->vTarget, 0.0);
		double dist = abs(planeNorm.x *asteroidPos.x + planeNorm.y * asteroidPos.y);
		//qDebug()<<"N: "<<i<<"   D: " <<dist;

		// Abgleich mit den Radien der Asteroiden
		double minDist = 0.0;
		double maxDist = 0.0;
		switch(aList[i]->size)
		{
			case Target::Small:
				minDist = Options::R.SmallMin;
				maxDist = Options::R.SmallMax;
				break;
			case Target::Medium:
				minDist = Options::R.MediumMin;
				maxDist = Options::R.MediumMax;
				break;
			case Target::Big:
				minDist = Options::R.BigMin;
				maxDist = Options::R.BigMax;
				break;
			default:
				break;
		}

		// TP-Filter damit auf jeden Fall FAR > FRR
		if(dist < minDist)
		{
			aList[i]->willCollide = true;
		}
		else if(dist >  maxDist)
		{
			aList[i]->willCollide = false;
		}

	}

}

void AICpu::checkThread2()
{
	FrameData *data = ai->getLast();
	if(!data->shipData.visible)
	{
		return;
	}

	
	QPointF shipPos = data->shipData.position;
	
	// Bedrphung durch Asteroiden
	QList<AsteroidData*> aList = data->asteroidDataList;
	for(int i = 0; i < aList.size(); i++)
	{
		// Nur möglich wenn eine Geschwindigkeit bekannt ist
		if(!aList[i]->hasSpeed)
		{
			continue;
		}

		// Den Bedrohungswert des letzten Zeitschritts übernehmen
		aList[i]->willCollide = aList[i]->last->willCollide;
		// Vektor vom Asteroid zum Schiff
		QPointF vA2S = shipPos - aList[i]->position;
		// Der skalare Abstand zwischen Schiff und Asteroid
		double length = sqrt(vA2S.x() * vA2S.x() + vA2S.y() * vA2S.y());
		// Normieren
		vA2S = vA2S / length;
		// Das Skalarproduckt zwischen dem Geschwindigkeitsvektor des Asteroiden und 
		// dem Verbindungsvektor zum Schiff
		double sp = vA2S.x() * aList[i]->vVec.x() + vA2S.y() * aList[i]->vVec.y();
		// Minimale Distanz auf die sich Schiff und Asteroid nähern
		double dist = length * sin(acos(sp));
		
		// Ermitteln der Distanzwerte, abhängig von der Asteroiden größe, 
		// für eine Beurteilung der Bedrohung
		double minDist = 0.0;
		double maxDist = 0.0;
		switch(aList[i]->size)
		{
			case Target::Small:
				minDist = Options::R.SmallMin;
				maxDist = Options::R.SmallMax;
				break;
			case Target::Medium:
				minDist = Options::R.MediumMin;
				maxDist = Options::R.MediumMax;
				break;
			case Target::Big:
				minDist = Options::R.BigMin;
				maxDist = Options::R.BigMax;
				break;
			default:
				break;
		}

		// Filter, dass entweder den Status Bedrohung sezt, oder zurück nimmt
		if(sp >= 0.0 && dist < minDist)
		{
			aList[i]->willCollide = true;
		}
		else if(sp < 0 || dist >  maxDist)
		{
			aList[i]->willCollide = false;
		}

		// Eintragen in die Liste der Bedrohungen
		if(aList[i]->willCollide)
		{
			data->threadList << aList[i];
		}
	}

	QList<ShotData*> sList = data->shotDataList;
	for(int i = 0; i < sList.size(); i++)
	{
		// Nur wenn das UFO da ist kann es auch gefährlich werden
		if(!data->saucerData.present)
		{
			break;
		}

		// Nur möglich wenn eine Geschwindigkeit bekannt ist
		if(!sList[i]->hasSpeed || sList[i]->owner != ShotData::Alien)
		{
			continue;
		}

		

		// Nur wenn die Spizte des Schiffs gegen die Bewegungsrichtung des Schusses Zeigt
		// (Eine Bedrohung ist zwar auch in anderen fällen möglich, aber unwahrscheinlich)
		//QPointF shipHeading = data->shipData.heading;
		//double headValue = shipHeading.x() * sList[i]->vVec.x() + shipHeading.y() * sList[i]->vVec.y();

		// Vektor vom Schuss zum Schiff
		QPointF vS2S = shipPos - sList[i]->position;
		// Der skalare Abstand zwischen Schiff und Schuss
		double length = sqrt(vS2S.x() * vS2S.x() + vS2S.y() * vS2S.y());
		// Normieren
		vS2S = vS2S / length;
		// Das Skalarproduckt zwischen dem Geschwindigkeitsvektor des Schusses und 
		// dem Verbindungsvektor zum Schiff
		double sp = vS2S.x() * sList[i]->vVec.x() + vS2S.y() * sList[i]->vVec.y();
		// Minimale Distanz auf die sich Schiff und Asteroid nähern
		double dist = length * sin(acos(sp));
		
		
		// Filter, dass entweder den Status Bedrohung sezt, oder zurück nimmt
		if(sp >= 0.0 && dist < 5.0)
		{
			data->deadlyFire = true;
		}
	}
}


void AICpu::calculateVelocities()
{
	FrameData *data = ai->getLast();
	QList<MovingObject*> movingObjectList = data->movingObjectList;
	for(int i = 0; i < movingObjectList.size(); i++)
	{
		MovingObject *current = movingObjectList[i];
		MovingObject *last = 0;
		switch(current->type)
		{
			case MovingObject::Asteroid:
				last = static_cast<AsteroidData*>(current)->last;
				break;
			case MovingObject::Saucer:
				last = static_cast<SaucerData*>(current)->last;
				break;
			case MovingObject::Ship:
				last = static_cast<ShipData*>(current)->last;
				break;
			case MovingObject::Shot:
				last = static_cast<ShotData*>(current)->last;
				break;
			
			default:
				break;

		}

		if(last)
		{
			QPointF velocitySample = current->position - last->position;
			// Gültigkeit prüfen um einen Übergang am Rand zu erkennen
			if(abs(velocitySample.x()) < 12.0 && abs(velocitySample.y()) < 12.0)
			{
				current->addVelocitySample(velocitySample);
			}
			else
			{
				current->hasSpeed = last->hasSpeed;
			}
		}
	}

}


void AICpu::findJob1()
{


	
		

	
}


void AICpu::findJob2()
{
	// Prüfen ob überhaupt etwas getan werden kann
	FrameData *data = ai->getLast();
	if(!data->shipData.visible)
	{
		return;
	}


	/*QList <Target*> targetList = data->targetList;
	for(int i = 0; i < targetList.size(); i++)
	{
		if(targetList[i]->targeded)
		{
			Job *job = new Job;
			job->target = targetList[i];
			if(job->target->type == MovingObject::Asteroid)
			{
				AsteroidData *aData = static_cast<AsteroidData*>(job->target);
				aData->color = Qt::blue;
			}
			return;
		}

	}*/
	
	// Bedrohung durch Asteroiden Behandeln
	QList<AsteroidData*> threadList = data->threadList;
	if(!threadList.isEmpty())
	{
		double distance = 10000000.0;
		int minDistIndex = -1;

		for(int i = 0; i < threadList.size(); i++)
		{
			if(distance > threadList[i]->selectionValue && !threadList[i]->ignoreTimeout && 
				threadList[i]->inRange && threadList[i]->timeToKill < 40)
			{
				distance = threadList[i]->selectionValue;
				minDistIndex = i;
			}
		}
		if(minDistIndex != -1)
		{
			Job *job = new Job;
			//job->asteroidData = threadList[minDistIndex];
			job->target = threadList[minDistIndex];	
			job->target->targeded = true;
			return;
		}
	}
	
	// Normale Asteroiden und UFOs
	QList<AsteroidData*> aList = data->asteroidDataList;
	double distance = 100000.0;
	int minDistIndex = -1;
	for(int i = 0; i < aList.size(); i++)
	{
		if(1 == aList.size()) // || aList[i]->size == 15)
		{
			distance = aList[i]->selectionValue;
			minDistIndex = i;
		}
		else if(distance > aList[i]->selectionValue && !aList[i]->ignoreTimeout  && aList[i]->timeToKill < 75  && aList[i]->inRange)
		{
			distance = aList[i]->selectionValue;
			minDistIndex = i;
		}
		//else if(distance > aList[i]->selectionValue && !aList[i]->ignoreTimeout && aList[i]->inRange && aList[i]->timeToKill < 50 && aList.size() <= 5)
		//{
		//	distance = aList[i]->selectionValue;
		//	minDistIndex = i;
		//	
		//}
		/*else if((distance > aList[i]->distTarget) && !aList[i]->ignoreTimeout && aList[i]->inRange)
		{
			distance = aList[i]->distTarget;
			minDistIndex = i;
		}*/
	}

	if(minDistIndex != -1)
	{
		Job *job = new Job;
		//job->asteroidData = aList[minDistIndex];
		job->target = aList[minDistIndex];
		job->target->targeded = true;
		//job->asteroidData->color = Qt::blue;
		//aList[minDistIndex]->color = QColor(Qt::yellow);
		if(data->saucerData.present && !data->saucerData.ignoreTimeout)
		{
			//job->saucerData = &(data->saucerData);
			job->target = &(data->saucerData);
			job->target->targeded = true;
		}
	}
	else if(data->saucerData.present && (!data->saucerData.ignoreTimeout || aList.size() == 0))
	{
		Job *job = new Job;
		//job->saucerData = &(data->saucerData);
		job->target = &(data->saucerData);
		//job->asteroidData = new AsteroidData(QPointF(),1,Target::Small);
		job->target->targeded = true;
	}
}

void AICpu::findJob3()
{
	// Prüfen ob überhaupt etwas getan werden kann
	FrameData *data = ai->getLast();
	if(!data->shipData.visible)
	{
		return;
	}

	// Wenn das Ufo da ist dann gibs ihm!
	if(data->saucerData.present && !data->saucerData.ignoreTimeout)
	{
		Job *job = new Job;
		job->target = &(data->saucerData);
		job->thread = true;
		return;
	}

	// Bedrohung durch Asteroiden Behandeln
	double distance = 10000000.0;
	int minDistIndex = -1;
	QList<AsteroidData*> threadList = data->threadList;
	if(!threadList.isEmpty())
	{
		

		for(int i = 0; i < threadList.size(); i++)
		{
			if(distance > threadList[i]->selectionValue && !threadList[i]->ignoreTimeout && 
				threadList[i]->inRange && threadList[i]->timeToKill < 40)
			{
				distance = threadList[i]->selectionValue;
				minDistIndex = i;
			}
		}

		
	}

	if(minDistIndex != -1)
	{
		Job *job = new Job;
		job->target = threadList[minDistIndex];
		job->thread = true;
		return;
	}

	// Normale Asteroiden und UFOs
	distance = 100000.0;
	minDistIndex = -1;
	QList<AsteroidData*> aList = data->asteroidDataList;
	for(int i = 0; i < aList.size(); i++)
	{
		
		
		if(distance > aList[i]->selectionValue && !aList[i]->ignoreTimeout  && aList[i]->timeToKill < 75  && aList[i]->inRange)
		{
			distance = aList[i]->selectionValue;
			minDistIndex = i;
		}
	}

	if(minDistIndex != -1)
	{
		Job *job = new Job;
		job->target = aList[minDistIndex];
		aList[minDistIndex]->color = Qt::blue;
		return;
	}
	else if(!aList.isEmpty() && aList[0]->inRange)
	{
		Job *job = new Job;
		job->target = aList[0];
		aList[0]->color = Qt::blue;
	}


}
void AICpu::whosShot()
{
	QList<ShotData*> sList = ai->getLast()->shotDataList;
	for(int i = 0; i < sList.size(); i++)
	{
		if(!sList[i]->owner)
		{
			
			// Abstand vom Schiff
			QPointF distVShip = sList[i]->position;
			double distShip = sqrt(distVShip.x() * distVShip.x() + distVShip.y() * distVShip.y());
			
			// Abstand vom Ufo
			QPointF saucerPos = ai->getLast()->saucerData.position;
			QPointF distVSaucer = sList[i]->position - saucerPos;
			double distSaucer = sqrt(distVSaucer.x() * distVSaucer.x() + distVSaucer.y() * distVSaucer.y());

			if(!ai->getLast()->saucerData.present)
			{
				distSaucer = 10000.0;
			}

			double dist = qMin(distSaucer, distShip);
			if(dist < 40.0)
			{
				if(distSaucer == dist)
				{
					sList[i]->owner = ShotData::Alien;
				}
				else if(distShip == dist)
				{
					sList[i]->owner = ShotData::Mine;
				}
			}


		}
	}
}

//void AICpu::killUfo() // THE DARKSIDEBots AM
//{
//	FrameData *data = ai->getLast();
//	
//	// ShipDaten
//	QPointF shipPos = data->shipData.heading;
//	QPointF shipHead = data->shipData.heading;
//	QPointF shipVec = data->shipData.heading;
//	double shipSpeed = data->shipData.velocity;
//
//	//UfoDaten
//	QPointF ufoPos = data->saucerData.position;
//	QPointF ufoVec = data->saucerData.vVec;
//	double astSpeed = data->saucerData.velocity;
//	
//	double shotSpeed = 8.0;
//	double time = 0.0;
//
//	// DatenAllgemein
//	QPointF distSUVec = shipPos - ufoPos;
//	QPointF distHUVec = shipHead - ufoPos;
//
//	double astSpeed2 = Power(astSpeed, 2);
//	double ufoVecx2 = Power(ufoVec.x(), 2);
//	double ufoVecy2 = Power(ufoVec.y(), 2);
//	double shipSpeed2 = Power(shipSpeed, 2);
//	double shipVecx2 = Power(shipVec.x(), 2);
//	double shipVecy2 = Power(shipVec.y(), 2);
//	double shotSpeed2 = Power(shotSpeed, 2);
//	double shipHeadx2 = Power(shipHead.x(), 2);
//	double shipHeady2 = Power(shipHead.y(), 2);
//
//	
//	double time3= -((ufoPos.x()*astSpeed*ufoVec.x())/(astSpeed2*ufoVecx2 + astSpeed2*ufoVecy2 - 
//           2*astSpeed*ufoVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 2*astSpeed*ufoVec.y()*shipSpeed*shipVec.y() + 
//		   shipSpeed2*shipVecy2 - shotSpeed2)) - (ufoPos.y()*astSpeed*ufoVec.y())/(astSpeed2*ufoVecx2 + 
//		   astSpeed2*ufoVecy2 - 2*astSpeed*ufoVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 
//		   2*astSpeed*ufoVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) + 
//		   (astSpeed*ufoVec.x()*shipHead.x())/(astSpeed2*ufoVecx2 + astSpeed2*ufoVecy2 - 
//		   2*astSpeed*ufoVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 2*astSpeed*ufoVec.y()*shipSpeed*shipVec.y() + 
//		   shipSpeed2*shipVecy2 - shotSpeed2) + (astSpeed*ufoVec.y()*shipHead.y())/(astSpeed2*ufoVecx2 + 
//		   astSpeed2*ufoVecy2 - 2*astSpeed*ufoVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 
//		   2*astSpeed*ufoVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) + 
//		   (ufoPos.x()*shipSpeed*shipVec.x())/(astSpeed2*ufoVecx2 + astSpeed2*ufoVecy2 - 
//		   2*astSpeed*ufoVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 2*astSpeed*ufoVec.y()*shipSpeed*shipVec.y() + 
//           shipSpeed2*shipVecy2 - shotSpeed2) - (shipHead.x()*shipSpeed*shipVec.x())/(astSpeed2*ufoVecx2 + 
//		   astSpeed2*ufoVecy2 - 2*astSpeed*ufoVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 
//		   2*astSpeed*ufoVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) + 
//		   (ufoPos.y()*shipSpeed*shipVec.y())/(astSpeed2*ufoVecx2 + astSpeed2*ufoVecy2 - 
//		   2*astSpeed*ufoVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 2*astSpeed*ufoVec.y()*shipSpeed*shipVec.y() + 
//           shipSpeed2*shipVecy2 - shotSpeed2) - (shipHead.y()*shipSpeed*shipVec.y())/(astSpeed2*ufoVecx2 + 
//		   astSpeed2*ufoVecy2 - 2*astSpeed*ufoVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 
//		   2*astSpeed*ufoVec.y()*shipSpeed*shipVec.y() + shipSpeed2*shipVecy2 - shotSpeed2) - 
//		   Sqrt(Power(2*ufoPos.x()*astSpeed*ufoVec.x() + 2*ufoPos.y()*astSpeed*ufoVec.y() - 2*astSpeed*ufoVec.x()*shipHead.x() - 
//		   2*astSpeed*ufoVec.y()*shipHead.y() - 2*ufoPos.x()*shipSpeed*shipVec.x() + 2*shipHead.x()*shipSpeed*shipVec.x() - 2*ufoPos.y()*shipSpeed*shipVec.y() + 
//		   2*shipHead.y()*shipSpeed*shipVec.y(),2) - 4*(Power(ufoPos.x(),2) + Power(ufoPos.y(),2) - 2*ufoPos.x()*shipHead.x() + shipHeadx2 - 
//		   2*ufoPos.y()*shipHead.y() + shipHeady2)*(astSpeed2*ufoVecx2 + astSpeed2*ufoVecy2 - 
//           2*astSpeed*ufoVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 2*astSpeed*ufoVec.y()*shipSpeed*shipVec.y() + 
//		   shipSpeed2*shipVecy2 - shotSpeed2))/(2.*(astSpeed2*ufoVecx2 + astSpeed2*ufoVecy2 - 
//           2*astSpeed*ufoVec.x()*shipSpeed*shipVec.x() + shipSpeed2*shipVecx2 - 2*astSpeed*ufoVec.y()*shipSpeed*shipVec.y() + 
//		   shipSpeed2*shipVecy2 - shotSpeed2));
//		
//		time = abs(time3);
//		
//		QPointF ufoVecCalc = ufoPos + ufoVec * time * astSpeed;
//		QPointF shipVecCalc = shipHead + shipVec * time * shipSpeed;
//		
//		QPointF SUvecF = (ufoVecCalc - shipVecCalc);
//		double distF = dist(ufoVecCalc, shipVecCalc);
//
//		double angUfoInTime = double(((180.0 / Pi) * acos(SUvecF.x() / distF)));
//		
//		if(SUvecF.y() < 0.0)
//			{
//				angUfoInTime = 360.0 - angUfoInTime; 
//			}
//
//		double shipAngle = ai->getShootAngle(n).second;
//		double diffAngle = angUfoInTime - shipAngle;
//		if(diffAngle >= 180.0)
//		{
//			diffAngle = diffAngle - 360.0;
//		}
//		else if(diffAngle <= -180.0)
//		{
//			diffAngle = diffAngle + 360.0;
//		}
//		
//	if(applyAngle(angUfoInTime))
//	{
//		fire(&(data->saucerData));
//	}
//}
//void AICpu::killUfo()
//{
//	FrameData *data = ai->getLast();
//	
//	//Positionen holen (ship, shiphead, ast oder ufo)
//	QPointF posShip = data->shipData.position;
//	//fliegen
//	QPointF dirShip = data->shipData.vVec;
//	double speedShip = data->shipData.velocity;
//	QPointF posUfo = data->saucerData.position;
//	QPointF dirUfo = data->saucerData.vVec;
//	double speedUfo = data->saucerData.velocity;
//	QPointF headShip = data->shipData.heading;
//	double angShip = data->shipData.angle;
//	//momentane schuss richtung und schussspeed bestimmen
//	double shotSpeed = 8.4; // + headdirektion speed
//	//aktuelle Distanz zwischen ship und ast (ufo)
//	//mit neuer Funktion dist(QPointF PosShip, QPointF PosAst)
//	double distance = dist(posShip, posUfo);
//	//differenz Winkel zw ship und ast bestimmen
//	QPointF dPosAU = (posShip - posUfo);
//	double angUfo = double(qRound(((180.0 / PI) * acos(dPosAU.x() / distance)))) + 180;
//	//Zeit für schuss von aktShip zu aktAst
//	double time = distance / shotSpeed; // + abs((angUfo - angShip) / 96);
//	//PosAst in Zeit bestimmen mit SpeedAst und Zeit für drehung Ship
//	QPointF ufoInTime = posUfo + dirUfo * speedUfo * time;
//	QPointF shipInTime = posShip + dirShip * speedShip * time;
//	//neue Distanz berechen zw ship und ast
//	double distInTime = dist(shipInTime, ufoInTime);
//	//?? unterschiede zw annähernden und sich entfernenden Ast??
//	dPosAU = (shipInTime - ufoInTime);
//	//neuen Winkel zw ship und ast bestimmen
//	double angUfoInTime = double(qRound(((180.0 / PI) * acos(dPosAU.x() / distInTime)))) + 180.0;
//		
//	if(angUfoInTime > 360)
//	{
//		angUfoInTime = angUfoInTime - 360.0;
//	}
//
//	if(dPosAU.y() < 0.0)
//	{
//		angUfoInTime = 360.0 - angUfoInTime; 
//	}	
//	//winkel an Option::angle übergeben
//	
//	if(applyAngle(angUfoInTime))
//	{
//		fire(&(data->saucerData));
//	}
//
//		//Options::Angle = angUfoInTime;
//
//}
//
//
//
//
//
