瀏覽代碼

- Reduced complexity to use the CMapGenerator(simpler interface) - Removed h3m.txt and tchar_amigaos4.h

beegee1 12 年之前
父節點
當前提交
c10266ed97
共有 14 個文件被更改,包括 400 次插入832 次删除
  1. 57 1
      AI/VCAI/VCAI.cpp
  2. 0 5
      Global.h
  3. 1 3
      client/CMT.cpp
  4. 二進制
      h3m.txt
  5. 15 23
      lib/CGameState.cpp
  6. 0 1
      lib/CMakeLists.txt
  7. 5 0
      lib/mapping/CMap.cpp
  8. 2 0
      lib/mapping/CMap.h
  9. 205 0
      lib/rmg/CMapGenOptions.cpp
  10. 79 137
      lib/rmg/CMapGenOptions.h
  11. 24 253
      lib/rmg/CMapGenerator.cpp
  12. 9 160
      lib/rmg/CMapGenerator.h
  13. 3 11
      server/CVCMIServer.cpp
  14. 0 238
      tchar_amigaos4.h

+ 57 - 1
AI/VCAI/VCAI.cpp

@@ -431,6 +431,7 @@ VCAI::VCAI(void)
     TRACE_BEGIN(logAi);
 	myCb = NULL;
 	makingTurn = NULL;
+    TRACE_END(logAi);
 }
 
 
@@ -443,6 +444,7 @@ void VCAI::availableCreaturesChanged(const CGDwelling *town)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::heroMoved(const TryMoveHero & details)
@@ -463,48 +465,56 @@ void VCAI::heroMoved(const TryMoveHero & details)
             logAi->debugStream() << boost::format("Found a pair of subterranean gates between %s and %s!") % from % to;
 		}
 	}
+    TRACE_END(logAi);
 }
 
 void VCAI::stackChagedCount(const StackLocation &location, const TQuantity &change, bool isAbsolute)
 {
-	NET_EVENT_HANDLER;
     TRACE_BEGIN_PARAMS(logAi, "isAbsolute '%i'", isAbsolute);
+	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::heroInGarrisonChange(const CGTownInstance *town)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::centerView(int3 pos, int focusTime)
 {
     TRACE_BEGIN_PARAMS(logAi, "focusTime '%i'", focusTime);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::artifactAssembled(const ArtifactLocation &al)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::showTavernWindow(const CGObjectInstance *townOrTavern)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::showThievesGuildWindow (const CGObjectInstance * obj)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::playerBlocked(int reason)
@@ -513,18 +523,21 @@ void VCAI::playerBlocked(int reason)
 	NET_EVENT_HANDLER;
 	if (reason == PlayerBlocked::UPCOMING_BATTLE)
 		status.setBattle(UPCOMING_BATTLE);
+    TRACE_END(logAi);
 }
 
 void VCAI::showPuzzleMap()
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::showShipyardDialog(const IShipyard *obj)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::gameOver(PlayerColor player, bool victory)
@@ -556,30 +569,35 @@ void VCAI::gameOver(PlayerColor player, bool victory)
 
 		finish();
 	}
+    TRACE_END(logAi);
 }
 
 void VCAI::artifactPut(const ArtifactLocation &al)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::artifactRemoved(const ArtifactLocation &al)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::stacksErased(const StackLocation &location)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::artifactDisassembled(const ArtifactLocation &al)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 
@@ -595,12 +613,14 @@ void VCAI::heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visi
 		remove_if_present(reservedHeroesMap[visitor], visitedObj);
 		completeGoal (CGoal(GET_OBJ).sethero(visitor)); //we don't need to visit in anymore
 	}
+    TRACE_END(logAi);
 }
 
 void VCAI::availableArtifactsChanged(const CGBlackMarket *bm /*= NULL*/)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town)
@@ -609,6 +629,7 @@ void VCAI::heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * tow
 	NET_EVENT_HANDLER;
 	//buildArmyIn(town);
 	//moveCreaturesToHero(town);
+    TRACE_END(logAi);
 }
 
 void VCAI::tileHidden(const boost::unordered_set<int3, ShashInt3> &pos)
@@ -619,6 +640,7 @@ void VCAI::tileHidden(const boost::unordered_set<int3, ShashInt3> &pos)
 // 		BOOST_FOREACH(const CGObjectInstance *obj, cb->getVisitableObjs(tile))
 // 			remove_if_present(visitableObjs, obj);
 	visitableObjs.erase(boost::remove_if(visitableObjs, [&](const CGObjectInstance *obj){return !myCb->getObj(obj->id);}), visitableObjs.end());
+    TRACE_END(logAi);
 }
 
 void VCAI::tileRevealed(const boost::unordered_set<int3, ShashInt3> &pos)
@@ -628,6 +650,7 @@ void VCAI::tileRevealed(const boost::unordered_set<int3, ShashInt3> &pos)
 	BOOST_FOREACH(int3 tile, pos)
 		BOOST_FOREACH(const CGObjectInstance *obj, myCb->getVisitableObjs(tile))
 			addVisitableObj(obj);
+    TRACE_END(logAi);
 }
 
 void VCAI::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2)
@@ -649,36 +672,42 @@ void VCAI::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2)
 		completeGoal(CGoal(VISIT_HERO).sethero(secondHero));
 		//TODO: exchange artifacts
 	});
+    TRACE_END(logAi);
 }
 
 void VCAI::heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val)
 {
     TRACE_BEGIN_PARAMS(logAi, "which '%i', val '%i'", which % val);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level)
 {
     TRACE_BEGIN_PARAMS(logAi, "level '%i'", level);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::heroMovePointsChanged(const CGHeroInstance * hero)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::stackChangedType(const StackLocation &location, const CCreature &newType)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::stacksRebalanced(const StackLocation &src, const StackLocation &dst, TQuantity count)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::newObject(const CGObjectInstance * obj)
@@ -687,6 +716,7 @@ void VCAI::newObject(const CGObjectInstance * obj)
 	NET_EVENT_HANDLER;
 	if(obj->isVisitable())
 		addVisitableObj(obj);
+    TRACE_END(logAi);
 }
 
 void VCAI::objectRemoved(const CGObjectInstance *obj)
@@ -708,6 +738,7 @@ void VCAI::objectRemoved(const CGObjectInstance *obj)
 	{
 		lostHero(cb->getHero(obj->id)); //we can promote, since objectRemoved is killed just before actual deletion
 	}
+    TRACE_END(logAi);
 }
 
 void VCAI::showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor)
@@ -719,36 +750,42 @@ void VCAI::showHillFortWindow(const CGObjectInstance *object, const CGHeroInstan
 	{
 		makePossibleUpgrades(visitor);
 	});
+    TRACE_END(logAi);
 }
 
 void VCAI::playerBonusChanged(const Bonus &bonus, bool gain)
 {
     TRACE_BEGIN_PARAMS(logAi, "gain '%i'", gain);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::newStackInserted(const StackLocation &location, const CStackInstance &stack)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::heroCreated(const CGHeroInstance*)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::advmapSpellCast(const CGHeroInstance * caster, int spellID)
 {
     TRACE_BEGIN_PARAMS(logAi, "spellID '%i", spellID);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID)
 {
     TRACE_BEGIN_PARAMS(logAi, "soundID '%i'", soundID);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::requestRealized(PackageApplied *pa)
@@ -766,36 +803,42 @@ void VCAI::requestRealized(PackageApplied *pa)
 	{
 		status.receivedAnswerConfirmation(pa->requestID, pa->result);
 	}
+    TRACE_END(logAi);
 }
 
 void VCAI::receivedResource(int type, int val)
 {
     TRACE_BEGIN_PARAMS(logAi, "type '%i', val '%i'", type % val);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::stacksSwapped(const StackLocation &loc1, const StackLocation &loc2)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::heroManaPointsChanged(const CGHeroInstance * hero)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val)
 {
     TRACE_BEGIN_PARAMS(logAi, "which '%', val '%'", which % val);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::battleResultsApplied()
@@ -804,6 +847,7 @@ void VCAI::battleResultsApplied()
 	NET_EVENT_HANDLER;
 	assert(status.getBattle() == ENDING_BATTLE);
 	status.setBattle(NO_BATTLE);
+    TRACE_END(logAi);
 }
 
 void VCAI::objectPropertyChanged(const SetObjectProperty * sop)
@@ -816,24 +860,28 @@ void VCAI::objectPropertyChanged(const SetObjectProperty * sop)
 			remove_if_present(visitableObjs, myCb->getObj(sop->id));
 		//TODO restore lost obj
 	}
