TankAICurrentTarget.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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         // Get the list of tanks we can shoot at
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         // Sort the tanks in score order
00201         std::list<Tank *> scoreSorted = possible;
00202         TankSort::getSortedTanks(scoreSorted, ScorchedServer::instance()->getContext());
00203 
00204         // Go through all possible tanks
00205         // and weight them according to the weightings
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         // Form the final list
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 }

Generated on Mon Feb 16 15:14:53 2009 for Scorched3D by  doxygen 1.5.3