CGMarket.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*
  2. *
  3. * CGMarket.cpp, part of VCMI engine
  4. *
  5. * Authors: listed in file AUTHORS in main folder
  6. *
  7. * License: GNU General Public License v2.0 or later
  8. * Full text of license available in license.txt file, in main folder
  9. *
  10. */
  11. #include "StdInc.h"
  12. #include "CGMarket.h"
  13. #include "../NetPacks.h"
  14. #include "../CGeneralTextHandler.h"
  15. using namespace boost::assign;
  16. ///helpers
  17. static void openWindow(const OpenWindow::EWindow type, const int id1, const int id2 = -1)
  18. {
  19. OpenWindow ow;
  20. ow.window = type;
  21. ow.id1 = id1;
  22. ow.id2 = id2;
  23. IObjectInterface::cb->sendAndApply(&ow);
  24. }
  25. bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode::EMarketMode mode) const
  26. {
  27. switch(mode)
  28. {
  29. case EMarketMode::RESOURCE_RESOURCE:
  30. {
  31. double effectiveness = std::min((getMarketEfficiency() + 1.0) / 20.0, 0.5);
  32. double r = VLC->objh->resVals[id1], //value of given resource
  33. g = VLC->objh->resVals[id2] / effectiveness; //value of wanted resource
  34. if(r>g) //if given resource is more expensive than wanted
  35. {
  36. val2 = ceil(r / g);
  37. val1 = 1;
  38. }
  39. else //if wanted resource is more expensive
  40. {
  41. val1 = (g / r) + 0.5;
  42. val2 = 1;
  43. }
  44. }
  45. break;
  46. case EMarketMode::CREATURE_RESOURCE:
  47. {
  48. const double effectivenessArray[] = {0.0, 0.3, 0.45, 0.50, 0.65, 0.7, 0.85, 0.9, 1.0};
  49. double effectiveness = effectivenessArray[std::min(getMarketEfficiency(), 8)];
  50. double r = VLC->creh->creatures[id1]->cost[6], //value of given creature in gold
  51. g = VLC->objh->resVals[id2] / effectiveness; //value of wanted resource
  52. if(r>g) //if given resource is more expensive than wanted
  53. {
  54. val2 = ceil(r / g);
  55. val1 = 1;
  56. }
  57. else //if wanted resource is more expensive
  58. {
  59. val1 = (g / r) + 0.5;
  60. val2 = 1;
  61. }
  62. }
  63. break;
  64. case EMarketMode::RESOURCE_PLAYER:
  65. val1 = 1;
  66. val2 = 1;
  67. break;
  68. case EMarketMode::RESOURCE_ARTIFACT:
  69. {
  70. double effectiveness = std::min((getMarketEfficiency() + 3.0) / 20.0, 0.6);
  71. double r = VLC->objh->resVals[id1], //value of offered resource
  72. g = VLC->arth->artifacts[id2]->price / effectiveness; //value of bought artifact in gold
  73. if(id1 != 6) //non-gold prices are doubled
  74. r /= 2;
  75. val1 = std::max(1, (int)((g / r) + 0.5)); //don't sell arts for less than 1 resource
  76. val2 = 1;
  77. }
  78. break;
  79. case EMarketMode::ARTIFACT_RESOURCE:
  80. {
  81. double effectiveness = std::min((getMarketEfficiency() + 3.0) / 20.0, 0.6);
  82. double r = VLC->arth->artifacts[id1]->price * effectiveness,
  83. g = VLC->objh->resVals[id2];
  84. // if(id2 != 6) //non-gold prices are doubled
  85. // r /= 2;
  86. val1 = 1;
  87. val2 = std::max(1, (int)((r / g) + 0.5)); //at least one resource is given in return
  88. }
  89. break;
  90. case EMarketMode::CREATURE_EXP:
  91. {
  92. val1 = 1;
  93. val2 = (VLC->creh->creatures[id1]->AIValue / 40) * 5;
  94. }
  95. break;
  96. case EMarketMode::ARTIFACT_EXP:
  97. {
  98. val1 = 1;
  99. int givenClass = VLC->arth->artifacts[id1]->getArtClassSerial();
  100. if(givenClass < 0 || givenClass > 3)
  101. {
  102. val2 = 0;
  103. return false;
  104. }
  105. static const int expPerClass[] = {1000, 1500, 3000, 6000};
  106. val2 = expPerClass[givenClass];
  107. }
  108. break;
  109. default:
  110. assert(0);
  111. return false;
  112. }
  113. return true;
  114. }
  115. bool IMarket::allowsTrade(EMarketMode::EMarketMode mode) const
  116. {
  117. return false;
  118. }
  119. int IMarket::availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial) const
  120. {
  121. switch(mode)
  122. {
  123. case EMarketMode::RESOURCE_RESOURCE:
  124. case EMarketMode::ARTIFACT_RESOURCE:
  125. case EMarketMode::CREATURE_RESOURCE:
  126. return -1;
  127. default:
  128. return 1;
  129. }
  130. }
  131. std::vector<int> IMarket::availableItemsIds(EMarketMode::EMarketMode mode) const
  132. {
  133. std::vector<int> ret;
  134. switch(mode)
  135. {
  136. case EMarketMode::RESOURCE_RESOURCE:
  137. case EMarketMode::ARTIFACT_RESOURCE:
  138. case EMarketMode::CREATURE_RESOURCE:
  139. for (int i = 0; i < 7; i++)
  140. ret.push_back(i);
  141. }
  142. return ret;
  143. }
  144. const IMarket * IMarket::castFrom(const CGObjectInstance *obj, bool verbose /*= true*/)
  145. {
  146. switch(obj->ID)
  147. {
  148. case Obj::TOWN:
  149. return static_cast<const CGTownInstance*>(obj);
  150. case Obj::ALTAR_OF_SACRIFICE:
  151. case Obj::BLACK_MARKET:
  152. case Obj::TRADING_POST:
  153. case Obj::TRADING_POST_SNOW:
  154. case Obj::FREELANCERS_GUILD:
  155. return static_cast<const CGMarket*>(obj);
  156. case Obj::UNIVERSITY:
  157. return static_cast<const CGUniversity*>(obj);
  158. default:
  159. if(verbose)
  160. logGlobal->errorStream() << "Cannot cast to IMarket object with ID " << obj->ID;
  161. return nullptr;
  162. }
  163. }
  164. IMarket::IMarket(const CGObjectInstance *O)
  165. :o(O)
  166. {
  167. }
  168. std::vector<EMarketMode::EMarketMode> IMarket::availableModes() const
  169. {
  170. std::vector<EMarketMode::EMarketMode> ret;
  171. for (int i = 0; i < EMarketMode::MARTKET_AFTER_LAST_PLACEHOLDER; i++)
  172. if(allowsTrade((EMarketMode::EMarketMode)i))
  173. ret.push_back((EMarketMode::EMarketMode)i);
  174. return ret;
  175. }
  176. void CGMarket::onHeroVisit(const CGHeroInstance * h) const
  177. {
  178. openWindow(OpenWindow::MARKET_WINDOW,id.getNum(),h->id.getNum());
  179. }
  180. int CGMarket::getMarketEfficiency() const
  181. {
  182. return 5;
  183. }
  184. bool CGMarket::allowsTrade(EMarketMode::EMarketMode mode) const
  185. {
  186. switch(mode)
  187. {
  188. case EMarketMode::RESOURCE_RESOURCE:
  189. case EMarketMode::RESOURCE_PLAYER:
  190. switch(ID)
  191. {
  192. case Obj::TRADING_POST:
  193. case Obj::TRADING_POST_SNOW:
  194. return true;
  195. default:
  196. return false;
  197. }
  198. case EMarketMode::CREATURE_RESOURCE:
  199. return ID == Obj::FREELANCERS_GUILD;
  200. //case ARTIFACT_RESOURCE:
  201. case EMarketMode::RESOURCE_ARTIFACT:
  202. return ID == Obj::BLACK_MARKET;
  203. case EMarketMode::ARTIFACT_EXP:
  204. case EMarketMode::CREATURE_EXP:
  205. return ID == Obj::ALTAR_OF_SACRIFICE; //TODO? check here for alignment of visiting hero? - would not be coherent with other checks here
  206. case EMarketMode::RESOURCE_SKILL:
  207. return ID == Obj::UNIVERSITY;
  208. default:
  209. return false;
  210. }
  211. }
  212. int CGMarket::availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial) const
  213. {
  214. return -1;
  215. }
  216. std::vector<int> CGMarket::availableItemsIds(EMarketMode::EMarketMode mode) const
  217. {
  218. switch(mode)
  219. {
  220. case EMarketMode::RESOURCE_RESOURCE:
  221. case EMarketMode::RESOURCE_PLAYER:
  222. return IMarket::availableItemsIds(mode);
  223. default:
  224. return std::vector<int>();
  225. }
  226. }
  227. CGMarket::CGMarket()
  228. :IMarket(this)
  229. {
  230. }
  231. std::vector<int> CGBlackMarket::availableItemsIds(EMarketMode::EMarketMode mode) const
  232. {
  233. switch(mode)
  234. {
  235. case EMarketMode::ARTIFACT_RESOURCE:
  236. return IMarket::availableItemsIds(mode);
  237. case EMarketMode::RESOURCE_ARTIFACT:
  238. {
  239. std::vector<int> ret;
  240. for(const CArtifact *a : artifacts)
  241. if(a)
  242. ret.push_back(a->id);
  243. else
  244. ret.push_back(-1);
  245. return ret;
  246. }
  247. default:
  248. return std::vector<int>();
  249. }
  250. }
  251. void CGBlackMarket::newTurn() const
  252. {
  253. if(cb->getDate(Date::DAY_OF_MONTH) != 1) //new month
  254. return;
  255. SetAvailableArtifacts saa;
  256. saa.id = id.getNum();
  257. cb->pickAllowedArtsSet(saa.arts);
  258. cb->sendAndApply(&saa);
  259. }
  260. void CGUniversity::initObj()
  261. {
  262. std::vector<int> toChoose;
  263. for(int i = 0; i < GameConstants::SKILL_QUANTITY; ++i)
  264. {
  265. if(cb->isAllowed(2, i))
  266. {
  267. toChoose.push_back(i);
  268. }
  269. }
  270. if(toChoose.size() < 4)
  271. {
  272. logGlobal->warnStream()<<"Warning: less then 4 available skills was found by University initializer!";
  273. return;
  274. }
  275. // get 4 skills
  276. for(int i = 0; i < 4; ++i)
  277. {
  278. // move randomly one skill to selected and remove from list
  279. auto it = RandomGeneratorUtil::nextItem(toChoose, cb->gameState()->getRandomGenerator());
  280. skills.push_back(*it);
  281. toChoose.erase(it);
  282. }
  283. }
  284. std::vector<int> CGUniversity::availableItemsIds(EMarketMode::EMarketMode mode) const
  285. {
  286. switch (mode)
  287. {
  288. case EMarketMode::RESOURCE_SKILL:
  289. return skills;
  290. default:
  291. return std::vector <int> ();
  292. }
  293. }
  294. void CGUniversity::onHeroVisit(const CGHeroInstance * h) const
  295. {
  296. openWindow(OpenWindow::UNIVERSITY_WINDOW,id.getNum(),h->id.getNum());
  297. }