00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <tankai/TankAIAimGuesser.h>
00022 #include <tank/Tank.h>
00023 #include <tank/TankLib.h>
00024 #include <tank/TankPosition.h>
00025 #include <server/ScorchedServer.h>
00026 #include <common/Logger.h>
00027 #include <common/RandomGenerator.h>
00028 #include <math.h>
00029
00030 TankAIAimGuesser::TankAIAimGuesser()
00031 {
00032 }
00033
00034 TankAIAimGuesser::~TankAIAimGuesser()
00035 {
00036 }
00037
00038 bool TankAIAimGuesser::guess(Tank *tank, Vector &target,
00039 float angleYZDegs, float distance,
00040 Vector &actualPosition)
00041 {
00042 tank->getPosition().rotateGunYZ(fixed::fromFloat(angleYZDegs), false);
00043
00044
00045 initialShot(tank, target);
00046
00047 for (int i=0;;i++)
00048 {
00049
00050 getCurrentGuess(tank);
00051 if (!collision_)
00052 {
00053
00054
00055 return false;
00056 }
00057
00058
00059 actualPosition = currentGuess_.getPosition().asVector();
00060 Vector direction = currentGuess_.getPosition().asVector() - target;
00061 float actualDistance =
00062 float(sqrt(direction[0]*direction[0] + direction[1]*direction[1]));
00063 if (actualDistance < distance)
00064 {
00065
00066
00067 return true;
00068 }
00069
00070 if (i > 25)
00071 {
00072
00073
00074 return false;
00075 }
00076
00077
00078 refineShot(tank, currentGuess_.getPosition().asVector(), target);
00079 }
00080
00081
00082 return false;
00083 }
00084
00085 void TankAIAimGuesser::initialShot(Tank *tank, Vector &target)
00086 {
00087 fixed angleXYDegs;
00088 fixed angleYZDegs;
00089 fixed power;
00090
00091
00092 RandomGenerator random;
00093 random.seed(rand());
00094 TankLib::getShotTowardsPosition(
00095 ScorchedServer::instance()->getContext(),
00096 random,
00097 tank->getPosition().getTankPosition(),
00098 FixedVector::fromVector(target),
00099 angleXYDegs, angleYZDegs, power);
00100
00101
00102
00103 tank->getPosition().rotateGunXY(angleXYDegs, false);
00104 tank->getPosition().changePower(power, false);
00105 }
00106
00107 void TankAIAimGuesser::refineShot(Tank *tank,
00108 Vector ¤tPos, Vector &wantedPos)
00109 {
00110
00111 FixedVector shotVelocity = tank->getPosition().getVelocityVector() *
00112 (tank->getPosition().getPower() + 1);
00113
00114
00115 Vector missedBy = wantedPos - currentPos;
00116
00117
00118 shotVelocity[0] += fixed::fromFloat(missedBy[0]) * fixed(true, 400);
00119 shotVelocity[1] += fixed::fromFloat(missedBy[1]) * fixed(true, 400);
00120
00121
00122 fixed angleXYRads = atan2x(shotVelocity[1], shotVelocity[0]);
00123 fixed angleXYDegs = (angleXYRads / fixed::XPI) * 180 - 90;
00124
00125 tank->getPosition().rotateGunXY(angleXYDegs, false);
00126
00127
00128 FixedVector resultingVelocity = tank->getPosition().getVelocityVector();
00129 fixed resultingDistance = (
00130 resultingVelocity[0] * resultingVelocity[0] +
00131 resultingVelocity[1] * resultingVelocity[1]).sqrt();
00132 fixed wantedDistance = (
00133 shotVelocity[0] * shotVelocity[0] +
00134 shotVelocity[1] * shotVelocity[1]).sqrt();
00135 fixed power = wantedDistance / resultingDistance - 1;
00136
00137 tank->getPosition().changePower(power, false);
00138 }
00139
00140 void TankAIAimGuesser::collision(PhysicsParticleObject &position,
00141 ScorchedCollisionId collisionId)
00142 {
00143 currentGuess_ = position;
00144 collision_ = true;
00145 }
00146
00147 void TankAIAimGuesser::wallCollision(PhysicsParticleObject &position,
00148 ScorchedCollisionId collisionId)
00149 {
00150
00151
00152 currentGuess_ = position;
00153 collision_ = true;
00154 }
00155
00156 void TankAIAimGuesser::getCurrentGuess(Tank *tank)
00157 {
00158 FixedVector shotVelocity = tank->getPosition().getVelocityVector() *
00159 (tank->getPosition().getPower() + 1);
00160 FixedVector shotPosition = tank->getPosition().getTankGunPosition();
00161
00162 PhysicsParticleObject particleObject;
00163 PhysicsParticleInfo info(ParticleTypeShot, tank->getPlayerId(), 0);
00164 particleObject.setPhysics(info, ScorchedServer::instance()->getContext(),
00165 shotPosition, shotVelocity);
00166 particleObject.setHandler(this);
00167
00168 collision_ = false;
00169 for (int i=0; i<10000 && !collision_; i++)
00170 {
00171 particleObject.simulate(1);
00172 }
00173 }