diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index 60d723954..f1011e755 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -1671,7 +1671,7 @@ CRandomMapTab::CRandomMapTab() { mapGenOptions.setPlayerCount(btnId); deactivateButtonsFrom(teamsCntGroup, btnId); - deactivateButtonsFrom(compOnlyPlayersCntGroup, 8 - btnId + 1); + deactivateButtonsFrom(compOnlyPlayersCntGroup, btnId); validatePlayersCnt(btnId); if(!SEL->isGuest()) updateMapInfo(); @@ -1694,7 +1694,6 @@ CRandomMapTab::CRandomMapTab() compOnlyPlayersCntGroup->pos.y += 285; compOnlyPlayersCntGroup->pos.x += BTNS_GROUP_LEFT_MARGIN; addButtonsWithRandToGroup(compOnlyPlayersCntGroup, numberDefs, 0, 7, NUMBERS_WIDTH, 224, 232); - compOnlyPlayersCntGroup->setSelected(0); compOnlyPlayersCntGroup->addCallback([&](int btnId) { mapGenOptions.setCompOnlyPlayerCount(btnId); @@ -1808,9 +1807,9 @@ void CRandomMapTab::validatePlayersCnt(int playersCnt) mapGenOptions.setTeamCount(playersCnt - 1); teamsCntGroup->setSelected(mapGenOptions.getTeamCount()); } - if(mapGenOptions.getCompOnlyPlayerCount() > 8 - playersCnt) + if(mapGenOptions.getCompOnlyPlayerCount() >= playersCnt) { - mapGenOptions.setCompOnlyPlayerCount(8 - playersCnt); + mapGenOptions.setCompOnlyPlayerCount(playersCnt - 1); compOnlyPlayersCntGroup->setSelected(mapGenOptions.getCompOnlyPlayerCount()); } diff --git a/config/schemas/template.json b/config/schemas/template.json index 2dcbb29ba..52362f985 100644 --- a/config/schemas/template.json +++ b/config/schemas/template.json @@ -11,7 +11,7 @@ { "zone":{ "type": "object", - "required" : ["type", "monsters", "size", "level"], + "required" : ["type", "monsters", "size"], "properties":{ "type":{"$ref" : "#/definitions/type"}, "size":{"$ref" : "#/definitions/size"}, @@ -35,9 +35,8 @@ } }, "type" :{ - "type" : "object", - "enum": ["playerStart", "treasure", "junction"] - "additionalProperties" : false + "enum": ["playerStart", "cpuStart", "treasure", "junction"], + "additionalProperties" : false, "type":"string" }, "size":{ @@ -50,13 +49,13 @@ "properties": { "zones":{ - "type": "array", - "items":{"$ref" : "#/definitions/zone" } + "type": "object", + "additionalProperties":{"$ref" : "#/definitions/zone" } }, "connections":{ "type": "array", "items":{"$ref" : "#/definitions/connection"} - } + }, "required" : ["zones", "connections"], "additionalProperties" : false } diff --git a/lib/rmg/CMapGenOptions.cpp b/lib/rmg/CMapGenOptions.cpp index dbdf8afb5..1213e4709 100644 --- a/lib/rmg/CMapGenOptions.cpp +++ b/lib/rmg/CMapGenOptions.cpp @@ -20,7 +20,7 @@ #include "../CTownHandler.h" CMapGenOptions::CMapGenOptions() : width(CMapHeader::MAP_SIZE_MIDDLE), height(CMapHeader::MAP_SIZE_MIDDLE), hasTwoLevels(false), - playerCount(RANDOM_SIZE), teamCount(RANDOM_SIZE), compOnlyPlayerCount(0), compOnlyTeamCount(RANDOM_SIZE), + playerCount(RANDOM_SIZE), teamCount(RANDOM_SIZE), compOnlyPlayerCount(RANDOM_SIZE), compOnlyTeamCount(RANDOM_SIZE), humanPlayersCount(0), waterContent(EWaterContent::RANDOM), monsterStrength(EMonsterStrength::RANDOM), mapTemplate(nullptr) { resetPlayersMap(); @@ -67,9 +67,11 @@ void CMapGenOptions::setPlayerCount(si8 value) { assert((value >= 1 && value <= PlayerColor::PLAYER_LIMIT_I) || value == RANDOM_SIZE); playerCount = value; - auto possibleCompPlayersCount = PlayerColor::PLAYER_LIMIT_I-value; - if(compOnlyPlayerCount > possibleCompPlayersCount) + auto possibleCompPlayersCount = value; + if (compOnlyPlayerCount > possibleCompPlayersCount) setCompOnlyPlayerCount(possibleCompPlayersCount); + + humanPlayersCount = playerCount - compOnlyPlayerCount; resetPlayersMap(); } @@ -91,8 +93,9 @@ si8 CMapGenOptions::getCompOnlyPlayerCount() const void CMapGenOptions::setCompOnlyPlayerCount(si8 value) { - assert(value == RANDOM_SIZE || (value >= 0 && value <= PlayerColor::PLAYER_LIMIT_I - playerCount)); + assert(value == RANDOM_SIZE || (value >= 0 && value <= playerCount)); compOnlyPlayerCount = value; + humanPlayersCount = playerCount - compOnlyPlayerCount; resetPlayersMap(); } @@ -130,12 +133,13 @@ void CMapGenOptions::setMonsterStrength(EMonsterStrength::EMonsterStrength value void CMapGenOptions::resetPlayersMap() { players.clear(); - int realPlayersCnt = playerCount == RANDOM_SIZE ? static_cast(PlayerColor::PLAYER_LIMIT_I) : playerCount; - int realCompOnlyPlayersCnt = compOnlyPlayerCount == RANDOM_SIZE ? (PlayerColor::PLAYER_LIMIT_I - realPlayersCnt) : compOnlyPlayerCount; + int realPlayersCnt = humanPlayersCount; + int realCompOnlyPlayersCnt = (compOnlyPlayerCount == RANDOM_SIZE) ? (PlayerColor::PLAYER_LIMIT_I - realPlayersCnt) : compOnlyPlayerCount; int totalPlayersLimit = realPlayersCnt + realCompOnlyPlayersCnt; if(playerCount == RANDOM_SIZE || compOnlyPlayerCount == RANDOM_SIZE) totalPlayersLimit = static_cast(PlayerColor::PLAYER_LIMIT_I); + //FIXME: what happens with human players here? for(int color = 0; color < totalPlayersLimit; ++color) { CPlayerSettings player; @@ -262,14 +266,12 @@ void CMapGenOptions::updatePlayers() void CMapGenOptions::updateCompOnlyPlayers() { - auto totalPlayersCnt = playerCount + compOnlyPlayerCount; - // 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 (players.size() <= playerCount) break; if(it->second.getPlayerType() == EPlayerType::COMP_ONLY) { players.erase(it); @@ -281,7 +283,7 @@ void CMapGenOptions::updateCompOnlyPlayers() } // Add some comp only players if necessary - auto compOnlyPlayersToAdd = totalPlayersCnt - players.size(); + auto compOnlyPlayersToAdd = playerCount - players.size(); for(int i = 0; i < compOnlyPlayersToAdd; ++i) { CPlayerSettings pSettings; @@ -340,31 +342,34 @@ const CRmgTemplate * CMapGenOptions::getPossibleTemplate(CRandomGenerator & rand bool isPlayerCountValid = false; if(playerCount != RANDOM_SIZE) { - if(tpl->getPlayers().isInRange(playerCount)) isPlayerCountValid = true; + if (tpl->getPlayers().isInRange(playerCount)) + isPlayerCountValid = true; } else { // Human players shouldn't be banned when playing with random player count auto playerNumbers = tpl->getPlayers().getNumbers(); - if(playerNumbers.lower_bound(countHumanPlayers()) != playerNumbers.end()) + if(countHumanPlayers() <= *boost::min_element(playerNumbers)) { isPlayerCountValid = true; } } - if(isPlayerCountValid) + if (isPlayerCountValid) { bool isCpuPlayerCountValid = false; if(compOnlyPlayerCount != RANDOM_SIZE) { - if(tpl->getCpuPlayers().isInRange(compOnlyPlayerCount)) isCpuPlayerCountValid = true; + if (tpl->getCpuPlayers().isInRange(compOnlyPlayerCount)) + isCpuPlayerCountValid = true; } else { isCpuPlayerCountValid = true; } - if(isCpuPlayerCountValid) potentialTpls.push_back(tpl); + if(isCpuPlayerCountValid) + potentialTpls.push_back(tpl); } } } diff --git a/lib/rmg/CMapGenOptions.h b/lib/rmg/CMapGenOptions.h index dc0c095de..1f7e3f29b 100644 --- a/lib/rmg/CMapGenOptions.h +++ b/lib/rmg/CMapGenOptions.h @@ -103,7 +103,7 @@ public: bool getHasTwoLevels() const; void setHasTwoLevels(bool value); - /// The count of the players ranging from 1 to PlayerColor::PLAYER_LIMIT or RANDOM_SIZE for random. If you call + /// The count of all (human or computer) 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 getPlayerCount() const; void setPlayerCount(si8 value); @@ -162,7 +162,7 @@ private: si32 width, height; bool hasTwoLevels; - si8 playerCount, teamCount, compOnlyPlayerCount, compOnlyTeamCount; + si8 playerCount, teamCount, humanPlayersCount, compOnlyPlayerCount, compOnlyTeamCount; EWaterContent::EWaterContent waterContent; EMonsterStrength::EMonsterStrength monsterStrength; std::map players; @@ -173,7 +173,7 @@ public: void serialize(Handler & h, const int version) { h & width & height & hasTwoLevels & playerCount & teamCount & compOnlyPlayerCount; - h & compOnlyTeamCount & waterContent & monsterStrength & players; + h & compOnlyTeamCount & waterContent & monsterStrength & players & humanPlayersCount; //TODO add name of template to class, enables selection of a template by a user } }; diff --git a/lib/rmg/CMapGenerator.cpp b/lib/rmg/CMapGenerator.cpp index 285e913d1..d755b77fb 100644 --- a/lib/rmg/CMapGenerator.cpp +++ b/lib/rmg/CMapGenerator.cpp @@ -144,7 +144,7 @@ std::string CMapGenerator::getMapDescription() const std::stringstream ss; ss << boost::str(boost::format(std::string("Map created by the Random Map Generator.\nTemplate was %s, Random seed was %d, size %dx%d") + - ", levels %s, humans %d, computers %d, water %s, monster %s, VCMI map") % mapGenOptions->getMapTemplate()->getName() % + ", levels %s, players %d, computers %d, water %s, monster %s, VCMI map") % mapGenOptions->getMapTemplate()->getName() % randomSeed % map->width % map->height % (map->twoLevel ? "2" : "1") % static_cast(mapGenOptions->getPlayerCount()) % static_cast(mapGenOptions->getCompOnlyPlayerCount()) % waterContentStr[mapGenOptions->getWaterContent()] % monsterStrengthStr[monsterStrengthIndex]);