CGameState.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203
  1. #define VCMI_DLL
  2. #include <algorithm>
  3. #include <queue>
  4. #include <fstream>
  5. #include "CGameState.h"
  6. #include "CGameInterface.h"
  7. #include "CPlayerInterface.h"
  8. #include "SDL_Extensions.h"
  9. #include "CBattleInterface.h" //for CBattleHex
  10. #include <boost/random/linear_congruential.hpp>
  11. #include "hch/CDefObjInfoHandler.h"
  12. #include "hch/CArtHandler.h"
  13. #include "hch/CTownHandler.h"
  14. #include "hch/CHeroHandler.h"
  15. #include "hch/CObjectHandler.h"
  16. #include "hch/CCreatureHandler.h"
  17. #include "lib/VCMI_Lib.h"
  18. #include "map.h"
  19. #include "StartInfo.h"
  20. #include "CLua.h"
  21. #include "CCallback.h"
  22. #include "CLuaHandler.h"
  23. boost::rand48 ran;
  24. class CMP_stack
  25. {
  26. public:
  27. bool operator ()(const CStack* a, const CStack* b)
  28. {
  29. return (a->creature->speed)>(b->creature->speed);
  30. }
  31. } cmpst ;
  32. CStack::CStack(CCreature * C, int A, int O, int I, bool AO)
  33. :creature(C),amount(A),owner(O), alive(true), position(-1), ID(I), attackerOwned(AO), firstHPleft(C->hitPoints)
  34. {
  35. }
  36. int CGameState::pickHero(int owner)
  37. {
  38. int h=-1;
  39. if(map->getHero(h = scenarioOps->getIthPlayersSettings(owner).hero,0) && h>=0) //we haven't used selected hero
  40. return h;
  41. int f = scenarioOps->getIthPlayersSettings(owner).castle;
  42. int i=0;
  43. do //try to find free hero of our faction
  44. {
  45. i++;
  46. h = scenarioOps->getIthPlayersSettings(owner).castle*HEROES_PER_TYPE*2+(ran()%(HEROES_PER_TYPE*2));//->scenarioOps->playerInfos[pru].hero = VLC->
  47. } while( map->getHero(h) && i<175);
  48. if(i>174) //probably no free heroes - there's no point in further search, we'll take first free
  49. {
  50. std::cout << "Warning: cannot find free hero - trying to get first available..."<<std::endl;
  51. for(int j=0; j<HEROES_PER_TYPE * 2 * F_NUMBER; j++)
  52. if(!map->getHero(j))
  53. h=j;
  54. }
  55. return h;
  56. }
  57. std::pair<int,int> CGameState::pickObject(CGObjectInstance *obj)
  58. {
  59. switch(obj->ID)
  60. {
  61. case 65: //random artifact
  62. return std::pair<int,int>(5,(ran()%136)+7); //tylko sensowny zakres - na poczatku sa katapulty itp, na koncu specjalne i blanki
  63. case 66: //random treasure artifact
  64. return std::pair<int,int>(5,VLC->arth->treasures[ran()%VLC->arth->treasures.size()]->id);
  65. case 67: //random minor artifact
  66. return std::pair<int,int>(5,VLC->arth->minors[ran()%VLC->arth->minors.size()]->id);
  67. case 68: //random major artifact
  68. return std::pair<int,int>(5,VLC->arth->majors[ran()%VLC->arth->majors.size()]->id);
  69. case 69: //random relic artifact
  70. return std::pair<int,int>(5,VLC->arth->relics[ran()%VLC->arth->relics.size()]->id);
  71. case 70: //random hero
  72. {
  73. return std::pair<int,int>(34,pickHero(obj->tempOwner));
  74. }
  75. case 71: //random monster
  76. return std::pair<int,int>(54,ran()%(VLC->creh->creatures.size()));
  77. case 72: //random monster lvl1
  78. return std::pair<int,int>(54,VLC->creh->levelCreatures[1][ran()%VLC->creh->levelCreatures[1].size()]->idNumber);
  79. case 73: //random monster lvl2
  80. return std::pair<int,int>(54,VLC->creh->levelCreatures[2][ran()%VLC->creh->levelCreatures[2].size()]->idNumber);
  81. case 74: //random monster lvl3
  82. return std::pair<int,int>(54,VLC->creh->levelCreatures[3][ran()%VLC->creh->levelCreatures[3].size()]->idNumber);
  83. case 75: //random monster lvl4
  84. return std::pair<int,int>(54,VLC->creh->levelCreatures[4][ran()%VLC->creh->levelCreatures[4].size()]->idNumber);
  85. case 76: //random resource
  86. return std::pair<int,int>(79,ran()%7); //now it's OH3 style, use %8 for mithril
  87. case 77: //random town
  88. {
  89. int align = ((CGTownInstance*)obj)->alignment,
  90. f;
  91. if(align>PLAYER_LIMIT-1)//same as owner / random
  92. {
  93. if(obj->tempOwner > PLAYER_LIMIT-1)
  94. f = -1; //random
  95. else
  96. f = scenarioOps->getIthPlayersSettings(obj->tempOwner).castle;
  97. }
  98. else
  99. {
  100. f = scenarioOps->getIthPlayersSettings(align).castle;
  101. }
  102. if(f<0) f = ran()%VLC->townh->towns.size();
  103. return std::pair<int,int>(98,f);
  104. }
  105. case 162: //random monster lvl5
  106. return std::pair<int,int>(54,VLC->creh->levelCreatures[5][ran()%VLC->creh->levelCreatures[5].size()]->idNumber);
  107. case 163: //random monster lvl6
  108. return std::pair<int,int>(54,VLC->creh->levelCreatures[6][ran()%VLC->creh->levelCreatures[6].size()]->idNumber);
  109. case 164: //random monster lvl7
  110. return std::pair<int,int>(54,VLC->creh->levelCreatures[7][ran()%VLC->creh->levelCreatures[7].size()]->idNumber);
  111. case 216: //random dwelling
  112. {
  113. int faction = ran()%F_NUMBER;
  114. CCreGen2ObjInfo* info =(CCreGen2ObjInfo*)obj->info;
  115. if (info->asCastle)
  116. {
  117. for(int i=0;i<map->objects.size();i++)
  118. {
  119. if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  120. {
  121. randomizeObject(map->objects[i]); //we have to randomize the castle first
  122. faction = map->objects[i]->subID;
  123. break;
  124. }
  125. else if(map->objects[i]->ID==98 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  126. {
  127. faction = map->objects[i]->subID;
  128. break;
  129. }
  130. }
  131. }
  132. else
  133. {
  134. while((!(info->castles[0]&(1<<faction))))
  135. {
  136. if((faction>7) && (info->castles[1]&(1<<(faction-8))))
  137. break;
  138. faction = ran()%F_NUMBER;
  139. }
  140. }
  141. int level = ((info->maxLevel-info->minLevel) ? (ran()%(info->maxLevel-info->minLevel)+info->minLevel) : (info->minLevel));
  142. int cid = VLC->townh->towns[faction].basicCreatures[level];
  143. for(int i=0;i<VLC->objh->cregens.size();i++)
  144. if(VLC->objh->cregens[i]==cid)
  145. return std::pair<int,int>(17,i);
  146. std::cout << "Cannot find a dwelling for creature "<<cid <<std::endl;
  147. return std::pair<int,int>(17,0);
  148. }
  149. case 217:
  150. {
  151. int faction = ran()%F_NUMBER;
  152. CCreGenObjInfo* info =(CCreGenObjInfo*)obj->info;
  153. if (info->asCastle)
  154. {
  155. for(int i=0;i<map->objects.size();i++)
  156. {
  157. if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  158. {
  159. randomizeObject(map->objects[i]); //we have to randomize the castle first
  160. faction = map->objects[i]->subID;
  161. break;
  162. }
  163. else if(map->objects[i]->ID==98 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  164. {
  165. faction = map->objects[i]->subID;
  166. break;
  167. }
  168. }
  169. }
  170. else
  171. {
  172. while((!(info->castles[0]&(1<<faction))))
  173. {
  174. if((faction>7) && (info->castles[1]&(1<<(faction-8))))
  175. break;
  176. faction = ran()%F_NUMBER;
  177. }
  178. }
  179. int cid = VLC->townh->towns[faction].basicCreatures[obj->subID];
  180. for(int i=0;i<VLC->objh->cregens.size();i++)
  181. if(VLC->objh->cregens[i]==cid)
  182. return std::pair<int,int>(17,i);
  183. std::cout << "Cannot find a dwelling for creature "<<cid <<std::endl;
  184. return std::pair<int,int>(17,0);
  185. }
  186. case 218:
  187. {
  188. CCreGen3ObjInfo* info =(CCreGen3ObjInfo*)obj->info;
  189. int level = ((info->maxLevel-info->minLevel) ? (ran()%(info->maxLevel-info->minLevel)+info->minLevel) : (info->minLevel));
  190. int cid = VLC->townh->towns[obj->subID].basicCreatures[level];
  191. for(int i=0;i<VLC->objh->cregens.size();i++)
  192. if(VLC->objh->cregens[i]==cid)
  193. return std::pair<int,int>(17,i);
  194. std::cout << "Cannot find a dwelling for creature "<<cid <<std::endl;
  195. return std::pair<int,int>(17,0);
  196. }
  197. }
  198. return std::pair<int,int>(-1,-1);
  199. }
  200. void CGameState::randomizeObject(CGObjectInstance *cur)
  201. {
  202. std::pair<int,int> ran = pickObject(cur);
  203. if(ran.first<0 || ran.second<0) //this is not a random object, or we couldn't find anything
  204. {
  205. if(cur->ID==98) //town - set def
  206. {
  207. CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
  208. if(t->hasCapitol())
  209. t->defInfo = capitols[t->subID];
  210. else if(t->hasFort())
  211. t->defInfo = forts[t->subID];
  212. else
  213. t->defInfo = villages[t->subID];
  214. }
  215. return;
  216. }
  217. else if(ran.first==34)//special code for hero
  218. {
  219. CGHeroInstance *h = dynamic_cast<CGHeroInstance *>(cur);
  220. if(!h) {std::cout<<"Wrong random hero at "<<cur->pos<<std::endl; return;}
  221. cur->ID = ran.first;
  222. cur->subID = ran.second;
  223. h->type = VLC->heroh->heroes[ran.second];
  224. map->heroes.push_back(h);
  225. return; //TODO: maybe we should do something with definfo?
  226. }
  227. else if(ran.first==98)//special code for town
  228. {
  229. CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
  230. if(!t) {std::cout<<"Wrong random town at "<<cur->pos<<std::endl; return;}
  231. cur->ID = ran.first;
  232. cur->subID = ran.second;
  233. t->town = &VLC->townh->towns[ran.second];
  234. if(t->hasCapitol())
  235. t->defInfo = capitols[t->subID];
  236. else if(t->hasFort())
  237. t->defInfo = forts[t->subID];
  238. else
  239. t->defInfo = villages[t->subID];
  240. map->towns.push_back(t);
  241. return;
  242. }
  243. //we have to replace normal random object
  244. cur->ID = ran.first;
  245. cur->subID = ran.second;
  246. map->defs.insert(cur->defInfo = VLC->dobjinfo->gobjs[ran.first][ran.second]);
  247. if(!cur->defInfo){std::cout<<"Missing def declaration for "<<cur->ID<<" "<<cur->subID<<std::endl;return;}
  248. }
  249. void CGameState::init(StartInfo * si, Mapa * map, int seed)
  250. {
  251. ran.seed((long)seed);
  252. scenarioOps = si;
  253. this->map = map;
  254. for(int i=0;i<F_NUMBER;i++)
  255. {
  256. villages[i] = new CGDefInfo(*VLC->dobjinfo->castles[i]);
  257. forts[i] = VLC->dobjinfo->castles[i];
  258. capitols[i] = new CGDefInfo(*VLC->dobjinfo->castles[i]);
  259. }
  260. //picking random factions for players
  261. for(int i=0;i<scenarioOps->playerInfos.size();i++)
  262. {
  263. if(scenarioOps->playerInfos[i].castle==-1)
  264. {
  265. int f;
  266. do
  267. {
  268. f = ran()%F_NUMBER;
  269. }while(!(map->players[scenarioOps->playerInfos[i].color].allowedFactions & 1<<f));
  270. scenarioOps->playerInfos[i].castle = f;
  271. }
  272. }
  273. //randomizing objects
  274. for(int no=0; no<map->objects.size(); ++no)
  275. {
  276. randomizeObject(map->objects[no]);
  277. if(map->objects[no]->ID==26)
  278. map->objects[no]->defInfo->handler=NULL;
  279. }
  280. //std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl;
  281. day=0;
  282. /*********creating players entries in gs****************************************/
  283. for (int i=0; i<scenarioOps->playerInfos.size();i++)
  284. {
  285. std::pair<int,PlayerState> ins(scenarioOps->playerInfos[i].color,PlayerState());
  286. ins.second.color=ins.first;
  287. ins.second.serial=i;
  288. players.insert(ins);
  289. }
  290. /******************RESOURCES****************************************************/
  291. //TODO: zeby komputer dostawal inaczej niz gracz
  292. std::vector<int> startres;
  293. std::ifstream tis("config/startres.txt");
  294. int k;
  295. for (int j=0;j<scenarioOps->difficulty;j++)
  296. {
  297. tis >> k;
  298. for (int z=0;z<RESOURCE_QUANTITY;z++)
  299. tis>>k;
  300. }
  301. tis >> k;
  302. for (int i=0;i<RESOURCE_QUANTITY;i++)
  303. {
  304. tis >> k;
  305. startres.push_back(k);
  306. }
  307. tis.close();
  308. for (std::map<int,PlayerState>::iterator i = players.begin(); i!=players.end(); i++)
  309. {
  310. (*i).second.resources.resize(RESOURCE_QUANTITY);
  311. for (int x=0;x<RESOURCE_QUANTITY;x++)
  312. (*i).second.resources[x] = startres[x];
  313. }
  314. /*************************HEROES************************************************/
  315. for (int i=0; i<map->heroes.size();i++) //heroes instances
  316. {
  317. if (map->heroes[i]->getOwner()<0)
  318. continue;
  319. CGHeroInstance * vhi = (map->heroes[i]);
  320. if(!vhi->type)
  321. vhi->type = VLC->heroh->heroes[vhi->subID];
  322. //vhi->subID = vhi->type->ID;
  323. if (vhi->level<1)
  324. {
  325. vhi->exp=40+ran()%50;
  326. vhi->level = 1;
  327. }
  328. if (vhi->level>1) ;//TODO dodac um dr, ale potrzebne los
  329. if ((!vhi->primSkills.size()) || (vhi->primSkills[0]<0))
  330. {
  331. if (vhi->primSkills.size()<PRIMARY_SKILLS)
  332. vhi->primSkills.resize(PRIMARY_SKILLS);
  333. vhi->primSkills[0] = vhi->type->heroClass->initialAttack;
  334. vhi->primSkills[1] = vhi->type->heroClass->initialDefence;
  335. vhi->primSkills[2] = vhi->type->heroClass->initialPower;
  336. vhi->primSkills[3] = vhi->type->heroClass->initialKnowledge;
  337. }
  338. vhi->mana = vhi->primSkills[3]*10;
  339. if (!vhi->name.length())
  340. {
  341. vhi->name = vhi->type->name;
  342. }
  343. if (!vhi->biography.length())
  344. {
  345. vhi->biography = vhi->type->biography;
  346. }
  347. if (vhi->portrait < 0)
  348. vhi->portrait = vhi->type->ID;
  349. //initial army
  350. if (!vhi->army.slots.size()) //standard army
  351. {
  352. int pom, pom2=0;
  353. for(int x=0;x<3;x++)
  354. {
  355. pom = (VLC->creh->nameToID[vhi->type->refTypeStack[x]]);
  356. if(pom>=145 && pom<=149) //war machine
  357. {
  358. pom2++;
  359. switch (pom)
  360. {
  361. case 145: //catapult
  362. vhi->artifWorn[16] = 3;
  363. break;
  364. default:
  365. pom-=145;
  366. vhi->artifWorn[13+pom] = 4+pom;
  367. break;
  368. }
  369. continue;
  370. }
  371. vhi->army.slots[x-pom2].first = &(VLC->creh->creatures[pom]);
  372. if((pom = (vhi->type->highStack[x]-vhi->type->lowStack[x])) > 0)
  373. vhi->army.slots[x-pom2].second = (ran()%pom)+vhi->type->lowStack[x];
  374. else
  375. vhi->army.slots[x-pom2].second = +vhi->type->lowStack[x];
  376. }
  377. }
  378. players[vhi->getOwner()].heroes.push_back(vhi);
  379. }
  380. /*************************FOG**OF**WAR******************************************/
  381. for(std::map<int, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
  382. {
  383. k->second.fogOfWarMap.resize(map->width);
  384. for(int g=0; g<map->width; ++g)
  385. k->second.fogOfWarMap[g].resize(map->height);
  386. for(int g=-0; g<map->width; ++g)
  387. for(int h=0; h<map->height; ++h)
  388. k->second.fogOfWarMap[g][h].resize(map->twoLevel+1, 0);
  389. for(int g=0; g<map->width; ++g)
  390. for(int h=0; h<map->height; ++h)
  391. for(int v=0; v<map->twoLevel+1; ++v)
  392. k->second.fogOfWarMap[g][h][v] = 0;
  393. for(int xd=0; xd<map->width; ++xd) //revealing part of map around heroes
  394. {
  395. for(int yd=0; yd<map->height; ++yd)
  396. {
  397. for(int ch=0; ch<k->second.heroes.size(); ++ch)
  398. {
  399. int deltaX = (k->second.heroes[ch]->getPosition(false).x-xd)*(k->second.heroes[ch]->getPosition(false).x-xd);
  400. int deltaY = (k->second.heroes[ch]->getPosition(false).y-yd)*(k->second.heroes[ch]->getPosition(false).y-yd);
  401. if(deltaX+deltaY<k->second.heroes[ch]->getSightDistance()*k->second.heroes[ch]->getSightDistance())
  402. k->second.fogOfWarMap[xd][yd][k->second.heroes[ch]->getPosition(false).z] = 1;
  403. }
  404. }
  405. }
  406. }
  407. /****************************TOWNS************************************************/
  408. for (int i=0;i<map->towns.size();i++)
  409. {
  410. CGTownInstance * vti =(map->towns[i]);
  411. if(!vti->town)
  412. vti->town = &VLC->townh->towns[vti->subID];
  413. if (vti->name.length()==0) // if town hasn't name we draw it
  414. vti->name=vti->town->names[ran()%vti->town->names.size()];
  415. if(vti->builtBuildings.find(-50)!=vti->builtBuildings.end()) //give standard set of buildings
  416. {
  417. vti->builtBuildings.erase(-50);
  418. vti->builtBuildings.insert(10);
  419. vti->builtBuildings.insert(5);
  420. vti->builtBuildings.insert(30);
  421. if(ran()%2)
  422. vti->builtBuildings.insert(31);
  423. }
  424. players[vti->getOwner()].towns.push_back(vti);
  425. }
  426. for(std::map<int, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
  427. {
  428. if(k->first==-1 || k->first==255)
  429. continue;
  430. for(int xd=0; xd<map->width; ++xd) //revealing part of map around towns
  431. {
  432. for(int yd=0; yd<map->height; ++yd)
  433. {
  434. for(int ch=0; ch<k->second.towns.size(); ++ch)
  435. {
  436. int deltaX = (k->second.towns[ch]->pos.x-xd)*(k->second.towns[ch]->pos.x-xd);
  437. int deltaY = (k->second.towns[ch]->pos.y-yd)*(k->second.towns[ch]->pos.y-yd);
  438. if(deltaX+deltaY<k->second.towns[ch]->getSightDistance()*k->second.towns[ch]->getSightDistance())
  439. k->second.fogOfWarMap[xd][yd][k->second.towns[ch]->pos.z] = 1;
  440. }
  441. }
  442. }
  443. //init visiting heroes
  444. for(int l=0; l<k->second.heroes.size();l++)
  445. {
  446. for(int m=0; m<k->second.towns.size();m++)
  447. {
  448. int3 vistile = k->second.towns[m]->pos; vistile.x--; //tile next to the entrance
  449. if(vistile == k->second.heroes[l]->pos)
  450. {
  451. k->second.towns[m]->visitingHero = k->second.heroes[l];
  452. break;
  453. }
  454. }
  455. }
  456. }
  457. ///****************************SCRIPTS************************************************/
  458. //std::map<int, std::map<std::string, CObjectScript*> > * skrypty = &objscr; //alias for easier access
  459. ///****************************C++ OBJECT SCRIPTS************************************************/
  460. //std::map<int,CCPPObjectScript*> scripts;
  461. //CScriptCallback * csc = new CScriptCallback();
  462. //csc->gs = this;
  463. //handleCPPObjS(&scripts,new CVisitableOPH(csc));
  464. //handleCPPObjS(&scripts,new CVisitableOPW(csc));
  465. //handleCPPObjS(&scripts,new CPickable(csc));
  466. //handleCPPObjS(&scripts,new CMines(csc));
  467. //handleCPPObjS(&scripts,new CTownScript(csc));
  468. //handleCPPObjS(&scripts,new CHeroScript(csc));
  469. //handleCPPObjS(&scripts,new CMonsterS(csc));
  470. //handleCPPObjS(&scripts,new CCreatureGen(csc));
  471. ////created map
  472. ///****************************LUA OBJECT SCRIPTS************************************************/
  473. //std::vector<std::string> * lf = CLuaHandler::searchForScripts("scripts/lua/objects"); //files
  474. //for (int i=0; i<lf->size(); i++)
  475. //{
  476. // try
  477. // {
  478. // std::vector<std::string> * temp = CLuaHandler::functionList((*lf)[i]);
  479. // CLuaObjectScript * objs = new CLuaObjectScript((*lf)[i]);
  480. // CLuaCallback::registerFuncs(objs->is);
  481. // //objs
  482. // for (int j=0; j<temp->size(); j++)
  483. // {
  484. // int obid ; //obj ID
  485. // int dspos = (*temp)[j].find_first_of('_');
  486. // obid = atoi((*temp)[j].substr(dspos+1,(*temp)[j].size()-dspos-1).c_str());
  487. // std::string fname = (*temp)[j].substr(0,dspos);
  488. // if (skrypty->find(obid)==skrypty->end())
  489. // skrypty->insert(std::pair<int, std::map<std::string, CObjectScript*> >(obid,std::map<std::string,CObjectScript*>()));
  490. // (*skrypty)[obid].insert(std::pair<std::string, CObjectScript*>(fname,objs));
  491. // }
  492. // delete temp;
  493. // }HANDLE_EXCEPTION
  494. //}
  495. ///****************************INITIALIZING OBJECT SCRIPTS************************************************/
  496. //std::string temps("newObject");
  497. //for (int i=0; i<map->objects.size(); i++)
  498. //{
  499. // //c++ scripts
  500. // if (scripts.find(map->objects[i]->ID) != scripts.end())
  501. // {
  502. // map->objects[i]->state = scripts[map->objects[i]->ID];
  503. // map->objects[i]->state->newObject(map->objects[i]);
  504. // }
  505. // else
  506. // {
  507. // map->objects[i]->state = NULL;
  508. // }
  509. // // lua scripts
  510. // if(checkFunc(map->objects[i]->ID,temps))
  511. // (*skrypty)[map->objects[i]->ID][temps]->newObject(map->objects[i]);
  512. //}
  513. //delete lf;
  514. }
  515. void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CArmedInstance *hero1, CArmedInstance *hero2)
  516. {/*
  517. curB = new BattleInfo();
  518. std::vector<CStack*> & stacks = (curB->stacks);
  519. curB->army1=army1;
  520. curB->army2=army2;
  521. curB->hero1=dynamic_cast<CGHeroInstance*>(hero1);
  522. curB->hero2=dynamic_cast<CGHeroInstance*>(hero2);
  523. curB->side1=(hero1)?(hero1->tempOwner):(-1);
  524. curB->side2=(hero2)?(hero2->tempOwner):(-1);
  525. curB->round = -2;
  526. curB->stackActionPerformed = false;
  527. for(std::map<int,std::pair<CCreature*,int> >::iterator i = army1->slots.begin(); i!=army1->slots.end(); i++)
  528. {
  529. stacks.push_back(new CStack(i->second.first,i->second.second,0, stacks.size(), true));
  530. stacks[stacks.size()-1]->ID = stacks.size()-1;
  531. }
  532. //initialization of positions
  533. switch(army1->slots.size()) //for attacker
  534. {
  535. case 0:
  536. break;
  537. case 1:
  538. stacks[0]->position = 86; //6
  539. break;
  540. case 2:
  541. stacks[0]->position = 35; //3
  542. stacks[1]->position = 137; //9
  543. break;
  544. case 3:
  545. stacks[0]->position = 35; //3
  546. stacks[1]->position = 86; //6
  547. stacks[2]->position = 137; //9
  548. break;
  549. case 4:
  550. stacks[0]->position = 1; //1
  551. stacks[1]->position = 69; //5
  552. stacks[2]->position = 103; //7
  553. stacks[3]->position = 171; //11
  554. break;
  555. case 5:
  556. stacks[0]->position = 1; //1
  557. stacks[1]->position = 35; //3
  558. stacks[2]->position = 86; //6
  559. stacks[3]->position = 137; //9
  560. stacks[4]->position = 171; //11
  561. break;
  562. case 6:
  563. stacks[0]->position = 1; //1
  564. stacks[1]->position = 35; //3
  565. stacks[2]->position = 69; //5
  566. stacks[3]->position = 103; //7
  567. stacks[4]->position = 137; //9
  568. stacks[5]->position = 171; //11
  569. break;
  570. case 7:
  571. stacks[0]->position = 1; //1
  572. stacks[1]->position = 35; //3
  573. stacks[2]->position = 69; //5
  574. stacks[3]->position = 86; //6
  575. stacks[4]->position = 103; //7
  576. stacks[5]->position = 137; //9
  577. stacks[6]->position = 171; //11
  578. break;
  579. default: //fault
  580. break;
  581. }
  582. for(std::map<int,std::pair<CCreature*,int> >::iterator i = army2->slots.begin(); i!=army2->slots.end(); i++)
  583. stacks.push_back(new CStack(i->second.first,i->second.second,1, stacks.size(), false));
  584. switch(army2->slots.size()) //for defender
  585. {
  586. case 0:
  587. break;
  588. case 1:
  589. stacks[0+army1->slots.size()]->position = 100; //6
  590. break;
  591. case 2:
  592. stacks[0+army1->slots.size()]->position = 49; //3
  593. stacks[1+army1->slots.size()]->position = 151; //9
  594. break;
  595. case 3:
  596. stacks[0+army1->slots.size()]->position = 49; //3
  597. stacks[1+army1->slots.size()]->position = 100; //6
  598. stacks[2+army1->slots.size()]->position = 151; //9
  599. break;
  600. case 4:
  601. stacks[0+army1->slots.size()]->position = 15; //1
  602. stacks[1+army1->slots.size()]->position = 83; //5
  603. stacks[2+army1->slots.size()]->position = 117; //7
  604. stacks[3+army1->slots.size()]->position = 185; //11
  605. break;
  606. case 5:
  607. stacks[0+army1->slots.size()]->position = 15; //1
  608. stacks[1+army1->slots.size()]->position = 49; //3
  609. stacks[2+army1->slots.size()]->position = 100; //6
  610. stacks[3+army1->slots.size()]->position = 151; //9
  611. stacks[4+army1->slots.size()]->position = 185; //11
  612. break;
  613. case 6:
  614. stacks[0+army1->slots.size()]->position = 15; //1
  615. stacks[1+army1->slots.size()]->position = 49; //3
  616. stacks[2+army1->slots.size()]->position = 83; //5
  617. stacks[3+army1->slots.size()]->position = 117; //7
  618. stacks[4+army1->slots.size()]->position = 151; //9
  619. stacks[5+army1->slots.size()]->position = 185; //11
  620. break;
  621. case 7:
  622. stacks[0+army1->slots.size()]->position = 15; //1
  623. stacks[1+army1->slots.size()]->position = 49; //3
  624. stacks[2+army1->slots.size()]->position = 83; //5
  625. stacks[3+army1->slots.size()]->position = 100; //6
  626. stacks[4+army1->slots.size()]->position = 117; //7
  627. stacks[5+army1->slots.size()]->position = 151; //9
  628. stacks[6+army1->slots.size()]->position = 185; //11
  629. break;
  630. default: //fault
  631. break;
  632. }
  633. for(int g=0; g<stacks.size(); ++g) //shifting positions of two-hex creatures
  634. {
  635. if((stacks[g]->position%17)==1 && stacks[g]->creature->isDoubleWide())
  636. {
  637. stacks[g]->position += 1;
  638. }
  639. else if((stacks[g]->position%17)==15 && stacks[g]->creature->isDoubleWide())
  640. {
  641. stacks[g]->position -= 1;
  642. }
  643. }
  644. std::stable_sort(stacks.begin(),stacks.end(),cmpst);
  645. //for start inform players about battle
  646. for(std::map<int, PlayerState>::iterator j=players.begin(); j!=players.end(); ++j)//->players.size(); ++j) //for testing
  647. {
  648. if (j->first > PLAYER_LIMIT)
  649. break;
  650. if(j->second.fogOfWarMap[tile.x][tile.y][tile.z])
  651. { //player should be notified
  652. tribool side = tribool::indeterminate_value;
  653. if(j->first == curB->side1) //player is attacker
  654. side = false;
  655. else if(j->first == curB->side2) //player is defender
  656. side = true;
  657. else
  658. continue; //no witnesses
  659. if(VLC->playerint[j->second.serial]->human)
  660. {
  661. ((CPlayerInterface*)( VLC->playerint[j->second.serial] ))->battleStart(army1, army2, tile, curB->hero1, curB->hero2, side);
  662. }
  663. else
  664. {
  665. //VLC->playerint[j->second.serial]->battleStart(army1, army2, tile, curB->hero1, curB->hero2, side);
  666. }
  667. }
  668. }
  669. curB->round++;
  670. if( (curB->hero1 && curB->hero1->getSecSkillLevel(19)>=0) || ( curB->hero2 && curB->hero2->getSecSkillLevel(19)>=0) )//someone has tactics
  671. {
  672. //TODO: wywolania dla rundy -1, ograniczenie pola ruchu, etc
  673. }
  674. curB->round++;
  675. //SDL_Thread * eventh = SDL_CreateThread(battleEventThread, NULL);
  676. while(true) //till the end of the battle ;]
  677. {
  678. bool battleEnd = false;
  679. //tell players about next round
  680. for(int v=0; v<VLC->playerint.size(); ++v)
  681. VLC->playerint[v]->battleNewRound(curB->round);
  682. //stack loop
  683. for(int i=0;i<stacks.size();i++)
  684. {
  685. curB->activeStack = i;
  686. curB->stackActionPerformed = false;
  687. if(stacks[i]->alive) //indicate posiibility of making action for this unit
  688. {
  689. unsigned char owner = (stacks[i]->owner)?(hero2 ? hero2->tempOwner : 255):(hero1->tempOwner);
  690. unsigned char serialOwner = -1;
  691. for(int g=0; g<VLC->playerint.size(); ++g)
  692. {
  693. if(VLC->playerint[g]->playerID == owner)
  694. {
  695. serialOwner = g;
  696. break;
  697. }
  698. }
  699. if(serialOwner==255) //neutral unit
  700. {
  701. }
  702. else if(VLC->playerint[serialOwner]->human)
  703. {
  704. BattleAction ba = ((CPlayerInterface*)VLC->playerint[serialOwner])->activeStack(stacks[i]->ID);
  705. switch(ba.actionType)
  706. {
  707. case 2: //walk
  708. {
  709. battleMoveCreatureStack(ba.stackNumber, ba.destinationTile);
  710. }
  711. case 3: //defend
  712. {
  713. break;
  714. }
  715. case 4: //retreat/flee
  716. {
  717. for(int v=0; v<VLC->playerint.size(); ++v) //tell about the end of this battle to interfaces
  718. VLC->playerint[v]->battleEnd(army1, army2, hero1, hero2, std::vector<int>(), 0, false);
  719. battleEnd = true;
  720. break;
  721. }
  722. case 6: //walk or attack
  723. {
  724. battleMoveCreatureStack(ba.stackNumber, ba.destinationTile);
  725. battleAttackCreatureStack(ba.stackNumber, ba.destinationTile);
  726. break;
  727. }
  728. }
  729. }
  730. else
  731. {
  732. //VLC->playerint[serialOwner]->activeStack(stacks[i]->ID);
  733. }
  734. }
  735. if(battleEnd)
  736. break;
  737. //sprawdzic czy po tej akcji ktoras strona nie wygrala bitwy
  738. }
  739. if(battleEnd)
  740. break;
  741. curB->round++;
  742. SDL_Delay(50);
  743. }
  744. for(int i=0;i<stacks.size();i++)
  745. delete stacks[i];
  746. delete curB;
  747. curB = NULL;*/
  748. }
  749. bool CGameState::battleMoveCreatureStack(int ID, int dest)
  750. {/*
  751. //first checks
  752. if(curB->stackActionPerformed) //because unit cannot be moved more than once
  753. return false;
  754. unsigned char owner = -1; //owner moved of unit
  755. for(int g=0; g<curB->stacks.size(); ++g)
  756. {
  757. if(curB->stacks[g]->ID == ID)
  758. {
  759. owner = curB->stacks[g]->owner;
  760. break;
  761. }
  762. }
  763. bool stackAtEnd = false; //true if there is a stack at the end of the path (we should attack it)
  764. int numberOfStackAtEnd = -1;
  765. for(int g=0; g<curB->stacks.size(); ++g)
  766. {
  767. if(curB->stacks[g]->position == dest
  768. || (curB->stacks[g]->creature->isDoubleWide() && curB->stacks[g]->attackerOwned && curB->stacks[g]->position-1 == dest)
  769. || (curB->stacks[g]->creature->isDoubleWide() && !curB->stacks[g]->attackerOwned && curB->stacks[g]->position+1 == dest))
  770. {
  771. if(curB->stacks[g]->alive)
  772. {
  773. stackAtEnd = true;
  774. numberOfStackAtEnd = g;
  775. break;
  776. }
  777. }
  778. }
  779. //selecting moved stack
  780. CStack * curStack = NULL;
  781. for(int y=0; y<curB->stacks.size(); ++y)
  782. {
  783. if(curB->stacks[y]->ID == ID)
  784. {
  785. curStack = curB->stacks[y];
  786. break;
  787. }
  788. }
  789. if(!curStack)
  790. return false;
  791. //initing necessary tables
  792. bool accessibility[187]; //accesibility of hexes
  793. for(int k=0; k<187; k++)
  794. accessibility[k] = true;
  795. for(int g=0; g<curB->stacks.size(); ++g)
  796. {
  797. if(curB->stacks[g]->ID != ID && curB->stacks[g]->alive) //we don't want to lock enemy's positions and this units' position
  798. {
  799. accessibility[curB->stacks[g]->position] = false;
  800. if(curB->stacks[g]->creature->isDoubleWide()) //if it's a double hex creature
  801. {
  802. if(curB->stacks[g]->attackerOwned)
  803. accessibility[curB->stacks[g]->position-1] = false;
  804. else
  805. accessibility[curB->stacks[g]->position+1] = false;
  806. }
  807. }
  808. }
  809. accessibility[dest] = true;
  810. if(curStack->creature->isDoubleWide()) //locking positions unreachable by two-hex creatures
  811. {
  812. bool mac[187];
  813. for(int b=0; b<187; ++b)
  814. {
  815. //
  816. // && ( ? (curStack->attackerOwned ? accessibility[curNext-1] : accessibility[curNext+1]) : true )
  817. mac[b] = accessibility[b];
  818. if( accessibility[b] && !(curStack->attackerOwned ? accessibility[b-1] : accessibility[b+1]))
  819. {
  820. mac[b] = false;
  821. }
  822. }
  823. mac[curStack->attackerOwned ? curStack->position+1 : curStack->position-1]=true;
  824. for(int v=0; v<187; ++v)
  825. accessibility[v] = mac[v];
  826. //removing accessibility for side hexes
  827. for(int v=0; v<187; ++v)
  828. if(curStack->attackerOwned ? (v%17)==1 : (v%17)==15)
  829. accessibility[v] = false;
  830. }
  831. if(!accessibility[dest])
  832. return false;
  833. int predecessor[187]; //for getting the Path
  834. for(int b=0; b<187; ++b)
  835. predecessor[b] = -1;
  836. //bfsing
  837. int dists[187]; //calculated distances
  838. std::queue<int> hexq; //bfs queue
  839. hexq.push(curStack->position);
  840. for(int g=0; g<187; ++g)
  841. dists[g] = 100000000;
  842. dists[hexq.front()] = 0;
  843. int curNext = -1; //for bfs loop only (helper var)
  844. while(!hexq.empty()) //bfs loop
  845. {
  846. int curHex = hexq.front();
  847. hexq.pop();
  848. curNext = curHex - ( (curHex/17)%2 ? 18 : 17 );
  849. if((curNext > 0) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top left
  850. {
  851. hexq.push(curNext);
  852. dists[curNext] = dists[curHex] + 1;
  853. predecessor[curNext] = curHex;
  854. }
  855. curNext = curHex - ( (curHex/17)%2 ? 17 : 16 );
  856. if((curNext > 0) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top right
  857. {
  858. hexq.push(curNext);
  859. dists[curNext] = dists[curHex] + 1;
  860. predecessor[curNext] = curHex;
  861. }
  862. curNext = curHex - 1;
  863. if((curNext > 0) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //left
  864. {
  865. hexq.push(curNext);
  866. dists[curNext] = dists[curHex] + 1;
  867. predecessor[curNext] = curHex;
  868. }
  869. curNext = curHex + 1;
  870. if((curNext < 187) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //right
  871. {
  872. hexq.push(curNext);
  873. dists[curNext] = dists[curHex] + 1;
  874. predecessor[curNext] = curHex;
  875. }
  876. curNext = curHex + ( (curHex/17)%2 ? 16 : 17 );
  877. if((curNext < 187) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom left
  878. {
  879. hexq.push(curNext);
  880. dists[curNext] = dists[curHex] + 1;
  881. predecessor[curNext] = curHex;
  882. }
  883. curNext = curHex + ( (curHex/17)%2 ? 17 : 18 );
  884. if((curNext < 187) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom right
  885. {
  886. hexq.push(curNext);
  887. dists[curNext] = dists[curHex] + 1;
  888. predecessor[curNext] = curHex;
  889. }
  890. }
  891. //following the Path
  892. if(dists[dest] > curStack->creature->speed && !(stackAtEnd && dists[dest] == curStack->creature->speed+1)) //we can attack a stack if we can go to adjacent hex
  893. return false;
  894. std::vector<int> path;
  895. int curElem = dest;
  896. while(curElem!=curStack->position)
  897. {
  898. path.push_back(curElem);
  899. curElem = predecessor[curElem];
  900. }
  901. for(int v=path.size()-1; v>=0; --v)
  902. {
  903. if(v!=0 || !stackAtEnd) //it's not the last step
  904. {
  905. LOCPLINT->battleStackMoved(ID, path[v], v==path.size()-1, v==0 || (stackAtEnd && v==1) );
  906. curStack->position = path[v];
  907. }
  908. else //if it's last step and we should attack unit at the end
  909. {
  910. LOCPLINT->battleStackAttacking(ID, path[v]);
  911. //counting dealt damage
  912. int numberOfCres = curStack->amount; //number of attacking creatures
  913. int attackDefenseBonus = curStack->creature->attack - curB->stacks[numberOfStackAtEnd]->creature->defence;
  914. int damageBase = 0;
  915. if(curStack->creature->damageMax == curStack->creature->damageMin) //constant damage
  916. {
  917. damageBase = curStack->creature->damageMin;
  918. }
  919. else
  920. {
  921. damageBase = ran()%(curStack->creature->damageMax - curStack->creature->damageMin) + curStack->creature->damageMin + 1;
  922. }
  923. float dmgBonusMultiplier = 1.0;
  924. if(attackDefenseBonus < 0) //decreasing dmg
  925. {
  926. if(0.02f * (-attackDefenseBonus) > 0.3f)
  927. {
  928. dmgBonusMultiplier += -0.3f;
  929. }
  930. else
  931. {
  932. dmgBonusMultiplier += 0.02f * attackDefenseBonus;
  933. }
  934. }
  935. else //increasing dmg
  936. {
  937. if(0.05f * attackDefenseBonus > 4.0f)
  938. {
  939. dmgBonusMultiplier += 4.0f;
  940. }
  941. else
  942. {
  943. dmgBonusMultiplier += 0.05f * attackDefenseBonus;
  944. }
  945. }
  946. int finalDmg = (float)damageBase * (float)curStack->amount * dmgBonusMultiplier;
  947. //applying damages
  948. int cresKilled = finalDmg / curB->stacks[numberOfStackAtEnd]->creature->hitPoints;
  949. int damageFirst = finalDmg % curB->stacks[numberOfStackAtEnd]->creature->hitPoints;
  950. if( curB->stacks[numberOfStackAtEnd]->firstHPleft <= damageFirst )
  951. {
  952. curB->stacks[numberOfStackAtEnd]->amount -= 1;
  953. curB->stacks[numberOfStackAtEnd]->firstHPleft += curB->stacks[numberOfStackAtEnd]->creature->hitPoints - damageFirst;
  954. }
  955. else
  956. {
  957. curB->stacks[numberOfStackAtEnd]->firstHPleft -= damageFirst;
  958. }
  959. int cresInstackBefore = curB->stacks[numberOfStackAtEnd]->amount;
  960. curB->stacks[numberOfStackAtEnd]->amount -= cresKilled;
  961. if(curB->stacks[numberOfStackAtEnd]->amount<=0) //stack killed
  962. {
  963. curB->stacks[numberOfStackAtEnd]->amount = 0;
  964. LOCPLINT->battleStackKilled(curB->stacks[numberOfStackAtEnd]->ID, finalDmg, std::min(cresKilled, cresInstackBefore) , ID);
  965. curB->stacks[numberOfStackAtEnd]->alive = false;
  966. }
  967. else
  968. {
  969. LOCPLINT->battleStackIsAttacked(curB->stacks[numberOfStackAtEnd]->ID, finalDmg, std::min(cresKilled, cresInstackBefore), ID);
  970. }
  971. //damage applied
  972. }
  973. }
  974. curB->stackActionPerformed = true;
  975. LOCPLINT->actionFinished(BattleAction());*/
  976. return true;
  977. }
  978. bool CGameState::battleAttackCreatureStack(int ID, int dest)
  979. {
  980. int attackedCreaure = -1; //-1 - there is no attacked creature
  981. for(int b=0; b<curB->stacks.size(); ++b) //TODO: make upgrades for two-hex cres.
  982. {
  983. if(curB->stacks[b]->position == dest)
  984. {
  985. attackedCreaure = curB->stacks[b]->ID;
  986. break;
  987. }
  988. }
  989. if(attackedCreaure == -1)
  990. return false;
  991. //LOCPLINT->cb->
  992. return true;
  993. }
  994. std::vector<int> CGameState::battleGetRange(int ID)
  995. {/*
  996. int initialPlace=-1; //position of unit
  997. int radius=-1; //range of unit
  998. unsigned char owner = -1; //owner of unit
  999. //selecting stack
  1000. CStack * curStack = NULL;
  1001. for(int y=0; y<curB->stacks.size(); ++y)
  1002. {
  1003. if(curB->stacks[y]->ID == ID)
  1004. {
  1005. curStack = curB->stacks[y];
  1006. break;
  1007. }
  1008. }
  1009. for(int g=0; g<curB->stacks.size(); ++g)
  1010. {
  1011. if(curB->stacks[g]->ID == ID)
  1012. {
  1013. initialPlace = curB->stacks[g]->position;
  1014. radius = curB->stacks[g]->creature->speed;
  1015. owner = curB->stacks[g]->owner;
  1016. break;
  1017. }
  1018. }
  1019. bool accessibility[187]; //accesibility of hexes
  1020. for(int k=0; k<187; k++)
  1021. accessibility[k] = true;
  1022. for(int g=0; g<curB->stacks.size(); ++g)
  1023. {
  1024. if(curB->stacks[g]->ID != ID && curB->stacks[g]->alive) //we don't want to lock current unit's position
  1025. {
  1026. accessibility[curB->stacks[g]->position] = false;
  1027. if(curB->stacks[g]->creature->isDoubleWide()) //if it's a double hex creature
  1028. {
  1029. if(curB->stacks[g]->attackerOwned)
  1030. accessibility[curB->stacks[g]->position-1] = false;
  1031. else
  1032. accessibility[curB->stacks[g]->position+1] = false;
  1033. }
  1034. }
  1035. }
  1036. if(curStack->creature->isDoubleWide()) //locking positions unreachable by two-hex creatures
  1037. {
  1038. bool mac[187];
  1039. for(int b=0; b<187; ++b)
  1040. {
  1041. //
  1042. // && ( ? (curStack->attackerOwned ? accessibility[curNext-1] : accessibility[curNext+1]) : true )
  1043. mac[b] = accessibility[b];
  1044. if( accessibility[b] && !(curStack->attackerOwned ? accessibility[b-1] : accessibility[b+1]))
  1045. {
  1046. mac[b] = false;
  1047. }
  1048. }
  1049. mac[curStack->attackerOwned ? curStack->position+1 : curStack->position-1]=true;
  1050. for(int v=0; v<187; ++v)
  1051. accessibility[v] = mac[v];
  1052. //removing accessibility for side hexes
  1053. for(int v=0; v<187; ++v)
  1054. if(curStack->attackerOwned ? (v%17)==1 : (v%17)==15)
  1055. accessibility[v] = false;
  1056. }
  1057. int dists[187]; //calculated distances
  1058. std::queue<int> hexq; //bfs queue
  1059. hexq.push(initialPlace);
  1060. for(int g=0; g<187; ++g)
  1061. dists[g] = 100000000;
  1062. dists[initialPlace] = 0;
  1063. int curNext = -1; //for bfs loop only (helper var)
  1064. while(!hexq.empty()) //bfs loop
  1065. {
  1066. int curHex = hexq.front();
  1067. hexq.pop();
  1068. curNext = curHex - ( (curHex/17)%2 ? 18 : 17 );
  1069. if((curNext > 0) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top left
  1070. {
  1071. hexq.push(curNext);
  1072. dists[curNext] = dists[curHex] + 1;
  1073. }
  1074. curNext = curHex - ( (curHex/17)%2 ? 17 : 16 );
  1075. if((curNext > 0) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top right
  1076. {
  1077. hexq.push(curNext);
  1078. dists[curNext] = dists[curHex] + 1;
  1079. }
  1080. curNext = curHex - 1;
  1081. if((curNext > 0) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //left
  1082. {
  1083. hexq.push(curNext);
  1084. dists[curNext] = dists[curHex] + 1;
  1085. }
  1086. curNext = curHex + 1;
  1087. if((curNext < 187) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //right
  1088. {
  1089. hexq.push(curNext);
  1090. dists[curNext] = dists[curHex] + 1;
  1091. }
  1092. curNext = curHex + ( (curHex/17)%2 ? 16 : 17 );
  1093. if((curNext < 187) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom left
  1094. {
  1095. hexq.push(curNext);
  1096. dists[curNext] = dists[curHex] + 1;
  1097. }
  1098. curNext = curHex + ( (curHex/17)%2 ? 17 : 18 );
  1099. if((curNext < 187) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom right
  1100. {
  1101. hexq.push(curNext);
  1102. dists[curNext] = dists[curHex] + 1;
  1103. }
  1104. }
  1105. std::vector<int> ret;
  1106. for(int i=0; i<187; ++i)
  1107. {
  1108. if(dists[i]<=radius)
  1109. {
  1110. ret.push_back(i);
  1111. }
  1112. }
  1113. std::vector<int> additionals;
  1114. //adding enemies' positions
  1115. for(int c=0; c<curB->stacks.size(); ++c)
  1116. {
  1117. if(curB->stacks[c]->alive && curB->stacks[c]->owner != owner)
  1118. {
  1119. for(int g=0; g<ret.size(); ++g)
  1120. {
  1121. if(CBattleHex::mutualPosition(ret[g], curB->stacks[c]->position) != -1)
  1122. {
  1123. additionals.push_back(curB->stacks[c]->position);
  1124. }
  1125. if(curB->stacks[c]->creature->isDoubleWide() && curB->stacks[c]->attackerOwned && CBattleHex::mutualPosition(ret[g], curB->stacks[c]->position-1) != -1)
  1126. {
  1127. additionals.push_back(curB->stacks[c]->position-1);
  1128. }
  1129. if(curB->stacks[c]->creature->isDoubleWide() && !curB->stacks[c]->attackerOwned && CBattleHex::mutualPosition(ret[g], curB->stacks[c]->position+1) != -1)
  1130. {
  1131. additionals.push_back(curB->stacks[c]->position+1);
  1132. }
  1133. }
  1134. }
  1135. }
  1136. for(int g=0; g<additionals.size(); ++g)
  1137. {
  1138. ret.push_back(additionals[g]);
  1139. }
  1140. std::sort(ret.begin(), ret.end());
  1141. std::vector<int>::iterator nend = std::unique(ret.begin(), ret.end());
  1142. std::vector<int> ret2;
  1143. for(std::vector<int>::iterator it = ret.begin(); it != nend; ++it)
  1144. {
  1145. ret2.push_back(*it);
  1146. }
  1147. return ret2;*/
  1148. return std::vector<int>();
  1149. }