+    TRACE_END(logAi);
 }
 
 void VCAI::buildChanged(const CGTownInstance *town, BuildingID buildingID, int what)
 {
     TRACE_BEGIN_PARAMS(logAi, "what '%i'", what);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::heroBonusChanged(const CGHeroInstance *hero, const Bonus &bonus, bool gain)
 {
     TRACE_BEGIN_PARAMS(logAi, "gain '%i'", gain);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::showMarketWindow(const IMarket *market, const CGHeroInstance *visitor)
 {
     TRACE_BEGIN(logAi);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::init(CCallback * CB)
@@ -850,6 +898,7 @@ void VCAI::init(CCallback * CB)
 		fh = new FuzzyHelper();
 
 	retreiveVisitableObjs(visitableObjs);
+    TRACE_END(logAi);
 }
 
 void VCAI::yourTurn()
@@ -858,6 +907,7 @@ void VCAI::yourTurn()
 	NET_EVENT_HANDLER;
 	status.startedTurn();
 	makingTurn = new boost::thread(&VCAI::makeTurn, this);
+    TRACE_END(logAi);
 }
 
 void VCAI::heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, int queryID)
@@ -866,6 +916,7 @@ void VCAI::heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill p
 	NET_EVENT_HANDLER;
 	status.addQuery(queryID, boost::str(boost::format("Hero %s got level %d") % hero->name % hero->level));
 	requestActionASAP([=]{ answerQuery(queryID, 0); });
+    TRACE_END(logAi);
 }
 
 void VCAI::commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, int queryID)
@@ -874,6 +925,7 @@ void VCAI::commanderGotLevel (const CCommanderInstance * commander, std::vector<
 	NET_EVENT_HANDLER;
 	status.addQuery(queryID, boost::str(boost::format("Commander %s of %s got level %d") % commander->name % commander->armyObj->nodeName() % (int)commander->level));
 	requestActionASAP([=]{ answerQuery(queryID, 0); });
+    TRACE_END(logAi);
 }
 
 void VCAI::showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, const int soundID, bool selection, bool cancel)
@@ -894,6 +946,7 @@ void VCAI::showBlockingDialog(const std::string &text, const std::vector<Compone
 	{
 		answerQuery(askID, sel);
 	});
+    TRACE_END(logAi);
 }
 
 void VCAI::showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, int queryID)
@@ -912,18 +965,21 @@ void VCAI::showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *do
 		pickBestCreatures (down, up);
 		answerQuery(queryID, 0);
 	});
