123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513 |
- //
- // LevelGenerate.cpp
- // Test
- //
- // Created by 高慕白 on 2024/12/3.
- //
- #include "LevelGenerate.hpp"
- #include <iostream>
- #include <cassert>
- #include <unordered_map>
- #include "FillGlobalConfig.hpp"
- #include <tuple>
- #include "BoxPositionTool.hpp"
- using namespace std;
- bool LevelGenerate::generate( FillGlobalConfig::LevelData levelData,
- vector<tuple<int,vector<vector<FillResult>>>>& resultPlateFillResults,
- vector<ContourData::Point>& resultPlateCenterPointArr
- )
- {
- resultPlateFillResults.clear() ;
- resultPlateCenterPointArr.clear() ;
-
- auto ms0 = std::chrono::system_clock::now().time_since_epoch() ;
- uint64_t ms00 = std::chrono::duration_cast<chrono::milliseconds>(ms0).count() ;
-
- srand(_seed);
- unordered_map<int,tuple<int,int> > jewIdSzCntStorageMap ;
- FillGlobalConfig* fgc = FillGlobalConfig::getInstance() ;
- int bigJewelCnt = 0 ;
- int midJewelCnt = 0;
- int smlJewelCnt = 0 ;
- for(int ij = 0 ; ij < levelData._jewelIds.size();++ ij ) {
- int jewId = levelData._jewelIds[ij] ;
- int cnt = levelData._cnts[ij] ;
- FillGlobalConfig::JewelItem* jewItem = fgc->getJewelItemById(jewId) ;
- jewIdSzCntStorageMap[jewId] = {jewItem->_size,cnt} ;
- if( jewItem->_size == FILLGLOBALCONFIG_JEWELSIZE_SM ) {
- smlJewelCnt+=cnt ;
- }else if( jewItem->_size == FILLGLOBALCONFIG_JEWELSIZE_MD ) {
- midJewelCnt += cnt ;
- }else if( jewItem->_size == FILLGLOBALCONFIG_JEWELSIZE_LG ) {
- bigJewelCnt += cnt ;
- }
- }
- //每个盘子类型小号宝石承载量
- //按顺序分别为大横,大竖,小。这里不考虑迷你。
- FillGlobalConfig::PlateItem* bigPlate = fgc->getPlateItemBySzNIndex(FILLGLOBALCONFIG_PLATESIZE_LG, 0) ;
- FillGlobalConfig::PlateItem* midPlate = fgc->getPlateItemBySzNIndex(FILLGLOBALCONFIG_PLATESIZE_MD, 0) ;
- FillGlobalConfig::PlateItem* smlPlate = fgc->getPlateItemBySzNIndex(FILLGLOBALCONFIG_PLATESIZE_SM, 0) ;
- vector<FillGlobalConfig::PlateItem*> usedPlates = {bigPlate,midPlate,smlPlate} ;
- int maxSmlJewCapPerPlate = 0;
- int minSmlJewCapPerPlate = 99999 ;
- for(int ip=0;ip<usedPlates.size();++ip ) {
- maxSmlJewCapPerPlate = fmax( usedPlates[ip]->_bigJewCap*4 , maxSmlJewCapPerPlate) ;
- minSmlJewCapPerPlate = fmin( usedPlates[ip]->_bigJewCap*4 , minSmlJewCapPerPlate) ;
- }
- //等效小宝石数量
- int effSmallJewelsCount = bigJewelCnt*4 + midJewelCnt*2 + smlJewelCnt ;
- cout<<"bigJewelCnt "<<bigJewelCnt<<endl;
- cout<<"midJewelCnt "<<midJewelCnt<<endl;
- cout<<"smlJewelCnt "<<smlJewelCnt<<endl;
- cout<<"effSmallJewelsCount "<<effSmallJewelsCount<<endl;
-
- //构建符合难度条件的盘子和层数组合
- vector<PlateIdAndLayerCnt> resPlateNLyrCnt = generatePlateTypeAndLayerCnts(levelData._difficulty,effSmallJewelsCount);
- if( resPlateNLyrCnt.size()==0 ) {
- cout<<"failed at generatePlateTypeAndLayerCnts"<<endl;
- return false ;
- }
-
- //计算盘子的最大层数
- int maxLyrCnt = 0;
- for(auto it = resPlateNLyrCnt.begin();it!=resPlateNLyrCnt.end();++it ) maxLyrCnt=fmax(maxLyrCnt,it->_layerCnt) ;
-
- //对每个盘子组合进行填充宝石
- RandomGridFiller filler ;
- filler._seed = this->_seed ;
-
- //构建每个盘子每个层的填充结果容器
- vector< tuple<int,int,vector<FillResult>> > plateIdLyrFillResultsArray ;// tuple<plateId, layerIndex, fillresults_array >
-
-
- //从顶到底部,逐层进行填充
- int residues = 0 ;
- for(int nlayer = maxLyrCnt; nlayer > 0 ; nlayer-- ) {
- cout<<"for layer "<<nlayer<<endl;
-
- //满足该层数的所有盘子ID
- vector<int> plateIdArr ;
- for(auto it = resPlateNLyrCnt.begin();it!=resPlateNLyrCnt.end();++it ) if(it->_layerCnt>=nlayer) plateIdArr.push_back(it->_plateId) ;
-
- //该层总计需要填充多少小宝石
- int currLyrNeedEquvSmlCnt = 0 ;
- for(int ip=0;ip<plateIdArr.size();++ip ) {
- currLyrNeedEquvSmlCnt += fgc->getPlateItemById(plateIdArr[ip])->_bigJewCap*4 ;
- }
- cout<<"layer need eqsmCnt "<<currLyrNeedEquvSmlCnt<<endl;
-
- //根据所需数量和所需求解百分比,计算从库存取出每类宝石多少个。
- float solPercent = 0.7 ;//根据需求文档,每层可解百分比都是70%.
- unordered_map<int, int> chosenJewIdNCnt = randPickJewels(currLyrNeedEquvSmlCnt, solPercent, jewIdSzCntStorageMap) ;
- int choseEqSmCnt=0;
- for(auto itp=chosenJewIdNCnt.begin();itp!=chosenJewIdNCnt.end();++itp) {
- choseEqSmCnt += jewSz2SmlCnt( fgc->getJewelItemById(itp->first)->_size) * itp->second ;
- }
- cout<<"layer choose eqsmCnt "<<choseEqSmCnt<<endl;
-
- //逐个盘子填充
- for(auto itpid = plateIdArr.begin();itpid!=plateIdArr.end();++itpid) {
- vector<FillResult> fr = fillPlateOneLayer(filler, *itpid, chosenJewIdNCnt) ;
- tuple<int,int,vector<FillResult>> plateLyrFillResult={*itpid,nlayer,fr} ;
- plateIdLyrFillResultsArray.push_back(plateLyrFillResult);
- }
-
- //检查为该层挑选的宝石是不是全部填完了,如果没有填完还要还给库存,给下一轮填充用
- residues = 0 ;
- for(auto itjn = chosenJewIdNCnt.begin();itjn!=chosenJewIdNCnt.end();++itjn){
- if( itjn->second>0 ) {
- residues+=itjn->second;
- std::get<1>(jewIdSzCntStorageMap[itjn->first]) += itjn->second ;//剩余的加回到库存里
- }
- }
- cout<<"layer chosen jewels residues "<<residues<<endl;
- }
-
- //查看库存是否全部用掉了
- if( residues>0 ) {
- int extraPlateCnt = 0 ;
- //剩了,添加一个小盘子和层,仍然剩了再继续加盘子加层
- unordered_map<int, int> residueJewIdAndCnts = findUnfilledInStorages(jewIdSzCntStorageMap) ;
- while( residueJewIdAndCnts.size()>0 ) {
- //新建一个小盘子
- extraPlateCnt++;
- cout<<"add extra plate "<< extraPlateCnt <<endl;
- int plateId = smlPlate->_id ;
- for(int ilyr = 1 ; ilyr <= maxLyrCnt; ++ ilyr ) {
- vector<FillResult> frs = fillPlateOneLayer(filler, plateId, residueJewIdAndCnts) ;
- plateIdLyrFillResultsArray.push_back( {plateId,ilyr,frs} );
- cout<<"add extra lyr "<<endl;
- if( residueJewIdAndCnts.size()==0 ) break ;
- }
- if( residueJewIdAndCnts.size()==0 ) break ;
- }
- }
-
- //整理数据
- regroupPlateLyrFillResults(plateIdLyrFillResultsArray, resultPlateFillResults);
-
- //摆放盘子
- {
- vector<int> plateIdArr1;
- for(auto itp = resultPlateFillResults.begin();itp!=resultPlateFillResults.end();++itp) plateIdArr1.push_back( std::get<0>(*itp) );
- placePlates(plateIdArr1, resultPlateCenterPointArr) ;
- }
-
-
- auto ms1 = std::chrono::system_clock::now().time_since_epoch() ;
- uint64_t ms11 = std::chrono::duration_cast<chrono::milliseconds>(ms1).count() ;
- cout<<"duration "<<ms11-ms00<<endl;
- return true ;
- }
- vector<LevelGenerate::PlateIdAndLayerCnt> LevelGenerate::generatePlateTypeAndLayerCnts( const int difficulty,const int totEquvSmallJewelCnt)
- {
- assert(difficulty>=0&&difficulty<=2) ;
- vector<vector<LevelGenerate::PlateIdAndLayerCnt>> possibleResults ;
- vector<LevelGenerate::PlateIdAndLayerCnt> results ;
- assert(totEquvSmallJewelCnt>0) ;
-
- FillGlobalConfig* fgc = FillGlobalConfig::getInstance() ;
- FillGlobalConfig::PlateItem* bigPlate = fgc->getPlateItemBySzNIndex(FILLGLOBALCONFIG_PLATESIZE_LG, 0) ;
- FillGlobalConfig::PlateItem* midPlate = fgc->getPlateItemBySzNIndex(FILLGLOBALCONFIG_PLATESIZE_MD, 0) ;
- FillGlobalConfig::PlateItem* smlPlate = fgc->getPlateItemBySzNIndex(FILLGLOBALCONFIG_PLATESIZE_SM, 0) ;
- vector<FillGlobalConfig::PlateItem*> usedPlates = {bigPlate,midPlate,smlPlate} ;
-
- //一个关卡最多出现大、中、小盘子个数
- const int PLATE_BG_MAX_CNT = 9 ;// 1个大盘子=2两个中盘子=6个小盘子
- const int PLATE_MD_MAX_CNT = 18 ;
- const int PLATE_SM_MAX_CNT = 54 ;
- //每个关卡最大容纳等效小盘子的个数 就是54个
- // 普通 难 极难
- vector< vector<float> > diffPlateCntPercent0 = { {0.3,0.3,0.0}, {0.2,0.4,0.0}, {0.1,0.5,0.0} } ;
- vector< vector<float> > diffPlateCntPercent1 = { {0.7,0.7,0.0}, {0.6,0.8,0.1}, {0.5,0.9,0.1} } ;
-
- for(int ipbig = 1; ipbig <= PLATE_BG_MAX_CNT; ++ ipbig ) {
- for(int ipmid = 1 ; ipmid <= PLATE_MD_MAX_CNT; ++ ipmid ) {
- int effsmPlateCnt = ipbig*6 + ipmid*3 ;
- if( effsmPlateCnt>PLATE_SM_MAX_CNT ) continue ;
- for(int ipsml = 0 ; ipsml <= PLATE_SM_MAX_CNT; ++ ipsml ) {
- //等效小盘子个数
- effsmPlateCnt += ipsml ;
- if( effsmPlateCnt>PLATE_SM_MAX_CNT ) continue ;
-
- float bigPlateCntPercent = ipbig*6.0 / effsmPlateCnt ;
- float midPlateCntPercent = ipmid*3.0 / effsmPlateCnt ;
- float smlPlateCntPercent = ipsml*1.0 / effsmPlateCnt ;
- vector<float> percentArr = {bigPlateCntPercent,midPlateCntPercent,smlPlateCntPercent} ;
-
- //判断每个盘子百分比是否满足难度要求
- bool percentOk = true ;
- for(int iplatetype=0;iplatetype<percentArr.size();++iplatetype) {
- if( diffPlateCntPercent0[difficulty][iplatetype]>percentArr[iplatetype] || diffPlateCntPercent1[difficulty][iplatetype]<percentArr[iplatetype] )
- percentOk=false;
- }
- if(!percentOk) continue ;//盘子百分比不符合要求,跳过
-
- //计算每个类型的层数
- if( difficulty== FILLGLOBALCONFIG_DIFFCULTY_NORM ) {
- //全部两层
- vector<int> pidArr ;
- vector<int> capArr ;
- vector<int> lyrArr ;
- for(int it=0;it<ipbig;++it) { pidArr.push_back(bigPlate->_id);capArr.push_back(bigPlate->_bigJewCap*4); lyrArr.push_back(2); }
- for(int it=0;it<ipmid;++it) { pidArr.push_back(midPlate->_id);capArr.push_back(midPlate->_bigJewCap*4); lyrArr.push_back(2); }
- for(int it=0;it<ipsml;++it) { pidArr.push_back(smlPlate->_id);capArr.push_back(smlPlate->_bigJewCap*4); lyrArr.push_back(2); }
- bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt) ;
- if(!lyrOk) continue;
-
- //保存结果
- vector<LevelGenerate::PlateIdAndLayerCnt> tres(capArr.size()) ;
- for(int it = 0 ; it < capArr.size(); ++ it ) {
- tres[it]._plateId = pidArr[it] ;
- tres[it]._layerCnt = lyrArr[it] ;
- }
- possibleResults.push_back(tres) ;
-
- }else if( difficulty==FILLGLOBALCONFIG_DIFFCULTY_HARD2 ) {
- //全部3层
- vector<int> pidArr ;
- vector<int> capArr ;
- vector<int> lyrArr ;
- for(int it=0;it<ipbig;++it) { pidArr.push_back(bigPlate->_id);capArr.push_back(bigPlate->_bigJewCap*4); lyrArr.push_back(3); }
- for(int it=0;it<ipmid;++it) { pidArr.push_back(midPlate->_id);capArr.push_back(midPlate->_bigJewCap*4); lyrArr.push_back(3); }
- for(int it=0;it<ipsml;++it) { pidArr.push_back(smlPlate->_id);capArr.push_back(smlPlate->_bigJewCap*4); lyrArr.push_back(3); }
- bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt) ;
- if(!lyrOk) continue;
- //保存结果
- vector<LevelGenerate::PlateIdAndLayerCnt> tres(capArr.size()) ;
- for(int it = 0 ; it < capArr.size(); ++ it ) {
- tres[it]._plateId = pidArr[it] ;
- tres[it]._layerCnt = lyrArr[it] ;
- }
- possibleResults.push_back(tres) ;
- }else{
- //50% 2层, 50% 3层
- vector<int> pidArr ;
- vector<int> capArr ;
- vector<int> lyrArr ;
- 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); }
- 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); }
- 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); }
- bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt) ;
- if(!lyrOk) continue;
- //保存结果
- vector<LevelGenerate::PlateIdAndLayerCnt> tres(capArr.size()) ;
- for(int it = 0 ; it < capArr.size(); ++ it ) {
- tres[it]._plateId = pidArr[it] ;
- tres[it]._layerCnt = lyrArr[it] ;
- }
- possibleResults.push_back(tres) ;
- }
- }
- }
- }
- //debug 查看全部符合要求的结果
- if( possibleResults.size()> 0 ) {
- int randindex = rand() % possibleResults.size();
- results = possibleResults[randindex] ;
- }
- return results ;
- }
- //随机排序数组索引值
- vector<int> LevelGenerate::randIndices(const int count0 ) {
- int count = count0 ;
- vector<int> indices ;
- unordered_map<int, bool> dict ;
- while( count > 0 ) {
- int r = rand()%count0;
- if( dict.find(r) == dict.end() ) {
- dict[r] = true ;
- indices.push_back(r) ;
- count-- ;
- }
- }
- return indices;
- }
-
- bool LevelGenerate::isJustFilledAll2(
- const vector<int>& plateCaps,//每个盘子的容量
- const vector<int> eachPlateLyrCnt,//对应盘子的层数
- const int totSmlJewCnt )
- {
- assert(plateCaps.size()>0);
- assert(plateCaps.size()==eachPlateLyrCnt.size());
- int fillcnt1 = 0;
- for(int ip = 0 ;ip<plateCaps.size();++ip ) {
- fillcnt1 += plateCaps[ip] * eachPlateLyrCnt[ip] ;
- }
- if( fillcnt1 < totSmlJewCnt ) return false ;
- if( fillcnt1 == totSmlJewCnt ) return true ;
- for(int ip = 0 ; ip < plateCaps.size();++ip ) {
- int fillcnt2 = fillcnt1 - plateCaps[ip] ;
- if( fillcnt2 < totSmlJewCnt ) {
- return true ;
- }
- }
- return false ;
- }
- unordered_map<int, int> LevelGenerate::randPickJewels( const int needEquvSmlCnt,const float solvedPercent, unordered_map<int,tuple<int,int>>& jewStorages )
- {
- int needEquvSmlCnt2 = needEquvSmlCnt ;
- int storageEquvSmlCnt = 0 ;
- int storageJewTypeCnt = jewStorages.size() ;
- for(auto it=jewStorages.begin();it!=jewStorages.end();++it) storageEquvSmlCnt+= std::get<1>(it->second)*jewSz2SmlCnt(std::get<0>(it->second)) ;
- unordered_map<int, int> res ;
- const float solPer = fmax(0.0,fmin(solvedPercent,1.0f)) ;
-
- //首先尝试可解的百分比部分
- int solEqSmGrpCnt = needEquvSmlCnt*solPer/3 ;
- // 随机尝试solEqSmGrpCnt*2 次取宝石,每次取一组。
- int loopCnt=solEqSmGrpCnt*storageJewTypeCnt*10;//随机迭代数量加大10倍,避免有始终选不到的情况
- while( solEqSmGrpCnt> 0 && storageEquvSmlCnt>0 && loopCnt>0) {
- int randJewI = rand()%storageJewTypeCnt ;
- auto itjew = jewStorages.begin() ;
- std::advance(itjew, randJewI) ;
- int jid = itjew->first ;
- int storage1 = std::get<1>( itjew->second ) ;
- int oneGrpEqSmGrpCnt = jewSz2SmlCnt( std::get<0>(itjew->second) ) ;
- if( storage1>=3 && oneGrpEqSmGrpCnt<=solEqSmGrpCnt ) {
- //库存有,且满足所需可解组数
- std::get<1>(itjew->second)-=3 ;
- solEqSmGrpCnt -= oneGrpEqSmGrpCnt ;
- storageEquvSmlCnt -= oneGrpEqSmGrpCnt*3 ;
- needEquvSmlCnt2 -= oneGrpEqSmGrpCnt*3 ; //本次所需的剩余等效小宝石个数
- res[jid] += 3 ;
- }
- --loopCnt ;
- }
-
- //尝试剩余百分比和上一步剩余没有符合条件的个数
- loopCnt = needEquvSmlCnt2*storageJewTypeCnt ;
- int jindex = 0 ;
- while( loopCnt>0 && needEquvSmlCnt2> 0 && storageEquvSmlCnt>0 ) {
- auto itjew = jewStorages.begin() ;
- std::advance(itjew, jindex) ;
- int jid = itjew->first;
- int sz = std::get<0>(itjew->second) ;
- int stor = std::get<1>(itjew->second) ;
- int eqsmCnt = jewSz2SmlCnt(sz) ;
- if( stor>0 && eqsmCnt <= needEquvSmlCnt2 ) {
- std::get<1>(itjew->second)-=1 ;
- needEquvSmlCnt2-=eqsmCnt ;
- storageEquvSmlCnt-=eqsmCnt ;
- res[jid] += 1 ;
- }
- ++jindex ; if(jindex>=storageJewTypeCnt) jindex=0;//循环取之,直到本层所需全部取完
- --loopCnt;
- }
- return res ;
- }
- int LevelGenerate::jewSz2SmlCnt(int sz)
- {
- switch (sz) {
- case FILLGLOBALCONFIG_JEWELSIZE_LG:
- return 4;break;
- case FILLGLOBALCONFIG_JEWELSIZE_MD:
- return 2;break;
- default:
- return 1;break;
- }
- return 1;
- }
- vector<FillResult> LevelGenerate::fillPlateOneLayer(RandomGridFiller& filler,const int plateId, unordered_map<int,int>& jewStoragesForUse )
- {
- auto fgc = FillGlobalConfig::getInstance() ;
- vector<RandomGridFiller::JewelBox> jewBoxArray ;
- FillGlobalConfig::PlateItem* pl = FillGlobalConfig::getInstance()->getPlateItemById(plateId) ;
- int plateEqSmCap = pl->_bigJewCap*4 ;
- int jewTypeCnt = jewStoragesForUse.size() ;
- int eqSmStorageCnt = 0 ;
- for(auto it = jewStoragesForUse.begin();it!=jewStoragesForUse.end();++it) {
- int jewEqSmCnt = jewSz2SmlCnt( fgc->getJewelItemById(it->first)->_size );
- eqSmStorageCnt+=it->second*jewEqSmCnt ;
- }
- static int s_debug_cnt = 0;
- cout<<"debug "<< s_debug_cnt << " storage eqsm count "<<eqSmStorageCnt<< " currplate cap "<< plateEqSmCap <<endl;
- unordered_map<int, int> jewForPlateMap ;// <jewId,Cnt>
- int loopCnt = plateEqSmCap*jewTypeCnt*4;// 随机数量多给4倍
- while(plateEqSmCap>0 && eqSmStorageCnt>0 && loopCnt>0 ) {
- int radv = rand() % jewTypeCnt ;
- auto it = jewStoragesForUse.begin() ;
- std::advance(it, radv) ;
- int jewEqSmCnt = jewSz2SmlCnt( fgc->getJewelItemById(it->first)->_size );
- if( it->second>0 ) {
- if( jewEqSmCnt <= plateEqSmCap ) {
- plateEqSmCap -= jewEqSmCnt ;
- it->second -=1 ;
- eqSmStorageCnt -= jewEqSmCnt ;
- jewForPlateMap[it->first] += 1 ;
- if( it->second== 0 ) {
- jewStoragesForUse.erase(it) ;
- jewTypeCnt-- ;
- }
- }
- }else{
- jewStoragesForUse.erase(it) ;
- jewTypeCnt-- ;
- }
- --loopCnt ;
- }
-
- cout<<"debug "<< s_debug_cnt ++ <<" storage eqsm count "<<eqSmStorageCnt<< " currplate cap "<< plateEqSmCap <<endl;
-
- for(auto it = jewForPlateMap.begin();it!=jewForPlateMap.end();++it) {
- RandomGridFiller::JewelBox jbox ;
- jbox._cnt = it->second ;
- jbox._jewelTypeId = it->first ;
- jbox._width = fgc->getJewelItemById(it->first)->_bbWidth ;
- jbox._height = fgc->getJewelItemById(it->first)->_bbHeight ;
- jewBoxArray.push_back(jbox) ;
- }
-
- vector<FillResult> fillresults ;
- filler.fill(jewBoxArray, pl->_blx, pl->_bly, pl->_trx, pl->_try, fillresults) ;
- return fillresults ;
- }
- unordered_map<int, int> LevelGenerate::findUnfilledInStorages( unordered_map<int,tuple<int,int>>& jewStorages)
- {
- unordered_map<int, int> res ;
- for(auto itj = jewStorages.begin();itj!=jewStorages.end();++itj) {
- int stor = std::get<1>(itj->second) ;
- int jid = itj->first ;
- if( stor>0 ) {
- res[jid] = stor ;
- std::get<1>(itj->second) = 0 ;
- }
- }
- return res ;
- }
- void LevelGenerate::regroupPlateLyrFillResults( vector<tuple<int,int,vector<FillResult>>>& pidlyrFillArray, vector<tuple<int,vector<vector<FillResult>>>>& results )
- {
- int currLayer = 1 ;//从底层到顶层构建结果数据结构
- int num = pidlyrFillArray.size() ;
- int nloop = num ;
- while( nloop > 0 ) {
- cout<<"regroup for layer "<<currLayer<<endl;
- for( auto itlyr = pidlyrFillArray.begin(); itlyr!=pidlyrFillArray.end(); ++ itlyr ) {
- int pid = std::get<0>( *itlyr ) ;
- int lyr = std::get<1>( *itlyr ) ;
- vector<FillResult>& frs = std::get<2>(*itlyr) ;
- if(pid>=0) {
- if( lyr==currLayer ) {
- if( lyr==1 ) {
- vector<vector<FillResult>> frArr = {frs} ;
- results.push_back( {pid, frArr } ) ;
- num-- ;
- std::get<0>( *itlyr ) = -1 ;
- }else {
- for(auto itr = results.begin();itr!=results.end();++itr ) {
- int pidr = std::get<0>(*itr) ;
- vector<vector<FillResult>>& frArr = std::get<1>(*itr) ;
- if( pidr == pid && frArr.size()==currLayer-1 ) {
- frArr.push_back(frs);
- num-- ;
- std::get<0>( *itlyr ) = -1 ;
- break ;
- }
- }
- }
- }
- }
- }
- currLayer++ ;
- if( num==0 ) break ;
- nloop--;
- }
- cout<<"last plate lyr num "<<num<<endl;
- }
- void LevelGenerate::placePlates( const vector<int>& plateIdArr, vector<ContourData::Point>& resultPlateCenterPointArr )
- {
- auto fgc = FillGlobalConfig::getInstance() ;
- vector<vector<int>> plateSizeArr ;
- for(int ip = 0 ; ip < plateIdArr.size();++ip ) {
- FillGlobalConfig::PlateItem* plate1 = fgc->getPlateItemById(plateIdArr[ip]) ;
- vector<int> sz = { (int)plate1->_bbwid, (int)plate1->_bbhei } ;
- plateSizeArr.push_back(sz) ;
- }
- BoxPositionTool positionTool ;
- vector<vector<int>> resPosis ;
- const int GAME_REGION_WIDTH = 640 ;
- const int GAME_REGION_HEIGHT = 720 ;
- positionTool.solve(GAME_REGION_WIDTH,GAME_REGION_HEIGHT,plateSizeArr, resPosis) ;
- for(int ip=0;ip<resPosis.size();++ip ) {
- resultPlateCenterPointArr.push_back( { (float)resPosis[ip][0] , (float)resPosis[ip][1]} ) ;
- }
- }
|