git-svn-id: https://scorched3d.svn.sourceforge.net/svnroot/scorched3d/trunk/scorched...
[scorched3d/parasti.git] / src / server / tankai / TankAIWeaponSets.cpp
blob46c391a00181fd2d905bf257e4c2e7f7587fc368
1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
3 //
4 // This file is part of Scorched3D.
5 //
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Scorched3D; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ////////////////////////////////////////////////////////////////////////////////
21 #include <tankai/TankAIWeaponSets.h>
22 #include <tank/Tank.h>
23 #include <tank/TankScore.h>
24 #include <tank/TankAccessories.h>
25 #include <server/ScorchedServer.h>
26 #include <common/OptionsScorched.h>
27 #include <common/OptionsTransient.h>
28 #include <weapons/AccessoryStore.h>
29 #include <XML/XMLFile.h>
31 TankAIWeaponSets *TankAIWeaponSets::instance()
33 static TankAIWeaponSets instance;
34 return &instance;
37 TankAIWeaponSets::TankAIWeaponSets()
39 parseConfig();
42 TankAIWeaponSets::~TankAIWeaponSets()
46 bool TankAIWeaponSets::parseConfig()
48 XMLFile file;
49 std::string fileName = S3D::getDataFile("data/tankaiweaponsets.xml");
50 if (!file.readFile(fileName.c_str()))
52 S3D::dialogMessage("TankAIWeaponSets", S3D::formatStringBuffer(
53 "Failed to parse \"%s\":%s\n",
54 fileName.c_str(),
55 file.getParserError()));
56 return false;
58 if (!file.getRootNode())
60 S3D::dialogMessage("TankAIWeaponSets", S3D::formatStringBuffer(
61 "Failed to weapon sets definition file \"%s\"",
62 fileName.c_str()));
63 return false;
66 XMLNode *weaponsetNode = 0;
67 while (file.getRootNode()->getNamedChild("weaponset", weaponsetNode, false))
69 WeaponSet weaponSet;
70 if (!weaponSet.parseConfig(weaponsetNode)) return false;
71 weaponSets_[weaponSet.name] = weaponSet;
74 return file.getRootNode()->failChildren();
77 TankAIWeaponSets::WeaponSet *TankAIWeaponSets::getWeaponSet(const char *name)
79 std::map<std::string, WeaponSet>::iterator findItor =
80 weaponSets_.find(name);
81 if (findItor == weaponSets_.end()) return 0;
83 return &findItor->second;
86 bool TankAIWeaponSets::WeaponSet::parseConfig(XMLNode *node)
88 if (!node->getNamedChild("name", name)) return false;
89 XMLNode *setNode = 0, *weaponNode = 0;
90 if (!node->getNamedChild("set", setNode)) return false;
91 while (setNode->getNamedChild("weapon", weaponNode, false))
93 WeaponSetEntry weapon;
94 if (!weapon.parseConfig(weaponNode)) return false;
95 weapons.push_back(weapon);
98 return node->failChildren();
101 void TankAIWeaponSets::WeaponSet::buyWeapons(Tank *tank, bool lastRound)
103 for (;;)
105 // Get all of the weapons we can buy
106 std::multimap<unsigned int, WeaponSetEntry *> potentialWeapons;
107 std::vector<WeaponSetEntry>::iterator itor;
108 for (itor = weapons.begin();
109 itor != weapons.end();
110 itor++)
112 WeaponSetEntry &weapon = *itor;
113 if (weapon.weaponValid(tank, lastRound))
115 potentialWeapons.insert(
116 std::pair<unsigned int, WeaponSetEntry *>
117 (weapon.prioritybuy, &weapon));
120 if (potentialWeapons.empty()) break;
122 // Choose one of the potential weapons
123 // from the list of the highest priority
124 std::vector<WeaponSetEntry *> priorityWeapons;
125 std::multimap<unsigned int, WeaponSetEntry *>::reverse_iterator ritor;
126 for (ritor = potentialWeapons.rbegin();
127 ritor != potentialWeapons.rend();
128 ritor++)
130 WeaponSetEntry *weapon = ritor->second;
131 priorityWeapons.push_back(weapon);
132 if (weapon->prioritybuy < priorityWeapons.back()->prioritybuy) break;
134 WeaponSetEntry *choosenWeapon = priorityWeapons[rand() % priorityWeapons.size()];
135 Accessory *choosenAccessory = choosenWeapon->accessory;
137 // Buy this weapon
138 tank->getAccessories().add(choosenAccessory, choosenAccessory->getBundle());
139 tank->getScore().setMoney(tank->getScore().getMoney() -
140 choosenAccessory->getPrice());
144 Accessory *TankAIWeaponSets::WeaponSet::
145 getTankAccessoryByType(Tank *tank, const char *getType)
147 DIALOG_ASSERT(WeaponSetEntry::checkType(getType));
149 WeaponSetEntry *result = 0;
151 std::vector<WeaponSetEntry>::iterator itor;
152 for (itor = weapons.begin();
153 itor != weapons.end();
154 itor++)
156 WeaponSetEntry &current = *itor;
157 if (current.type == getType)
159 if ((10 - current.accessory->getArmsLevel()) <=
160 ScorchedServer::instance()->getOptionsTransient().getArmsLevel() ||
161 ScorchedServer::instance()->getOptionsGame().getGiveAllWeapons())
163 if (tank->getAccessories().canUse(current.accessory))
165 if (!result ||
166 result->priorityuse < current.priorityuse)
168 result = &current;
175 return (result?result->accessory:0);
178 bool TankAIWeaponSets::WeaponSetEntry::parseConfig(XMLNode *node)
180 std::string name;
181 if (!node->getNamedChild("name", name)) return false;
182 accessory = ScorchedServer::instance()->getAccessoryStore().
183 findByPrimaryAccessoryName(name.c_str());
184 if (!accessory)
186 return node->returnError(
187 S3D::formatStringBuffer("Unknown accessory %s", name.c_str()));
190 if (!node->getNamedChild("buymin", buymin)) return false;
191 if (!node->getNamedChild("buymax", buymax)) return false;
192 if (!node->getNamedChild("moneymin", moneymin)) return false;
193 if (!node->getNamedChild("moneymax", moneymax)) return false;
194 if (!node->getNamedChild("prioritybuy", prioritybuy)) return false;
195 if (!node->getNamedChild("priorityuse", priorityuse)) return false;
196 if (!node->getNamedChild("type", type)) return false;
198 if (!checkType(type.c_str()))
200 return node->returnError(
201 S3D::formatStringBuffer("Unknown type %s", type.c_str()));
204 return node->failChildren();
207 bool TankAIWeaponSets::WeaponSetEntry::checkType(const char *type)
209 if (0 != strcmp(type, "explosionhuge") &&
210 0 != strcmp(type, "explosionlarge") &&
211 0 != strcmp(type, "explosionsmall") &&
212 0 != strcmp(type, "uncover") &&
213 0 != strcmp(type, "digger") &&
214 0 != strcmp(type, "roller") &&
215 0 != strcmp(type, "napalm") &&
216 0 != strcmp(type, "laser") &&
217 0 != strcmp(type, "shield") &&
218 0 != strcmp(type, "other") &&
219 0 != strcmp(type, "fuel") &&
220 0 != strcmp(type, "autodefense") &&
221 0 != strcmp(type, "parachute"))
223 return false;
225 return true;
228 bool TankAIWeaponSets::WeaponSetEntry::weaponValid(Tank *tank, bool lastRound)
230 int currentCount = tank->getAccessories().getAccessoryCount(accessory);
231 int currentMoney = tank->getScore().getMoney();
233 int maxCount = accessory->getMaximumNumber();
234 if (currentCount >= maxCount) return false;
236 if (currentCount < 0) return false;
237 if (currentMoney < accessory->getPrice()) return false;
239 if ((10 - accessory->getArmsLevel()) <=
240 ScorchedServer::instance()->getOptionsTransient().getArmsLevel() ||
241 ScorchedServer::instance()->getOptionsGame().getGiveAllWeapons()) {}
242 else return false;
244 if (type == "autodefense")
246 // Don't buy autodefense when simultaneous
247 if (ScorchedServer::instance()->getOptionsGame().getTurnType() ==
248 OptionsGame::TurnSimultaneous)
250 return false;
254 if (!lastRound)
256 if (currentCount > buymin) return false;
257 if ((currentMoney < moneymin && moneymin != 0) ||
258 (currentMoney > moneymax && moneymax != 0)) return false;
261 return true;