LevelGenerate.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. //
  2. // LevelGenerate.cpp
  3. // Test
  4. //
  5. // Created by 高慕白 on 2024/12/3.
  6. //
  7. #include "LevelGenerate.hpp"
  8. #include <iostream>
  9. #include <cassert>
  10. #include <unordered_map>
  11. #include "FillGlobalConfig.hpp"
  12. #include <tuple>
  13. #include "BoxPositionTool.hpp"
  14. using namespace std;
  15. bool LevelGenerate::generate( FillGlobalConfig::LevelData levelData,
  16. vector<tuple<int,vector<vector<FillResult>>>>& resultPlateFillResults,
  17. vector<ContourData::Point>& resultPlateCenterPointArr
  18. )
  19. {
  20. resultPlateFillResults.clear() ;
  21. resultPlateCenterPointArr.clear() ;
  22. auto ms0 = std::chrono::system_clock::now().time_since_epoch() ;
  23. uint64_t ms00 = std::chrono::duration_cast<chrono::milliseconds>(ms0).count() ;
  24. srand(_seed);
  25. unordered_map<int,tuple<int,int> > jewIdSzCntStorageMap ;
  26. FillGlobalConfig* fgc = FillGlobalConfig::getInstance() ;
  27. int bigJewelCnt = 0 ;
  28. int midJewelCnt = 0;
  29. int smlJewelCnt = 0 ;
  30. for(int ij = 0 ; ij < levelData._jewelIds.size();++ ij ) {
  31. int jewId = levelData._jewelIds[ij] ;
  32. int cnt = levelData._cnts[ij] ;
  33. FillGlobalConfig::JewelItem* jewItem = fgc->getJewelItemById(jewId) ;
  34. jewIdSzCntStorageMap[jewId] = {jewItem->_size,cnt} ;
  35. if( jewItem->_size == FILLGLOBALCONFIG_JEWELSIZE_SM ) {
  36. smlJewelCnt+=cnt ;
  37. }else if( jewItem->_size == FILLGLOBALCONFIG_JEWELSIZE_MD ) {
  38. midJewelCnt += cnt ;
  39. }else if( jewItem->_size == FILLGLOBALCONFIG_JEWELSIZE_LG ) {
  40. bigJewelCnt += cnt ;
  41. }
  42. }
  43. //每个盘子类型小号宝石承载量
  44. //按顺序分别为大横,大竖,小。这里不考虑迷你。
  45. FillGlobalConfig::PlateItem* bigPlate = fgc->getPlateItemBySzNIndex(FILLGLOBALCONFIG_PLATESIZE_LG, 0) ;
  46. FillGlobalConfig::PlateItem* midPlate = fgc->getPlateItemBySzNIndex(FILLGLOBALCONFIG_PLATESIZE_MD, 0) ;
  47. FillGlobalConfig::PlateItem* smlPlate = fgc->getPlateItemBySzNIndex(FILLGLOBALCONFIG_PLATESIZE_SM, 0) ;
  48. vector<FillGlobalConfig::PlateItem*> usedPlates = {bigPlate,midPlate,smlPlate} ;
  49. int maxSmlJewCapPerPlate = 0;
  50. int minSmlJewCapPerPlate = 99999 ;
  51. for(int ip=0;ip<usedPlates.size();++ip ) {
  52. maxSmlJewCapPerPlate = fmax( usedPlates[ip]->_bigJewCap*4 , maxSmlJewCapPerPlate) ;
  53. minSmlJewCapPerPlate = fmin( usedPlates[ip]->_bigJewCap*4 , minSmlJewCapPerPlate) ;
  54. }
  55. //等效小宝石数量
  56. int effSmallJewelsCount = bigJewelCnt*4 + midJewelCnt*2 + smlJewelCnt ;
  57. cout<<"bigJewelCnt "<<bigJewelCnt<<endl;
  58. cout<<"midJewelCnt "<<midJewelCnt<<endl;
  59. cout<<"smlJewelCnt "<<smlJewelCnt<<endl;
  60. cout<<"effSmallJewelsCount "<<effSmallJewelsCount<<endl;
  61. //构建符合难度条件的盘子和层数组合
  62. vector<PlateIdAndLayerCnt> resPlateNLyrCnt = generatePlateTypeAndLayerCnts(levelData._difficulty,effSmallJewelsCount);
  63. if( resPlateNLyrCnt.size()==0 ) {
  64. cout<<"failed at generatePlateTypeAndLayerCnts"<<endl;
  65. return false ;
  66. }
  67. //计算盘子的最大层数
  68. int maxLyrCnt = 0;
  69. for(auto it = resPlateNLyrCnt.begin();it!=resPlateNLyrCnt.end();++it ) maxLyrCnt=fmax(maxLyrCnt,it->_layerCnt) ;
  70. //对每个盘子组合进行填充宝石
  71. RandomGridFiller filler ;
  72. filler._seed = this->_seed ;
  73. //构建每个盘子每个层的填充结果容器
  74. vector< tuple<int,int,vector<FillResult>> > plateIdLyrFillResultsArray ;// tuple<plateId, layerIndex, fillresults_array >
  75. //从顶到底部,逐层进行填充
  76. int residues = 0 ;
  77. for(int nlayer = maxLyrCnt; nlayer > 0 ; nlayer-- ) {
  78. cout<<"for layer "<<nlayer<<endl;
  79. //满足该层数的所有盘子ID
  80. vector<int> plateIdArr ;
  81. for(auto it = resPlateNLyrCnt.begin();it!=resPlateNLyrCnt.end();++it ) if(it->_layerCnt>=nlayer) plateIdArr.push_back(it->_plateId) ;
  82. //该层总计需要填充多少小宝石
  83. int currLyrNeedEquvSmlCnt = 0 ;
  84. for(int ip=0;ip<plateIdArr.size();++ip ) {
  85. currLyrNeedEquvSmlCnt += fgc->getPlateItemById(plateIdArr[ip])->_bigJewCap*4 ;
  86. }
  87. cout<<"layer need eqsmCnt "<<currLyrNeedEquvSmlCnt<<endl;
  88. //根据所需数量和所需求解百分比,计算从库存取出每类宝石多少个。
  89. float solPercent = 0.7 ;//根据需求文档,每层可解百分比都是70%.
  90. unordered_map<int, int> chosenJewIdNCnt = randPickJewels(currLyrNeedEquvSmlCnt, solPercent, jewIdSzCntStorageMap) ;
  91. int choseEqSmCnt=0;
  92. for(auto itp=chosenJewIdNCnt.begin();itp!=chosenJewIdNCnt.end();++itp) {
  93. choseEqSmCnt += jewSz2SmlCnt( fgc->getJewelItemById(itp->first)->_size) * itp->second ;
  94. }
  95. cout<<"layer choose eqsmCnt "<<choseEqSmCnt<<endl;
  96. //逐个盘子填充
  97. for(auto itpid = plateIdArr.begin();itpid!=plateIdArr.end();++itpid) {
  98. vector<FillResult> fr = fillPlateOneLayer(filler, *itpid, chosenJewIdNCnt) ;
  99. tuple<int,int,vector<FillResult>> plateLyrFillResult={*itpid,nlayer,fr} ;
  100. plateIdLyrFillResultsArray.push_back(plateLyrFillResult);
  101. }
  102. //检查为该层挑选的宝石是不是全部填完了,如果没有填完还要还给库存,给下一轮填充用
  103. residues = 0 ;
  104. for(auto itjn = chosenJewIdNCnt.begin();itjn!=chosenJewIdNCnt.end();++itjn){
  105. if( itjn->second>0 ) {
  106. residues+=itjn->second;
  107. std::get<1>(jewIdSzCntStorageMap[itjn->first]) += itjn->second ;//剩余的加回到库存里
  108. }
  109. }
  110. cout<<"layer chosen jewels residues "<<residues<<endl;
  111. }
  112. //查看库存是否全部用掉了
  113. if( residues>0 ) {
  114. int extraPlateCnt = 0 ;
  115. //剩了,添加一个小盘子和层,仍然剩了再继续加盘子加层
  116. unordered_map<int, int> residueJewIdAndCnts = findUnfilledInStorages(jewIdSzCntStorageMap) ;
  117. while( residueJewIdAndCnts.size()>0 ) {
  118. //新建一个小盘子
  119. extraPlateCnt++;
  120. cout<<"add extra plate "<< extraPlateCnt <<endl;
  121. int plateId = smlPlate->_id ;
  122. for(int ilyr = 1 ; ilyr <= maxLyrCnt; ++ ilyr ) {
  123. vector<FillResult> frs = fillPlateOneLayer(filler, plateId, residueJewIdAndCnts) ;
  124. plateIdLyrFillResultsArray.push_back( {plateId,ilyr,frs} );
  125. cout<<"add extra lyr "<<endl;
  126. if( residueJewIdAndCnts.size()==0 ) break ;
  127. }
  128. if( residueJewIdAndCnts.size()==0 ) break ;
  129. }
  130. }
  131. //整理数据
  132. regroupPlateLyrFillResults(plateIdLyrFillResultsArray, resultPlateFillResults);
  133. //摆放盘子
  134. {
  135. vector<int> plateIdArr1;
  136. for(auto itp = resultPlateFillResults.begin();itp!=resultPlateFillResults.end();++itp) plateIdArr1.push_back( std::get<0>(*itp) );
  137. placePlates(plateIdArr1, resultPlateCenterPointArr) ;
  138. }
  139. auto ms1 = std::chrono::system_clock::now().time_since_epoch() ;
  140. uint64_t ms11 = std::chrono::duration_cast<chrono::milliseconds>(ms1).count() ;
  141. cout<<"duration "<<ms11-ms00<<endl;
  142. return true ;
  143. }
  144. vector<LevelGenerate::PlateIdAndLayerCnt> LevelGenerate::generatePlateTypeAndLayerCnts( const int difficulty,const int totEquvSmallJewelCnt)
  145. {
  146. assert(difficulty>=0&&difficulty<=2) ;
  147. vector<vector<LevelGenerate::PlateIdAndLayerCnt>> possibleResults ;
  148. vector<LevelGenerate::PlateIdAndLayerCnt> results ;
  149. assert(totEquvSmallJewelCnt>0) ;
  150. FillGlobalConfig* fgc = FillGlobalConfig::getInstance() ;
  151. FillGlobalConfig::PlateItem* bigPlate = fgc->getPlateItemBySzNIndex(FILLGLOBALCONFIG_PLATESIZE_LG, 0) ;
  152. FillGlobalConfig::PlateItem* midPlate = fgc->getPlateItemBySzNIndex(FILLGLOBALCONFIG_PLATESIZE_MD, 0) ;
  153. FillGlobalConfig::PlateItem* smlPlate = fgc->getPlateItemBySzNIndex(FILLGLOBALCONFIG_PLATESIZE_SM, 0) ;
  154. vector<FillGlobalConfig::PlateItem*> usedPlates = {bigPlate,midPlate,smlPlate} ;
  155. //一个关卡最多出现大、中、小盘子个数
  156. const int PLATE_BG_MAX_CNT = 9 ;// 1个大盘子=2两个中盘子=6个小盘子
  157. const int PLATE_MD_MAX_CNT = 18 ;
  158. const int PLATE_SM_MAX_CNT = 54 ;
  159. //每个关卡最大容纳等效小盘子的个数 就是54个
  160. // 普通 难 极难
  161. vector< vector<float> > diffPlateCntPercent0 = { {0.3,0.3,0.0}, {0.2,0.4,0.0}, {0.1,0.5,0.0} } ;
  162. vector< vector<float> > diffPlateCntPercent1 = { {0.7,0.7,0.0}, {0.6,0.8,0.1}, {0.5,0.9,0.1} } ;
  163. for(int ipbig = 1; ipbig <= PLATE_BG_MAX_CNT; ++ ipbig ) {
  164. for(int ipmid = 1 ; ipmid <= PLATE_MD_MAX_CNT; ++ ipmid ) {
  165. int effsmPlateCnt = ipbig*6 + ipmid*3 ;
  166. if( effsmPlateCnt>PLATE_SM_MAX_CNT ) continue ;
  167. for(int ipsml = 0 ; ipsml <= PLATE_SM_MAX_CNT; ++ ipsml ) {
  168. //等效小盘子个数
  169. effsmPlateCnt += ipsml ;
  170. if( effsmPlateCnt>PLATE_SM_MAX_CNT ) continue ;
  171. float bigPlateCntPercent = ipbig*6.0 / effsmPlateCnt ;
  172. float midPlateCntPercent = ipmid*3.0 / effsmPlateCnt ;
  173. float smlPlateCntPercent = ipsml*1.0 / effsmPlateCnt ;
  174. vector<float> percentArr = {bigPlateCntPercent,midPlateCntPercent,smlPlateCntPercent} ;
  175. //判断每个盘子百分比是否满足难度要求
  176. bool percentOk = true ;
  177. for(int iplatetype=0;iplatetype<percentArr.size();++iplatetype) {
  178. if( diffPlateCntPercent0[difficulty][iplatetype]>percentArr[iplatetype] || diffPlateCntPercent1[difficulty][iplatetype]<percentArr[iplatetype] )
  179. percentOk=false;
  180. }
  181. if(!percentOk) continue ;//盘子百分比不符合要求,跳过
  182. //计算每个类型的层数
  183. if( difficulty== FILLGLOBALCONFIG_DIFFCULTY_NORM ) {
  184. //全部两层
  185. vector<int> pidArr ;
  186. vector<int> capArr ;
  187. vector<int> lyrArr ;
  188. for(int it=0;it<ipbig;++it) { pidArr.push_back(bigPlate->_id);capArr.push_back(bigPlate->_bigJewCap*4); lyrArr.push_back(2); }
  189. for(int it=0;it<ipmid;++it) { pidArr.push_back(midPlate->_id);capArr.push_back(midPlate->_bigJewCap*4); lyrArr.push_back(2); }
  190. for(int it=0;it<ipsml;++it) { pidArr.push_back(smlPlate->_id);capArr.push_back(smlPlate->_bigJewCap*4); lyrArr.push_back(2); }
  191. bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt) ;
  192. if(!lyrOk) continue;
  193. //保存结果
  194. vector<LevelGenerate::PlateIdAndLayerCnt> tres(capArr.size()) ;
  195. for(int it = 0 ; it < capArr.size(); ++ it ) {
  196. tres[it]._plateId = pidArr[it] ;
  197. tres[it]._layerCnt = lyrArr[it] ;
  198. }
  199. possibleResults.push_back(tres) ;
  200. }else if( difficulty==FILLGLOBALCONFIG_DIFFCULTY_HARD2 ) {
  201. //全部3层
  202. vector<int> pidArr ;
  203. vector<int> capArr ;
  204. vector<int> lyrArr ;
  205. for(int it=0;it<ipbig;++it) { pidArr.push_back(bigPlate->_id);capArr.push_back(bigPlate->_bigJewCap*4); lyrArr.push_back(3); }
  206. for(int it=0;it<ipmid;++it) { pidArr.push_back(midPlate->_id);capArr.push_back(midPlate->_bigJewCap*4); lyrArr.push_back(3); }
  207. for(int it=0;it<ipsml;++it) { pidArr.push_back(smlPlate->_id);capArr.push_back(smlPlate->_bigJewCap*4); lyrArr.push_back(3); }
  208. bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt) ;
  209. if(!lyrOk) continue;
  210. //保存结果
  211. vector<LevelGenerate::PlateIdAndLayerCnt> tres(capArr.size()) ;
  212. for(int it = 0 ; it < capArr.size(); ++ it ) {
  213. tres[it]._plateId = pidArr[it] ;
  214. tres[it]._layerCnt = lyrArr[it] ;
  215. }
  216. possibleResults.push_back(tres) ;
  217. }else{
  218. //50% 2层, 50% 3层
  219. vector<int> pidArr ;
  220. vector<int> capArr ;
  221. vector<int> lyrArr ;
  222. for(int it=0;it<ipbig;++it) { pidArr.push_back(bigPlate->_id);capArr.push_back(bigPlate->_bigJewCap*4); lyrArr.push_back((rand()%2==0)?2:3); }
  223. for(int it=0;it<ipmid;++it) { pidArr.push_back(midPlate->_id);capArr.push_back(midPlate->_bigJewCap*4); lyrArr.push_back((rand()%2==0)?2:3); }
  224. for(int it=0;it<ipsml;++it) { pidArr.push_back(smlPlate->_id);capArr.push_back(smlPlate->_bigJewCap*4); lyrArr.push_back((rand()%2==0)?2:3); }
  225. bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt) ;
  226. if(!lyrOk) continue;
  227. //保存结果
  228. vector<LevelGenerate::PlateIdAndLayerCnt> tres(capArr.size()) ;
  229. for(int it = 0 ; it < capArr.size(); ++ it ) {
  230. tres[it]._plateId = pidArr[it] ;
  231. tres[it]._layerCnt = lyrArr[it] ;
  232. }
  233. possibleResults.push_back(tres) ;
  234. }
  235. }
  236. }
  237. }
  238. //debug 查看全部符合要求的结果
  239. if( possibleResults.size()> 0 ) {
  240. int randindex = rand() % possibleResults.size();
  241. results = possibleResults[randindex] ;
  242. }
  243. return results ;
  244. }
  245. //随机排序数组索引值
  246. vector<int> LevelGenerate::randIndices(const int count0 ) {
  247. int count = count0 ;
  248. vector<int> indices ;
  249. unordered_map<int, bool> dict ;
  250. while( count > 0 ) {
  251. int r = rand()%count0;
  252. if( dict.find(r) == dict.end() ) {
  253. dict[r] = true ;
  254. indices.push_back(r) ;
  255. count-- ;
  256. }
  257. }
  258. return indices;
  259. }
  260. bool LevelGenerate::isJustFilledAll2(
  261. const vector<int>& plateCaps,//每个盘子的容量
  262. const vector<int> eachPlateLyrCnt,//对应盘子的层数
  263. const int totSmlJewCnt )
  264. {
  265. assert(plateCaps.size()>0);
  266. assert(plateCaps.size()==eachPlateLyrCnt.size());
  267. int fillcnt1 = 0;
  268. for(int ip = 0 ;ip<plateCaps.size();++ip ) {
  269. fillcnt1 += plateCaps[ip] * eachPlateLyrCnt[ip] ;
  270. }
  271. if( fillcnt1 < totSmlJewCnt ) return false ;
  272. if( fillcnt1 == totSmlJewCnt ) return true ;
  273. for(int ip = 0 ; ip < plateCaps.size();++ip ) {
  274. int fillcnt2 = fillcnt1 - plateCaps[ip] ;
  275. if( fillcnt2 < totSmlJewCnt ) {
  276. return true ;
  277. }
  278. }
  279. return false ;
  280. }
  281. unordered_map<int, int> LevelGenerate::randPickJewels( const int needEquvSmlCnt,const float solvedPercent, unordered_map<int,tuple<int,int>>& jewStorages )
  282. {
  283. int needEquvSmlCnt2 = needEquvSmlCnt ;
  284. int storageEquvSmlCnt = 0 ;
  285. int storageJewTypeCnt = jewStorages.size() ;
  286. for(auto it=jewStorages.begin();it!=jewStorages.end();++it) storageEquvSmlCnt+= std::get<1>(it->second)*jewSz2SmlCnt(std::get<0>(it->second)) ;
  287. unordered_map<int, int> res ;
  288. const float solPer = fmax(0.0,fmin(solvedPercent,1.0f)) ;
  289. //首先尝试可解的百分比部分
  290. int solEqSmGrpCnt = needEquvSmlCnt*solPer/3 ;
  291. // 随机尝试solEqSmGrpCnt*2 次取宝石,每次取一组。
  292. int loopCnt=solEqSmGrpCnt*storageJewTypeCnt*10;//随机迭代数量加大10倍,避免有始终选不到的情况
  293. while( solEqSmGrpCnt> 0 && storageEquvSmlCnt>0 && loopCnt>0) {
  294. int randJewI = rand()%storageJewTypeCnt ;
  295. auto itjew = jewStorages.begin() ;
  296. std::advance(itjew, randJewI) ;
  297. int jid = itjew->first ;
  298. int storage1 = std::get<1>( itjew->second ) ;
  299. int oneGrpEqSmGrpCnt = jewSz2SmlCnt( std::get<0>(itjew->second) ) ;
  300. if( storage1>=3 && oneGrpEqSmGrpCnt<=solEqSmGrpCnt ) {
  301. //库存有,且满足所需可解组数
  302. std::get<1>(itjew->second)-=3 ;
  303. solEqSmGrpCnt -= oneGrpEqSmGrpCnt ;
  304. storageEquvSmlCnt -= oneGrpEqSmGrpCnt*3 ;
  305. needEquvSmlCnt2 -= oneGrpEqSmGrpCnt*3 ; //本次所需的剩余等效小宝石个数
  306. res[jid] += 3 ;
  307. }
  308. --loopCnt ;
  309. }
  310. //尝试剩余百分比和上一步剩余没有符合条件的个数
  311. loopCnt = needEquvSmlCnt2*storageJewTypeCnt ;
  312. int jindex = 0 ;
  313. while( loopCnt>0 && needEquvSmlCnt2> 0 && storageEquvSmlCnt>0 ) {
  314. auto itjew = jewStorages.begin() ;
  315. std::advance(itjew, jindex) ;
  316. int jid = itjew->first;
  317. int sz = std::get<0>(itjew->second) ;
  318. int stor = std::get<1>(itjew->second) ;
  319. int eqsmCnt = jewSz2SmlCnt(sz) ;
  320. if( stor>0 && eqsmCnt <= needEquvSmlCnt2 ) {
  321. std::get<1>(itjew->second)-=1 ;
  322. needEquvSmlCnt2-=eqsmCnt ;
  323. storageEquvSmlCnt-=eqsmCnt ;
  324. res[jid] += 1 ;
  325. }
  326. ++jindex ; if(jindex>=storageJewTypeCnt) jindex=0;//循环取之,直到本层所需全部取完
  327. --loopCnt;
  328. }
  329. return res ;
  330. }
  331. int LevelGenerate::jewSz2SmlCnt(int sz)
  332. {
  333. switch (sz) {
  334. case FILLGLOBALCONFIG_JEWELSIZE_LG:
  335. return 4;break;
  336. case FILLGLOBALCONFIG_JEWELSIZE_MD:
  337. return 2;break;
  338. default:
  339. return 1;break;
  340. }
  341. return 1;
  342. }
  343. vector<FillResult> LevelGenerate::fillPlateOneLayer(RandomGridFiller& filler,const int plateId, unordered_map<int,int>& jewStoragesForUse )
  344. {
  345. auto fgc = FillGlobalConfig::getInstance() ;
  346. vector<RandomGridFiller::JewelBox> jewBoxArray ;
  347. FillGlobalConfig::PlateItem* pl = FillGlobalConfig::getInstance()->getPlateItemById(plateId) ;
  348. int plateEqSmCap = pl->_bigJewCap*4 ;
  349. int jewTypeCnt = jewStoragesForUse.size() ;
  350. int eqSmStorageCnt = 0 ;
  351. for(auto it = jewStoragesForUse.begin();it!=jewStoragesForUse.end();++it) {
  352. int jewEqSmCnt = jewSz2SmlCnt( fgc->getJewelItemById(it->first)->_size );
  353. eqSmStorageCnt+=it->second*jewEqSmCnt ;
  354. }
  355. static int s_debug_cnt = 0;
  356. cout<<"debug "<< s_debug_cnt << " storage eqsm count "<<eqSmStorageCnt<< " currplate cap "<< plateEqSmCap <<endl;
  357. unordered_map<int, int> jewForPlateMap ;// <jewId,Cnt>
  358. int loopCnt = plateEqSmCap*jewTypeCnt*4;// 随机数量多给4倍
  359. while(plateEqSmCap>0 && eqSmStorageCnt>0 && loopCnt>0 ) {
  360. int radv = rand() % jewTypeCnt ;
  361. auto it = jewStoragesForUse.begin() ;
  362. std::advance(it, radv) ;
  363. int jewEqSmCnt = jewSz2SmlCnt( fgc->getJewelItemById(it->first)->_size );
  364. if( it->second>0 ) {
  365. if( jewEqSmCnt <= plateEqSmCap ) {
  366. plateEqSmCap -= jewEqSmCnt ;
  367. it->second -=1 ;
  368. eqSmStorageCnt -= jewEqSmCnt ;
  369. jewForPlateMap[it->first] += 1 ;
  370. if( it->second== 0 ) {
  371. jewStoragesForUse.erase(it) ;
  372. jewTypeCnt-- ;
  373. }
  374. }
  375. }else{
  376. jewStoragesForUse.erase(it) ;
  377. jewTypeCnt-- ;
  378. }
  379. --loopCnt ;
  380. }
  381. cout<<"debug "<< s_debug_cnt ++ <<" storage eqsm count "<<eqSmStorageCnt<< " currplate cap "<< plateEqSmCap <<endl;
  382. for(auto it = jewForPlateMap.begin();it!=jewForPlateMap.end();++it) {
  383. RandomGridFiller::JewelBox jbox ;
  384. jbox._cnt = it->second ;
  385. jbox._jewelTypeId = it->first ;
  386. jbox._width = fgc->getJewelItemById(it->first)->_bbWidth ;
  387. jbox._height = fgc->getJewelItemById(it->first)->_bbHeight ;
  388. jewBoxArray.push_back(jbox) ;
  389. }
  390. vector<FillResult> fillresults ;
  391. filler.fill(jewBoxArray, pl->_blx, pl->_bly, pl->_trx, pl->_try, fillresults) ;
  392. return fillresults ;
  393. }
  394. unordered_map<int, int> LevelGenerate::findUnfilledInStorages( unordered_map<int,tuple<int,int>>& jewStorages)
  395. {
  396. unordered_map<int, int> res ;
  397. for(auto itj = jewStorages.begin();itj!=jewStorages.end();++itj) {
  398. int stor = std::get<1>(itj->second) ;
  399. int jid = itj->first ;
  400. if( stor>0 ) {
  401. res[jid] = stor ;
  402. std::get<1>(itj->second) = 0 ;
  403. }
  404. }
  405. return res ;
  406. }
  407. void LevelGenerate::regroupPlateLyrFillResults( vector<tuple<int,int,vector<FillResult>>>& pidlyrFillArray, vector<tuple<int,vector<vector<FillResult>>>>& results )
  408. {
  409. int currLayer = 1 ;//从底层到顶层构建结果数据结构
  410. int num = pidlyrFillArray.size() ;
  411. int nloop = num ;
  412. while( nloop > 0 ) {
  413. cout<<"regroup for layer "<<currLayer<<endl;
  414. for( auto itlyr = pidlyrFillArray.begin(); itlyr!=pidlyrFillArray.end(); ++ itlyr ) {
  415. int pid = std::get<0>( *itlyr ) ;
  416. int lyr = std::get<1>( *itlyr ) ;
  417. vector<FillResult>& frs = std::get<2>(*itlyr) ;
  418. if(pid>=0) {
  419. if( lyr==currLayer ) {
  420. if( lyr==1 ) {
  421. vector<vector<FillResult>> frArr = {frs} ;
  422. results.push_back( {pid, frArr } ) ;
  423. num-- ;
  424. std::get<0>( *itlyr ) = -1 ;
  425. }else {
  426. for(auto itr = results.begin();itr!=results.end();++itr ) {
  427. int pidr = std::get<0>(*itr) ;
  428. vector<vector<FillResult>>& frArr = std::get<1>(*itr) ;
  429. if( pidr == pid && frArr.size()==currLayer-1 ) {
  430. frArr.push_back(frs);
  431. num-- ;
  432. std::get<0>( *itlyr ) = -1 ;
  433. break ;
  434. }
  435. }
  436. }
  437. }
  438. }
  439. }
  440. currLayer++ ;
  441. if( num==0 ) break ;
  442. nloop--;
  443. }
  444. cout<<"last plate lyr num "<<num<<endl;
  445. }
  446. void LevelGenerate::placePlates( const vector<int>& plateIdArr, vector<ContourData::Point>& resultPlateCenterPointArr )
  447. {
  448. auto fgc = FillGlobalConfig::getInstance() ;
  449. vector<vector<int>> plateSizeArr ;
  450. for(int ip = 0 ; ip < plateIdArr.size();++ip ) {
  451. FillGlobalConfig::PlateItem* plate1 = fgc->getPlateItemById(plateIdArr[ip]) ;
  452. vector<int> sz = { (int)plate1->_bbwid, (int)plate1->_bbhei } ;
  453. plateSizeArr.push_back(sz) ;
  454. }
  455. BoxPositionTool positionTool ;
  456. vector<vector<int>> resPosis ;
  457. const int GAME_REGION_WIDTH = 640 ;
  458. const int GAME_REGION_HEIGHT = 720 ;
  459. positionTool.solve(GAME_REGION_WIDTH,GAME_REGION_HEIGHT,plateSizeArr, resPosis) ;
  460. for(int ip=0;ip<resPosis.size();++ip ) {
  461. resultPlateCenterPointArr.push_back( { (float)resPosis[ip][0] , (float)resPosis[ip][1]} ) ;
  462. }
  463. }