浏览代码

Fixed generation of CPU teams.

DjWarmonger 10 年之前
父节点
当前提交
c6f714db9c

+ 1 - 1
Mods/vcmi/Mods/defaultTemplates/Mods/Jebus Cross/Content/config/defaultTemplates/jebusCross.json

@@ -2,7 +2,7 @@
 	"Jebus Cross":
 	{
 		"minSize" : "l+u", "maxSize" : "xl+u",
-		"players" : "4",
+		"players" : "2-4",
 		"zones":
 		{
 			"1":

+ 40 - 2
lib/rmg/CMapGenOptions.cpp

@@ -201,7 +201,7 @@ const std::map<std::string, CRmgTemplate *> & CMapGenOptions::getAvailableTempla
 void CMapGenOptions::finalize(CRandomGenerator & rand)
 {
 	logGlobal->infoStream() << boost::format ("RMG settings: players %d, teams %d, computer players %d, computer teams %d, water %d, monsters %d")
-											% getPlayerCount() % getTeamCount() % getCompOnlyPlayerCount() % getCompOnlyTeamCount() % getWaterContent() % getMonsterStrength();
+											% (int)getPlayerCount() % (int)getTeamCount() % (int)getCompOnlyPlayerCount() % (int)getCompOnlyTeamCount() % (int)getWaterContent() % (int)getMonsterStrength();
 
 	if(!mapTemplate)
 	{
@@ -212,7 +212,8 @@ void CMapGenOptions::finalize(CRandomGenerator & rand)
 	if (getPlayerCount() == RANDOM_SIZE)
 	{
 		auto possiblePlayers = mapTemplate->getPlayers().getNumbers();
-		possiblePlayers.erase(possiblePlayers.begin(), possiblePlayers.lower_bound(countHumanPlayers()));
+		//ignore all non-randomized players, make sure these players will not be missing after roll
+		possiblePlayers.erase(possiblePlayers.begin(), possiblePlayers.lower_bound(countHumanPlayers() + countCompOnlyPlayers()));
 		assert(!possiblePlayers.empty());
 		setPlayerCount (*RandomGeneratorUtil::nextItem(possiblePlayers, rand));
 		updatePlayers();
@@ -246,9 +247,37 @@ void CMapGenOptions::finalize(CRandomGenerator & rand)
 	assert (vstd::iswithin(waterContent, EWaterContent::NONE, EWaterContent::ISLANDS));
 	assert (vstd::iswithin(monsterStrength, EMonsterStrength::GLOBAL_WEAK, EMonsterStrength::GLOBAL_STRONG));
 
+
 	//rectangular maps are the future of gaming
 	//setHeight(20);
 	//setWidth(50);
+
+	logGlobal->traceStream() << "Player config:";
+	int humanPlayers = 0, cpuOnlyPlayers = 0, AIplayers = 0;
+	for (auto player : players)
+	{
+		std::string playerType;
+		switch (player.second.getPlayerType())
+		{
+		case EPlayerType::AI:
+			playerType = "AI";
+			AIplayers++;
+			break;
+		case EPlayerType::COMP_ONLY:
+			playerType = "computer only";
+			cpuOnlyPlayers++;
+			break;
+		case EPlayerType::HUMAN:
+			playerType = "human only";
+			humanPlayers++;
+			break;
+			default:
+				assert(false);
+		}
+		logGlobal->traceStream() << boost::format("Player %d: %s") % player.second.getColor() % playerType;
+	}
+	setCompOnlyPlayerCount(cpuOnlyPlayers); //human players are set automaticlaly (?)
+	logGlobal->infoStream() << boost::format("Final player config: %d total, %d cpu-only") % players.size() % (int)getCompOnlyPlayerCount();
 }
 
 void CMapGenOptions::updatePlayers()
@@ -313,6 +342,15 @@ int CMapGenOptions::countHumanPlayers() const
 	}));
 }
 
