00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <tankai/TankAICurrentTarget.h>
00022 #include <server/ScorchedServer.h>
00023 #include <tank/TankContainer.h>
00024 #include <tank/TankSort.h>
00025 #include <tank/TankPosition.h>
00026 #include <target/TargetLife.h>
00027 #include <target/TargetShield.h>
00028 #include <weapons/Shield.h>
00029 #include <weapons/Accessory.h>
00030 #include <common/Defines.h>
00031 #include <XML/XMLNode.h>
00032
00033 TankAICurrentTarget::TankAICurrentTarget()
00034 {
00035 }
00036
00037 TankAICurrentTarget::~TankAICurrentTarget()
00038 {
00039 }
00040
00041 bool TankAICurrentTarget::parseConfig(XMLNode *node)
00042 {
00043 if (!node->getNamedChild("health", health_)) return false;
00044 if (!node->getNamedChild("random", random_)) return false;
00045 if (!node->getNamedChild("score", score_)) return false;
00046 if (!node->getNamedChild("shield", shield_)) return false;
00047 if (!node->getNamedChild("repeat", repeat_)) return false;
00048 if (!node->getNamedChild("damagetaken", damagetaken_)) return false;
00049 if (!node->getNamedChild("damagedone", damagedone_)) return false;
00050 if (!node->getNamedChild("player", player_)) return false;
00051 if (!node->getNamedChild("distance", distance_)) return false;
00052
00053 return true;
00054 }
00055
00056 void TankAICurrentTarget::clear()
00057 {
00058 damageGiven_.clear();
00059 damageTaken_.clear();
00060 shotAt_.clear();
00061 }
00062
00063 float TankAICurrentTarget::getTotalDamageTaken()
00064 {
00065 float damage = 0.0f;
00066 std::map<Tank *, float>::iterator itor;
00067 for (itor = damageTaken_.begin();
00068 itor != damageTaken_.end();
00069 itor++)
00070 {
00071 damage += itor->second;
00072 }
00073 return damage;
00074 }
00075
00076 void TankAICurrentTarget::gaveDamage(Tank *tank, float damage)
00077 {
00078 std::map<Tank *, float>::iterator findItor =
00079 damageGiven_.find(tank);
00080 if (findItor == damageGiven_.end())
00081 {
00082 damageGiven_[tank] = damage;
00083 }
00084 else
00085 {
00086 damageGiven_[tank] += damage;
00087 }
00088 }
00089
00090 void TankAICurrentTarget::tookDamage(Tank *tank, float damage)
00091 {
00092 std::map<Tank *, float>::iterator findItor =
00093 damageTaken_.find(tank);
00094 if (findItor == damageTaken_.end())
00095 {
00096 damageTaken_[tank] = damage;
00097 }
00098 else
00099 {
00100 damageTaken_[tank] += damage;
00101 }
00102 }
00103
00104 void TankAICurrentTarget::shotAt(Tank *tank)
00105 {
00106 std::map<Tank *, float>::iterator findItor =
00107 shotAt_.find(tank);
00108 if (findItor == shotAt_.end())
00109 {
00110 shotAt_[tank] = 1.0f;
00111 }
00112 else
00113 {
00114 shotAt_[tank] += 1.0f;
00115 }
00116 }
00117
00118 float TankAICurrentTarget::rankPlayer(std::list<Tank *> &players, Tank *player)
00119 {
00120 int position = 1;
00121 std::list<Tank *>::iterator itor;
00122 for (itor = players.begin();
00123 itor != players.end();
00124 itor++, position++)
00125 {
00126 Tank *currentTank = *itor;
00127 if (currentTank == player)
00128 {
00129 float score = 1.0f - (float(position * 2) / float(players.size()));
00130 return score;
00131 }
00132 }
00133
00134 return -1.0f;
00135 }
00136
00137 float TankAICurrentTarget::rankPlayer(std::multimap<float, Tank *> &players, Tank *player)
00138 {
00139 int position = 1;
00140 std::multimap<float, Tank *>::iterator itor;
00141 for (itor = players.begin();
00142 itor != players.end();
00143 itor++, position++)
00144 {
00145 Tank *currentTank = itor->second;
00146 if (currentTank == player)
00147 {
00148 float score = (float(position * 2) / float(players.size())) - 1.0f;
00149 return score;
00150 }
00151 }
00152
00153 return -1.0f;
00154 }
00155
00156 void TankAICurrentTarget::getTargets(Tank *thisTank, std::list<Tank *> &resultTargets)
00157 {
00158 std::list<Tank *> possible;
00159 std::multimap<float, Tank *> damageTakenSorted;
00160 std::multimap<float, Tank *> damageGivenSorted;
00161 std::multimap<float, Tank *> shotAtSorted;
00162 std::multimap<float, Tank *> distanceSorted;
00163
00164
00165 std::map<unsigned int, Tank *> &tanks =
00166 ScorchedServer::instance()->getTankContainer().getAllTanks();
00167 std::map<unsigned int, Tank *>::iterator posItor;
00168 for (posItor = tanks.begin();
00169 posItor != tanks.end();
00170 posItor++)
00171 {
00172 Tank *currentTank = posItor->second;
00173 if (currentTank == thisTank) continue;
00174 if (thisTank->getTeam() > 0 &&
00175 currentTank->getTeam() == thisTank->getTeam()) continue;
00176 if (!currentTank->getAlive()) continue;
00177
00178 possible.push_back(currentTank);
00179
00180 if (damageTaken_.find(currentTank) != damageTaken_.end())
00181 {
00182 damageTakenSorted.insert(std::pair<float, Tank *>(
00183 damageTaken_[currentTank], currentTank));
00184 }
00185 if (damageGiven_.find(currentTank) != damageGiven_.end())
00186 {
00187 damageGivenSorted.insert(std::pair<float, Tank *>(
00188 damageGiven_[currentTank], currentTank));
00189 }
00190 if (shotAt_.find(currentTank) != shotAt_.end())
00191 {
00192 shotAtSorted.insert(std::pair<float, Tank *>(
00193 shotAt_[currentTank], currentTank));
00194 }
00195 distanceSorted.insert(std::pair<float, Tank *>(
00196 ((currentTank->getPosition().getTankPosition() -
00197 thisTank->getPosition().getTankPosition()).Magnitude()).asFloat(), currentTank));
00198 }
00199
00200
00201 std::list<Tank *> scoreSorted = possible;
00202 TankSort::getSortedTanks(scoreSorted, ScorchedServer::instance()->getContext());
00203
00204
00205
00206 std::multimap<float, Tank *> weightedTanks;
00207 std::list<Tank *>::iterator itor;
00208 for (itor = possible.begin();
00209 itor != possible.end();
00210 itor++)
00211 {
00212 Tank *currentTank = *itor;
00213
00214 float healthScore = ((currentTank->getLife().getLife() * 2)
00215 / currentTank->getLife().getMaxLife()).asFloat() - 1.0f;
00216 float randomScore = RAND * 2.0f - 1.0f;
00217 float playerScore = ((currentTank->getDestinationId() == 0)?-1.0f:1.0f);
00218 float shieldScore = ((currentTank->getShield().getShieldPower() * 2).asFloat()
00219 / 100.0f) - 1.0f;
00220 float scoreScore = rankPlayer(scoreSorted, currentTank);
00221 float repeatScore = rankPlayer(shotAtSorted, currentTank);
00222 float damagetakenScore = rankPlayer(damageTakenSorted, currentTank);
00223 float damagedoneScore = rankPlayer(damageGivenSorted, currentTank);
00224 float distanceScore = rankPlayer(distanceSorted, currentTank);
00225
00226 float weight =
00227 healthScore * health_ +
00228 randomScore * random_ +
00229 playerScore * player_ +
00230 shieldScore * shield_ +
00231 scoreScore * score_ +
00232 repeatScore * repeat_ +
00233 damagetakenScore * damagetaken_ +
00234 damagedoneScore * damagedone_ +
00235 distanceScore * distance_;
00236 weightedTanks.insert(std::pair<float, Tank *>(weight, currentTank));
00237 }
00238
00239
00240 std::multimap<float, Tank *>::reverse_iterator weightedItor;
00241 for (weightedItor = weightedTanks.rbegin();
00242 weightedItor != weightedTanks.rend();
00243 weightedItor++)
00244 {
00245 resultTargets.push_back(weightedItor->second);
00246 }
00247 }