+    TRACE_END(logAi);
 }
 
 void VCAI::serialize(COSer<CSaveFile> &h, const int version)
 {
     TRACE_BEGIN_PARAMS(logAi, "version '%i'", version);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void VCAI::serialize(CISer<CLoadFile> &h, const int version)
 {
     TRACE_BEGIN_PARAMS(logAi, "version '%i'", version);
 	NET_EVENT_HANDLER;
+    TRACE_END(logAi);
 }
 
 void makePossibleUpgrades(const CArmedInstance *obj)

+ 0 - 5
Global.h

@@ -65,11 +65,6 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
 #define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
 #include <cstdio>
 #include <stdio.h>
-#ifdef _WIN32
-#include <tchar.h>
-#else
-#include "tchar_amigaos4.h"
-#endif
 
 #include <algorithm>
 #include <array>

+ 1 - 3
client/CMT.cpp

@@ -176,9 +176,7 @@ static void prog_help(const po::options_description &opts)
 void OSX_checkForUpdates();
 #endif
 
-#ifdef _WIN32
-int _tmain(int argc, _TCHAR* argv[])
-#elif defined(__APPLE__)
+#if defined(__APPLE__)
 int SDL_main(int argc, char *argv[])
 #else
 int main(int argc, char** argv)

二進制
h3m.txt


+ 15 - 23
lib/CGameState.cpp

@@ -862,43 +862,35 @@ void CGameState::init(StartInfo * si)
                 logGlobal->infoStream() << "Create random map.";
 
 				// Create player settings for RMG
-				std::map<PlayerColor, CMapGenerator::CPlayerSettings> players;
-				BOOST_FOREACH(auto pInfo, scenarioOps->playerInfos)
+                BOOST_FOREACH(const auto & pair, scenarioOps->playerInfos)
 				{
-					const PlayerSettings & startSettings = pInfo.second;
-					CMapGenerator::CPlayerSettings player;
-					player.setColor(startSettings.color);
-					player.setStartingTown(startSettings.castle);
-					if(startSettings.playerID > 0)
+                    const auto & playerSettings = pair.second;
+                    scenarioOps->mapGenOptions->setStartingTownForPlayer(playerSettings.color, playerSettings.castle);
+                    if(playerSettings.playerID > 0)
 					{
-						player.setPlayerType(CMapGenerator::CPlayerSettings::HUMAN);
+                        scenarioOps->mapGenOptions->setPlayerTypeForStandardPlayer(playerSettings.color, EPlayerType::HUMAN);
 					}
-					else if(startSettings.compOnly)
-					{
-						player.setPlayerType(CMapGenerator::CPlayerSettings::COMP_ONLY);
-					}
-					players[player.getColor()] = player;
 				}
 
 				// Gen map
-				CMapGenerator mapGen(*scenarioOps->mapGenOptions, players, scenarioOps->seedToBeUsed);
+                CMapGenerator mapGen(*(scenarioOps->mapGenOptions), scenarioOps->seedToBeUsed);
 				map = mapGen.generate().release();
 
 				// Update starting options
 				for(int i = 0; i < map->players.size(); ++i)
 				{
-					const PlayerInfo & pInfo = map->players[i];
-					if(pInfo.canComputerPlay || pInfo.canHumanPlay)
+                    const auto & playerInfo = map->players[i];
+                    if(playerInfo.canAnyonePlay())
 					{
-						PlayerSettings & pSettings = scenarioOps->playerInfos[PlayerColor(i)];
-						pSettings.compOnly = !pInfo.canHumanPlay;
-						pSettings.team = pInfo.team;
-						pSettings.castle = pInfo.defaultCastle();
-						if(pSettings.playerID == PlayerSettings::PLAYER_AI && pSettings.name.empty())
+                        PlayerSettings & playerSettings = scenarioOps->playerInfos[PlayerColor(i)];
+                        playerSettings.compOnly = !playerInfo.canHumanPlay;
+                        playerSettings.team = playerInfo.team;
+                        playerSettings.castle = playerInfo.defaultCastle();
+                        if(playerSettings.playerID == PlayerSettings::PLAYER_AI && playerSettings.name.empty())
 						{
-							pSettings.name = VLC->generaltexth->allTexts[468];
+                            playerSettings.name = VLC->generaltexth->allTexts[468];
 						}
-						pSettings.color = PlayerColor(i);
+                        playerSettings.color = PlayerColor(i);
 					}
 					else
 					{

+ 0 - 1
lib/CMakeLists.txt

@@ -59,7 +59,6 @@ set(lib_SRCS
 
 set(lib_HEADERS
 		../Global.h
-		../tchar_amigaos4.h
 		filesystem/CInputStream.h
 		filesystem/ISimpleResourceLoader.h
 		AI_Base.h

+ 5 - 0
lib/mapping/CMap.cpp

@@ -45,6 +45,11 @@ si8 PlayerInfo::defaultHero() const
 	return -2;
 }
 
+bool PlayerInfo::canAnyonePlay() const
+{
+    return canHumanPlay || canComputerPlay;
+}
+
 LossCondition::LossCondition() : typeOfLossCon(ELossConditionType::LOSSSTANDARD),
 	pos(int3(-1, -1, -1)), timeLimit(-1), obj(nullptr)
 {

+ 2 - 0
lib/mapping/CMap.h

@@ -92,6 +92,8 @@ struct DLL_LINKAGE PlayerInfo
 	 */
 	si8 defaultHero() const;
 
+    bool canAnyonePlay() const;
+
 	/** True if the player can be played by a human. */
 	bool canHumanPlay;
 

+ 205 - 0
lib/rmg/CMapGenOptions.cpp

@@ -2,6 +2,9 @@
 #include "CMapGenOptions.h"
 
 #include "../GameConstants.h"
+#include "../CRandomGenerator.h"
+#include "../VCMI_Lib.h"
+#include "../CTownHandler.h"
 
 CMapGenOptions::CMapGenOptions() : width(72), height(72), hasTwoLevels(true),
 	playersCnt(RANDOM_SIZE), teamsCnt(RANDOM_SIZE), compOnlyPlayersCnt(0), compOnlyTeamsCnt(RANDOM_SIZE),
@@ -64,6 +67,7 @@ void CMapGenOptions::setPlayersCnt(si8 value)
 	if((value >= 1 && value <= PlayerColor::PLAYER_LIMIT_I) || value == RANDOM_SIZE)
 	{
 		playersCnt = value;
+        resetPlayersMap();
 	}
 	else
 	{
@@ -100,6 +104,7 @@ void CMapGenOptions::setCompOnlyPlayersCnt(si8 value)
 	if(value == RANDOM_SIZE || (value >= 0 && value <= PlayerColor::PLAYER_LIMIT_I - playersCnt))
 	{
 		compOnlyPlayersCnt = value;
+        resetPlayersMap();
 	}
 	else
 	{
@@ -147,3 +152,203 @@ void CMapGenOptions::setMonsterStrength(EMonsterStrength::EMonsterStrength value
 {
 	monsterStrength = value;
 }
+
+void CMapGenOptions::resetPlayersMap()
+{
+    players.clear();
+    int realPlayersCnt = playersCnt == RANDOM_SIZE ? PlayerColor::PLAYER_LIMIT_I : playersCnt;
+    int realCompOnlyPlayersCnt = compOnlyPlayersCnt == RANDOM_SIZE ? (PlayerColor::PLAYER_LIMIT_I - realPlayersCnt) : compOnlyPlayersCnt;
+    for(int color = 0; color < (realPlayersCnt + realCompOnlyPlayersCnt); ++color)
+    {
+        CPlayerSettings player;
+        player.setColor(PlayerColor(color));
+        player.setPlayerType((color >= playersCnt) ? EPlayerType::COMP_ONLY : EPlayerType::AI);
+        players[PlayerColor(color)] = player;
+    }
+}
+
+const std::map<PlayerColor, CMapGenOptions::CPlayerSettings> & CMapGenOptions::getPlayersSettings() const
+{
+    return players;
+}
+
+void CMapGenOptions::setStartingTownForPlayer(PlayerColor color, si32 town)
+{
+    auto it = players.find(color);
+    if(it == players.end()) throw std::runtime_error(boost::str(boost::format("Cannot set starting town for the player with the color '%i'.") % color));
+    it->second.setStartingTown(town);
+}
+
+void CMapGenOptions::setPlayerTypeForStandardPlayer(PlayerColor color, EPlayerType::EPlayerType playerType)
+{
+    auto it = players.find(color);
+    if(it == players.end()) throw std::runtime_error(boost::str(boost::format("Cannot set player type for the player with the color '%i'.") % color));
+    if(playerType == EPlayerType::COMP_ONLY) throw std::runtime_error("Cannot set player type computer only to a standard player.");
+    it->second.setPlayerType(playerType);
+}
+
+void CMapGenOptions::finalize()
+{
+    CRandomGenerator gen;
+    finalize(gen);
+}
+
+void CMapGenOptions::finalize(CRandomGenerator & gen)
+{
+    if(playersCnt == RANDOM_SIZE)
+    {
+        // 1 human is required at least
+        auto humanPlayers = countHumanPlayers();
+        if(humanPlayers == 0) humanPlayers = 1;
+        playersCnt = gen.getInteger(humanPlayers, PlayerColor::PLAYER_LIMIT_I);
+
+        // Remove AI players only from the end of the players map if necessary
+        for(auto itrev = players.end(); itrev != players.begin();)
+        {
+            auto it = itrev;
+            --it;
+            if(players.size() == playersCnt) break;
+            if(it->second.getPlayerType() == EPlayerType::AI)
+            {
+                players.erase(it);
+            }
+            else
+            {
+                --itrev;
+            }
+        }
+    }
+    if(teamsCnt == RANDOM_SIZE)
+    {
+        teamsCnt = gen.getInteger(0, playersCnt - 1);
+    }
+    if(compOnlyPlayersCnt == RANDOM_SIZE)
+    {
+        compOnlyPlayersCnt = gen.getInteger(0, 8 - playersCnt);
+        auto totalPlayersCnt = playersCnt + compOnlyPlayersCnt;
+
+        // Remove comp only players only from the end of the players map if necessary
+        for(auto itrev = players.end(); itrev != players.begin();)
+        {
+            auto it = itrev;
+            --it;
+            if(players.size() <= totalPlayersCnt) break;
+            if(it->second.getPlayerType() == EPlayerType::COMP_ONLY)
+            {
+                players.erase(it);
+            }
+            else
+            {
+                --itrev;
+            }
+        }
+
+        // Add some comp only players if necessary
+        auto compOnlyPlayersToAdd = totalPlayersCnt - players.size();
+        for(int i = 0; i < compOnlyPlayersToAdd; ++i)
+        {
+            CPlayerSettings pSettings;
+            pSettings.setPlayerType(EPlayerType::COMP_ONLY);
+            pSettings.setColor(getNextPlayerColor());
+            players[pSettings.getColor()] = pSettings;
+        }
+    }
+    if(compOnlyTeamsCnt == RANDOM_SIZE)
+    {
+        compOnlyTeamsCnt = gen.getInteger(0, std::max(compOnlyPlayersCnt - 1, 0));
+    }
+
+    // There should be at least 2 players (1-player-maps aren't allowed)
+    if(playersCnt + compOnlyPlayersCnt < 2)
+    {
+        CPlayerSettings pSettings;
+        pSettings.setPlayerType(EPlayerType::AI);
+        pSettings.setColor(getNextPlayerColor());
+        players[pSettings.getColor()] = pSettings;
+        playersCnt = 2;
+    }
+
+    // 1 team isn't allowed
+    if(teamsCnt == 1 && compOnlyPlayersCnt == 0)
+    {
+        teamsCnt = 0;
+    }
+
+    if(waterContent == EWaterContent::RANDOM)
+    {
+        waterContent = static_cast<EWaterContent::EWaterContent>(gen.getInteger(0, 2));
+    }
+    if(monsterStrength == EMonsterStrength::RANDOM)
+    {
+        monsterStrength = static_cast<EMonsterStrength::EMonsterStrength>(gen.getInteger(0, 2));
+    }
+}
+
+int CMapGenOptions::countHumanPlayers() const
+{
+    return static_cast<int>(boost::count_if(players, [](const std::pair<PlayerColor, CPlayerSettings> & pair)
+    {
+        return pair.second.getPlayerType() == EPlayerType::HUMAN;
+    }));
+}
+
+PlayerColor CMapGenOptions::getNextPlayerColor() const
+{
+    for(PlayerColor i = PlayerColor(0); i < PlayerColor::PLAYER_LIMIT; i.advance(1))
+    {
+        if(!players.count(i))
+        {
+            return i;
+        }
+    }
+    throw std::runtime_error("Shouldn't happen. No free player color exists.");
+}
+
+CMapGenOptions::CPlayerSettings::CPlayerSettings() : color(0), startingTown(RANDOM_TOWN), playerType(EPlayerType::AI)
+{
+
+}
+
+PlayerColor CMapGenOptions::CPlayerSettings::getColor() const
+{
+    return color;
+}
+
+void CMapGenOptions::CPlayerSettings::setColor(PlayerColor value)
+{
+    if(value >= PlayerColor(0) && value < PlayerColor::PLAYER_LIMIT)
+    {
+        color = value;
+    }
+    else
+    {
+        throw std::runtime_error("The color of the player is not in a valid range.");
+    }
+}
+
+si32 CMapGenOptions::CPlayerSettings::getStartingTown() const
+{
+    return startingTown;
+}
+
+void CMapGenOptions::CPlayerSettings::setStartingTown(si32 value)
+{
+    if(value >= -1 && value < static_cast<int>(VLC->townh->towns.size()))
+    {
+        startingTown = value;
+    }
+    else
+    {
+        throw std::runtime_error("The starting town of the player is not in a valid range.");
+    }
+}
+
+EPlayerType::EPlayerType CMapGenOptions::CPlayerSettings::getPlayerType() const
+{
+    return playerType;
+}
+
+void CMapGenOptions::CPlayerSettings::setPlayerType(EPlayerType::EPlayerType value)
+{
+    playerType = value;
+}

+ 79 - 137
lib/rmg/CMapGenOptions.h

@@ -11,6 +11,10 @@
 
 #pragma once
 
+#include "../GameConstants.h"
+
+class CRandomGenerator;
+
 namespace EWaterContent
 {
 	enum EWaterContent
@@ -33,189 +37,127 @@ namespace EMonsterStrength
 	};
 }
 
-/**
- * The map gen options class holds values about general map
- * generation settings e.g. the size of the map, the count of players,...
- */
+namespace EPlayerType
+{
+    enum EPlayerType
+    {
+        HUMAN,
+        AI,
+        COMP_ONLY
+    };
+}
+
+/// The map gen options class holds values about general map generation settings
+/// e.g. the size of the map, the count of players,...
 class DLL_LINKAGE CMapGenOptions
 {
 public:
-	/**
-	 * C-tor.
-	 */
+    /// The player settings class maps the player color, starting town and human player flag.
+    class CPlayerSettings
+    {
+    public:
+        CPlayerSettings();
+
+        /// The color of the player ranging from 0 to PlayerColor::PLAYER_LIMIT - 1.
+        /// The default value is 0.
+        PlayerColor getColor() const;
+        void setColor(PlayerColor value);
+
+        /// The starting town of the player ranging from 0 to town max count or RANDOM_TOWN.
+        /// The default value is RANDOM_TOWN.
+        si32 getStartingTown() const;
+        void setStartingTown(si32 value);
+
+        /// The default value is EPlayerType::AI.
+        EPlayerType::EPlayerType getPlayerType() const;
+        void setPlayerType(EPlayerType::EPlayerType value);
+
+        /// Constant for a random town selection.
+        static const si32 RANDOM_TOWN = -1;
+
+    private:
+        PlayerColor color;
+        si32 startingTown;
+        EPlayerType::EPlayerType playerType;
+
+    public:
+        template <typename Handler>
+        void serialize(Handler & h, const int version)
+        {
+            h & color & startingTown & playerType;
+        }
+    };
+
 	CMapGenOptions();
 
-	/**
-	 * Gets the width of the map. The default value is 72.
-	 *
-	 * @return width of the map in tiles
-	 */
 	si32 getWidth() const;
-
-	/**
-	 * Sets the width of the map.
-	 *
-	 * @param value the width of the map in tiles, any values higher than 0 are allowed
-	 */
 	void setWidth(si32 value);
 
-	/**
-	 * Gets the height of the map. The default value is 72.
-	 *
-	 * @return height of the map in tiles
-	 */
 	si32 getHeight() const;
-
-	/**
-	 * Sets the height of the map.
-	 *
-	 * @param value the height of the map in tiles, any values higher than 0 are allowed
-	 */
 	void setHeight(si32 value);
 
-	/**
-	 * Gets the flag whether the map should be generated with two levels. The
-	 * default value is true.
-	 *
-	 * @return true for two level map
-	 */
 	bool getHasTwoLevels() const;
-
-	/**
-	 * Sets the flag whether the map should be generated with two levels.
-	 *
-	 * @param value true for two level map
-	 */
 	void setHasTwoLevels(bool value);
 
-	/**
-	 * Gets the count of the players. The default value is RANDOM_SIZE representing a random
-	 * player count.
-	 *
-	 * @return the count of the players ranging from 1 to PlayerColor::PLAYER_LIMIT or RANDOM_SIZE for random
-	 */
+    /// The count of the players ranging from 1 to PlayerColor::PLAYER_LIMIT or RANDOM_SIZE for random. If you call
+    /// this method, all player settings are reset to default settings.
 	si8 getPlayersCnt() const;
-
-	/**
-	 * Sets the count of the players.
-	 *
-	 * @param value the count of the players ranging from 1 to PlayerColor::PLAYER_LIMIT, RANDOM_SIZE for random
-	 */
 	void setPlayersCnt(si8 value);
 
-	/**
-	 * Gets the count of the teams. The default value is RANDOM_SIZE representing a random
-	 * team count.
-	 *
-	 * @return the count of the teams ranging from 0 to <players count - 1> or RANDOM_SIZE for random
-	 */
+    /// The count of the teams ranging from 0 to <players count - 1> or RANDOM_SIZE for random.
 	si8 getTeamsCnt() const;
-
-	/**
-	 * Sets the count of the teams
-	 *
-	 * @param value the count of the teams ranging from 0 to <players count - 1>, RANDOM_SIZE for random
-	 */
 	void setTeamsCnt(si8 value);
 
-	/**
-	 * Gets the count of the computer only players. The default value is 0.
-	 *
-	 * @return the count of the computer only players ranging from 0 to <PlayerColor::PLAYER_LIMIT - players count> or RANDOM_SIZE for random
-	 */
+    /// The count of the computer only players ranging from 0 to <PlayerColor::PLAYER_LIMIT - players count> or RANDOM_SIZE for random.
+    /// If you call this method, all player settings are reset to default settings.
 	si8 getCompOnlyPlayersCnt() const;
-
-	/**
-	 * Sets the count of the computer only players.
-	 *
-	 * @param value the count of the computer only players ranging from 0 to <PlayerColor::PLAYER_LIMIT - players count>, RANDOM_SIZE for random
-	 */
 	void setCompOnlyPlayersCnt(si8 value);
 
-	/**
-	 * Gets the count of the computer only teams. The default value is RANDOM_SIZE representing
-	 * a random computer only team count.
-	 *
-	 * @return the count of the computer only teams ranging from 0 to <comp only players - 1> or RANDOM_SIZE for random
-	 */
+    /// The count of the computer only teams ranging from 0 to <comp only players - 1> or RANDOM_SIZE for random.
 	si8 getCompOnlyTeamsCnt() const;
-
-	/**
-	 * Sets the count of the computer only teams.
-	 *
-	 * @param value the count of the computer only teams ranging from 0 to <comp only players - 1>, RANDOM_SIZE for random
-	 */
 	void setCompOnlyTeamsCnt(si8 value);
 
-	/**
-	 * Gets the water content. The default value is random.
-	 *
-	 * @return the water content
-	 */
 	EWaterContent::EWaterContent getWaterContent() const;
-
-	/**
-	 * Sets the water content.
-	 *
-	 * @param value the water content
-	 */
 	void setWaterContent(EWaterContent::EWaterContent value);
 
-	/**
-	 * Gets the strength of the monsters. The default value is random.
-	 *
-	 * @return the strenght of the monsters
-	 */
 	EMonsterStrength::EMonsterStrength getMonsterStrength() const;
-
-	/**
-	 * Sets the strength of the monsters.
-	 *
-	 * @param value the strenght of the monsters
-	 */
 	void setMonsterStrength(EMonsterStrength::EMonsterStrength value);
 
-	/** The constant for specifying a random number of sth. */
+    /// The first player colors belong to standard players and the last player colors belong to comp only players.
+    /// All standard players are by default of type EPlayerType::AI.
+    const std::map<PlayerColor, CPlayerSettings> & getPlayersSettings() const;
+    void setStartingTownForPlayer(PlayerColor color, si32 town);
+    /// Sets a player type for a standard player. A standard player is the opposite of a computer only player. The
+    /// values which can be chosen for the player type are EPlayerType::AI or EPlayerType::HUMAN. Calling this method
+    /// has no effect for the map itself, but it adds some informational text for the map description.
+    void setPlayerTypeForStandardPlayer(PlayerColor color, EPlayerType::EPlayerType playerType);
+
+    /// Finalizes the options. All random sizes for various properties will be overwritten by numbers from
+    /// a random number generator by keeping the options in a valid state.
+    void finalize();
+    void finalize(CRandomGenerator & gen);
+
 	static const si8 RANDOM_SIZE = -1;
 
 private:
-	/** The width of the map in tiles. */
-	si32 width;
-
-	/** The height of the map in tiles. */
-	si32 height;
+    void resetPlayersMap();
+    int countHumanPlayers() const;
+    PlayerColor getNextPlayerColor() const;
 
-	/** True if the map has two levels that means an underground. */
+    si32 width, height;
 	bool hasTwoLevels;
-
-	/** The count of the players(human + computer). */
-	si8 playersCnt;
-
-	/** The count of the teams. */
-	si8 teamsCnt;
-
-	/** The count of computer only players. */
-	si8 compOnlyPlayersCnt;
-
-	/** The count of computer only teams. */
-	si8 compOnlyTeamsCnt;
-
-	/** The amount of water content. */
+    si8 playersCnt, teamsCnt, compOnlyPlayersCnt, compOnlyTeamsCnt;
 	EWaterContent::EWaterContent waterContent;
-
-	/** The strength of the monsters. */
 	EMonsterStrength::EMonsterStrength monsterStrength;
+    std::map<PlayerColor, CPlayerSettings> players;
 
 public:
-	/**
-	 * Serialize method.
-	 */
 	template <typename Handler>
 	void serialize(Handler & h, const int version)
 	{
 		//FIXME: Enum is not a fixed with data type. Add enum class to both enums
 		// later. For now it is ok.
 		h & width & height & hasTwoLevels & playersCnt & teamsCnt & compOnlyPlayersCnt;
-		h & compOnlyTeamsCnt & waterContent & monsterStrength;
+        h & compOnlyTeamsCnt & waterContent & monsterStrength & players;
 	}
 };

+ 24 - 253
lib/rmg/CMapGenerator.cpp

@@ -11,11 +11,10 @@
 #include "../CTownHandler.h"
 #include "../StringConstants.h"
 
-CMapGenerator::CMapGenerator(const CMapGenOptions & mapGenOptions, const std::map<PlayerColor, CPlayerSettings> & players, int randomSeed) :
-	mapGenOptions(mapGenOptions), randomSeed(randomSeed), players(players)
+CMapGenerator::CMapGenerator(const CMapGenOptions & mapGenOptions, int randomSeed) :
+    mapGenOptions(mapGenOptions), randomSeed(randomSeed)
 {
-	gen.seed(randomSeed);
-	validateOptions();
+    gen.seed(randomSeed);
 }
 
 CMapGenerator::~CMapGenerator()
@@ -25,7 +24,7 @@ CMapGenerator::~CMapGenerator()
 
 std::unique_ptr<CMap> CMapGenerator::generate()
 {
-	finalizeMapGenOptions();
+    mapGenOptions.finalize(gen);
 
 	//TODO select a template based on the map gen options or adapt it if necessary
 
@@ -40,165 +39,6 @@ std::unique_ptr<CMap> CMapGenerator::generate()
 	return std::move(map);
 }
 
-void CMapGenerator::validateOptions() const
-{
-	int playersCnt = 0;
-	int compOnlyPlayersCnt = 0;
-	BOOST_FOREACH(const auto & pair, players)
-	{
-		if(pair.second.getPlayerType() == CPlayerSettings::COMP_ONLY)
-		{
-			++compOnlyPlayersCnt;
-		}
-		else
-		{
-			++playersCnt;
-		}
-	}
-	if(mapGenOptions.getPlayersCnt() == CMapGenOptions::RANDOM_SIZE)
-	{
-		if(playersCnt != PlayerColor::PLAYER_LIMIT_I)
-		{
-			throw std::runtime_error(std::string("If the count of players is random size, ")
-				+ "the count of the items in the players map should equal PlayerColor::PLAYER_LIMIT.");
-		}
-		if(playersCnt == mapGenOptions.getPlayersCnt())
-		{
-			throw std::runtime_error(std::string("If the count of players is random size, ")
-				+ "all items in the players map should be either of player type AI or HUMAN.");
-		}
-	}
-	else
-	{
-		if(mapGenOptions.getCompOnlyPlayersCnt() != CMapGenOptions::RANDOM_SIZE)
-		{
-			if(playersCnt != mapGenOptions.getPlayersCnt() || compOnlyPlayersCnt != mapGenOptions.getCompOnlyPlayersCnt())
-			{
-				throw std::runtime_error(std::string("The count of players and computer only players in the players map ")
-					+ "doesn't conform with the specified map gen options.");
-			}
-		}
-		else
-		{
-			if(playersCnt != mapGenOptions.getPlayersCnt() || (playersCnt == mapGenOptions.getPlayersCnt()
-				&& compOnlyPlayersCnt != PlayerColor::PLAYER_LIMIT_I - playersCnt))
-			{
-				throw std::runtime_error(std::string("If the count of players is fixed and the count of comp only players random, ")
-					+ "the items in the players map should equal PlayerColor::PLAYER_LIMIT.");
-			}
-		}
-	}
-
-	if(countHumanPlayers() < 1)
-	{
-		throw std::runtime_error("1 human player is required at least");
-	}
-
-	BOOST_FOREACH(const auto & pair, players)
-	{
-		if(pair.first != pair.second.getColor())
-		{
-			throw std::runtime_error("The color of an item in player settings and the key of it has to be the same.");
-		}
-	}
-}
-
-void CMapGenerator::finalizeMapGenOptions()
-{
-	if(mapGenOptions.getPlayersCnt() == CMapGenOptions::RANDOM_SIZE)
-	{
-		mapGenOptions.setPlayersCnt(gen.getInteger(countHumanPlayers(), PlayerColor::PLAYER_LIMIT_I));
-
-		// Remove AI players only from the end of the players map if necessary
-		for(auto itrev = players.end(); itrev != players.begin();)
-		{
-			auto it = itrev;
-			--it;
-			if(players.size() == mapGenOptions.getPlayersCnt())
-			{
-				break;
-			}
-			const CPlayerSettings & pSettings = it->second;
-			if(pSettings.getPlayerType() == CPlayerSettings::AI)
-			{
-				players.erase(it);
-			}
-			else
-			{
-				--itrev;
-			}
-		}
-	}
-	if(mapGenOptions.getTeamsCnt() == CMapGenOptions::RANDOM_SIZE)
-	{
-		mapGenOptions.setTeamsCnt(gen.getInteger(0, mapGenOptions.getPlayersCnt() - 1));
-	}
-	if(mapGenOptions.getCompOnlyPlayersCnt() == CMapGenOptions::RANDOM_SIZE)
-	{
-		mapGenOptions.setCompOnlyPlayersCnt(gen.getInteger(0, 8 - mapGenOptions.getPlayersCnt()));
-		int totalPlayersCnt = mapGenOptions.getPlayersCnt() + mapGenOptions.getCompOnlyPlayersCnt();
-
-		// Remove comp only players only from the end of the players map if necessary
-		for(auto itrev = players.end(); itrev != players.begin();)
-		{
-			auto it = itrev;
-			--it;
-			if(players.size() <= totalPlayersCnt)
-			{
-				break;
-			}
-			const CPlayerSettings & pSettings = it->second;
-			if(pSettings.getPlayerType() == CPlayerSettings::COMP_ONLY)
-			{
-				players.erase(it);
-			}
-			else
-			{
-				--itrev;
-			}
-		}
-
-		// Add some comp only players if necessary
-		int compOnlyPlayersToAdd = totalPlayersCnt - players.size();
-		for(int i = 0; i < compOnlyPlayersToAdd; ++i)
-		{
-			CPlayerSettings pSettings;
-			pSettings.setPlayerType(CPlayerSettings::COMP_ONLY);
-			pSettings.setColor(getNextPlayerColor());
-			players[pSettings.getColor()] = pSettings;
-		}
-	}
-	if(mapGenOptions.getCompOnlyTeamsCnt() == CMapGenOptions::RANDOM_SIZE)
-	{
-		mapGenOptions.setCompOnlyTeamsCnt(gen.getInteger(0, std::max(mapGenOptions.getCompOnlyPlayersCnt() - 1, 0)));
-	}
-
-	// There should be at least 2 players (1-player-maps aren't allowed)
-	if(mapGenOptions.getPlayersCnt() + mapGenOptions.getCompOnlyPlayersCnt() < 2)
-	{
-		CPlayerSettings pSettings;
-		pSettings.setPlayerType(CPlayerSettings::AI);
-		pSettings.setColor(getNextPlayerColor());
-		players[pSettings.getColor()] = pSettings;
-		mapGenOptions.setPlayersCnt(2);
-	}
-
-	// 1 team isn't allowed
-	if(mapGenOptions.getTeamsCnt() == 1 && mapGenOptions.getCompOnlyPlayersCnt() == 0)
-	{
-		mapGenOptions.setTeamsCnt(0);
-	}
-
-	if(mapGenOptions.getWaterContent() == EWaterContent::RANDOM)
-	{
-		mapGenOptions.setWaterContent(static_cast<EWaterContent::EWaterContent>(gen.getInteger(0, 2)));
-	}
-	if(mapGenOptions.getMonsterStrength() == EMonsterStrength::RANDOM)
-	{
-		mapGenOptions.setMonsterStrength(static_cast<EMonsterStrength::EMonsterStrength>(gen.getInteger(0, 2)));
-	}
-}
-
 std::string CMapGenerator::getMapDescription() const
 {
 	const std::string waterContentStr[3] = { "none", "normal", "islands" };
@@ -212,14 +52,14 @@ std::string CMapGenerator::getMapDescription() const
 	ss << static_cast<int>(mapGenOptions.getCompOnlyPlayersCnt()) << ", water " << waterContentStr[mapGenOptions.getWaterContent()];
 	ss << ", monster " << monsterStrengthStr[mapGenOptions.getMonsterStrength()] << ", second expansion map";
 
-	BOOST_FOREACH(const auto & pair, players)
+    BOOST_FOREACH(const auto & pair, mapGenOptions.getPlayersSettings())
 	{
-		const CPlayerSettings & pSettings = pair.second;
-		if(pSettings.getPlayerType() == CPlayerSettings::HUMAN)
+        const auto & pSettings = pair.second;
+        if(pSettings.getPlayerType() == EPlayerType::HUMAN)
 		{
 			ss << ", " << GameConstants::PLAYER_COLOR_NAMES[pSettings.getColor().getNum()] << " is human";
 		}
-		if(pSettings.getStartingTown() != CPlayerSettings::RANDOM_TOWN)
+        if(pSettings.getStartingTown() != CMapGenOptions::CPlayerSettings::RANDOM_TOWN)
 		{
 			ss << ", " << GameConstants::PLAYER_COLOR_NAMES[pSettings.getColor().getNum()]
 				<< " town choice is " << ETownType::names[pSettings.getStartingTown()];
@@ -265,12 +105,12 @@ void CMapGenerator::addPlayerInfo()
 	}
 
 	// Team numbers are assigned randomly to every player
-	BOOST_FOREACH(const auto & pair, players)
+    BOOST_FOREACH(const auto & pair, mapGenOptions.getPlayersSettings())
 	{
-		const CPlayerSettings & pSettings = pair.second;
+        const auto & pSettings = pair.second;
 		PlayerInfo player;
 		player.canComputerPlay = true;
-		int j = pSettings.getPlayerType() == CPlayerSettings::COMP_ONLY ? 1 : 0;
+        int j = pSettings.getPlayerType() == EPlayerType::COMP_ONLY ? 1 : 0;
 		if(j == 0)
 		{
 			player.canHumanPlay = true;
@@ -285,14 +125,6 @@ void CMapGenerator::addPlayerInfo()
 			+ (mapGenOptions.getCompOnlyTeamsCnt() == 0 ? mapGenOptions.getCompOnlyPlayersCnt() : mapGenOptions.getCompOnlyTeamsCnt());
 }
 
-int CMapGenerator::countHumanPlayers() const
-{
-	return static_cast<int>(boost::count_if(players, [](const std::pair<PlayerColor, CPlayerSettings> & pair)
-	{
-		return pair.second.getPlayerType() == CMapGenerator::CPlayerSettings::HUMAN;
-	}));
-}
-
 void CMapGenerator::genTerrain()
 {
 	map->initTerrain(); //FIXME nicer solution
@@ -304,13 +136,15 @@ void CMapGenerator::genTowns()
 {
 	//FIXME mock gen
 	const int3 townPos[2] = { int3(17, 13, 0), int3(25,13, 0) };
-	const TFaction townTypes[2] = { ETownType::CASTLE, ETownType::DUNGEON };
+    const int townTypes[2] = { ETownType::CASTLE, ETownType::DUNGEON };
 
-	for(auto it = players.begin(); it != players.end(); ++it)
+    for(size_t i = 0; i < map->players.size(); ++i)
 	{
-		PlayerColor owner = it->first;
-		int pos = std::distance(players.begin(), it);
-		int side = pos % 2;
+        auto & playerInfo = map->players[i];
+        if(!playerInfo.canAnyonePlay()) break;
+
+        PlayerColor owner(i);
+        int side = i % 2;
 		CGTownInstance * town = new CGTownInstance();
 		town->ID = Obj::TOWN;
 		town->subID = townTypes[side];
@@ -318,15 +152,14 @@ void CMapGenerator::genTowns()
 		town->defInfo = VLC->dobjinfo->gobjs[town->ID][town->subID];
 		town->builtBuildings.insert(BuildingID::FORT);
 		town->builtBuildings.insert(BuildingID::DEFAULT);
-		mapMgr->insertObject(town, townPos[side].x, townPos[side].y + (pos / 2) * 5, false);
+        mapMgr->insertObject(town, townPos[side].x, townPos[side].y + (i / 2) * 5, false);
 
 		// Update player info
-		PlayerInfo & pInfo = map->players[owner.getNum()];
-		pInfo.allowedFactions.clear();
-		pInfo.allowedFactions.insert(townTypes[side]);
-		pInfo.hasMainTown = true;
-		pInfo.posOfMainTown = town->pos - int3(2, 0, 0);
-		pInfo.generateHeroAtMainTown = true;
+        playerInfo.allowedFactions.clear();
+        playerInfo.allowedFactions.insert(townTypes[side]);
+        playerInfo.hasMainTown = true;
+        playerInfo.posOfMainTown = town->pos - int3(2, 0, 0);
+        playerInfo.generateHeroAtMainTown = true;
 	}
 }
 
@@ -341,65 +174,3 @@ void CMapGenerator::addHeaderInfo()
 	map->difficulty = 1;
 	addPlayerInfo();
 }
-
-PlayerColor CMapGenerator::getNextPlayerColor() const
-{
-	for(PlayerColor i = PlayerColor(0); i < PlayerColor::PLAYER_LIMIT; i.advance(1))
-	{
-		if(!players.count(i))
-		{
-			return i;
-		}
-	}
-	throw std::runtime_error("Shouldn't happen. No free player color exists.");
-}
-
-CMapGenerator::CPlayerSettings::CPlayerSettings() : color(0), startingTown(RANDOM_TOWN), playerType(AI)
-{
-
-}
-
-PlayerColor CMapGenerator::CPlayerSettings::getColor() const
-{
-	return color;
-}
-
-
-void CMapGenerator::CPlayerSettings::setColor(PlayerColor value)
-{
-	if(value >= PlayerColor(0) && value < PlayerColor::PLAYER_LIMIT)
-	{
-		color = value;
-	}
-	else
-	{
-		throw std::runtime_error("The color of the player is not in a valid range.");
-	}
-}
-
-int CMapGenerator::CPlayerSettings::getStartingTown() const
-{
-	return startingTown;
-}
-
-void CMapGenerator::CPlayerSettings::setStartingTown(int value)
-{
-	if(value >= -1 && value < static_cast<int>(VLC->townh->towns.size()))
-	{
-		startingTown = value;
-	}
-	else
-	{
-		throw std::runtime_error("The starting town of the player is not in a valid range.");
-	}
-}
-
-CMapGenerator::CPlayerSettings::EPlayerType CMapGenerator::CPlayerSettings::getPlayerType() const
-{
-	return playerType;
-}
-
-void CMapGenerator::CPlayerSettings::setPlayerType(EPlayerType value)
-{
-	playerType = value;
-}

+ 9 - 160
lib/rmg/CMapGenerator.h

@@ -19,178 +19,27 @@ class CMap;
 class CTerrainViewPatternConfig;
 class CMapEditManager;
 
-/**
- * The map generator creates a map randomly.
- */
-class CMapGenerator
+/// The map generator creates a map randomly.
+class DLL_LINKAGE CMapGenerator
 {
 public:
-	/**
-	 * The player settings class maps the player color, starting town and human player flag.
-	 */
-	class CPlayerSettings
-	{
-	public:
-		enum EPlayerType
-		{
-			HUMAN,
-			AI,
-			COMP_ONLY
-		};
-
-		/**
-		 * Constructor.
-		 */
-		CPlayerSettings();
-
-		/**
-		 * Gets the color of the player. The default value is 0.
-		 *
-		 * @return the color of the player ranging from 0 to PlayerColor::PLAYER_LIMIT - 1
-		 */
-		PlayerColor getColor() const;
-
-		/**
-		 * Sets the color of the player.
-		 *
-		 * @param value the color of the player ranging from 0 to PlayerColor::PLAYER_LIMIT - 1
-		 */
-		void setColor(PlayerColor value);
-
-		/**
-		 * Gets the starting town of the player. The default value is RANDOM_TOWN.
-		 *
-		 * @return the starting town of the player ranging from 0 to town max count or RANDOM_TOWN
-		 */
-		int getStartingTown() const;
-
-		/**
-		 * Sets the starting town of the player.
-		 *
-		 * @param value the starting town of the player ranging from 0 to town max count or RANDOM_TOWN
-		 */
-		void setStartingTown(int value);
-
-		/**
-		 * Gets the type of the player. The default value is EPlayerType::AI.
-		 *
-		 * @return the type of the player
-		 */
-		EPlayerType getPlayerType() const;
-
-		/**
-		 * Sets the type of the player.
-		 *
-		 * @param playerType the type of the player
-		 */
-		void setPlayerType(EPlayerType value);
-
-		/** Constant for a random town selection. */
-		static const int RANDOM_TOWN = -1;
-
-	private:
-		/** The color of the player. */
-		PlayerColor color;
-
-		/** The starting town of the player. */
-		int startingTown;
-
-		/** The type of the player e.g. human, comp only,... */
-		EPlayerType playerType;
-	};
-
-	/**
-	 * Constructor.
-	 *
-	 * @param mapGenOptions these options describe how to generate the map.
-	 * @param players the random gen player settings
-	 * @param randomSeed a random seed is required to get random numbers.
-	 */
-	CMapGenerator(const CMapGenOptions & mapGenOptions, const std::map<PlayerColor, CPlayerSettings> & players, int randomSeed);
-
-	/**
-	 * Destructor.
-	 */
-	~CMapGenerator();
+    CMapGenerator(const CMapGenOptions & mapGenOptions, int randomSeed);
+    ~CMapGenerator(); // required due to unique_ptr
 
-	/**
-	 * Generates a map.
-	 *
-	 * @return the generated map object stored in a unique ptr
-	 */
 	std::unique_ptr<CMap> generate();
 
 private:
-	/**
-	 * Validates map gen options and players options. On errors exceptions will be thrown.
-	 */
-	void validateOptions() const;
-
-	/**
-	 * Finalizes map generation options. Random sizes for various properties are
-	 * converted to fixed values.
-	 */
-	void finalizeMapGenOptions();
-
-	/**
-	 * Gets the map description of the generated map.
-	 *
-	 * @return the map description of the generated map
-	 */
-	std::string getMapDescription() const;
-
-	/**
-	 * Adds player information.(teams, colors, etc...)
-	 */
-	void addPlayerInfo();
-
-	/**
-	 * Counts the amount of human players.
-	 *
-	 * @return the amount of human players ranging from 0 to PlayerColor::PLAYER_LIMIT
-	 */
-	int countHumanPlayers() const;
-
-	/**
-	 * Generate terrain.
-	 */
+    /// Generation methods
+    std::string getMapDescription() const;
+    void addPlayerInfo();
+    void addHeaderInfo();
 	void genTerrain();
-
-	/**
-	 * Generate towns.
-	 */
 	void genTowns();
 
-	/**
-	 * Adds header info(size, description, etc...)
-	 */
-	void addHeaderInfo();
-
-	/**
-	 * Gets the next free player color.
-	 *
-	 * @return the next free player color
-	 */
-	PlayerColor getNextPlayerColor() const;
-
-	/** The map options which describes the size of the map and contain player info. */
 	CMapGenOptions mapGenOptions;
-
-	/** The generated map. */
 	std::unique_ptr<CMap> map;
-
-	/** The random number generator. */
 	CRandomGenerator gen;
-
-	/** The random seed, it is used for the map description. */
 	int randomSeed;
-
-	/** The terrain view pattern config. */
 	std::unique_ptr<CTerrainViewPatternConfig> terViewPatternConfig;
-
-	/** The map edit manager. */
-	std::unique_ptr<CMapEditManager> mapMgr;
-
-	/** The random gen player settings. */
-	std::map<PlayerColor, CPlayerSettings> players;
+    std::unique_ptr<CMapEditManager> mapMgr;
 };

+ 3 - 11
server/CVCMIServer.cpp

@@ -501,24 +501,16 @@ void CVCMIServer::loadGame()
 	gh.run(true);
 }
 
-#ifndef __GNUC__
-int _tmain(int argc, _TCHAR* argv[])
-#else
 int main(int argc, char** argv)
-#endif
 {
 	console = new CConsoleHandler;
 	CBasicLogConfigurator logConfig(VCMIDirs::get().localPath() + "/VCMI_Server_log.txt", console);
     logConfig.configureDefault();
-	//boost::thread t(boost::bind(&CConsoleHandler::run,::console));
 	if(argc > 1)
 	{
-#ifdef _MSC_VER
-		port = _tstoi(argv[1]);
-#else
-		port = _ttoi(argv[1]);
-#endif
-	}
+        port = std::stoi(argv[1]);
+    }
+
 	preinitDLL(console);
     settings.init();
     logConfig.configure();

+ 0 - 238
tchar_amigaos4.h

@@ -1,238 +0,0 @@
-/*
- * tchar.h
- *
- * Unicode mapping layer for the standard C library. By including this
- * file and using the 't' names for string functions
- * (eg. _tprintf) you can make code which can be easily adapted to both
- * Unicode and non-unicode environments. In a unicode enabled compile define
- * _UNICODE before including tchar.h, otherwise the standard non-unicode
- * library functions will be used.
- *
- * Note that you still need to include string.h or stdlib.h etc. to define
- * the appropriate functions. Also note that there are several defines
- * included for non-ANSI functions which are commonly available (but using
- * the convention of prepending an underscore to non-ANSI library function
- * names).
- *
- * This file is part of the Mingw32 package.
- *
- * Contributors:
- *  Created by Colin Peters <[email protected]>
- *
- *  THIS SOFTWARE IS NOT COPYRIGHTED
- *
- *  This source code is offered for use in the public domain. You may
- *  use, modify or distribute it freely.
- *
- *  This code is distributed in the hope that it will be useful but
- *  WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
- *  DISCLAMED. This includes but is not limited to warranties of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $Revision: 1.1.1.1 $
- * $Author: brandon6684 $
- * $Date: 2001/12/18 22:54:08 $
- *
- */
-
-#ifndef	_TCHAR_H_
-#define _TCHAR_H_
-
-/*
- * NOTE: This tests _UNICODE, which is different from the UNICODE define
- *       used to differentiate Win32 API calls.
- */
-#ifdef __unix__
-#define _TCHAR char*
-#endif
-#ifdef	_UNICODE
-
-
-/*
- * Use TCHAR instead of char or wchar_t. It will be appropriately translated
- * if _UNICODE is correctly defined (or not).
- */
-#ifndef _TCHAR_DEFINED
-#ifndef RC_INVOKED
-typedef	wchar_t	TCHAR;
-#endif	/* Not RC_INVOKED */
-#define _TCHAR_DEFINED
-#endif
-
-
-/*
- * Enclose constant strings and literal characters in the _TEXT and _T macro to make
- * them unicode constant strings when _UNICODE is defined.
- */
-#define	_TEXT(x)	L ## x
-#define	_T(x)		L ## x
-
-/*
- * Unicode functions
- */
-
-#define	_tprintf		wprintf
-#define	_ftprintf		fwprintf
-#define	_stprintf		swprintf
-#define	_sntprintf	_snwprintf
-#define	_vtprintf		vwprintf
-#define	_vftprintf	vfwprintf
-#define	_vstprintf	vswprintf
-#define	_vsntprintf	_vsnwprintf
-#define	_tscanf		wscanf
-#define	_ftscanf		fwscanf
-#define	_stscanf		swscanf
-#define	_fgettc		fgetwc
-#define	_fgettchar	_fgetwchar
-#define	_fgetts		fgetws
-#define	_fputtc		fputwc
-#define	_fputtchar	_fputwchar
-#define	_fputts		fputws
-#define	_gettc		getwc
-#define	_getts		getws
-#define	_puttc		putwc
-#define	_putts		putws
-#define	_ungettc	ungetwc
-#define	_tcstod		wcstod
-#define	_tcstol		wcstol
-#define	_tcstoul		wcstoul
-#define	_tcscat		wcscat
-#define	_tcschr		wcschr
-#define	_tcscmp		wcscmp
-#define	_tcscpy		wcscpy
-#define	_tcscspn	wcscspn
-#define	_tcslen		wcslen
-#define	_tcsncat		wcsncat
-#define	_tcsncmp	wcsncmp
-#define	_tcsncpy	wcsncpy
-#define	_tcspbrk		wcspbrk
-#define	_tcsrchr		wcsrchr
-#define	_tcsspn		wcsspn
-#define	_tcsstr		wcsstr
-#define	_tcstok		wcstok
-#define	_tcsdup		_wcsdup
-#define	_tcsicmp	_wcsicmp
-#define	_tcsnicmp	_wcsnicmp
-#define	_tcsnset		_wcsnset
-#define	_tcsrev		_wcsrev
-#define	_tcsset		_wcsset
-#define	_tcslwr		_wcslwr
-#define	_tcsupr		_wcsupr
-#define	_tcsxfrm		wcsxfrm
-#define	_tcscoll		wcscoll
-#define	_tcsicoll		_wcsicoll
-#define	_istalpha	iswalpha
-#define	_istupper	iswupper
-#define	_istlower	iswlower
-#define	_istdigit		iswdigit
-#define	_istxdigit	iswxdigit
-#define	_istspace	iswspace
-#define	_istpunct	iswpunct
-#define	_istalnum	iswalnum
-#define	_istprint		iswprint
-#define	_istgraph	iswgraph
-#define	_istcntrl		iswcntrl
-#define	_istascii		iswascii
-#define	_totupper	towupper
-#define	_totlower	towlower
-#define	_ttoi		_wtoi
-#define	_tcsftime	wcsftime
-
-#else	/* Not _UNICODE */
-
-/*
- * TCHAR, the type you should use instead of char.
- */
-#ifndef _TCHAR_DEFINED
-#ifndef RC_INVOKED
-typedef char	TCHAR;
-#endif
-#define _TCHAR_DEFINED
-#endif
-
-/*
- * Enclose constant strings and characters in the _TEXT and _T macro.
- */
-#define	_TEXT(x)	x
-#define	_T(x)		x
-
-
-/*
- * Non-unicode (standard) functions
- */
-
-#define	_tprintf	printf
-#define _ftprintf	fprintf
-#define	_stprintf	sprintf
-#define	_sntprintf	_snprintf
-#define	_vtprintf	vprintf
-#define	_vftprintf	vfprintf
-#define _vstprintf	vsprintf
-#define	_vsntprintf	_vsnprintf
-#define	_tscanf		scanf
-#define	_ftscanf	fscanf
-#define	_stscanf	sscanf
-#define	_fgettc		fgetc
-#define	_fgettchar	_fgetchar
-#define	_fgetts		fgets
-#define	_fputtc		fputc
-#define	_fputtchar	_fputchar
-#define	_fputts		fputs
-#define	_gettc		getc
-#define	_getts		gets
-#define	_puttc		putc
-#define	_putts		puts
-#define	_ungettc	ungetc
-#define	_tcstod		strtod
-#define	_tcstol		strtol
-#define _tcstoul	strtoul
-#define	_tcscat		strcat
-#define _tcschr		strchr
-#define _tcscmp		strcmp
-#define _tcscpy		strcpy
-#define _tcscspn	strcspn
-#define	_tcslen		strlen
-#define	_tcsncat	strncat
-#define	_tcsncmp	strncmp
-#define	_tcsncpy	strncpy
-#define	_tcspbrk	strpbrk
-#define	_tcsrchr	strrchr
-#define _tcsspn		strspn
-#define	_tcsstr		strstr
-#define _tcstok		strtok
-#define	_tcsdup		_strdup
-#define	_tcsicmp	_stricmp
-#define	_tcsnicmp	_strnicmp
-#define	_tcsnset	_strnset
-#define	_tcsrev		_strrev
-#define _tcsset		_strset
-#define	_tcslwr		_strlwr
-#define	_tcsupr		_strupr
-#define	_tcsxfrm	strxfrm
-#define	_tcscoll	strcoll
-#define	_tcsicoll	_stricoll
-#define	_istalpha	isalpha
-#define	_istupper	isupper
-#define	_istlower	islower
-#define	_istdigit	isdigit
-#define	_istxdigit	isxdigit
-#define	_istspace	isspace
-#define	_istpunct	ispunct
-#define	_istalnum	isalnum
-#define	_istprint	isprint
-#define	_istgraph	isgraph
-#define	_istcntrl	iscntrl
-#define	_istascii	isascii
-#define _totupper	toupper
-#define	_totlower	tolower
-#define	_ttoi		atoi
-#define _tcsftime	strftime
-
-#ifdef __amigaos4__
-#define _TCHAR wchar_t
-#endif
-
-#endif	/* Not _UNICODE */
-
-#endif	/* Not _TCHAR_H_ */
-