CGameState.cpp 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692
  1. #define VCMI_DLL
  2. #include <algorithm>
  3. #include <queue>
  4. #include <fstream>
  5. #include "CGameState.h"
  6. #include <boost/random/linear_congruential.hpp>
  7. #include "hch/CDefObjInfoHandler.h"
  8. #include "hch/CArtHandler.h"
  9. #include "hch/CBuildingHandler.h"
  10. #include "hch/CGeneralTextHandler.h"
  11. #include "hch/CTownHandler.h"
  12. #include "hch/CSpellHandler.h"
  13. #include "hch/CHeroHandler.h"
  14. #include "hch/CObjectHandler.h"
  15. #include "hch/CCreatureHandler.h"
  16. #include "lib/VCMI_Lib.h"
  17. #include "map.h"
  18. #include "StartInfo.h"
  19. #include "lib/NetPacks.h"
  20. #include <boost/foreach.hpp>
  21. #include <boost/thread.hpp>
  22. #include <boost/thread/shared_mutex.hpp>
  23. boost::rand48 ran;
  24. #ifdef min
  25. #undef min
  26. #endif
  27. #ifdef max
  28. #undef max
  29. #endif
  30. std::string DLL_EXPORT toString(MetaString &ms)
  31. {
  32. std::string ret;
  33. for(size_t i=0;i<ms.message.size();++i)
  34. {
  35. if(ms.message[i]>0)
  36. {
  37. ret += ms.strings[ms.message[i]-1];
  38. }
  39. else
  40. {
  41. std::vector<std::string> *vec;
  42. int type = ms.texts[-ms.message[i]-1].first,
  43. ser = ms.texts[-ms.message[i]-1].second;
  44. if(type == 5)
  45. {
  46. ret += VLC->arth->artifacts[ser].Name();
  47. continue;
  48. }
  49. else if(type == 7)
  50. {
  51. ret += VLC->creh->creatures[ser].namePl;
  52. continue;
  53. }
  54. else if(type == 9)
  55. {
  56. ret += VLC->generaltexth->mines[ser].first;
  57. continue;
  58. }
  59. else if(type == 10)
  60. {
  61. ret += VLC->generaltexth->mines[ser].second;
  62. continue;
  63. }
  64. else
  65. {
  66. switch(type)
  67. {
  68. case 1:
  69. vec = &VLC->generaltexth->allTexts;
  70. break;
  71. case 2:
  72. vec = &VLC->generaltexth->xtrainfo;
  73. break;
  74. case 3:
  75. vec = &VLC->generaltexth->names;
  76. break;
  77. case 4:
  78. vec = &VLC->generaltexth->restypes;
  79. break;
  80. case 6:
  81. vec = &VLC->generaltexth->arraytxt;
  82. break;
  83. case 8:
  84. vec = &VLC->generaltexth->creGens;
  85. break;
  86. case 11:
  87. vec = &VLC->generaltexth->advobtxt;
  88. break;
  89. case 12:
  90. vec = &VLC->generaltexth->artifEvents;
  91. break;
  92. }
  93. ret += (*vec)[ser];
  94. }
  95. }
  96. }
  97. for(size_t i=0; i < ms.replacements.size(); ++i)
  98. {
  99. ret.replace(ret.find("%s"),2,ms.replacements[i]);
  100. }
  101. return ret;
  102. }
  103. CGObjectInstance * createObject(int id, int subid, int3 pos, int owner)
  104. {
  105. CGObjectInstance * nobj;
  106. switch(id)
  107. {
  108. case HEROI_TYPE: //hero
  109. {
  110. CGHeroInstance * nobj = new CGHeroInstance();
  111. nobj->pos = pos;
  112. nobj->tempOwner = owner;
  113. nobj->subID = subid;
  114. //nobj->initHero(ran);
  115. return nobj;
  116. }
  117. case TOWNI_TYPE: //town
  118. nobj = new CGTownInstance;
  119. break;
  120. default: //rest of objects
  121. nobj = new CGObjectInstance;
  122. nobj->defInfo = VLC->dobjinfo->gobjs[id][subid];
  123. break;
  124. }
  125. nobj->ID = id;
  126. nobj->subID = subid;
  127. if(!nobj->defInfo)
  128. tlog3 <<"No def declaration for " <<id <<" "<<subid<<std::endl;
  129. nobj->pos = pos;
  130. //nobj->state = NULL;//new CLuaObjectScript();
  131. nobj->tempOwner = owner;
  132. nobj->info = NULL;
  133. nobj->defInfo->id = id;
  134. nobj->defInfo->subid = subid;
  135. //assigning defhandler
  136. if(nobj->ID==HEROI_TYPE || nobj->ID==TOWNI_TYPE)
  137. return nobj;
  138. nobj->defInfo = VLC->dobjinfo->gobjs[id][subid];
  139. return nobj;
  140. }
  141. CStack * BattleInfo::getStack(int stackID)
  142. {
  143. for(int g=0; g<stacks.size(); ++g)
  144. {
  145. if(stacks[g]->ID == stackID)
  146. return stacks[g];
  147. }
  148. return NULL;
  149. }
  150. CStack * BattleInfo::getStackT(int tileID)
  151. {
  152. for(int g=0; g<stacks.size(); ++g)
  153. {
  154. if(stacks[g]->position == tileID
  155. || (stacks[g]->creature->isDoubleWide() && stacks[g]->attackerOwned && stacks[g]->position-1 == tileID)
  156. || (stacks[g]->creature->isDoubleWide() && !stacks[g]->attackerOwned && stacks[g]->position+1 == tileID))
  157. {
  158. if(stacks[g]->alive())
  159. {
  160. return stacks[g];
  161. }
  162. }
  163. }
  164. return NULL;
  165. }
  166. void BattleInfo::getAccessibilityMap(bool *accessibility, int stackToOmmit)
  167. {
  168. memset(accessibility,1,BFIELD_SIZE); //initialize array with trues
  169. for(int g=0; g<stacks.size(); ++g)
  170. {
  171. if(!stacks[g]->alive() || stacks[g]->ID==stackToOmmit) //we don't want to lock position of this stack
  172. continue;
  173. accessibility[stacks[g]->position] = false;
  174. if(stacks[g]->creature->isDoubleWide()) //if it's a double hex creature
  175. {
  176. if(stacks[g]->attackerOwned)
  177. accessibility[stacks[g]->position-1] = false;
  178. else
  179. accessibility[stacks[g]->position+1] = false;
  180. }
  181. }
  182. //obstacles
  183. for(int b=0; b<obstacles.size(); ++b)
  184. {
  185. std::vector<int> blocked = VLC->heroh->obstacles[obstacles[b].ID].getBlocked(obstacles[b].pos);
  186. for(int c=0; c<blocked.size(); ++c)
  187. {
  188. if(blocked[c] >=0 && blocked[c] < BFIELD_SIZE)
  189. accessibility[blocked[c]] = false;
  190. }
  191. }
  192. }
  193. void BattleInfo::getAccessibilityMapForTwoHex(bool *accessibility, bool atackerSide, int stackToOmmit, bool addOccupiable) //send pointer to at least 187 allocated bytes
  194. {
  195. bool mac[BFIELD_SIZE];
  196. getAccessibilityMap(mac,stackToOmmit);
  197. memcpy(accessibility,mac,BFIELD_SIZE);
  198. }
  199. void BattleInfo::makeBFS(int start, bool*accessibility, int *predecessor, int *dists) //both pointers must point to the at least 187-elements int arrays
  200. {
  201. //inits
  202. for(int b=0; b<BFIELD_SIZE; ++b)
  203. predecessor[b] = -1;
  204. for(int g=0; g<BFIELD_SIZE; ++g)
  205. dists[g] = 100000000;
  206. std::queue<int> hexq; //bfs queue
  207. hexq.push(start);
  208. dists[hexq.front()] = 0;
  209. int curNext = -1; //for bfs loop only (helper var)
  210. while(!hexq.empty()) //bfs loop
  211. {
  212. int curHex = hexq.front();
  213. std::vector<int> neighbours = neighbouringTiles(curHex);
  214. hexq.pop();
  215. for(int nr=0; nr<neighbours.size(); nr++)
  216. {
  217. curNext = neighbours[nr];
  218. if(!accessibility[curNext] || (dists[curHex]+1)>=dists[curNext])
  219. continue;
  220. hexq.push(curNext);
  221. dists[curNext] = dists[curHex] + 1;
  222. predecessor[curNext] = curHex;
  223. }
  224. }
  225. };
  226. std::vector<int> BattleInfo::getAccessibility(int stackID, bool addOccupiable)
  227. {
  228. std::vector<int> ret;
  229. bool ac[BFIELD_SIZE];
  230. CStack *s = getStack(stackID);
  231. if(s->creature->isDoubleWide())
  232. getAccessibilityMapForTwoHex(ac,s->attackerOwned,stackID,addOccupiable);
  233. else
  234. getAccessibilityMap(ac,stackID);
  235. int pr[BFIELD_SIZE], dist[BFIELD_SIZE];
  236. makeBFS(s->position,ac,pr,dist);
  237. if(s->creature->isDoubleWide())
  238. {
  239. if(!addOccupiable)
  240. {
  241. std::vector<int> rem;
  242. for(int b=0; b<BFIELD_SIZE; ++b)
  243. {
  244. if( ac[b] && !(s->attackerOwned ? ac[b-1] : ac[b+1]))
  245. {
  246. rem.push_back(b);
  247. }
  248. }
  249. for(int g=0; g<rem.size(); ++g)
  250. {
  251. ac[rem[g]] = false;
  252. }
  253. //removing accessibility for side hexes
  254. for(int v=0; v<BFIELD_SIZE; ++v)
  255. if(s->attackerOwned ? (v%BFIELD_WIDTH)==1 : (v%BFIELD_WIDTH)==(BFIELD_WIDTH - 2))
  256. ac[v] = false;
  257. }
  258. else
  259. {
  260. std::vector<int> rem;
  261. for(int b=0; b<BFIELD_SIZE; ++b)
  262. {
  263. if( ac[b] && (!ac[b-1] || dist[b-1] > s->speed() ) && ( !ac[b+1] || dist[b+1] > s->speed() ) && b%BFIELD_WIDTH != 0 && b%BFIELD_WIDTH != (BFIELD_WIDTH-1))
  264. {
  265. rem.push_back(b);
  266. }
  267. }
  268. for(int g=0; g<rem.size(); ++g)
  269. {
  270. ac[rem[g]] = false;
  271. }
  272. }
  273. }
  274. for(int i=0;i<BFIELD_SIZE;i++)
  275. if(dist[i] <= s->speed() && ac[i])
  276. {
  277. ret.push_back(i);
  278. }
  279. return ret;
  280. }
  281. bool BattleInfo::isStackBlocked(int ID)
  282. {
  283. CStack *our = getStack(ID);
  284. for(int i=0; i<stacks.size();i++)
  285. {
  286. if( !stacks[i]->alive()
  287. || stacks[i]->owner==our->owner
  288. )
  289. continue; //we omit dead and allied stacks
  290. if(stacks[i]->creature->isDoubleWide())
  291. {
  292. if( mutualPosition(stacks[i]->position, our->position) >= 0
  293. || mutualPosition(stacks[i]->position + (stacks[i]->attackerOwned ? -1 : 1), our->position) >= 0)
  294. return true;
  295. }
  296. else
  297. {
  298. if( mutualPosition(stacks[i]->position, our->position) >= 0 )
  299. return true;
  300. }
  301. }
  302. return false;
  303. }
  304. signed char BattleInfo::mutualPosition(int hex1, int hex2)
  305. {
  306. if(hex2 == hex1 - ( (hex1/17)%2 ? 18 : 17 )) //top left
  307. return 0;
  308. if(hex2 == hex1 - ( (hex1/17)%2 ? 17 : 16 )) //top right
  309. return 1;
  310. if(hex2 == hex1 - 1 && hex1%17 != 0) //left
  311. return 5;
  312. if(hex2 == hex1 + 1 && hex1%17 != 16) //right
  313. return 2;
  314. if(hex2 == hex1 + ( (hex1/17)%2 ? 16 : 17 )) //bottom left
  315. return 4;
  316. if(hex2 == hex1 + ( (hex1/17)%2 ? 17 : 18 )) //bottom right
  317. return 3;
  318. return -1;
  319. }
  320. std::vector<int> BattleInfo::neighbouringTiles(int hex)
  321. {
  322. #define CHECK_AND_PUSH(tile) {int hlp = (tile); if(hlp>=0 && hlp<BFIELD_SIZE && (hlp%BFIELD_WIDTH!=16) && hlp%BFIELD_WIDTH) ret.push_back(hlp);}
  323. std::vector<int> ret;
  324. CHECK_AND_PUSH(hex - ( (hex/17)%2 ? 18 : 17 ));
  325. CHECK_AND_PUSH(hex - ( (hex/17)%2 ? 17 : 16 ));
  326. CHECK_AND_PUSH(hex - 1);
  327. CHECK_AND_PUSH(hex + 1);
  328. CHECK_AND_PUSH(hex + ( (hex/17)%2 ? 16 : 17 ));
  329. CHECK_AND_PUSH(hex + ( (hex/17)%2 ? 17 : 18 ));
  330. #undef CHECK_AND_PUSH
  331. return ret;
  332. }
  333. std::vector<int> BattleInfo::getPath(int start, int dest, bool*accessibility)
  334. {
  335. int predecessor[BFIELD_SIZE]; //for getting the Path
  336. int dist[BFIELD_SIZE]; //calculated distances
  337. makeBFS(start,accessibility,predecessor,dist);
  338. //making the Path
  339. std::vector<int> path;
  340. int curElem = dest;
  341. while(curElem != start)
  342. {
  343. path.push_back(curElem);
  344. curElem = predecessor[curElem];
  345. }
  346. return path;
  347. }
  348. CStack::CStack(CCreature * C, int A, int O, int I, bool AO, int S)
  349. :creature(C),amount(A), baseAmount(A), owner(O), position(-1), ID(I), attackerOwned(AO), firstHPleft(C->hitPoints),
  350. shots(C->shots), slot(S), counterAttacks(1), effects(), state()
  351. {
  352. abilities = C->abilities;
  353. state.insert(ALIVE);
  354. }
  355. ui32 CStack::speed() const
  356. {
  357. int premy=0;
  358. const StackEffect *effect = 0;
  359. //haste effect check
  360. effect = getEffect(53);
  361. if(effect)
  362. premy += VLC->spellh->spells[effect->id].powers[effect->level];
  363. //slow effect check
  364. effect = getEffect(54);
  365. if(effect)
  366. premy -= (creature->speed * VLC->spellh->spells[effect->id].powers[effect->level])/100;
  367. //prayer effect check
  368. effect = getEffect(48);
  369. if(effect)
  370. premy += VLC->spellh->spells[effect->id].powers[effect->level];
  371. //bind effect check
  372. effect = getEffect(72);
  373. if(effect)
  374. {
  375. premy = creature->speed; //don't use '- creature->speed' - speed is unsigned!
  376. premy = -premy;
  377. }
  378. return creature->speed + premy;
  379. }
  380. const CStack::StackEffect * CStack::getEffect(ui16 id) const
  381. {
  382. for (int i=0; i< effects.size(); i++)
  383. if(effects[i].id == id)
  384. return &effects[i];
  385. return NULL;
  386. }
  387. si8 CStack::Morale() const
  388. {
  389. si8 ret = morale;
  390. if(getEffect(49)) //mirth
  391. {
  392. ret += VLC->spellh->spells[49].powers[getEffect(49)->level];
  393. }
  394. if(getEffect(50)) //sorrow
  395. {
  396. ret -= VLC->spellh->spells[50].powers[getEffect(50)->level];
  397. }
  398. if(ret > 3) ret = 3;
  399. if(ret < -3) ret = -3;
  400. return ret;
  401. }
  402. si8 CStack::Luck() const
  403. {
  404. si8 ret = luck;
  405. if(getEffect(51)) //fortune
  406. {
  407. ret += VLC->spellh->spells[51].powers[getEffect(51)->level];
  408. }
  409. if(getEffect(52)) //misfortune
  410. {
  411. ret -= VLC->spellh->spells[52].powers[getEffect(52)->level];
  412. }
  413. if(ret > 3) ret = 3;
  414. if(ret < -3) ret = -3;
  415. return ret;
  416. }
  417. CGHeroInstance* CGameState::HeroesPool::pickHeroFor(bool native, int player, const CTown *town, int notThatOne)
  418. {
  419. if(player<0 || player>=PLAYER_LIMIT)
  420. {
  421. tlog1 << "Cannot pick hero for " << town->Name() << ". Wrong owner!\n";
  422. return NULL;
  423. }
  424. std::vector<CGHeroInstance *> pool;
  425. int sum=0, r;
  426. if(native)
  427. {
  428. for(std::map<ui32,CGHeroInstance *>::iterator i=heroesPool.begin(); i!=heroesPool.end(); i++)
  429. {
  430. if(pavailable[i->first] & 1<<player
  431. && i->second->type->heroType/2 == town->typeID
  432. && i->second->subID != notThatOne
  433. )
  434. {
  435. pool.push_back(i->second);
  436. }
  437. }
  438. if(!pool.size())
  439. return pickHeroFor(false,player,town,notThatOne);
  440. else
  441. return pool[rand()%pool.size()];
  442. }
  443. else
  444. {
  445. for(std::map<ui32,CGHeroInstance *>::iterator i=heroesPool.begin(); i!=heroesPool.end(); i++)
  446. {
  447. if(pavailable[i->first] & 1<<player
  448. && i->second->subID != notThatOne
  449. )
  450. {
  451. pool.push_back(i->second);
  452. sum += i->second->type->heroClass->selectionProbability[town->typeID];
  453. }
  454. }
  455. if(!pool.size())
  456. {
  457. tlog1 << "There are no heroes available for player " << player<<"!\n";
  458. return NULL;
  459. }
  460. r = rand()%sum;
  461. for(int i=0; i<pool.size(); i++)
  462. {
  463. r -= pool[i]->type->heroClass->selectionProbability[town->typeID];
  464. if(r<0)
  465. return pool[i];
  466. }
  467. return pool[pool.size()-1];
  468. }
  469. }
  470. //void CGameState::apply(CPack * pack)
  471. //{
  472. // while(!mx->try_lock())
  473. // boost::this_thread::sleep(boost::posix_time::milliseconds(50)); //give other threads time to finish
  474. // //applyNL(pack);
  475. // mx->unlock();
  476. //}
  477. int CGameState::pickHero(int owner)
  478. {
  479. int h=-1;
  480. if(!map->getHero(h = scenarioOps->getIthPlayersSettings(owner).hero,0) && h>=0) //we haven't used selected hero
  481. return h;
  482. int f = scenarioOps->getIthPlayersSettings(owner).castle;
  483. int i=0;
  484. do //try to find free hero of our faction
  485. {
  486. i++;
  487. h = scenarioOps->getIthPlayersSettings(owner).castle*HEROES_PER_TYPE*2+(ran()%(HEROES_PER_TYPE*2));//->scenarioOps->playerInfos[pru].hero = VLC->
  488. } while( map->getHero(h) && i<175);
  489. if(i>174) //probably no free heroes - there's no point in further search, we'll take first free
  490. {
  491. tlog3 << "Warning: cannot find free hero - trying to get first available..."<<std::endl;
  492. for(int j=0; j<HEROES_PER_TYPE * 2 * F_NUMBER; j++)
  493. if(!map->getHero(j))
  494. h=j;
  495. }
  496. return h;
  497. }
  498. CGHeroInstance *CGameState::getHero(int objid)
  499. {
  500. if(objid<0 || objid>=map->objects.size() || map->objects[objid]->ID!=34)
  501. return NULL;
  502. return static_cast<CGHeroInstance *>(map->objects[objid]);
  503. }
  504. CGTownInstance *CGameState::getTown(int objid)
  505. {
  506. if(objid<0 || objid>=map->objects.size())
  507. return NULL;
  508. return static_cast<CGTownInstance *>(map->objects[objid]);
  509. }
  510. std::pair<int,int> CGameState::pickObject(CGObjectInstance *obj)
  511. {
  512. switch(obj->ID)
  513. {
  514. case 65: //random artifact
  515. return std::pair<int,int>(5,(ran()%136)+7); //tylko sensowny zakres - na poczatku sa katapulty itp, na koncu specjalne i blanki
  516. case 66: //random treasure artifact
  517. return std::pair<int,int>(5,VLC->arth->treasures[ran()%VLC->arth->treasures.size()]->id);
  518. case 67: //random minor artifact
  519. return std::pair<int,int>(5,VLC->arth->minors[ran()%VLC->arth->minors.size()]->id);
  520. case 68: //random major artifact
  521. return std::pair<int,int>(5,VLC->arth->majors[ran()%VLC->arth->majors.size()]->id);
  522. case 69: //random relic artifact
  523. return std::pair<int,int>(5,VLC->arth->relics[ran()%VLC->arth->relics.size()]->id);
  524. case 70: //random hero
  525. {
  526. return std::pair<int,int>(HEROI_TYPE,pickHero(obj->tempOwner));
  527. }
  528. case 71: //random monster
  529. {
  530. int r;
  531. do
  532. {
  533. r = ran()%197;
  534. } while (vstd::contains(VLC->creh->notUsedMonsters,r));
  535. return std::pair<int,int>(54,r);
  536. }
  537. case 72: //random monster lvl1
  538. return std::pair<int,int>(54,VLC->creh->levelCreatures[1][ran()%VLC->creh->levelCreatures[1].size()]->idNumber);
  539. case 73: //random monster lvl2
  540. return std::pair<int,int>(54,VLC->creh->levelCreatures[2][ran()%VLC->creh->levelCreatures[2].size()]->idNumber);
  541. case 74: //random monster lvl3
  542. return std::pair<int,int>(54,VLC->creh->levelCreatures[3][ran()%VLC->creh->levelCreatures[3].size()]->idNumber);
  543. case 75: //random monster lvl4
  544. return std::pair<int,int>(54,VLC->creh->levelCreatures[4][ran()%VLC->creh->levelCreatures[4].size()]->idNumber);
  545. case 76: //random resource
  546. return std::pair<int,int>(79,ran()%7); //now it's OH3 style, use %8 for mithril
  547. case 77: //random town
  548. {
  549. int align = ((CGTownInstance*)obj)->alignment,
  550. f;
  551. if(align>PLAYER_LIMIT-1)//same as owner / random
  552. {
  553. if(obj->tempOwner > PLAYER_LIMIT-1)
  554. f = -1; //random
  555. else
  556. f = scenarioOps->getIthPlayersSettings(obj->tempOwner).castle;
  557. }
  558. else
  559. {
  560. f = scenarioOps->getIthPlayersSettings(align).castle;
  561. }
  562. if(f<0) f = ran()%VLC->townh->towns.size();
  563. return std::pair<int,int>(TOWNI_TYPE,f);
  564. }
  565. case 162: //random monster lvl5
  566. return std::pair<int,int>(54,VLC->creh->levelCreatures[5][ran()%VLC->creh->levelCreatures[5].size()]->idNumber);
  567. case 163: //random monster lvl6
  568. return std::pair<int,int>(54,VLC->creh->levelCreatures[6][ran()%VLC->creh->levelCreatures[6].size()]->idNumber);
  569. case 164: //random monster lvl7
  570. return std::pair<int,int>(54,VLC->creh->levelCreatures[7][ran()%VLC->creh->levelCreatures[7].size()]->idNumber);
  571. case 216: //random dwelling
  572. {
  573. int faction = ran()%F_NUMBER;
  574. CCreGen2ObjInfo* info =(CCreGen2ObjInfo*)obj->info;
  575. if (info->asCastle)
  576. {
  577. for(int i=0;i<map->objects.size();i++)
  578. {
  579. if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  580. {
  581. randomizeObject(map->objects[i]); //we have to randomize the castle first
  582. faction = map->objects[i]->subID;
  583. break;
  584. }
  585. else if(map->objects[i]->ID==TOWNI_TYPE && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  586. {
  587. faction = map->objects[i]->subID;
  588. break;
  589. }
  590. }
  591. }
  592. else
  593. {
  594. while((!(info->castles[0]&(1<<faction))))
  595. {
  596. if((faction>7) && (info->castles[1]&(1<<(faction-8))))
  597. break;
  598. faction = ran()%F_NUMBER;
  599. }
  600. }
  601. int level = ((info->maxLevel-info->minLevel) ? (ran()%(info->maxLevel-info->minLevel)+info->minLevel) : (info->minLevel));
  602. int cid = VLC->townh->towns[faction].basicCreatures[level];
  603. for(int i=0;i<VLC->objh->cregens.size();i++)
  604. if(VLC->objh->cregens[i]==cid)
  605. return std::pair<int,int>(17,i);
  606. tlog3 << "Cannot find a dwelling for creature "<<cid <<std::endl;
  607. return std::pair<int,int>(17,0);
  608. }
  609. case 217:
  610. {
  611. int faction = ran()%F_NUMBER;
  612. CCreGenObjInfo* info =(CCreGenObjInfo*)obj->info;
  613. if (info->asCastle)
  614. {
  615. for(int i=0;i<map->objects.size();i++)
  616. {
  617. if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  618. {
  619. randomizeObject(map->objects[i]); //we have to randomize the castle first
  620. faction = map->objects[i]->subID;
  621. break;
  622. }
  623. else if(map->objects[i]->ID==TOWNI_TYPE && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  624. {
  625. faction = map->objects[i]->subID;
  626. break;
  627. }
  628. }
  629. }
  630. else
  631. {
  632. while((!(info->castles[0]&(1<<faction))))
  633. {
  634. if((faction>7) && (info->castles[1]&(1<<(faction-8))))
  635. break;
  636. faction = ran()%F_NUMBER;
  637. }
  638. }
  639. int cid = VLC->townh->towns[faction].basicCreatures[obj->subID];
  640. for(int i=0;i<VLC->objh->cregens.size();i++)
  641. if(VLC->objh->cregens[i]==cid)
  642. return std::pair<int,int>(17,i);
  643. tlog3 << "Cannot find a dwelling for creature "<<cid <<std::endl;
  644. return std::pair<int,int>(17,0);
  645. }
  646. case 218:
  647. {
  648. CCreGen3ObjInfo* info =(CCreGen3ObjInfo*)obj->info;
  649. int level = ((info->maxLevel-info->minLevel) ? (ran()%(info->maxLevel-info->minLevel)+info->minLevel) : (info->minLevel));
  650. int cid = VLC->townh->towns[obj->subID].basicCreatures[level];
  651. for(int i=0;i<VLC->objh->cregens.size();i++)
  652. if(VLC->objh->cregens[i]==cid)
  653. return std::pair<int,int>(17,i);
  654. tlog3 << "Cannot find a dwelling for creature "<<cid <<std::endl;
  655. return std::pair<int,int>(17,0);
  656. }
  657. }
  658. return std::pair<int,int>(-1,-1);
  659. }
  660. void CGameState::randomizeObject(CGObjectInstance *cur)
  661. {
  662. std::pair<int,int> ran = pickObject(cur);
  663. if(ran.first<0 || ran.second<0) //this is not a random object, or we couldn't find anything
  664. {
  665. if(cur->ID==TOWNI_TYPE) //town - set def
  666. {
  667. CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
  668. if(t->hasCapitol())
  669. t->defInfo = capitols[t->subID];
  670. else if(t->hasFort())
  671. t->defInfo = forts[t->subID];
  672. else
  673. t->defInfo = villages[t->subID];
  674. }
  675. return;
  676. }
  677. else if(ran.first==HEROI_TYPE)//special code for hero
  678. {
  679. CGHeroInstance *h = dynamic_cast<CGHeroInstance *>(cur);
  680. if(!h) {tlog2<<"Wrong random hero at "<<cur->pos<<std::endl; return;}
  681. cur->ID = ran.first;
  682. h->portrait = cur->subID = ran.second;
  683. h->type = VLC->heroh->heroes[ran.second];
  684. map->heroes.push_back(h);
  685. return; //TODO: maybe we should do something with definfo?
  686. }
  687. else if(ran.first==TOWNI_TYPE)//special code for town
  688. {
  689. CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
  690. if(!t) {tlog2<<"Wrong random town at "<<cur->pos<<std::endl; return;}
  691. cur->ID = ran.first;
  692. cur->subID = ran.second;
  693. t->town = &VLC->townh->towns[ran.second];
  694. if(t->hasCapitol())
  695. t->defInfo = capitols[t->subID];
  696. else if(t->hasFort())
  697. t->defInfo = forts[t->subID];
  698. else
  699. t->defInfo = villages[t->subID];
  700. map->towns.push_back(t);
  701. return;
  702. }
  703. //we have to replace normal random object
  704. cur->ID = ran.first;
  705. cur->subID = ran.second;
  706. map->removeBlockVisTiles(cur); //recalculate blockvis tiles - picked object might have different than random placeholder
  707. map->defy.push_back(cur->defInfo = VLC->dobjinfo->gobjs[ran.first][ran.second]);
  708. if(!cur->defInfo)
  709. {
  710. tlog1<<"*BIG* WARNING: Missing def declaration for "<<cur->ID<<" "<<cur->subID<<std::endl;
  711. return;
  712. }
  713. map->addBlockVisTiles(cur);
  714. }
  715. int CGameState::getDate(int mode) const
  716. {
  717. int temp;
  718. switch (mode)
  719. {
  720. case 0:
  721. return day;
  722. break;
  723. case 1:
  724. temp = (day)%7;
  725. if (temp)
  726. return temp;
  727. else return 7;
  728. break;
  729. case 2:
  730. temp = ((day-1)/7)+1;
  731. if (!(temp%4))
  732. return 4;
  733. else
  734. return (temp%4);
  735. break;
  736. case 3:
  737. return ((day-1)/28)+1;
  738. break;
  739. }
  740. return 0;
  741. }
  742. CGameState::CGameState()
  743. {
  744. mx = new boost::shared_mutex();
  745. map = NULL;
  746. curB = NULL;
  747. scenarioOps = NULL;
  748. }
  749. CGameState::~CGameState()
  750. {
  751. delete mx;
  752. delete map;
  753. delete curB;
  754. delete scenarioOps;
  755. }
  756. void CGameState::init(StartInfo * si, Mapa * map, int Seed)
  757. {
  758. day = 0;
  759. seed = Seed;
  760. ran.seed((boost::int32_t)seed);
  761. scenarioOps = si;
  762. this->map = map;
  763. loadTownDInfos();
  764. //picking random factions for players
  765. for(int i=0;i<scenarioOps->playerInfos.size();i++)
  766. {
  767. if(scenarioOps->playerInfos[i].castle==-1)
  768. {
  769. int f;
  770. do
  771. {
  772. f = ran()%F_NUMBER;
  773. }while(!(map->players[scenarioOps->playerInfos[i].color].allowedFactions & 1<<f));
  774. scenarioOps->playerInfos[i].castle = f;
  775. }
  776. }
  777. //randomizing objects
  778. for(int no=0; no<map->objects.size(); ++no)
  779. {
  780. randomizeObject(map->objects[no]);
  781. if(map->objects[no]->ID==26)
  782. {
  783. map->objects[no]->defInfo->handler=NULL;
  784. map->removeBlockVisTiles(map->objects[no]);
  785. map->objects[no]->defInfo->blockMap[5] = 255;
  786. map->addBlockVisTiles(map->objects[no]);
  787. }
  788. map->objects[no]->hoverName = VLC->generaltexth->names[map->objects[no]->ID];
  789. }
  790. //std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl;
  791. /*********give starting hero****************************************/
  792. for(int i=0;i<PLAYER_LIMIT;i++)
  793. {
  794. if((map->players[i].generateHeroAtMainTown && map->players[i].hasMainTown) || (map->players[i].hasMainTown && map->version==RoE))
  795. {
  796. int3 hpos = map->players[i].posOfMainTown;
  797. hpos.x+=1;// hpos.y+=1;
  798. int j;
  799. for(j=0; j<scenarioOps->playerInfos.size(); j++)
  800. if(scenarioOps->playerInfos[j].color == i)
  801. break;
  802. if(j == scenarioOps->playerInfos.size())
  803. continue;
  804. int h=pickHero(i);
  805. CGHeroInstance * nnn = static_cast<CGHeroInstance*>(createObject(HEROI_TYPE,h,hpos,i));
  806. nnn->id = map->objects.size();
  807. hpos = map->players[i].posOfMainTown;hpos.x+=2;
  808. for(int o=0;o<map->towns.size();o++) //find main town
  809. {
  810. if(map->towns[o]->pos == hpos)
  811. {
  812. map->towns[o]->visitingHero = nnn;
  813. nnn->visitedTown = map->towns[o];
  814. nnn->inTownGarrison = false;
  815. break;
  816. }
  817. }
  818. nnn->initHero();
  819. map->heroes.push_back(nnn);
  820. map->objects.push_back(nnn);
  821. map->addBlockVisTiles(nnn);
  822. }
  823. }
  824. /*********creating players entries in gs****************************************/
  825. for (int i=0; i<scenarioOps->playerInfos.size();i++)
  826. {
  827. std::pair<int,PlayerState> ins(scenarioOps->playerInfos[i].color,PlayerState());
  828. ins.second.color=ins.first;
  829. ins.second.serial=i;
  830. players.insert(ins);
  831. }
  832. /******************RESOURCES****************************************************/
  833. //TODO: computer player should receive other amount of resource than computer (depending on difficulty)
  834. std::vector<int> startres;
  835. std::ifstream tis("config/startres.txt");
  836. int k;
  837. for (int j=0;j<scenarioOps->difficulty;j++)
  838. {
  839. tis >> k;
  840. for (int z=0;z<RESOURCE_QUANTITY;z++)
  841. tis>>k;
  842. }
  843. tis >> k;
  844. for (int i=0;i<RESOURCE_QUANTITY;i++)
  845. {
  846. tis >> k;
  847. startres.push_back(k);
  848. }
  849. tis.close();
  850. tis.clear();
  851. for (std::map<ui8,PlayerState>::iterator i = players.begin(); i!=players.end(); i++)
  852. {
  853. (*i).second.resources.resize(RESOURCE_QUANTITY);
  854. for (int x=0;x<RESOURCE_QUANTITY;x++)
  855. (*i).second.resources[x] = startres[x];
  856. }
  857. tis.open("config/resources.txt");
  858. tis >> k;
  859. int pom;
  860. for(int i=0;i<k;i++)
  861. {
  862. tis >> pom;
  863. resVals.push_back(pom);
  864. }
  865. /*************************HEROES************************************************/
  866. std::set<int> hids;
  867. for(int i=0; i<map->allowedHeroes.size(); i++) //add to hids all allowed heroes
  868. if(map->allowedHeroes[i])
  869. hids.insert(i);
  870. for (int i=0; i<map->heroes.size();i++) //heroes instances initialization
  871. {
  872. if (map->heroes[i]->getOwner()<0)
  873. {
  874. tlog2 << "Warning - hero with uninitialized owner!\n";
  875. continue;
  876. }
  877. CGHeroInstance * vhi = (map->heroes[i]);
  878. vhi->initHero();
  879. players.find(vhi->getOwner())->second.heroes.push_back(vhi);
  880. hids.erase(vhi->subID);
  881. }
  882. for(int i=0; i<map->predefinedHeroes.size(); i++)
  883. {
  884. if(!vstd::contains(hids,map->predefinedHeroes[i]->subID))
  885. continue;
  886. map->predefinedHeroes[i]->initHero();
  887. hpool.heroesPool[map->predefinedHeroes[i]->subID] = map->predefinedHeroes[i];
  888. hpool.pavailable[map->predefinedHeroes[i]->subID] = 0xff;
  889. hids.erase(map->predefinedHeroes[i]->subID);
  890. }
  891. BOOST_FOREACH(int hid, hids) //all not used allowed heroes go into the pool
  892. {
  893. CGHeroInstance * vhi = new CGHeroInstance();
  894. vhi->initHero(hid);
  895. hpool.heroesPool[hid] = vhi;
  896. hpool.pavailable[hid] = 0xff;
  897. }
  898. for(int i=0; i<map->disposedHeroes.size(); i++)
  899. {
  900. hpool.pavailable[map->disposedHeroes[i].ID] = map->disposedHeroes[i].players;
  901. }
  902. /*************************FOG**OF**WAR******************************************/
  903. for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
  904. {
  905. k->second.fogOfWarMap.resize(map->width);
  906. for(int g=0; g<map->width; ++g)
  907. k->second.fogOfWarMap[g].resize(map->height);
  908. for(int g=-0; g<map->width; ++g)
  909. for(int h=0; h<map->height; ++h)
  910. k->second.fogOfWarMap[g][h].resize(map->twoLevel+1, 0);
  911. for(int g=0; g<map->width; ++g)
  912. for(int h=0; h<map->height; ++h)
  913. for(int v=0; v<map->twoLevel+1; ++v)
  914. k->second.fogOfWarMap[g][h][v] = 0;
  915. for(int xd=0; xd<map->width; ++xd) //revealing part of map around heroes
  916. {
  917. for(int yd=0; yd<map->height; ++yd)
  918. {
  919. for(int ch=0; ch<k->second.heroes.size(); ++ch)
  920. {
  921. int deltaX = (k->second.heroes[ch]->getPosition(false).x-xd)*(k->second.heroes[ch]->getPosition(false).x-xd);
  922. int deltaY = (k->second.heroes[ch]->getPosition(false).y-yd)*(k->second.heroes[ch]->getPosition(false).y-yd);
  923. if(deltaX+deltaY<k->second.heroes[ch]->getSightDistance()*k->second.heroes[ch]->getSightDistance())
  924. k->second.fogOfWarMap[xd][yd][k->second.heroes[ch]->getPosition(false).z] = 1;
  925. }
  926. }
  927. }
  928. //starting bonus
  929. if(si->playerInfos[k->second.serial].bonus==brandom)
  930. si->playerInfos[k->second.serial].bonus = ran()%3;
  931. switch(si->playerInfos[k->second.serial].bonus)
  932. {
  933. case bgold:
  934. k->second.resources[6] += 500 + (ran()%6)*100;
  935. break;
  936. case bresource:
  937. {
  938. int res = VLC->townh->towns[si->playerInfos[k->second.serial].castle].primaryRes;
  939. if(res == 127)
  940. {
  941. k->second.resources[0] += 5 + ran()%6;
  942. k->second.resources[2] += 5 + ran()%6;
  943. }
  944. else
  945. {
  946. k->second.resources[res] += 3 + ran()%4;
  947. }
  948. break;
  949. }
  950. case bartifact:
  951. {
  952. if(!k->second.heroes.size())
  953. {
  954. tlog5 << "Cannot give starting artifact - no heroes!" << std::endl;
  955. break;
  956. }
  957. CArtifact *toGive;
  958. do
  959. {
  960. toGive = VLC->arth->treasures[ran() % VLC->arth->treasures.size()];
  961. } while (!map->allowedArtifact[toGive->id]);
  962. CGHeroInstance *hero = k->second.heroes[0];
  963. std::vector<ui16>::iterator slot = vstd::findFirstNot(hero->artifWorn,toGive->possibleSlots);
  964. if(slot!=toGive->possibleSlots.end())
  965. hero->artifWorn[*slot] = toGive->id;
  966. else
  967. hero->artifacts.push_back(toGive->id);
  968. }
  969. }
  970. }
  971. /****************************TOWNS************************************************/
  972. for (int i=0;i<map->towns.size();i++)
  973. {
  974. CGTownInstance * vti =(map->towns[i]);
  975. if(!vti->town)
  976. vti->town = &VLC->townh->towns[vti->subID];
  977. if (vti->name.length()==0) // if town hasn't name we draw it
  978. vti->name = vti->town->Names()[ran()%vti->town->Names().size()];
  979. //init buildings
  980. if(vti->builtBuildings.find(-50)!=vti->builtBuildings.end()) //give standard set of buildings
  981. {
  982. vti->builtBuildings.erase(-50);
  983. vti->builtBuildings.insert(10);
  984. vti->builtBuildings.insert(5);
  985. vti->builtBuildings.insert(30);
  986. if(ran()%2)
  987. vti->builtBuildings.insert(31);
  988. }
  989. //init spells
  990. vti->spells.resize(SPELL_LEVELS);
  991. CSpell *s;
  992. for(int z=0; z<vti->obligatorySpells.size();z++)
  993. {
  994. s = &VLC->spellh->spells[vti->obligatorySpells[z]];
  995. vti->spells[s->level-1].push_back(s->id);
  996. vti->possibleSpells -= s->id;
  997. }
  998. while(vti->possibleSpells.size())
  999. {
  1000. ui32 total=0, sel=-1;
  1001. for(int ps=0;ps<vti->possibleSpells.size();ps++)
  1002. total += VLC->spellh->spells[vti->possibleSpells[ps]].probabilities[vti->subID];
  1003. int r = (total)? ran()%total : -1;
  1004. for(int ps=0; ps<vti->possibleSpells.size();ps++)
  1005. {
  1006. r -= VLC->spellh->spells[vti->possibleSpells[ps]].probabilities[vti->subID];
  1007. if(r<0)
  1008. {
  1009. sel = ps;
  1010. break;
  1011. }
  1012. }
  1013. if(sel<0)
  1014. sel=0;
  1015. CSpell *s = &VLC->spellh->spells[vti->possibleSpells[sel]];
  1016. vti->spells[s->level-1].push_back(s->id);
  1017. vti->possibleSpells -= s->id;
  1018. }
  1019. //init garrisons
  1020. for (std::map<si32,std::pair<ui32,si32> >::iterator j=vti->army.slots.begin(); j!=vti->army.slots.end();j++)
  1021. {
  1022. if(j->second.first > 196 && j->second.first < 211)
  1023. {
  1024. if(j->second.first%2)
  1025. j->second.first = vti->town->basicCreatures[ (j->second.first-197) / 2 ];
  1026. else
  1027. j->second.first = vti->town->upgradedCreatures[ (j->second.first-197) / 2 ];
  1028. }
  1029. }
  1030. players[vti->getOwner()].towns.push_back(vti);
  1031. }
  1032. for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
  1033. {
  1034. if(k->first==-1 || k->first==255)
  1035. continue;
  1036. for(int xd=0; xd<map->width; ++xd) //revealing part of map around towns
  1037. {
  1038. for(int yd=0; yd<map->height; ++yd)
  1039. {
  1040. for(int ch=0; ch<k->second.towns.size(); ++ch)
  1041. {
  1042. int deltaX = (k->second.towns[ch]->pos.x-xd)*(k->second.towns[ch]->pos.x-xd);
  1043. int deltaY = (k->second.towns[ch]->pos.y-yd)*(k->second.towns[ch]->pos.y-yd);
  1044. if(deltaX+deltaY<k->second.towns[ch]->getSightDistance()*k->second.towns[ch]->getSightDistance())
  1045. k->second.fogOfWarMap[xd][yd][k->second.towns[ch]->pos.z] = 1;
  1046. }
  1047. }
  1048. }
  1049. //init visiting and garrisoned heroes
  1050. for(int l=0; l<k->second.heroes.size();l++)
  1051. {
  1052. for(int m=0; m<k->second.towns.size();m++)
  1053. {
  1054. int3 vistile = k->second.towns[m]->pos; vistile.x--; //tile next to the entrance
  1055. if(vistile == k->second.heroes[l]->pos || k->second.heroes[l]->pos==k->second.towns[m]->pos)
  1056. {
  1057. k->second.towns[m]->visitingHero = k->second.heroes[l];
  1058. k->second.heroes[l]->visitedTown = k->second.towns[m];
  1059. k->second.heroes[l]->inTownGarrison = false;
  1060. if(k->second.heroes[l]->pos==k->second.towns[m]->pos)
  1061. k->second.heroes[l]->pos.x -= 1;
  1062. break;
  1063. }
  1064. }
  1065. }
  1066. }
  1067. for(int i=0; i<map->defy.size(); i++)
  1068. {
  1069. map->defy[i]->serial = i;
  1070. }
  1071. for(int i=0; i<map->objects.size(); i++)
  1072. {
  1073. map->objects[i]->initObj();
  1074. if(map->objects[i]->ID == 62) //prison also needs to initialize hero
  1075. static_cast<CGHeroInstance*>(map->objects[i])->initHero();
  1076. }
  1077. }
  1078. bool CGameState::battleShootCreatureStack(int ID, int dest)
  1079. {
  1080. return true;
  1081. }
  1082. int CGameState::battleGetStack(int pos)
  1083. {
  1084. if(!curB)
  1085. return -1;
  1086. for(int g=0; g<curB->stacks.size(); ++g)
  1087. {
  1088. if((curB->stacks[g]->position == pos
  1089. || (curB->stacks[g]->creature->isDoubleWide()
  1090. &&( (curB->stacks[g]->attackerOwned && curB->stacks[g]->position-1 == pos)
  1091. || (!curB->stacks[g]->attackerOwned && curB->stacks[g]->position+1 == pos) )
  1092. ))
  1093. && curB->stacks[g]->alive()
  1094. )
  1095. return curB->stacks[g]->ID;
  1096. }
  1097. return -1;
  1098. }
  1099. int CGameState::battleGetBattlefieldType(int3 tile)
  1100. {
  1101. if(tile==int3() && curB)
  1102. tile = curB->tile;
  1103. else if(tile==int3() && !curB)
  1104. return -1;
  1105. //std::vector < std::pair<const CGObjectInstance*,SDL_Rect> > & objs = CGI->mh->ttiles[tile.x][tile.y][tile.z].objects;
  1106. //for(int g=0; g<objs.size(); ++g)
  1107. //{
  1108. // switch(objs[g].first->ID)
  1109. // {
  1110. // case 222: //clover field
  1111. // return 19;
  1112. // case 223: //cursed ground
  1113. // return 22;
  1114. // case 224: //evil fog
  1115. // return 20;
  1116. // case 225: //favourable winds
  1117. // return 21;
  1118. // case 226: //fiery fields
  1119. // return 14;
  1120. // case 227: //holy ground
  1121. // return 18;
  1122. // case 228: //lucid pools
  1123. // return 17;
  1124. // case 229: //magic clouds
  1125. // return 16;
  1126. // case 230: //magic plains
  1127. // return 9;
  1128. // case 231: //rocklands
  1129. // return 15;
  1130. // }
  1131. //}
  1132. switch(map->terrain[tile.x][tile.y][tile.z].tertype)
  1133. {
  1134. case dirt:
  1135. return rand()%3+3;
  1136. case sand:
  1137. return 2; //TODO: coast support
  1138. case grass:
  1139. return rand()%2+6;
  1140. case snow:
  1141. return rand()%2+10;
  1142. case swamp:
  1143. return 13;
  1144. case rough:
  1145. return 23;
  1146. case subterranean:
  1147. return 12;
  1148. case lava:
  1149. return 8;
  1150. case water:
  1151. return 25;
  1152. case rock:
  1153. return 15;
  1154. default:
  1155. return -1;
  1156. }
  1157. }
  1158. UpgradeInfo CGameState::getUpgradeInfo(CArmedInstance *obj, int stackPos)
  1159. {
  1160. UpgradeInfo ret;
  1161. CCreature *base = &VLC->creh->creatures[obj->army.slots[stackPos].first];
  1162. if((obj->ID == TOWNI_TYPE) || ((obj->ID == HEROI_TYPE) && static_cast<const CGHeroInstance*>(obj)->visitedTown))
  1163. {
  1164. CGTownInstance * t;
  1165. if(obj->ID == TOWNI_TYPE)
  1166. t = static_cast<CGTownInstance *>(const_cast<CArmedInstance *>(obj));
  1167. else
  1168. t = static_cast<const CGHeroInstance*>(obj)->visitedTown;
  1169. for(std::set<si32>::iterator i=t->builtBuildings.begin(); i!=t->builtBuildings.end(); i++)
  1170. {
  1171. if( (*i) >= 37 && (*i) < 44 ) //upgraded creature dwelling
  1172. {
  1173. int nid = t->town->upgradedCreatures[(*i)-37]; //upgrade offered by that building
  1174. if(base->upgrades.find(nid) != base->upgrades.end()) //possible upgrade
  1175. {
  1176. ret.newID.push_back(nid);
  1177. ret.cost.push_back(std::set<std::pair<int,int> >());
  1178. for(int j=0;j<RESOURCE_QUANTITY;j++)
  1179. {
  1180. int dif = VLC->creh->creatures[nid].cost[j] - base->cost[j];
  1181. if(dif)
  1182. ret.cost[ret.cost.size()-1].insert(std::make_pair(j,dif));
  1183. }
  1184. }
  1185. }
  1186. }//end for
  1187. }
  1188. //TODO: check if hero ability makes some upgrades possible
  1189. if(ret.newID.size())
  1190. ret.oldID = base->idNumber;
  1191. return ret;
  1192. }
  1193. float CGameState::getMarketEfficiency( int player, int mode/*=0*/ )
  1194. {
  1195. boost::shared_lock<boost::shared_mutex> lock(*mx);
  1196. if(mode) return -1; //todo - support other modes
  1197. int mcount = 0;
  1198. for(int i=0;i<players[player].towns.size();i++)
  1199. if(vstd::contains(players[player].towns[i]->builtBuildings,14))
  1200. mcount++;
  1201. float ret = std::min(((float)mcount+1.0f)/20.0f,0.5f);
  1202. return ret;
  1203. }
  1204. std::set<int3> CGameState::tilesToReveal(int3 pos, int radious, int player) const
  1205. {
  1206. std::set<int3> ret;
  1207. int xbeg = pos.x - radious - 2;
  1208. if(xbeg < 0)
  1209. xbeg = 0;
  1210. int xend = pos.x + radious + 2;
  1211. if(xend >= map->width)
  1212. xend = map->width;
  1213. int ybeg = pos.y - radious - 2;
  1214. if(ybeg < 0)
  1215. ybeg = 0;
  1216. int yend = pos.y + radious + 2;
  1217. if(yend >= map->height)
  1218. yend = map->height;
  1219. for(int xd=xbeg; xd<xend; ++xd) //revealing part of map around heroes
  1220. {
  1221. for(int yd=ybeg; yd<yend; ++yd)
  1222. {
  1223. int deltaX = (pos.x-xd)*(pos.x-xd);
  1224. int deltaY = (pos.y-yd)*(pos.y-yd);
  1225. if(deltaX+deltaY<radious*radious)
  1226. {
  1227. if(player<0 || players.find(player)->second.fogOfWarMap[xd][yd][pos.z]==0)
  1228. {
  1229. ret.insert(int3(xd,yd,pos.z));
  1230. }
  1231. }
  1232. }
  1233. }
  1234. return ret;
  1235. }
  1236. void CGameState::loadTownDInfos()
  1237. {
  1238. for(int i=0;i<F_NUMBER;i++)
  1239. {
  1240. villages[i] = new CGDefInfo(*VLC->dobjinfo->castles[i]);
  1241. forts[i] = VLC->dobjinfo->castles[i];
  1242. capitols[i] = new CGDefInfo(*VLC->dobjinfo->castles[i]);
  1243. }
  1244. }
  1245. void CGameState::getNeighbours(int3 tile, std::vector<int3> &vec, bool onLand)
  1246. {
  1247. vec.clear();
  1248. int3 hlp;
  1249. bool weAreOnLand = (map->getTile(tile).tertype != 8);
  1250. if(tile.x > 0)
  1251. {
  1252. hlp = int3(tile.x-1,tile.y,tile.z);
  1253. if((weAreOnLand == (map->getTile(hlp).tertype!=8)) && map->getTile(hlp).tertype!=9)
  1254. vec.push_back(hlp);
  1255. }
  1256. if(tile.y > 0)
  1257. {
  1258. hlp = int3(tile.x,tile.y-1,tile.z);
  1259. if((weAreOnLand == (map->getTile(hlp).tertype!=8)) && map->getTile(hlp).tertype!=9)
  1260. vec.push_back(hlp);
  1261. }
  1262. if(tile.x > 0 && tile.y > 0)
  1263. {
  1264. hlp = int3(tile.x-1,tile.y-1,tile.z);
  1265. if((weAreOnLand == (map->getTile(hlp).tertype!=8)) && map->getTile(hlp).tertype!=9)
  1266. vec.push_back(hlp);
  1267. }
  1268. if(tile.x > 0 && tile.y < map->height-1)
  1269. {
  1270. hlp = int3(tile.x-1,tile.y+1,tile.z);
  1271. if((weAreOnLand == (map->getTile(hlp).tertype!=8)) && map->getTile(hlp).tertype!=9)
  1272. vec.push_back(hlp);
  1273. }
  1274. if(tile.y < map->height-1)
  1275. {
  1276. hlp = int3(tile.x,tile.y+1,tile.z);
  1277. if((weAreOnLand == (map->getTile(hlp).tertype!=8)) && map->getTile(hlp).tertype!=9)
  1278. vec.push_back(hlp);
  1279. }
  1280. if(tile.x < map->width-1)
  1281. {
  1282. hlp = int3(tile.x+1,tile.y,tile.z);
  1283. if((weAreOnLand == (map->getTile(hlp).tertype!=8)) && map->getTile(hlp).tertype!=9)
  1284. vec.push_back(hlp);
  1285. }
  1286. if(tile.x < map->width-1 && tile.y > 0)
  1287. {
  1288. hlp = int3(tile.x+1,tile.y-1,tile.z);
  1289. if((weAreOnLand == (map->getTile(hlp).tertype!=8)) && map->getTile(hlp).tertype!=9)
  1290. vec.push_back(hlp);
  1291. }
  1292. if(tile.x < map->width-1 && tile.y < map->height-1)
  1293. {
  1294. hlp = int3(tile.x+1,tile.y+1,tile.z);
  1295. if((weAreOnLand == (map->getTile(hlp).tertype!=8)) && map->getTile(hlp).tertype!=9)
  1296. vec.push_back(hlp);
  1297. }
  1298. }
  1299. int CGameState::getMovementCost(const CGHeroInstance *h, int3 src, int3 dest, int remainingMovePoints, bool checkLast)
  1300. {
  1301. TerrainTile &s = map->terrain[src.x][src.y][src.z],
  1302. &d = map->terrain[dest.x][dest.y][dest.z];
  1303. //get basic cost
  1304. int ret = h->getTileCost(d,s);
  1305. if(src.x!=dest.x && src.y!=dest.y) //diagonal move costs too much but normal move is possible
  1306. {
  1307. int old = ret;
  1308. ret *= 1.414;
  1309. if(ret > remainingMovePoints && remainingMovePoints > old)
  1310. {
  1311. return remainingMovePoints;
  1312. }
  1313. }
  1314. int left = remainingMovePoints-ret;
  1315. if(checkLast && left > 0 && remainingMovePoints-ret < 250) //it might be the last tile - if no further move possible we take all move points
  1316. {
  1317. std::vector<int3> vec;
  1318. getNeighbours(dest,vec,true);
  1319. for(size_t i=0; i < vec.size(); i++)
  1320. {
  1321. int fcost = getMovementCost(h,dest,vec[i],left,false);
  1322. if(fcost <= left)
  1323. {
  1324. return ret;
  1325. }
  1326. }
  1327. ret = remainingMovePoints;
  1328. }
  1329. return ret;
  1330. }
  1331. int CGameState::canBuildStructure( const CGTownInstance *t, int ID )
  1332. {
  1333. int ret = 7; //allowed by default
  1334. //can we build it?
  1335. if(t->forbiddenBuildings.find(ID)!=t->forbiddenBuildings.end())
  1336. ret = 2; //forbidden
  1337. else if(t->builded >= MAX_BUILDING_PER_TURN)
  1338. ret = 5; //building limit
  1339. //checking resources
  1340. CBuilding * pom = VLC->buildh->buildings[t->subID][ID];
  1341. for(int res=0;res<7;res++) //TODO: support custom amount of resources
  1342. {
  1343. if(pom->resources[res] > players[t->tempOwner].resources[res])
  1344. ret = 6; //lack of res
  1345. }
  1346. //checking for requirements
  1347. for( std::set<int>::iterator ri = VLC->townh->requirements[t->subID][ID].begin();
  1348. ri != VLC->townh->requirements[t->subID][ID].end();
  1349. ri++ )
  1350. {
  1351. if(t->builtBuildings.find(*ri)==t->builtBuildings.end())
  1352. ret = 8; //lack of requirements - cannot build
  1353. }
  1354. if(ID == 13) //capitol
  1355. {
  1356. for(int in = 0; in < map->towns.size(); in++)
  1357. {
  1358. if(map->towns[in]->tempOwner==t->tempOwner && vstd::contains(map->towns[in]->builtBuildings,13))
  1359. {
  1360. ret = 0; //no more than one capitol
  1361. break;
  1362. }
  1363. }
  1364. }
  1365. else if(ID == 6) //shipyard
  1366. {
  1367. if(map->getTile(t->pos + int3(-1,3,0)).tertype != water && map->getTile(t->pos + int3(-3,3,0)).tertype != water)
  1368. ret = 1; //lack of water
  1369. }
  1370. return ret;
  1371. }
  1372. int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting)
  1373. {
  1374. int attackerAttackBonus = attacker->creature->attack + (attackerHero ? attackerHero->getPrimSkillLevel(0) : 0);
  1375. if(attacker->getEffect(56)) //frenzy for attacker
  1376. {
  1377. attackerAttackBonus += (VLC->spellh->spells[attacker->getEffect(56)->id].powers[attacker->getEffect(56)->level]/100.0) *(attacker->creature->defence + (attackerHero ? attackerHero->getPrimSkillLevel(1) : 0));
  1378. }
  1379. int defenderDefenseBonus = defender->creature->defence + (defendingHero ? defendingHero->getPrimSkillLevel(1) : 0);
  1380. if(defender->getEffect(56)) //frenzy for defender
  1381. {
  1382. defenderDefenseBonus = 0;
  1383. }
  1384. int attackDefenseBonus = attackerAttackBonus - defenderDefenseBonus;
  1385. if(defender->getEffect(48)) //defender's prayer handling
  1386. {
  1387. attackDefenseBonus -= VLC->spellh->spells[defender->getEffect(48)->id].powers[defender->getEffect(48)->level];
  1388. }
  1389. if(attacker->getEffect(48)) //attacker's prayer handling
  1390. {
  1391. attackDefenseBonus += VLC->spellh->spells[attacker->getEffect(48)->id].powers[attacker->getEffect(48)->level];
  1392. }
  1393. if(defender->getEffect(46)) //stone skin handling
  1394. {
  1395. attackDefenseBonus -= VLC->spellh->spells[defender->getEffect(46)->id].powers[defender->getEffect(46)->level];
  1396. }
  1397. if(attacker->getEffect(45)) //weakness handling
  1398. {
  1399. attackDefenseBonus -= VLC->spellh->spells[attacker->getEffect(45)->id].powers[attacker->getEffect(45)->level];
  1400. }
  1401. if(!shooting && attacker->getEffect(43)) //bloodlust handling
  1402. {
  1403. attackDefenseBonus += VLC->spellh->spells[attacker->getEffect(43)->id].powers[attacker->getEffect(43)->level];
  1404. }
  1405. int damageBase = 0;
  1406. if(attacker->getEffect(42)) //curse handling (partial, the rest is below)
  1407. {
  1408. damageBase = attacker->creature->damageMin;
  1409. damageBase -= VLC->spellh->spells[attacker->getEffect(42)->id].powers[attacker->getEffect(42)->level];
  1410. }
  1411. else if(attacker->getEffect(41)) //bless handling
  1412. {
  1413. damageBase = attacker->creature->damageMax;
  1414. damageBase += VLC->spellh->spells[attacker->getEffect(41)->id].powers[attacker->getEffect(41)->level];
  1415. }
  1416. else if(attacker->creature->damageMax == attacker->creature->damageMin) //constant damage
  1417. {
  1418. damageBase = attacker->creature->damageMin;
  1419. }
  1420. else
  1421. {
  1422. damageBase = rand()%(attacker->creature->damageMax - attacker->creature->damageMin) + attacker->creature->damageMin + 1;
  1423. }
  1424. float dmgBonusMultiplier = 1.0f;
  1425. if(attackDefenseBonus < 0) //decreasing dmg
  1426. {
  1427. if(0.02f * (-attackDefenseBonus) > 0.3f)
  1428. {
  1429. dmgBonusMultiplier += -0.3f;
  1430. }
  1431. else
  1432. {
  1433. dmgBonusMultiplier += 0.02f * attackDefenseBonus;
  1434. }
  1435. }
  1436. else //increasing dmg
  1437. {
  1438. if(0.05f * attackDefenseBonus > 4.0f)
  1439. {
  1440. dmgBonusMultiplier += 4.0f;
  1441. }
  1442. else
  1443. {
  1444. dmgBonusMultiplier += 0.05f * attackDefenseBonus;
  1445. }
  1446. }
  1447. //handling secondary abilities
  1448. if(attackerHero)
  1449. {
  1450. if(shooting)
  1451. {
  1452. switch(attackerHero->getSecSkillLevel(1)) //archery
  1453. {
  1454. case 1: //basic
  1455. dmgBonusMultiplier *= 1.1f;
  1456. break;
  1457. case 2: //advanced
  1458. dmgBonusMultiplier *= 1.25f;
  1459. break;
  1460. case 3: //expert
  1461. dmgBonusMultiplier *= 1.5f;
  1462. break;
  1463. }
  1464. }
  1465. else
  1466. {
  1467. switch(attackerHero->getSecSkillLevel(22)) //offence
  1468. {
  1469. case 1: //basic
  1470. dmgBonusMultiplier *= 1.1f;
  1471. break;
  1472. case 2: //advanced
  1473. dmgBonusMultiplier *= 1.2f;
  1474. break;
  1475. case 3: //expert
  1476. dmgBonusMultiplier *= 1.3f;
  1477. break;
  1478. }
  1479. }
  1480. }
  1481. if(defendingHero)
  1482. {
  1483. switch(defendingHero->getSecSkillLevel(23)) //armourer
  1484. {
  1485. case 1: //basic
  1486. dmgBonusMultiplier *= 0.95f;
  1487. break;
  1488. case 2: //advanced
  1489. dmgBonusMultiplier *= 0.9f;
  1490. break;
  1491. case 3: //expert
  1492. dmgBonusMultiplier *= 0.85f;
  1493. break;
  1494. }
  1495. }
  1496. //handling spell effects
  1497. if(!shooting && defender->getEffect(27)) //shield
  1498. {
  1499. if(defender->getEffect(27)->level<=1) //none or basic
  1500. dmgBonusMultiplier *= 0.85f;
  1501. else //adv or expert
  1502. dmgBonusMultiplier *= 0.7f;
  1503. }
  1504. if(shooting && defender->getEffect(28)) //air shield
  1505. {
  1506. if(defender->getEffect(28)->level<=1) //none or basic
  1507. dmgBonusMultiplier *= 0.75f;
  1508. else //adv or expert
  1509. dmgBonusMultiplier *= 0.5f;
  1510. }
  1511. if(attacker->getEffect(42)) //curse, second part of handling
  1512. {
  1513. if(attacker->getEffect(42)->level>=2) //adv or expert
  1514. dmgBonusMultiplier *= 0.8f;
  1515. }
  1516. return (float)damageBase * (float)attacker->amount * dmgBonusMultiplier;
  1517. }
  1518. void BattleInfo::calculateCasualties( std::set<std::pair<ui32,si32> > *casualties )
  1519. {
  1520. for(int i=0; i<stacks.size();i++)//setting casualties
  1521. {
  1522. if(!stacks[i]->alive())
  1523. {
  1524. casualties[!stacks[i]->attackerOwned].insert(std::pair<ui32,si32>(stacks[i]->creature->idNumber,stacks[i]->baseAmount));
  1525. }
  1526. else if(stacks[i]->amount != stacks[i]->baseAmount)
  1527. {
  1528. casualties[!stacks[i]->attackerOwned].insert(std::pair<ui32,si32>(stacks[i]->creature->idNumber,stacks[i]->baseAmount - stacks[i]->amount));
  1529. }
  1530. }
  1531. }
  1532. CStack * BattleInfo::getNextStack()
  1533. {
  1534. CStack *current = getStack(activeStack);
  1535. for (int i = 0; i < stacks.size(); i++) //find fastest not moved/waited stack (stacks vector is sorted by speed)
  1536. {
  1537. if(vstd::contains(stacks[i]->state,DEFENDING)
  1538. ||vstd::contains(stacks[i]->state,WAITING)
  1539. ||vstd::contains(stacks[i]->state,MOVED)
  1540. ||!stacks[i]->alive()
  1541. )
  1542. continue;
  1543. return stacks[i];
  1544. }
  1545. for (int i = stacks.size() - 1; i >= 0 ; i--) //find slowest waiting stack
  1546. {
  1547. if(vstd::contains(stacks[i]->state,DEFENDING)
  1548. ||vstd::contains(stacks[i]->state,MOVED)
  1549. ||!stacks[i]->alive()
  1550. )
  1551. continue;
  1552. return stacks[i];
  1553. }
  1554. return NULL; //all stacks moved or defending!
  1555. }
  1556. std::vector<CStack> BattleInfo::getStackQueue()
  1557. {
  1558. std::vector<CStack> ret;
  1559. std::vector<int> taken; //if non-zero value, corresponding stack has been placed in ret
  1560. taken.resize(stacks.size());
  1561. for(int g=0; g<taken.size(); ++g)
  1562. {
  1563. taken[g] = 0;
  1564. }
  1565. for(int moved=0; moved<2; ++moved) //in first cycle we add stacks that can act in current turn, in second one the rest of them
  1566. {
  1567. for(int gc=0; gc<stacks.size(); ++gc)
  1568. {
  1569. int id = -1, speed = -1;
  1570. for(int i=0; i<stacks.size(); ++i) //find not waited stacks only
  1571. {
  1572. if((moved == 1 ||!vstd::contains(stacks[i]->state,DEFENDING))
  1573. && stacks[i]->alive()
  1574. && (moved == 1 || !vstd::contains(stacks[i]->state,MOVED))
  1575. && !vstd::contains(stacks[i]->state,WAITING)
  1576. && taken[i]==0)
  1577. {
  1578. if(speed == -1 || stacks[i]->speed() > speed)
  1579. {
  1580. id = i;
  1581. speed = stacks[i]->speed();
  1582. }
  1583. }
  1584. }
  1585. if(id != -1)
  1586. {
  1587. ret.push_back(*stacks[id]);
  1588. taken[id] = 1;
  1589. }
  1590. else //choose something from not moved stacks
  1591. {
  1592. int id = -1, speed = 10000; //infinite speed
  1593. for(int i=0; i<stacks.size(); ++i) //find waited stacks only
  1594. {
  1595. if((moved == 1 ||!vstd::contains(stacks[i]->state,DEFENDING))
  1596. && stacks[i]->alive()
  1597. && (moved == 1 || !vstd::contains(stacks[i]->state,MOVED))
  1598. && vstd::contains(stacks[i]->state,WAITING)
  1599. && taken[i]==0)
  1600. {
  1601. if(stacks[i]->speed() < speed) //slowest one
  1602. {
  1603. id = i;
  1604. speed = stacks[i]->speed();
  1605. }
  1606. }
  1607. }
  1608. if(id != -1)
  1609. {
  1610. ret.push_back(*stacks[id]);
  1611. taken[id] = 1;
  1612. }
  1613. else
  1614. {
  1615. break; //no stacks have been found, so none of them will be found in next iterations
  1616. }
  1617. }
  1618. }
  1619. }
  1620. return ret;
  1621. }