+int CMapGenOptions::countCompOnlyPlayers() const
+{
+	return static_cast<int>(boost::count_if(players, [](const std::pair<PlayerColor, CPlayerSettings> & pair)
+	{
+		return pair.second.getPlayerType() == EPlayerType::COMP_ONLY;
+	}));
+}
+
+
 PlayerColor CMapGenOptions::getNextPlayerColor() const
 {
 	for(PlayerColor i = PlayerColor(0); i < PlayerColor::PLAYER_LIMIT; i.advance(1))

+ 1 - 0
lib/rmg/CMapGenOptions.h

@@ -155,6 +155,7 @@ public:
 private:
 	void resetPlayersMap();
 	int countHumanPlayers() const;
+	int CMapGenOptions::countCompOnlyPlayers() const;
 	PlayerColor getNextPlayerColor() const;
 	void updateCompOnlyPlayers();
 	void updatePlayers();

+ 28 - 9
lib/rmg/CMapGenerator.cpp

@@ -169,19 +169,32 @@ std::string CMapGenerator::getMapDescription() const
 void CMapGenerator::addPlayerInfo()
 {
 	// Calculate which team numbers exist
-	std::array<std::list<int>, 2> teamNumbers; // 0= cpu/human, 1= cpu only
+
+	enum ETeams {CPHUMAN = 0, CPUONLY = 1, AFTER_LAST = 2};
+	std::array<std::list<int>, 2> teamNumbers;
+
 	int teamOffset = 0;
-	for(int i = 0; i < 2; ++i)
-	{
-		int playerCount = i == 0 ? mapGenOptions->getPlayerCount() : mapGenOptions->getCompOnlyPlayerCount();
-		int teamCount = i == 0 ? mapGenOptions->getTeamCount() : mapGenOptions->getCompOnlyTeamCount();
+	int playerCount = 0;
+	int teamCount = 0;
 
+	for (int i = CPHUMAN; i < AFTER_LAST; ++i)
+	{
+		if (i == CPHUMAN)
+		{
+			playerCount = mapGenOptions->getPlayerCount();
+			teamCount = mapGenOptions->getTeamCount();
+		}
+		else
+		{
+			playerCount = mapGenOptions->getCompOnlyPlayerCount();
+			teamCount = mapGenOptions->getCompOnlyTeamCount();
+		}
+		
 		if(playerCount == 0)
 		{
 			continue;
 		}
-		int playersPerTeam = playerCount /
-				(teamCount == 0 ? playerCount : teamCount);
+		int playersPerTeam = playerCount / (teamCount == 0 ? playerCount : teamCount);
 		int teamCountNorm = teamCount;
 		if(teamCountNorm == 0)
 		{
@@ -202,17 +215,23 @@ void CMapGenerator::addPlayerInfo()
 	}
 
 	// Team numbers are assigned randomly to every player
+	//TODO: allow customize teams in rmg template
 	for(const auto & pair : mapGenOptions->getPlayersSettings())
 	{
 		const auto & pSettings = pair.second;
 		PlayerInfo player;
 		player.canComputerPlay = true;
-		int j = pSettings.getPlayerType() == EPlayerType::COMP_ONLY ? 1 : 0;
-		if(j == 0)
+		int j = (pSettings.getPlayerType() == EPlayerType::COMP_ONLY) ? CPUONLY : CPHUMAN;
+		if (j == CPHUMAN)
 		{
 			player.canHumanPlay = true;
 		}
 
+		if (teamNumbers[j].empty())
+		{
+			logGlobal->errorStream() << boost::format("Not enough places in team for %s player") % ((j == CPUONLY) ? "CPU" : "CPU or human");
+			assert (teamNumbers[j].size());
+		}
         auto itTeam = RandomGeneratorUtil::nextItem(teamNumbers[j], rand);
 		player.team = TeamID(*itTeam);
 		teamNumbers[j].erase(itTeam);