TankAIWeaponSets.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/TankAIWeaponSets.h>
00022 #include <tank/Tank.h>
00023 #include <tank/TankScore.h>
00024 #include <tank/TankAccessories.h>
00025 #include <server/ScorchedServer.h>
00026 #include <common/OptionsScorched.h>
00027 #include <common/OptionsTransient.h>
00028 #include <weapons/AccessoryStore.h>
00029 #include <XML/XMLFile.h>
00030 
00031 TankAIWeaponSets *TankAIWeaponSets::instance()
00032 {
00033         static TankAIWeaponSets instance;
00034         return &instance;
00035 }
00036 
00037 TankAIWeaponSets::TankAIWeaponSets()
00038 {
00039         parseConfig();
00040 }
00041 
00042 TankAIWeaponSets::~TankAIWeaponSets()
00043 {
00044 }
00045 
00046 bool TankAIWeaponSets::parseConfig()
00047 {
00048         XMLFile file;
00049         std::string fileName = S3D::getDataFile("data/tankaiweaponsets.xml");
00050         if (!file.readFile(fileName.c_str()))
00051         {
00052                 S3D::dialogMessage("TankAIWeaponSets", S3D::formatStringBuffer(
00053                         "Failed to parse \"%s\":%s\n", 
00054                         fileName.c_str(),
00055                         file.getParserError()));
00056                 return false;
00057         }
00058         if (!file.getRootNode())
00059         {
00060                 S3D::dialogMessage("TankAIWeaponSets", S3D::formatStringBuffer(
00061                         "Failed to weapon sets definition file \"%s\"",
00062                                 fileName.c_str()));
00063                 return false;           
00064         }
00065 
00066         XMLNode *weaponsetNode = 0;
00067         while (file.getRootNode()->getNamedChild("weaponset", weaponsetNode, false))
00068         {
00069                 WeaponSet weaponSet;
00070                 if (!weaponSet.parseConfig(weaponsetNode)) return false;
00071                 weaponSets_[weaponSet.name] = weaponSet;
00072         }
00073 
00074         return file.getRootNode()->failChildren();
00075 }
00076 
00077 TankAIWeaponSets::WeaponSet *TankAIWeaponSets::getWeaponSet(const char *name)
00078 {
00079         std::map<std::string, WeaponSet>::iterator findItor =
00080                 weaponSets_.find(name);
00081         if (findItor == weaponSets_.end()) return 0;
00082 
00083         return &findItor->second;
00084 }
00085 
00086 bool TankAIWeaponSets::WeaponSet::parseConfig(XMLNode *node)
00087 {
00088         if (!node->getNamedChild("name", name)) return false;
00089         XMLNode *setNode = 0, *weaponNode = 0;
00090         if (!node->getNamedChild("set", setNode)) return false;
00091         while (setNode->getNamedChild("weapon", weaponNode, false))
00092         {
00093                 WeaponSetEntry weapon;
00094                 if (!weapon.parseConfig(weaponNode)) return false;
00095                 weapons.push_back(weapon);
00096         }
00097 
00098         return node->failChildren();
00099 }
00100 
00101 void TankAIWeaponSets::WeaponSet::buyWeapons(Tank *tank, bool lastRound)
00102 {
00103         for (;;)
00104         {
00105                 // Get all of the weapons we can buy
00106                 std::multimap<unsigned int, WeaponSetEntry *> potentialWeapons;
00107                 std::vector<WeaponSetEntry>::iterator itor;
00108                 for (itor = weapons.begin();
00109                         itor != weapons.end();
00110                         itor++)
00111                 {
00112                         WeaponSetEntry &weapon = *itor;
00113                         if (weapon.weaponValid(tank, lastRound))
00114                         {
00115                                 potentialWeapons.insert(
00116                                         std::pair<unsigned int, WeaponSetEntry *>
00117                                                 (weapon.prioritybuy, &weapon));
00118                         }
00119                 }
00120                 if (potentialWeapons.empty()) break;
00121 
00122                 // Choose one of the potential weapons
00123                 // from the list of the highest priority
00124                 std::vector<WeaponSetEntry *> priorityWeapons;
00125                 std::multimap<unsigned int, WeaponSetEntry *>::reverse_iterator ritor;
00126                 for (ritor = potentialWeapons.rbegin();
00127                         ritor != potentialWeapons.rend();
00128                         ritor++)
00129                 {
00130                         WeaponSetEntry *weapon = ritor->second;
00131                         priorityWeapons.push_back(weapon);
00132                         if (weapon->prioritybuy < priorityWeapons.back()->prioritybuy) break;
00133                 }
00134                 WeaponSetEntry *choosenWeapon = priorityWeapons[rand() % priorityWeapons.size()];
00135                 Accessory *choosenAccessory = choosenWeapon->accessory;
00136 
00137                 // Buy this weapon
00138                 tank->getAccessories().add(choosenAccessory, choosenAccessory->getBundle());
00139                 tank->getScore().setMoney(tank->getScore().getMoney() - 
00140                         choosenAccessory->getPrice());
00141         }
00142 }
00143 
00144 Accessory *TankAIWeaponSets::WeaponSet::
00145 	getTankAccessoryByType(Tank *tank, const char *getType)
00146 {
00147         DIALOG_ASSERT(WeaponSetEntry::checkType(getType));
00148 
00149         WeaponSetEntry *result = 0;
00150 
00151         std::vector<WeaponSetEntry>::iterator itor;
00152         for (itor = weapons.begin();
00153                 itor != weapons.end();
00154                 itor++)
00155         {
00156                 WeaponSetEntry &current = *itor;
00157                 if (current.type == getType)
00158                 {
00159                         if ((10 - current.accessory->getArmsLevel()) <=
00160                                 ScorchedServer::instance()->getOptionsTransient().getArmsLevel() ||
00161                                 ScorchedServer::instance()->getOptionsGame().getGiveAllWeapons())
00162                         {
00163                                 if (tank->getAccessories().canUse(current.accessory))
00164                                 {
00165                                         if (!result ||
00166                                                 result->priorityuse < current.priorityuse)
00167                                         {
00168                                                 result = &current;
00169                                         }
00170                                 }
00171                         }
00172                 }
00173         }
00174 
00175         return (result?result->accessory:0);
00176 }
00177 
00178 bool TankAIWeaponSets::WeaponSetEntry::parseConfig(XMLNode *node)
00179 {
00180         std::string name;
00181         if (!node->getNamedChild("name", name)) return false;
00182         accessory = ScorchedServer::instance()->getAccessoryStore().
00183                 findByPrimaryAccessoryName(name.c_str());
00184         if (!accessory)
00185         {
00186                 return node->returnError(
00187                         S3D::formatStringBuffer("Unknown accessory %s", name.c_str()));
00188         }
00189 
00190         if (!node->getNamedChild("buymin", buymin)) return false;
00191         if (!node->getNamedChild("buymax", buymax)) return false;
00192         if (!node->getNamedChild("moneymin", moneymin)) return false;
00193         if (!node->getNamedChild("moneymax", moneymax)) return false;
00194         if (!node->getNamedChild("prioritybuy", prioritybuy)) return false;
00195         if (!node->getNamedChild("priorityuse", priorityuse)) return false;
00196         if (!node->getNamedChild("type", type)) return false;
00197 
00198         if (!checkType(type.c_str()))
00199         {
00200                 return node->returnError(
00201                         S3D::formatStringBuffer("Unknown type %s", type.c_str()));
00202         }
00203 
00204         return node->failChildren();
00205 }
00206 
00207 bool TankAIWeaponSets::WeaponSetEntry::checkType(const char *type)
00208 {
00209         if (0 != strcmp(type, "explosionhuge") &&
00210                 0 != strcmp(type, "explosionlarge") &&
00211                 0 != strcmp(type, "explosionsmall") &&
00212                 0 != strcmp(type, "uncover") &&
00213                 0 != strcmp(type, "digger") &&
00214                 0 != strcmp(type, "roller") &&
00215                 0 != strcmp(type, "napalm") &&
00216                 0 != strcmp(type, "laser") &&
00217                 0 != strcmp(type, "shield") &&
00218                 0 != strcmp(type, "other") &&
00219                 0 != strcmp(type, "fuel") &&
00220                 0 != strcmp(type, "autodefense") &&
00221                 0 != strcmp(type, "parachute"))
00222         {
00223                 return false;
00224         }
00225         return true;
00226 }
00227 
00228 bool TankAIWeaponSets::WeaponSetEntry::weaponValid(Tank *tank, bool lastRound)
00229 {
00230         if (accessory->getNoBuy()) return false;
00231 
00232         int currentCount = tank->getAccessories().getAccessoryCount(accessory);
00233         int currentMoney = tank->getScore().getMoney();
00234 
00235         int maxCount = accessory->getMaximumNumber();
00236         if (currentCount >= maxCount) return false;
00237 
00238         if (currentCount < 0) return false;
00239         if (currentMoney < accessory->getPrice()) return false;
00240 
00241         if ((10 - accessory->getArmsLevel()) <=
00242                 ScorchedServer::instance()->getOptionsTransient().getArmsLevel() ||
00243                 ScorchedServer::instance()->getOptionsGame().getGiveAllWeapons()) {}
00244         else return false;
00245 
00246         if (type == "autodefense")
00247         {
00248                 // Don't buy autodefense when simultaneous
00249                 if (ScorchedServer::instance()->getOptionsGame().getTurnType() == 
00250                         OptionsGame::TurnSimultaneous)
00251                 {
00252                         return false;
00253                 }
00254         }
00255 
00256         if (!lastRound)
00257         {
00258                 if (currentCount > buymin) return false;
00259                 if ((currentMoney < moneymin && moneymin != 0) || 
00260                         (currentMoney > moneymax && moneymax != 0)) return false;
00261         }
00262         
00263         return true;
00264 }

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