CGameState.cpp 40 KB

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