1 #include <iterator>
2 #include <iostream>
3 #include <fstream>
4 #include <stdlib.h>
5
6 #include "spring_api.h"
7 #include "AI/Wrappers/Cpp/src-generated/SkirmishAI.h"
8 #include "AI/Wrappers/Cpp/src-generated/WrappUnit.h"
9
CSpringGame(springai::OOAICallback * callback)10 CSpringGame::CSpringGame(springai::OOAICallback* callback)
11 : callback(callback), datadirs(callback->GetDataDirs()),
12 economy(callback->GetEconomy()), resources(callback->GetResources()),
13 game(callback->GetGame()), lastUnitUpdate(-1) {
14 ai = new CTestAI(this);
15 springai::Cheats* cheat = callback->GetCheats();
16 cheat->SetEnabled(true);
17 delete cheat;
18
19 std::vector<springai::UnitDef*> defs = callback->GetUnitDefs();
20 if(!defs.empty()){
21 std::vector<springai::UnitDef*>::iterator i = defs.begin();
22 for(;i!=defs.end();++i){
23 springai::UnitDef* u = *i;
24 std::string name = u->GetName();
25 CSpringUnitType* udef = new CSpringUnitType(this,callback,u);
26 definitions[name] = udef;
27 }
28 }
29 map = new CSpringMap(callback,this);
30
31 }
32
~CSpringGame()33 CSpringGame::~CSpringGame(){
34 delete ai;
35 delete map;
36 std::map<std::string,CSpringUnitType*>::iterator iter = definitions.begin();
37 while(iter != definitions.end()) {
38 delete iter->second;
39 ++iter;
40 }
41 for (int i = 0; i < resources.size(); i += 1) {
42 delete resources[i];
43 }
44 delete datadirs;
45 delete economy;
46 delete game;
47 for (std::map<int, CSpringUnit*>::iterator i = aliveUnits.begin(); i != aliveUnits.end(); ++i) {
48 delete i->second;
49 }
50 }
51
Map()52 IMap* CSpringGame::Map(){
53 return map;
54 }
55
56
GameID()57 std::string CSpringGame::GameID(){
58 return "";//callback->;
59 }
60
SendToConsole(std::string message)61 void CSpringGame::SendToConsole(std::string message){
62 game->SendTextMessage(message.c_str(), 0);
63 }
64
Frame()65 int CSpringGame::Frame(){
66 return game->GetCurrentFrame();
67 }
68
IsPaused()69 bool CSpringGame::IsPaused(){
70 return game->IsPaused();
71 }
72
73
74
GetTypeByName(std::string typeName)75 IUnitType* CSpringGame::GetTypeByName(std::string typeName){
76 std::map<std::string,CSpringUnitType*>::iterator i = definitions.find(typeName);
77 if(i != definitions.end()){
78 return i->second;
79 }else{
80 return 0;
81 }
82 }
83
ConfigFolderPath()84 const char* CSpringGame::ConfigFolderPath(){
85 return datadirs->GetConfigDir();
86 }
87
ReadFile(std::string filename)88 std::string CSpringGame::ReadFile(std::string filename){
89
90 std::ifstream InFile( filename.c_str());
91 if( !InFile ) {
92 //cerr << "Couldn't open input file" << endl;
93 return "";
94 }
95
96 std::string s ="";
97
98 // create reader objects
99 std::istream_iterator<std::string> DataBegin( InFile );
100 std::istream_iterator<std::string> DataEnd;
101
102 while( DataBegin != DataEnd ) {
103 s += *DataBegin;
104 DataBegin++;
105 }
106 return s;
107 }
108
Me()109 IAI* CSpringGame::Me(){
110 return ai;
111 }
112
GameName()113 std::string CSpringGame::GameName(){
114 springai::Mod* mod = callback->GetMod();
115 std::string name = mod->GetShortName();
116 delete mod;
117 return name;
118 }
119
120
121
FileExists(std::string filename)122 bool CSpringGame::FileExists(std::string filename){
123 filename = ConfigFolderPath() + std::string("/ai/")+filename;
124 std::ifstream InFile( filename.c_str());
125 bool r = InFile.is_open();
126 if(r){
127 InFile.close();
128 }
129 return r;
130 }
131
LocatePath(std::string & filename)132 bool CSpringGame::LocatePath(std::string& filename){
133 static const size_t absPath_sizeMax = 2048;
134 char absPath[absPath_sizeMax];
135 const bool dir = !filename.empty() && (*filename.rbegin() == '/' || *filename.rbegin() == '\\');
136 const bool located = datadirs->LocatePath(absPath, absPath_sizeMax, filename.c_str(), false /*writable*/, false /*create*/, dir, false /*common*/);
137 if (located){
138 filename=absPath;
139 }
140 return located;
141 }
142
AddMarker(Position p,std::string label)143 void CSpringGame::AddMarker(Position p,std::string label){
144 const springai::AIFloat3 pos(p.x, p.y, p.z);
145 springai::Map* map = callback->GetMap();
146 springai::Drawer* drawer = map->GetDrawer();
147 drawer->AddPoint(pos, label.c_str());
148 delete drawer;
149 delete map;
150 }
151
SendToContent(std::string data)152 std::string CSpringGame::SendToContent(std::string data){
153 springai::Lua* lua = callback->GetLua();
154 std::string res = lua->CallRules(data.c_str(), -1);
155 delete lua;
156 return res;
157 }
158
159
160
ToIUnitType(springai::UnitDef * def)161 IUnitType* CSpringGame::ToIUnitType(springai::UnitDef* def){
162 if(def){
163 std::string name = def->GetName();
164 return GetTypeByName(name);
165 }else{
166 return NULL;
167 }
168 }
169
CreateUnit(int id)170 CSpringUnit* CSpringGame::CreateUnit(int id) {
171 if (id < 0) {
172 SendToConsole("shard-runtime warning: tried to create unit with id < 0");
173 return NULL;
174 }
175 springai::Unit* unit = springai::WrappUnit::GetInstance(callback->GetSkirmishAIId(), id);
176 if (unit) {
177 return CreateUnit(unit);
178 } else {
179 SendToConsole("shard-runtime warning: Could not create unit, WrappUnit returned NULL.");
180 return NULL;
181 }
182 }
183
184
CreateUnit(springai::Unit * unit,bool addToVectors)185 CSpringUnit* CSpringGame::CreateUnit(springai::Unit* unit, bool addToVectors) {
186 std::map<int, CSpringUnit*>::iterator i = aliveUnits.find(unit->GetUnitId());
187 if (i == aliveUnits.end()) {
188 CSpringUnit* u = new CSpringUnit(callback, unit, this);
189 aliveUnits[unit->GetUnitId()] = u;
190
191 if (addToVectors) {
192 if (u->Team() == GetTeamID()) {
193 teamUnits.push_back(u);
194 friendlyUnits.push_back(u);
195 } else if (u->IsAlly(game->GetMyAllyTeam())) {
196 friendlyUnits.push_back(u);
197 } else {
198 enemyUnits.push_back(u);
199 }
200 }
201
202 return u;
203 } else {
204 delete unit;
205 return i->second;
206 }
207 }
208
DestroyUnit(int id)209 void CSpringGame::DestroyUnit(int id) {
210 CSpringUnit* u = GetUnitById(id);
211 if (u) {
212 u->SetDead(true);
213 }
214 }
215
GetUnitById(int id)216 CSpringUnit* CSpringGame::GetUnitById(int id) {
217 if (id < 0) {
218 return NULL;
219 }
220
221 std::map<int, CSpringUnit*>::iterator i = aliveUnits.find(id);
222 if (i == aliveUnits.end()) {
223 return NULL;
224 } else {
225 return i->second;
226 }
227 }
228
FillUnitVector(std::vector<IUnit * > & target,std::vector<springai::Unit * > source)229 void CSpringGame::FillUnitVector(std::vector<IUnit*>& target, std::vector<springai::Unit*> source)
230 {
231 target.clear();
232
233 std::vector<springai::Unit*>::iterator i = source.begin();
234 for(;i != source.end(); ++i){
235 if (!(*i)) {
236 continue;
237 }
238
239 CSpringUnit* unit = GetUnitById((*i)->GetUnitId());
240 if (!unit) {
241 unit = CreateUnit(*i, false);
242 } else {
243 delete (*i);
244 }
245
246 if (unit) {
247 target.push_back(unit);
248 }
249 }
250 }
251
UpdateUnits()252 void CSpringGame::UpdateUnits()
253 {
254 if (lastUnitUpdate < Frame())
255 {
256 /* deleting dead units seems not really necessary.
257 Also the fillunitvector methods below will add them back again, anyways.
258 std::map<int, CSpringUnit*>::iterator i = aliveUnits.begin();
259 while(i != aliveUnits.end()) {
260 if (!i->second->IsAlive() && i->second->Died() < Frame() - 100) { //delete dead units after 100 frames.
261 i = aliveUnits.erase(i);
262 } else {
263 ++i;
264 }
265 }*/
266
267 FillUnitVector(enemyUnits, callback->GetEnemyUnits()); //events about enemy unit seem to not reach us.
268 FillUnitVector(friendlyUnits, callback->GetFriendlyUnits());
269 FillUnitVector(teamUnits, callback->GetTeamUnits());
270
271 /*if (lastUnitUpdate % 500 == 0) {
272 std::stringstream msg;
273 msg << "Friendlies: " << friendlyUnits.size() << " Team: " << teamUnits.size() << " Enemies: " << enemyUnits.size();
274 SendToConsole(msg.str());
275 }*/
276
277 lastUnitUpdate = Frame();
278 }
279 }
280
HasEnemies()281 bool CSpringGame::HasEnemies(){
282 UpdateUnits();
283 return !enemyUnits.empty();
284 }
285
GetEnemies()286 std::vector<IUnit*> CSpringGame::GetEnemies(){
287 UpdateUnits();
288 return enemyUnits;
289 }
290
HasFriendlies()291 bool CSpringGame::HasFriendlies(){
292 UpdateUnits();
293 return !friendlyUnits.empty();
294 }
295
GetFriendlies()296 std::vector<IUnit*> CSpringGame::GetFriendlies(){
297 UpdateUnits();
298 return friendlyUnits;
299 }
300
GetTeamID()301 int CSpringGame::GetTeamID(){
302 springai::SkirmishAI* ai = callback->GetSkirmishAI();
303 int id = ai->GetTeamId();
304 delete ai;
305 return id;
306 }
307
GetUnits()308 std::vector<IUnit*> CSpringGame::GetUnits(){
309 UpdateUnits();
310 return teamUnits;
311 }
312
313
GetResource(int idx)314 SResourceData CSpringGame::GetResource(int idx){
315 SResourceData res;
316 if(!resources.empty()){
317 std::vector<springai::Resource*>::iterator i = resources.begin();
318 for(;i != resources.end();++i){
319 springai::Resource* r = *i;
320 if(r->GetResourceId() == idx){
321 res.id = r->GetResourceId();
322 res.name = r->GetName();
323 res.gameframe = this->Frame();
324 res.income = economy->GetIncome(r);
325 res.usage = economy->GetUsage(r);
326 res.capacity = economy->GetStorage(r);
327 res.reserves = economy->GetCurrent(r);
328 return res;
329 }
330 }
331 }
332 return res;
333 }
334
GetResourceCount()335 int CSpringGame::GetResourceCount(){
336 if(resources.empty()){
337 return 0;
338 }else{
339 return resources.size();
340 }
341
342 }
343
GetResourceByName(std::string name)344 SResourceData CSpringGame::GetResourceByName(std::string name){
345 SResourceData res;
346 if(!resources.empty()){
347 std::vector<springai::Resource*>::iterator i = resources.begin();
348 for(;i != resources.end();++i){
349 springai::Resource* r = *i;
350 std::string rname = r->GetName();
351 if(rname == name){
352 res.name = rname;
353 res.id = r->GetResourceId();
354 res.gameframe = this->Frame();
355 res.income = economy->GetIncome(r);
356 res.usage = economy->GetUsage(r);
357 res.capacity = economy->GetStorage(r);
358 res.reserves = economy->GetCurrent(r);
359 return res;
360 }
361 }
362 }
363 return res;
364 }
365
getUnitByID(int unit_id)366 IUnit* CSpringGame::getUnitByID( int unit_id ) {
367 return ai->GetGame()->getUnitByID( unit_id );
368 }
369
370 /*void CSpringGame::removeUnit( IUnit* dead_unit ) {
371 std::map<int, CSpringUnit* >::iterator i = aliveUnits.find(evt->unit);
372 if(i != aliveUnits.end()){
373 CSpringUnit* u = i->second;
374 game->Me()->UnitDead(u);
375 aliveUnits.erase(i);
376 delete u;
377 }
378 }*/
379