CMapGenerator.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include "StdInc.h"
  2. #include "CMapGenerator.h"
  3. #include "../mapping/CMap.h"
  4. #include "../VCMI_Lib.h"
  5. #include "../CGeneralTextHandler.h"
  6. #include "../mapping/CMapEditManager.h"
  7. #include "../CObjectHandler.h"
  8. #include "../CDefObjInfoHandler.h"
  9. #include "../GameConstants.h"
  10. #include "../CTownHandler.h"
  11. #include "../StringConstants.h"
  12. CMapGenerator::CMapGenerator(const CMapGenOptions & mapGenOptions, int randomSeed) :
  13. mapGenOptions(mapGenOptions), randomSeed(randomSeed)
  14. {
  15. gen.seed(randomSeed);
  16. }
  17. CMapGenerator::~CMapGenerator()
  18. {
  19. }
  20. std::unique_ptr<CMap> CMapGenerator::generate()
  21. {
  22. mapGenOptions.finalize(gen);
  23. //TODO select a template based on the map gen options or adapt it if necessary
  24. map = make_unique<CMap>();
  25. addHeaderInfo();
  26. terViewPatternConfig = make_unique<CTerrainViewPatternConfig>();
  27. mapMgr = make_unique<CMapEditManager>(terViewPatternConfig.get(), map.get(), randomSeed);
  28. genTerrain();
  29. genTowns();
  30. return std::move(map);
  31. }
  32. std::string CMapGenerator::getMapDescription() const
  33. {
  34. const std::string waterContentStr[3] = { "none", "normal", "islands" };
  35. const std::string monsterStrengthStr[3] = { "weak", "normal", "strong" };
  36. std::stringstream ss;
  37. ss << "Map created by the Random Map Generator.\nTemplate was <MOCK>, ";
  38. ss << "Random seed was " << randomSeed << ", size " << map->width << "x";
  39. ss << map->height << ", levels " << (map->twoLevel ? "2" : "1") << ", ";
  40. ss << "humans " << static_cast<int>(mapGenOptions.getPlayersCnt()) << ", computers ";
  41. ss << static_cast<int>(mapGenOptions.getCompOnlyPlayersCnt()) << ", water " << waterContentStr[mapGenOptions.getWaterContent()];
  42. ss << ", monster " << monsterStrengthStr[mapGenOptions.getMonsterStrength()] << ", second expansion map";
  43. BOOST_FOREACH(const auto & pair, mapGenOptions.getPlayersSettings())
  44. {
  45. const auto & pSettings = pair.second;
  46. if(pSettings.getPlayerType() == EPlayerType::HUMAN)
  47. {
  48. ss << ", " << GameConstants::PLAYER_COLOR_NAMES[pSettings.getColor().getNum()] << " is human";
  49. }
  50. if(pSettings.getStartingTown() != CMapGenOptions::CPlayerSettings::RANDOM_TOWN)
  51. {
  52. ss << ", " << GameConstants::PLAYER_COLOR_NAMES[pSettings.getColor().getNum()]
  53. << " town choice is " << ETownType::names[pSettings.getStartingTown()];
  54. }
  55. }
  56. return ss.str();
  57. }
  58. void CMapGenerator::addPlayerInfo()
  59. {
  60. // Calculate which team numbers exist
  61. std::array<std::list<int>, 2> teamNumbers; // 0= cpu/human, 1= cpu only
  62. int teamOffset = 0;
  63. for(int i = 0; i < 2; ++i)
  64. {
  65. int playersCnt = i == 0 ? mapGenOptions.getPlayersCnt() : mapGenOptions.getCompOnlyPlayersCnt();
  66. int teamsCnt = i == 0 ? mapGenOptions.getTeamsCnt() : mapGenOptions.getCompOnlyTeamsCnt();
  67. if(playersCnt == 0)
  68. {
  69. continue;
  70. }
  71. int playersPerTeam = playersCnt /
  72. (teamsCnt == 0 ? playersCnt : teamsCnt);
  73. int teamsCntNorm = teamsCnt;
  74. if(teamsCntNorm == 0)
  75. {
  76. teamsCntNorm = playersCnt;
  77. }
  78. for(int j = 0; j < teamsCntNorm; ++j)
  79. {
  80. for(int k = 0; k < playersPerTeam; ++k)
  81. {
  82. teamNumbers[i].push_back(j + teamOffset);
  83. }
  84. }
  85. for(int j = 0; j < playersCnt - teamsCntNorm * playersPerTeam; ++j)
  86. {
  87. teamNumbers[i].push_back(j + teamOffset);
  88. }
  89. teamOffset += teamsCntNorm;
  90. }
  91. // Team numbers are assigned randomly to every player
  92. BOOST_FOREACH(const auto & pair, mapGenOptions.getPlayersSettings())
  93. {
  94. const auto & pSettings = pair.second;
  95. PlayerInfo player;
  96. player.canComputerPlay = true;
  97. int j = pSettings.getPlayerType() == EPlayerType::COMP_ONLY ? 1 : 0;
  98. if(j == 0)
  99. {
  100. player.canHumanPlay = true;
  101. }
  102. auto itTeam = std::next(teamNumbers[j].begin(), gen.getInteger(0, teamNumbers[j].size() - 1));
  103. player.team = TeamID(*itTeam);
  104. teamNumbers[j].erase(itTeam);
  105. map->players[pSettings.getColor().getNum()] = player;
  106. }
  107. map->howManyTeams = (mapGenOptions.getTeamsCnt() == 0 ? mapGenOptions.getPlayersCnt() : mapGenOptions.getTeamsCnt())
  108. + (mapGenOptions.getCompOnlyTeamsCnt() == 0 ? mapGenOptions.getCompOnlyPlayersCnt() : mapGenOptions.getCompOnlyTeamsCnt());
  109. }
  110. void CMapGenerator::genTerrain()
  111. {
  112. map->initTerrain(); //FIXME nicer solution
  113. mapMgr->clearTerrain();
  114. mapMgr->drawTerrain(ETerrainType::GRASS, 10, 10, 20, 30, false);
  115. }
  116. void CMapGenerator::genTowns()
  117. {
  118. //FIXME mock gen
  119. const int3 townPos[2] = { int3(17, 13, 0), int3(25,13, 0) };
  120. const int townTypes[2] = { ETownType::CASTLE, ETownType::DUNGEON };
  121. for(size_t i = 0; i < map->players.size(); ++i)
  122. {
  123. auto & playerInfo = map->players[i];
  124. if(!playerInfo.canAnyonePlay()) break;
  125. PlayerColor owner(i);
  126. int side = i % 2;
  127. CGTownInstance * town = new CGTownInstance();
  128. town->ID = Obj::TOWN;
  129. town->subID = townTypes[side];
  130. town->tempOwner = owner;
  131. town->defInfo = VLC->dobjinfo->gobjs[town->ID][town->subID];
  132. town->builtBuildings.insert(BuildingID::FORT);
  133. town->builtBuildings.insert(BuildingID::DEFAULT);
  134. mapMgr->insertObject(town, townPos[side].x, townPos[side].y + (i / 2) * 5, false);
  135. // Update player info
  136. playerInfo.allowedFactions.clear();
  137. playerInfo.allowedFactions.insert(townTypes[side]);
  138. playerInfo.hasMainTown = true;
  139. playerInfo.posOfMainTown = town->pos - int3(2, 0, 0);
  140. playerInfo.generateHeroAtMainTown = true;
  141. }
  142. }
  143. void CMapGenerator::addHeaderInfo()
  144. {
  145. map->version = EMapFormat::SOD;
  146. map->width = mapGenOptions.getWidth();
  147. map->height = mapGenOptions.getHeight();
  148. map->twoLevel = mapGenOptions.getHasTwoLevels();
  149. map->name = VLC->generaltexth->allTexts[740];
  150. map->description = getMapDescription();
  151. map->difficulty = 1;
  152. addPlayerInfo();
  153. }