00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00123
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
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 ¤t = *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 = ¤t;
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
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 }