|
@@ -13,12 +13,60 @@
|
|
|
#include <tuple>
|
|
|
#include "BoxPositionTool.hpp"
|
|
|
#include "GridPositionTool.hpp"
|
|
|
+//#include "LevelThumbTool.hpp"
|
|
|
+#include "LevelOutputWriter.hpp"
|
|
|
+
|
|
|
+#define MOVEID_NO_MOVE 0
|
|
|
+#define MOVEID_1ST_LINE 1
|
|
|
+#define MOVEID_2ND_LINE 2
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
+void LevelGenerate::generateAll(FillGlobalConfig::LevelData levelData, string outname)
|
|
|
+{
|
|
|
+ cout<<"debug level "<<levelData._id<<" subid "<<levelData._subId<<endl;
|
|
|
+ auto fgc = FillGlobalConfig::getInstance() ;
|
|
|
+ fgc->clearGridBoxFilledStatus() ;//每次填充盘子前必须清空盘子占位情况
|
|
|
+ vector<PlateFillResult> resultPlateFRs ;
|
|
|
+ vector<ContourData::Point> resultPlateCenterPosiArr ;
|
|
|
+ generate(levelData, false, nullptr , resultPlateFRs, resultPlateCenterPosiArr) ;
|
|
|
+ //输出结果
|
|
|
+// string pngName0 = outname + "_000000.png" ;
|
|
|
+// LevelThumbTool ltt ;
|
|
|
+// ltt.makeThumb3(pngName0, resultPlateFRs, resultPlateCenterPosiArr) ;
|
|
|
+
|
|
|
+ string jsonName = outname + "_000000.json" ;
|
|
|
+ LevelOutputWriter out ;
|
|
|
+ out.writeLevelJson(resultPlateFRs, resultPlateCenterPosiArr, jsonName) ;
|
|
|
+
|
|
|
+ //对于所有移动的配置
|
|
|
+ vector<FillGlobalConfig::MultiMoveConfig> mmcArr = fgc->getAllMoveConfigByJewels(levelData) ;
|
|
|
+ for(int im=0;im < mmcArr.size();++ im ) {
|
|
|
+ string moveName = mmcArr[im]._first->_type ;
|
|
|
+ if( mmcArr[im]._second ) moveName += mmcArr[im]._second->_type ;
|
|
|
+ else moveName += "00" ;
|
|
|
+ cout<<"debug moveName "<<moveName<<endl;
|
|
|
+ fgc->clearGridBoxFilledStatus() ;//每次填充盘子前必须清空盘子占位情况
|
|
|
+ vector<PlateFillResult> resultPlateFRs1 ;
|
|
|
+ vector<ContourData::Point> resultPlateCenterPosiArr1 ;
|
|
|
+ generate(levelData, true, &mmcArr[im] , resultPlateFRs1, resultPlateCenterPosiArr1) ;
|
|
|
+ //输出结果
|
|
|
+// string pngName1 = outname + "_" + moveName;
|
|
|
+// pngName1 += ".png" ;
|
|
|
+// ltt.makeThumb3(pngName1, resultPlateFRs1, resultPlateCenterPosiArr1) ;
|
|
|
+
|
|
|
+ string jsonName1 = outname + "_" + moveName + ".json" ;
|
|
|
+ LevelOutputWriter out1 ;
|
|
|
+ out1.writeLevelJson(resultPlateFRs1, resultPlateCenterPosiArr1, jsonName1) ;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
bool LevelGenerate::generate( FillGlobalConfig::LevelData levelData,
|
|
|
const bool isMovable,
|
|
|
- vector<tuple<int,vector<vector<FillResult>>>>& resultPlateFillResults,
|
|
|
+ const FillGlobalConfig::MultiMoveConfig* mulMoveConfig , //移动盘子配置,如果isMovable为false,这个参数忽略,可以传入nullptr
|
|
|
+ vector<PlateFillResult>& resultPlateFillResults,
|
|
|
vector<ContourData::Point>& resultPlateCenterPointArr
|
|
|
)
|
|
|
{
|
|
@@ -29,7 +77,7 @@ bool LevelGenerate::generate( FillGlobalConfig::LevelData levelData,
|
|
|
uint64_t ms00 = std::chrono::duration_cast<chrono::milliseconds>(ms0).count() ;
|
|
|
|
|
|
srand(_seed);
|
|
|
- unordered_map<int,tuple<int,int> > jewIdSzCntStorageMap ;
|
|
|
+ unordered_map<int,tuple<int,int> > jewIdSzCntStorageMap ;// unordered_map<宝石ID,tuple<尺寸,库存数量> >
|
|
|
FillGlobalConfig* fgc = FillGlobalConfig::getInstance() ;
|
|
|
int bigJewelCnt = 0 ;
|
|
|
int midJewelCnt = 0;
|
|
@@ -48,11 +96,14 @@ bool LevelGenerate::generate( FillGlobalConfig::LevelData levelData,
|
|
|
}
|
|
|
}
|
|
|
//每个盘子类型小号宝石承载量
|
|
|
- //按顺序分别为大横,大竖,小。这里不考虑迷你。
|
|
|
- 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} ;
|
|
|
+ //按顺序分别为大和中
|
|
|
+ FillGlobalConfig::PlateItem* bigPlateH = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_LG, 1) ;
|
|
|
+ FillGlobalConfig::PlateItem* midPlateH = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_MD, 1) ;
|
|
|
+ FillGlobalConfig::PlateItem* bigPlateV = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_LG, 0) ;
|
|
|
+ FillGlobalConfig::PlateItem* midPlateV = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_MD, 0) ;
|
|
|
+
|
|
|
+ //FillGlobalConfig::PlateItem* smlPlate = fgc->getPlateItemBySzNIndex(FILLGLOBALCONFIG_PLATESIZE_SM, 0) ;
|
|
|
+ vector<FillGlobalConfig::PlateItem*> usedPlates = {bigPlateH,midPlateH,bigPlateV,midPlateV} ;//{bigPlate,midPlate,smlPlate} ;
|
|
|
int maxSmlJewCapPerPlate = 0;
|
|
|
int minSmlJewCapPerPlate = 99999 ;
|
|
|
for(int ip=0;ip<usedPlates.size();++ip ) {
|
|
@@ -66,8 +117,8 @@ bool LevelGenerate::generate( FillGlobalConfig::LevelData levelData,
|
|
|
//cout<<"smlJewelCnt "<<smlJewelCnt<<endl;
|
|
|
//cout<<"effSmallJewelsCount "<<effSmallJewelsCount<<endl;
|
|
|
|
|
|
- //构建符合难度条件的盘子和层数组合
|
|
|
- vector<PlateIdAndLayerCnt> resPlateNLyrCnt = generatePlateTypeAndLayerCnts2(isMovable, levelData._difficulty,effSmallJewelsCount);
|
|
|
+ //构建符合难度条件的盘子和层数组合(包括可移动的盘子)
|
|
|
+ vector<PlateIdAndLayerCnt> resPlateNLyrCnt = generatePlateTypeAndLayerCnts2(isMovable, mulMoveConfig, levelData._difficulty,effSmallJewelsCount);
|
|
|
if( resPlateNLyrCnt.size()==0 ) {
|
|
|
//cout<<"failed at generatePlateTypeAndLayerCnts"<<endl;
|
|
|
return false ;
|
|
@@ -83,7 +134,7 @@ bool LevelGenerate::generate( FillGlobalConfig::LevelData levelData,
|
|
|
srand(filler._seed);
|
|
|
|
|
|
//构建每个盘子每个层的填充结果容器
|
|
|
- vector< tuple<int,int,vector<FillResult>> > plateIdLyrFillResultsArray ;// tuple<plateId, layerIndex, fillresults_array >
|
|
|
+ vector< tuple<int,int,vector<FillResult>,int> > plateIdLyrFillResultsMoveIdArray ;// tuple<plateId, layerIndex, fillresults_array ,moveId>
|
|
|
|
|
|
|
|
|
//从顶到底部,逐层进行填充
|
|
@@ -92,8 +143,15 @@ bool LevelGenerate::generate( FillGlobalConfig::LevelData levelData,
|
|
|
//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) ;
|
|
|
+ vector<int> plateIdArr ;//临时符合当前层次的盘子类型ID
|
|
|
+ vector<int> moveIdArr ;//临时保存对应盘子是否是可移动的,0-不可移动,1-第一移动行,2-第二移动行
|
|
|
+ for(auto it = resPlateNLyrCnt.begin();it!=resPlateNLyrCnt.end();++it )
|
|
|
+ {
|
|
|
+ if(it->_layerCnt>=nlayer) {
|
|
|
+ plateIdArr.push_back(it->_plateId) ;
|
|
|
+ moveIdArr.push_back( it->_moveId ) ;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
//该层总计需要填充多少小宝石
|
|
|
int currLyrNeedEquvSmlCnt = 0 ;
|
|
@@ -112,10 +170,12 @@ bool LevelGenerate::generate( FillGlobalConfig::LevelData levelData,
|
|
|
//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);
|
|
|
+ for(int ipid = 0 ; ipid !=plateIdArr.size();++ipid) {
|
|
|
+ int plateId1 = plateIdArr[ipid] ;
|
|
|
+ int moveId1 = moveIdArr[ipid] ;
|
|
|
+ vector<FillResult> fr = fillPlateOneLayer(filler, plateId1 , chosenJewIdNCnt) ;
|
|
|
+ tuple<int,int,vector<FillResult>,int> plateLyrFillResult={plateId1 , nlayer , fr , moveId1 } ;
|
|
|
+ plateIdLyrFillResultsMoveIdArray.push_back(plateLyrFillResult);
|
|
|
}
|
|
|
|
|
|
//检查为该层挑选的宝石是不是全部填完了,如果没有填完还要还给库存,给下一轮填充用
|
|
@@ -135,13 +195,13 @@ bool LevelGenerate::generate( FillGlobalConfig::LevelData levelData,
|
|
|
//剩了,添加一个小盘子和层,仍然剩了再继续加盘子加层
|
|
|
unordered_map<int, int> residueJewIdAndCnts = findUnfilledInStorages(jewIdSzCntStorageMap) ;
|
|
|
while( residueJewIdAndCnts.size()>0 ) {
|
|
|
- //新建一个小盘子
|
|
|
+ //新建一个中盘子
|
|
|
extraPlateCnt++;
|
|
|
//cout<<"add extra plate "<< extraPlateCnt <<endl;
|
|
|
- int plateId = smlPlate->_id ;
|
|
|
+ int plateId = midPlateH->_id ;
|
|
|
for(int ilyr = 1 ; ilyr <= maxLyrCnt; ++ ilyr ) {
|
|
|
vector<FillResult> frs = fillPlateOneLayer(filler, plateId, residueJewIdAndCnts) ;
|
|
|
- plateIdLyrFillResultsArray.push_back( {plateId,ilyr,frs} );
|
|
|
+ plateIdLyrFillResultsMoveIdArray.push_back( {plateId,ilyr,frs, MOVEID_NO_MOVE } );
|
|
|
//cout<<"add extra lyr "<<endl;
|
|
|
if( residueJewIdAndCnts.size()==0 ) break ;
|
|
|
}
|
|
@@ -150,13 +210,11 @@ bool LevelGenerate::generate( FillGlobalConfig::LevelData levelData,
|
|
|
}
|
|
|
|
|
|
//整理数据
|
|
|
- regroupPlateLyrFillResults(plateIdLyrFillResultsArray, resultPlateFillResults);
|
|
|
+ regroupPlateLyrFillResults(plateIdLyrFillResultsMoveIdArray, resultPlateFillResults);
|
|
|
|
|
|
//摆放盘子
|
|
|
{
|
|
|
- vector<int> plateIdArr1;
|
|
|
- for(auto itp = resultPlateFillResults.begin();itp!=resultPlateFillResults.end();++itp) plateIdArr1.push_back( std::get<0>(*itp) );
|
|
|
- placePlates(isMovable, plateIdArr1, resultPlateCenterPointArr) ;
|
|
|
+ placePlates(isMovable,mulMoveConfig, resultPlateFillResults, resultPlateCenterPointArr) ;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -170,343 +228,217 @@ bool LevelGenerate::generate( FillGlobalConfig::LevelData levelData,
|
|
|
[[deprecated]]
|
|
|
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} } ;
|
|
|
- bool isFirstGood = false;//由于盘子百分比计算不一定能满足盘子和宝石要求,为了保证至少有一个盘子组合可以用这里保留第一个可以装下宝石的盘子组合,如果有更优的方案替换之。
|
|
|
- vector<LevelGenerate::PlateIdAndLayerCnt> firstAvailablePlateComb ;
|
|
|
-
|
|
|
- for(int ipbig = 1; ipbig <= PLATE_BG_MAX_CNT; ++ ipbig ) {
|
|
|
- for(int ipmid = 0 ; 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( isFirstGood == true ){
|
|
|
- //至少有一个装下宝石的方案了
|
|
|
- if( !percentOk ) continue ;//盘子百分比不符合要求,跳过
|
|
|
- }
|
|
|
-
|
|
|
- if( isFirstGood==false ) {
|
|
|
- //保证至少有一个可以满足宝石的盘子组合
|
|
|
- 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(1); }
|
|
|
- for(int it=0;it<ipmid;++it) { pidArr.push_back(midPlate->_id);capArr.push_back(midPlate->_bigJewCap*4); lyrArr.push_back(1); }
|
|
|
- for(int it=0;it<ipsml;++it) { pidArr.push_back(smlPlate->_id);capArr.push_back(smlPlate->_bigJewCap*4); lyrArr.push_back(1); }
|
|
|
- bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt) ;
|
|
|
- if( lyrOk ){
|
|
|
- isFirstGood = true ;
|
|
|
- //保存结果
|
|
|
- firstAvailablePlateComb.resize(capArr.size());
|
|
|
- for(int it = 0 ; it < capArr.size(); ++ it ) {
|
|
|
- firstAvailablePlateComb[it]._plateId = pidArr[it] ;
|
|
|
- firstAvailablePlateComb[it]._layerCnt = lyrArr[it] ;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- //计算每个类型的层数
|
|
|
- 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) ;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- //随机挑选一个结果返回
|
|
|
- if( possibleResults.size()> 0 ) {
|
|
|
- int randindex = rand() % possibleResults.size();
|
|
|
- results = possibleResults[randindex] ;
|
|
|
- }else {
|
|
|
- results = firstAvailablePlateComb ;
|
|
|
- }
|
|
|
+ //...
|
|
|
+ //...
|
|
|
return results ;
|
|
|
}
|
|
|
|
|
|
//考虑可移动关卡的条件
|
|
|
-vector<LevelGenerate::PlateIdAndLayerCnt> LevelGenerate::generatePlateTypeAndLayerCnts2(const bool isMovable,const int difficulty,const int totEquvSmallJewelCnt)
|
|
|
+vector<LevelGenerate::PlateIdAndLayerCnt> LevelGenerate::generatePlateTypeAndLayerCnts2(
|
|
|
+ const bool isMovable,
|
|
|
+ const FillGlobalConfig::MultiMoveConfig* mulMoveConfig,
|
|
|
+ const int difficulty,
|
|
|
+ const int totEquvSmallJewelCnt
|
|
|
+ )
|
|
|
{
|
|
|
- //移动关卡相当于多了一个 大盘子,整个关卡最多可以达到10个大盘子
|
|
|
//如果是移动关卡,那么至少需要保证如下等价小盘子数量,如果减少层数仍然不能满足那么就有几个盘子输出几个
|
|
|
- const int MAX_LG_PLATE_CNT = 9 + (isMovable?1:0) ;
|
|
|
- const int MAX_SM_PLATE_CNT = MAX_LG_PLATE_CNT*4 ;
|
|
|
- const int MAX_SM_JEWEL_CNT_PER_LAYER = MAX_LG_PLATE_CNT * 24 ;
|
|
|
+ //const int MAX_LG_PLATE_CNT = 9 ;// + (isMovable?1:0) ;
|
|
|
+ // const int MAX_SM_PLATE_CNT = MAX_LG_PLATE_CNT*4 ;
|
|
|
+ //const int MAX_SM_JEWEL_CNT_PER_LAYER = MAX_LG_PLATE_CNT * 24 ;
|
|
|
+ const int MID_PLATE_CAP = 12 ;//中盘子对小宝石的容量
|
|
|
|
|
|
- const int minEquaSmPlateCntForMovable = 16 ; //
|
|
|
- const int smPlateEquaSmJewelCnt = 6 ;// 小盘子装1.5个大,3个中,6个小
|
|
|
+ //const int minEquaSmPlateCntForMovable = 16 ; //
|
|
|
+ //const int smPlateEquaSmJewelCnt = 6 ;// 小盘子装1.5个大,3个中,6个小
|
|
|
|
|
|
//一个关卡最多出现大、中、小盘子个数
|
|
|
- int bigPlateMaxCnt = 9 ;// 1个大盘子=2两个中盘子=4个小盘子
|
|
|
- if( isMovable ) {
|
|
|
- bigPlateMaxCnt = 10 ;
|
|
|
- }
|
|
|
- int midPlateMaxCnt = bigPlateMaxCnt * 2 ;
|
|
|
- int smlPlateMaxCnt = bigPlateMaxCnt * 2 ;
|
|
|
+ int tempBigPlateCnt1 = 9 ;// 1个大盘子=2两个中盘子
|
|
|
+ int tempMidPlateCnt1 = 0 ;
|
|
|
+ computePlateCount(mulMoveConfig, tempBigPlateCnt1, tempMidPlateCnt1) ;
|
|
|
+ int midPlateMaxCnt = tempBigPlateCnt1 * 2 + tempMidPlateCnt1 ;//大盘子数量换算成中盘子
|
|
|
|
|
|
|
|
|
- vector<LevelGenerate::PlateIdAndLayerCnt> results ;
|
|
|
-
|
|
|
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} ;
|
|
|
+ FillGlobalConfig::PlateItem* bigPlateH = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_LG, 1) ;
|
|
|
+ FillGlobalConfig::PlateItem* midPlateH = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_MD, 1) ;
|
|
|
+ FillGlobalConfig::PlateItem* bigPlateV = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_LG, 0) ;
|
|
|
+ FillGlobalConfig::PlateItem* midPlateV = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_MD, 0) ;
|
|
|
|
|
|
- int equvSmPlateCnt = ceil( totEquvSmallJewelCnt * 1.0 / 6) ; // 本款需要多少个一层小盘子的总数量
|
|
|
+ //如果是移动关卡,先构建移动盘子
|
|
|
+ int totEquvSmallJewelCnt2 = totEquvSmallJewelCnt ;
|
|
|
+ vector<LevelGenerate::PlateIdAndLayerCnt> results ;
|
|
|
+ //剩余可以用的中盘子个数
|
|
|
+ if( isMovable ) {
|
|
|
+ int residueEquvSmlJewelCnt = 0 ;
|
|
|
+ results = generatePlateTypeAndLayerCntsForMovablePlates(mulMoveConfig, totEquvSmallJewelCnt2, residueEquvSmlJewelCnt) ;
|
|
|
+ totEquvSmallJewelCnt2 = residueEquvSmlJewelCnt ;
|
|
|
+ //减去移动的盘子
|
|
|
+ for(int ir = 0 ; ir < results.size(); ++ ir ){
|
|
|
+ if( fgc->getPlateItemById(results[ir]._plateId)->_size == FILLGLOBALCONFIG_PLATESIZE_LG ) {
|
|
|
+ midPlateMaxCnt-=2 ;//减去移动的盘子
|
|
|
+ }else if(fgc->getPlateItemById(results[ir]._plateId)->_size == FILLGLOBALCONFIG_PLATESIZE_MD) {
|
|
|
+ midPlateMaxCnt-=1 ;//减去移动的盘子
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ int equvMidPlateCnt = ceil( totEquvSmallJewelCnt2 * 1.0 / MID_PLATE_CAP) ; // 本关需要多少个一层中盘子的总数量
|
|
|
int layerCnt0 = 1 ;//盘子层数下限
|
|
|
int layerCnt1 = 1 ;//盘子层数上限
|
|
|
|
|
|
//计算可能的层取值范围
|
|
|
- bool forceToFitMovable = false ;
|
|
|
- if( isMovable ) {
|
|
|
- if( equvSmPlateCnt <= minEquaSmPlateCntForMovable ) {
|
|
|
- //不足移动关卡所需最小的等效小盘子个数,那么直接组合盘子即可。
|
|
|
- layerCnt0 = 1 ;
|
|
|
- layerCnt1 = 1 ;
|
|
|
- forceToFitMovable = false ;
|
|
|
- }else
|
|
|
- {
|
|
|
- //10个大盘子,6个大宝石,等效于每层最多放置 10*6*4=240个小宝石
|
|
|
- layerCnt0 = fmax(1 , totEquvSmallJewelCnt / MAX_SM_JEWEL_CNT_PER_LAYER ) ;
|
|
|
- if( layerCnt0<3 ) layerCnt1 = 3 ;
|
|
|
- else layerCnt1 = layerCnt0 + 1 ;
|
|
|
- forceToFitMovable = true ;
|
|
|
- }
|
|
|
- }else {
|
|
|
- layerCnt0 = fmax(1 , totEquvSmallJewelCnt / MAX_SM_JEWEL_CNT_PER_LAYER ) ;
|
|
|
+ {
|
|
|
+ layerCnt0 = fmax(1 , totEquvSmallJewelCnt2 / (midPlateMaxCnt*MID_PLATE_CAP) ) ;
|
|
|
if( layerCnt0<3 ) layerCnt1 = 3 ;
|
|
|
else layerCnt1 = layerCnt0 + 1 ;
|
|
|
- forceToFitMovable = false ;
|
|
|
}
|
|
|
|
|
|
- int bigPlateCnt0 = totEquvSmallJewelCnt * 1.0 / layerCnt1 / 24 ; //大盘子最少需要数量
|
|
|
- int bigPlateCnt1 = totEquvSmallJewelCnt * 1.0 / layerCnt0 / 24 + 1; //大盘子最多需要数量
|
|
|
+ int bigPlateCnt0 = totEquvSmallJewelCnt2 * 1.0 / layerCnt1 / 24 ; //大盘子最少需要数量
|
|
|
+ int bigPlateCnt1 = totEquvSmallJewelCnt2 * 1.0 / layerCnt0 / 24 + 1; //大盘子最多需要数量
|
|
|
int midPlateCnt0 = bigPlateCnt0*2 ;
|
|
|
int midPlateCnt1 = bigPlateCnt1*2 ;
|
|
|
- int smlPlateCnt0 = bigPlateCnt0*4 ;
|
|
|
- int smlPlateCnt1 = bigPlateCnt1*4 ;
|
|
|
|
|
|
- bigPlateCnt1 = fmin( bigPlateMaxCnt ,bigPlateCnt1 ) ;
|
|
|
+ bigPlateCnt1 = fmin( midPlateMaxCnt/2 ,bigPlateCnt1 ) ;
|
|
|
midPlateCnt1 = fmin( midPlateMaxCnt ,midPlateCnt1 ) ;
|
|
|
- smlPlateCnt1 = fmin( smlPlateMaxCnt ,smlPlateCnt1 ) ;
|
|
|
|
|
|
bool findFirstAvailableComb = false ;//第一个完全放入宝石的组合,用于当不满足任何条件时,至少返回一个可装入全部宝石的默认方案
|
|
|
vector<vector<LevelGenerate::PlateIdAndLayerCnt>> possibleResults ;//满足全部百分比要求的组合
|
|
|
vector<LevelGenerate::PlateIdAndLayerCnt> firstAvailablePlateComb ;//第一个满足全部宝石填充的组合,如果需要移动还要考虑最小移动盘子个数的条件
|
|
|
int firstAvailableLyrCnt = 0 ;
|
|
|
|
|
|
- //难度对盘子数量的限制 普通 难 极难
|
|
|
- vector< vector<float> > hardPlateCntPercent0 = { {0.3,0.3,0.0}, {0.2,0.4,0.0}, {0.1,0.5,0.0} } ;
|
|
|
- vector< vector<float> > hardPlateCntPercent1 = { {0.7,0.7,0.0}, {0.6,0.8,0.1}, {0.5,0.9,0.1} } ;
|
|
|
+ //难度对盘子数量的限制 普通 难 极难
|
|
|
+ vector< vector<float> > hardPlateCntPercent0 = { {0.3,0.3}, {0.2,0.4}, {0.1,0.5} } ;
|
|
|
+ vector< vector<float> > hardPlateCntPercent1 = { {0.7,0.7}, {0.6,0.8}, {0.5,0.9} } ;
|
|
|
|
|
|
//穷举全部盘子和层的组合找到符合条件的组合
|
|
|
for(int ibig = 0; ibig <= bigPlateCnt1; ++ ibig ) {
|
|
|
for(int imid = 0; imid <= midPlateCnt1 ; ++ imid ) {
|
|
|
- for(int isml = 0 ; isml <= smlPlateCnt1; ++ isml ) {
|
|
|
- int equvSmPlateCnt1 = isml+imid*2+ibig*4 ;
|
|
|
- if( equvSmPlateCnt1==0 || equvSmPlateCnt1 > MAX_SM_PLATE_CNT ) continue ;
|
|
|
- if( equvSmPlateCnt1 < smlPlateCnt0 ) continue ;
|
|
|
- if( isMovable && forceToFitMovable ) if( equvSmPlateCnt1<minEquaSmPlateCntForMovable ) continue ;
|
|
|
-
|
|
|
- float bigPlateCntPercent = ibig*4.0 / equvSmPlateCnt1 ;
|
|
|
- float midPlateCntPercent = imid*2.0 / equvSmPlateCnt1 ;
|
|
|
- float smlPlateCntPercent = isml*1.0 / equvSmPlateCnt1 ;
|
|
|
- vector<float> percentArr = {bigPlateCntPercent,midPlateCntPercent,smlPlateCntPercent} ;
|
|
|
- //判断每个盘子百分比是否满足难度要求
|
|
|
- bool percentOk = true ;
|
|
|
- for(int iplatetype=0;iplatetype<percentArr.size();++iplatetype) {
|
|
|
- if( hardPlateCntPercent0[difficulty][iplatetype]>percentArr[iplatetype] || hardPlateCntPercent1[difficulty][iplatetype]<percentArr[iplatetype] )
|
|
|
- percentOk=false;
|
|
|
- }
|
|
|
- if( findFirstAvailableComb == true ){
|
|
|
- //至少有一个装下宝石的方案了
|
|
|
- if( !percentOk ) continue ;//盘子百分比不符合要求,跳过
|
|
|
- }
|
|
|
-
|
|
|
- if( findFirstAvailableComb==false || (findFirstAvailableComb && firstAvailableLyrCnt>3 ) ) {
|
|
|
- //保证至少有一个可以满足宝石的盘子组合,优先保存总层数大于3的情况
|
|
|
- //当前盘子组合下最小满足的层数
|
|
|
- int upperLyrCnt = ceil( totEquvSmallJewelCnt * 1.0 / (equvSmPlateCnt1*6) ) ;
|
|
|
- bool upperLyrCntOk = true ;
|
|
|
- if( findFirstAvailableComb ) {
|
|
|
- if( upperLyrCnt >= firstAvailableLyrCnt ) {
|
|
|
- upperLyrCntOk = false ;
|
|
|
- }
|
|
|
- }
|
|
|
- vector<int> pidArr ;
|
|
|
- vector<int> capArr ;
|
|
|
- vector<int> lyrArr ;
|
|
|
- for(int it=0;it<ibig;++it) { pidArr.push_back(bigPlate->_id);capArr.push_back(bigPlate->_bigJewCap*4); lyrArr.push_back(upperLyrCnt); }
|
|
|
- for(int it=0;it<imid;++it) { pidArr.push_back(midPlate->_id);capArr.push_back(midPlate->_bigJewCap*4); lyrArr.push_back(upperLyrCnt); }
|
|
|
- for(int it=0;it<isml;++it) { pidArr.push_back(smlPlate->_id);capArr.push_back(smlPlate->_bigJewCap*4); lyrArr.push_back(upperLyrCnt); }
|
|
|
- bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt) ;
|
|
|
- if( lyrOk==false && upperLyrCnt>1 ) {
|
|
|
- for(int it=0;it<lyrArr.size();++it ) {
|
|
|
- lyrArr[it] -= 1 ;
|
|
|
- lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt) ;
|
|
|
- if( lyrOk ) break ;
|
|
|
- }
|
|
|
- }
|
|
|
- if( lyrOk && upperLyrCntOk ){
|
|
|
- findFirstAvailableComb = true ;
|
|
|
- firstAvailableLyrCnt = upperLyrCnt ;
|
|
|
- //保存结果
|
|
|
- firstAvailablePlateComb.resize(capArr.size());
|
|
|
- for(int it = 0 ; it < capArr.size(); ++ it ) {
|
|
|
- firstAvailablePlateComb[it]._plateId = pidArr[it] ;
|
|
|
- firstAvailablePlateComb[it]._layerCnt = lyrArr[it] ;
|
|
|
- }
|
|
|
+ int currEquvMidPlateCnt = imid+ibig*2 ;
|
|
|
+ if( currEquvMidPlateCnt==0 || currEquvMidPlateCnt > midPlateMaxCnt ) continue ;
|
|
|
+
|
|
|
+ float bigPlateCntPercent = ibig*2.0 / currEquvMidPlateCnt ;
|
|
|
+ float midPlateCntPercent = imid*1.0 / currEquvMidPlateCnt ;
|
|
|
+ vector<float> percentArr = {bigPlateCntPercent,midPlateCntPercent} ;
|
|
|
+ //判断每个盘子百分比是否满足难度要求
|
|
|
+ bool percentOk = true ;
|
|
|
+ for(int iplatetype=0;iplatetype<percentArr.size();++iplatetype) {
|
|
|
+ if( hardPlateCntPercent0[difficulty][iplatetype]>percentArr[iplatetype] || hardPlateCntPercent1[difficulty][iplatetype]<percentArr[iplatetype] )
|
|
|
+ percentOk=false;
|
|
|
+ }
|
|
|
+ if( findFirstAvailableComb == true ){
|
|
|
+ //至少有一个装下宝石的方案了
|
|
|
+ if( !percentOk ) continue ;//盘子百分比不符合要求,跳过
|
|
|
+ }
|
|
|
+
|
|
|
+ if( findFirstAvailableComb==false || (findFirstAvailableComb && firstAvailableLyrCnt>3 ) ) {
|
|
|
+ //保证至少有一个可以满足宝石的盘子组合,优先保存总层数大于3的情况
|
|
|
+ //当前盘子组合下最小满足的层数
|
|
|
+ int upperLyrCnt = ceil( totEquvSmallJewelCnt2 * 1.0 / (currEquvMidPlateCnt*MID_PLATE_CAP) ) ;
|
|
|
+ bool upperLyrCntOk = true ;
|
|
|
+ if( findFirstAvailableComb ) {
|
|
|
+ if( upperLyrCnt >= firstAvailableLyrCnt ) {
|
|
|
+ upperLyrCntOk = false ;
|
|
|
}
|
|
|
}
|
|
|
- //计算每个类型的层数
|
|
|
- if( difficulty== FILLGLOBALCONFIG_DIFFCULTY_NORM ) {
|
|
|
- //全部两层
|
|
|
- vector<int> pidArr ;
|
|
|
- vector<int> capArr ;
|
|
|
- vector<int> lyrArr ;
|
|
|
- for(int it=0;it<ibig;++it) { pidArr.push_back(bigPlate->_id);capArr.push_back(bigPlate->_bigJewCap*4); lyrArr.push_back(2); }
|
|
|
- for(int it=0;it<imid;++it) { pidArr.push_back(midPlate->_id);capArr.push_back(midPlate->_bigJewCap*4); lyrArr.push_back(2); }
|
|
|
- for(int it=0;it<isml;++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] ;
|
|
|
+ vector<int> pidArr ;
|
|
|
+ vector<int> capArr ;
|
|
|
+ vector<int> lyrArr ;
|
|
|
+ //根据需求文档,非移动盘子,大盘子只用竖的,中盘子只用横的。
|
|
|
+ for(int it=0;it<ibig;++it) { pidArr.push_back(bigPlateV->_id);capArr.push_back(bigPlateV->_bigJewCap*4); lyrArr.push_back(upperLyrCnt); }
|
|
|
+ for(int it=0;it<imid;++it) { pidArr.push_back(midPlateH->_id);capArr.push_back(midPlateH->_bigJewCap*4); lyrArr.push_back(upperLyrCnt); }
|
|
|
+ bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt2) ;
|
|
|
+ if( lyrOk==false && upperLyrCnt>1 ) {
|
|
|
+ for(int it=0;it<lyrArr.size();++it ) {
|
|
|
+ lyrArr[it] -= 1 ;
|
|
|
+ lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt2) ;
|
|
|
+ if( lyrOk ) break ;
|
|
|
}
|
|
|
- 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<ibig;++it) { pidArr.push_back(bigPlate->_id);capArr.push_back(bigPlate->_bigJewCap*4); lyrArr.push_back(3); }
|
|
|
- for(int it=0;it<imid;++it) { pidArr.push_back(midPlate->_id);capArr.push_back(midPlate->_bigJewCap*4); lyrArr.push_back(3); }
|
|
|
- for(int it=0;it<isml;++it) { pidArr.push_back(smlPlate->_id);capArr.push_back(smlPlate->_bigJewCap*4); lyrArr.push_back(3); }
|
|
|
- //cout<<"debug big "<<ibig<<" mid "<<imid<<" sml "<<isml<<endl;
|
|
|
- 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<ibig;++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<imid;++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<isml;++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;
|
|
|
+ }
|
|
|
+ if( lyrOk && upperLyrCntOk ){
|
|
|
+ findFirstAvailableComb = true ;
|
|
|
+ firstAvailableLyrCnt = upperLyrCnt ;
|
|
|
//保存结果
|
|
|
- vector<LevelGenerate::PlateIdAndLayerCnt> tres(capArr.size()) ;
|
|
|
+ firstAvailablePlateComb.resize(capArr.size());
|
|
|
for(int it = 0 ; it < capArr.size(); ++ it ) {
|
|
|
- tres[it]._plateId = pidArr[it] ;
|
|
|
- tres[it]._layerCnt = lyrArr[it] ;
|
|
|
+ firstAvailablePlateComb[it]._plateId = pidArr[it] ;
|
|
|
+ firstAvailablePlateComb[it]._layerCnt = lyrArr[it] ;
|
|
|
+ firstAvailablePlateComb[it]._moveId = MOVEID_NO_MOVE ;
|
|
|
}
|
|
|
- possibleResults.push_back(tres) ;
|
|
|
}
|
|
|
+ }
|
|
|
+ //计算每个类型的层数
|
|
|
+ if( difficulty== FILLGLOBALCONFIG_DIFFCULTY_NORM ) {
|
|
|
+ //全部两层
|
|
|
+ vector<int> pidArr ;
|
|
|
+ vector<int> capArr ;
|
|
|
+ vector<int> lyrArr ;
|
|
|
+ //根据需求文档,非移动盘子,大盘子只用竖的,中盘子只用横的。
|
|
|
+ for(int it=0;it<ibig;++it) { pidArr.push_back(bigPlateV->_id);capArr.push_back(bigPlateV->_bigJewCap*4); lyrArr.push_back(2); }
|
|
|
+ for(int it=0;it<imid;++it) { pidArr.push_back(midPlateH->_id);capArr.push_back(midPlateH->_bigJewCap*4); lyrArr.push_back(2); }
|
|
|
+ bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt2) ;
|
|
|
+ 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] ;
|
|
|
+ tres[it]._moveId = MOVEID_NO_MOVE ;//不会移动的盘子
|
|
|
+ }
|
|
|
+ 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<ibig;++it) { pidArr.push_back(bigPlateV->_id);capArr.push_back(bigPlateV->_bigJewCap*4); lyrArr.push_back(3); }
|
|
|
+ for(int it=0;it<imid;++it) { pidArr.push_back(midPlateH->_id);capArr.push_back(midPlateH->_bigJewCap*4); lyrArr.push_back(3); }
|
|
|
+ //cout<<"debug big "<<ibig<<" mid "<<imid<<" sml "<<isml<<endl;
|
|
|
+ bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt2) ;
|
|
|
+ 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] ;
|
|
|
+ tres[it]._moveId = MOVEID_NO_MOVE ;//不会移动的盘子
|
|
|
+ }
|
|
|
+ possibleResults.push_back(tres) ;
|
|
|
+ }else{
|
|
|
+ //50% 2层, 50% 3层
|
|
|
+ vector<int> pidArr ;
|
|
|
+ vector<int> capArr ;
|
|
|
+ vector<int> lyrArr ;
|
|
|
+ //根据需求文档,非移动盘子,大盘子只用竖的,中盘子只用横的。
|
|
|
+ for(int it=0;it<ibig;++it) { pidArr.push_back(bigPlateV->_id);capArr.push_back(bigPlateV->_bigJewCap*4); lyrArr.push_back((rand()%2==0)?2:3); }
|
|
|
+ for(int it=0;it<imid;++it) { pidArr.push_back(midPlateH->_id);capArr.push_back(midPlateH->_bigJewCap*4); lyrArr.push_back((rand()%2==0)?2:3); }
|
|
|
+ bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt2) ;
|
|
|
+ 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] ;
|
|
|
+ tres[it]._moveId = MOVEID_NO_MOVE ;//不会移动的盘子
|
|
|
+ }
|
|
|
+ possibleResults.push_back(tres) ;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
//随机挑选一个结果返回
|
|
|
if( possibleResults.size()> 0 ) {
|
|
|
int randindex = rand() % possibleResults.size();
|
|
|
- results = possibleResults[randindex] ;
|
|
|
+ for(int ip = 0 ; ip < possibleResults[randindex].size();++ ip ) {
|
|
|
+ results.push_back(possibleResults[randindex][ip]) ;
|
|
|
+ }
|
|
|
}else {
|
|
|
- results = firstAvailablePlateComb ;
|
|
|
+ for(int ip = 0 ; ip < firstAvailablePlateComb.size();++ ip ) {
|
|
|
+ results.push_back(firstAvailablePlateComb[ip]) ;
|
|
|
+ }
|
|
|
}
|
|
|
- return results ;
|
|
|
+ return results ;//
|
|
|
|
|
|
}
|
|
|
|
|
@@ -687,29 +619,38 @@ unordered_map<int, int> LevelGenerate::findUnfilledInStorages( unordered_map<int
|
|
|
}
|
|
|
|
|
|
|
|
|
-void LevelGenerate::regroupPlateLyrFillResults( vector<tuple<int,int,vector<FillResult>>>& pidlyrFillArray, vector<tuple<int,vector<vector<FillResult>>>>& results )
|
|
|
+void LevelGenerate::regroupPlateLyrFillResults(
|
|
|
+ vector<tuple<int,int,vector<FillResult>,int>>& pidlyrFillMvidArray,
|
|
|
+ vector<PlateFillResult>& results)
|
|
|
{
|
|
|
int currLayer = 1 ;//从底层到顶层构建结果数据结构
|
|
|
- int num = pidlyrFillArray.size() ;
|
|
|
+ int num = pidlyrFillMvidArray.size() ;
|
|
|
int nloop = num ;
|
|
|
while( nloop > 0 ) {
|
|
|
//cout<<"regroup for layer "<<currLayer<<endl;
|
|
|
- for( auto itlyr = pidlyrFillArray.begin(); itlyr!=pidlyrFillArray.end(); ++ itlyr ) {
|
|
|
+ for( auto itlyr = pidlyrFillMvidArray.begin(); itlyr!=pidlyrFillMvidArray.end(); ++ itlyr ) {
|
|
|
int pid = std::get<0>( *itlyr ) ;
|
|
|
int lyr = std::get<1>( *itlyr ) ;
|
|
|
vector<FillResult>& frs = std::get<2>(*itlyr) ;
|
|
|
+ int moveId = std::get<3>(*itlyr) ;
|
|
|
+
|
|
|
if(pid>=0) {
|
|
|
if( lyr==currLayer ) {
|
|
|
if( lyr==1 ) {
|
|
|
vector<vector<FillResult>> frArr = {frs} ;
|
|
|
- results.push_back( {pid, frArr } ) ;
|
|
|
+ PlateFillResult pfr ;
|
|
|
+ pfr._layersFillResults = frArr ;
|
|
|
+ pfr._moveId = moveId ;
|
|
|
+ pfr._plateTypeId = pid ;
|
|
|
+ results.push_back( pfr ) ;
|
|
|
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 ) {
|
|
|
+ for(auto itPfr = results.begin();itPfr!=results.end();++itPfr ) {
|
|
|
+ int pidr = itPfr->_plateTypeId ;
|
|
|
+ int mvid = itPfr->_moveId ;
|
|
|
+ vector<vector<FillResult>>& frArr = itPfr->_layersFillResults ;
|
|
|
+ if( pidr == pid && mvid == moveId && frArr.size()==currLayer-1 ) {
|
|
|
frArr.push_back(frs);
|
|
|
num-- ;
|
|
|
std::get<0>( *itlyr ) = -1 ;
|
|
@@ -729,12 +670,144 @@ void LevelGenerate::regroupPlateLyrFillResults( vector<tuple<int,int,vector<Fill
|
|
|
|
|
|
|
|
|
|
|
|
-void LevelGenerate::placePlates(const bool movable, const vector<int>& plateIdArr, vector<ContourData::Point>& resultPlateCenterPointArr )
|
|
|
+void LevelGenerate::placePlates(const bool movable,
|
|
|
+ const FillGlobalConfig::MultiMoveConfig* mulMoveConfig,
|
|
|
+ const vector<PlateFillResult>& plateFRArr,
|
|
|
+ vector<ContourData::Point>& resultPlateCenterPointArr )
|
|
|
{
|
|
|
GridPositionTool gpt ;
|
|
|
+ vector<int> plateIdArr ;
|
|
|
+ vector<int> moveIdArr ;
|
|
|
+ for(int ip = 0 ; ip < plateFRArr.size(); ++ ip ) {
|
|
|
+ plateIdArr.push_back( plateFRArr[ip]._plateTypeId ) ;
|
|
|
+ moveIdArr.push_back( plateFRArr[ip]._moveId ) ;
|
|
|
+ }
|
|
|
+
|
|
|
vector<vector<int>> resPosis ;
|
|
|
- gpt.solve(movable, plateIdArr, resPosis) ;
|
|
|
+
|
|
|
+ string firstMoveTypeCode = "" ;
|
|
|
+ string secondMoveTypeCode = "" ;
|
|
|
+ if( movable ) {
|
|
|
+ firstMoveTypeCode = mulMoveConfig->_first->_type[0] ;
|
|
|
+ if( mulMoveConfig->_second ) secondMoveTypeCode = mulMoveConfig->_second->_type[0] ;
|
|
|
+ }
|
|
|
+ gpt.solve(movable,
|
|
|
+ firstMoveTypeCode ,
|
|
|
+ secondMoveTypeCode,
|
|
|
+ plateIdArr,
|
|
|
+ moveIdArr,
|
|
|
+ resPosis //这里结果是盘子左下角坐标,下面需要转换成中心坐标。
|
|
|
+ ) ;
|
|
|
+
|
|
|
for(int ip=0;ip<resPosis.size();++ip ) {
|
|
|
- resultPlateCenterPointArr.push_back( { (float)resPosis[ip][0] , (float)resPosis[ip][1]} ) ;
|
|
|
+ FillGlobalConfig::PlateItem* platePtr = FillGlobalConfig::getInstance()->getPlateItemById(plateIdArr[ip]) ;
|
|
|
+ resultPlateCenterPointArr.push_back( { (float)resPosis[ip][0]+platePtr->_bbwid/2 , (float)resPosis[ip][1]+platePtr->_bbhei/2} ) ;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+vector<LevelGenerate::PlateIdAndLayerCnt>
|
|
|
+ LevelGenerate::generatePlateTypeAndLayerCntsForMovablePlates(
|
|
|
+ const FillGlobalConfig::MultiMoveConfig* mulMoveConfig,
|
|
|
+ const int totEquvSmallJewelCnt,
|
|
|
+ int& retResidueEquvSmlJewelCnt )
|
|
|
+{
|
|
|
+ vector<LevelGenerate::PlateIdAndLayerCnt> results ;
|
|
|
+ retResidueEquvSmlJewelCnt = totEquvSmallJewelCnt ;
|
|
|
+ FillGlobalConfig* fgc = FillGlobalConfig::getInstance() ;
|
|
|
+ FillGlobalConfig::PlateItem* bigPlateH = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_LG, 1) ;
|
|
|
+ FillGlobalConfig::PlateItem* midPlateH = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_MD, 1) ;
|
|
|
+ FillGlobalConfig::PlateItem* bigPlateV = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_LG, 0) ;
|
|
|
+ FillGlobalConfig::PlateItem* midPlateV = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_MD, 0) ;
|
|
|
+
|
|
|
+ const int MAX_MOVE_CONFIG_CNT = 2;
|
|
|
+ FillGlobalConfig::MoveConfig* arr[MAX_MOVE_CONFIG_CNT] = { mulMoveConfig->_first , mulMoveConfig->_second } ;
|
|
|
+ for(int ii = 0 ; ii < MAX_MOVE_CONFIG_CNT ; ++ ii ) {
|
|
|
+ FillGlobalConfig::MoveConfig* moveConfig = arr[ii] ;
|
|
|
+ if( moveConfig==nullptr ) continue ;
|
|
|
+ //中盘子横
|
|
|
+ for(int imid = 0 ; imid < moveConfig->_midPlateCntH ; ++ imid ) {
|
|
|
+ PlateIdAndLayerCnt palc ;
|
|
|
+ palc._layerCnt = moveConfig->_nLayer ;
|
|
|
+ palc._plateId = midPlateH->_id ;
|
|
|
+ palc._moveId = ii+1 ;//第一行为1,第二行为2
|
|
|
+ results.push_back(palc) ;
|
|
|
+ retResidueEquvSmlJewelCnt -= midPlateH->_bigJewCap*4*palc._layerCnt ;
|
|
|
+ }
|
|
|
+ //中盘子竖
|
|
|
+ for(int imid = 0 ; imid < moveConfig->_midPlateCntV ; ++ imid ) {
|
|
|
+ PlateIdAndLayerCnt palc ;
|
|
|
+ palc._layerCnt = moveConfig->_nLayer ;
|
|
|
+ palc._plateId = midPlateV->_id ;
|
|
|
+ palc._moveId = ii+1 ;
|
|
|
+ results.push_back(palc) ;
|
|
|
+ retResidueEquvSmlJewelCnt -= midPlateV->_bigJewCap*4*palc._layerCnt ;
|
|
|
+ }
|
|
|
+ //大盘子横
|
|
|
+ for(int ibig = 0 ; ibig < moveConfig->_bigPlateCntH ; ++ ibig ) {
|
|
|
+ PlateIdAndLayerCnt palc ;
|
|
|
+ palc._layerCnt = moveConfig->_nLayer ;
|
|
|
+ palc._plateId = bigPlateH->_id ;
|
|
|
+ palc._moveId = ii+1 ;
|
|
|
+ results.push_back(palc) ;
|
|
|
+ retResidueEquvSmlJewelCnt -= bigPlateH->_bigJewCap*4*palc._layerCnt ;
|
|
|
+ }
|
|
|
+ //大盘子竖
|
|
|
+ for(int ibig = 0 ; ibig < moveConfig->_bigPlateCntV ; ++ ibig ) {
|
|
|
+ PlateIdAndLayerCnt palc ;
|
|
|
+ palc._layerCnt = moveConfig->_nLayer ;
|
|
|
+ palc._plateId = bigPlateV->_id ;
|
|
|
+ palc._moveId = ii+1 ;
|
|
|
+ results.push_back(palc) ;
|
|
|
+ retResidueEquvSmlJewelCnt -= bigPlateV->_bigJewCap*4*palc._layerCnt ;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return results ;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void LevelGenerate::computePlateCount(const FillGlobalConfig::MultiMoveConfig* mmc ,int& retBigPlateCnt, int& retMidPlateCnt )
|
|
|
+{
|
|
|
+ if( mmc==nullptr ) {
|
|
|
+ retBigPlateCnt = 9 ;
|
|
|
+ retMidPlateCnt = 0 ;
|
|
|
+ }else
|
|
|
+ if( mmc->_first && mmc->_second ) {
|
|
|
+ if( mmc->_first->_type.find("A") != string::npos && mmc->_second->_type.compare("A") != string::npos ) {
|
|
|
+ retBigPlateCnt = 6 ;
|
|
|
+ retMidPlateCnt = 8 ;
|
|
|
+ }else if( mmc->_first->_type.compare("B") != string::npos && mmc->_second->_type.compare("B") != string::npos ) {
|
|
|
+ retBigPlateCnt = 9 ;
|
|
|
+ retMidPlateCnt = 0 ;
|
|
|
+ }else if( mmc->_first->_type.compare("C") != string::npos && mmc->_second->_type.compare("C") != string::npos ) {
|
|
|
+ retBigPlateCnt = 11 ;
|
|
|
+ retMidPlateCnt = 0 ;
|
|
|
+ }else if( mmc->_first->_type.compare("B") != string::npos && mmc->_second->_type.compare("A") != string::npos) {
|
|
|
+ retBigPlateCnt = 6 ;
|
|
|
+ retMidPlateCnt = 7 ;
|
|
|
+ }else if( mmc->_first->_type.compare("C") != string::npos && mmc->_second->_type.compare("B") != string::npos ) {
|
|
|
+ retBigPlateCnt = 10 ;
|
|
|
+ retMidPlateCnt = 0 ;
|
|
|
+ }else if( mmc->_first->_type.compare("C") != string::npos && mmc->_second->_type.compare("A") != string::npos ) {
|
|
|
+ retBigPlateCnt = 7 ;
|
|
|
+ retMidPlateCnt = 7 ;
|
|
|
+ }
|
|
|
+
|
|
|
+ }else if( mmc->_first && mmc->_second==nullptr ) {
|
|
|
+ if( mmc->_first->_type.compare("A") != string::npos ) {
|
|
|
+ retBigPlateCnt = 6 ;
|
|
|
+ retMidPlateCnt = 7 ;
|
|
|
+ }else if( mmc->_first->_type.compare("B") != string::npos ) {
|
|
|
+ retBigPlateCnt = 9 ;
|
|
|
+ retMidPlateCnt = 0 ;
|
|
|
+ }else if( mmc->_first->_type.compare("C") != string::npos ) {
|
|
|
+ retBigPlateCnt = 10 ;
|
|
|
+ retMidPlateCnt = 0 ;
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ retBigPlateCnt = 9 ;
|
|
|
+ retMidPlateCnt = 0 ;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|