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