void CGVisitableOPW::setRandomReward(CRandomGenerator &rand) { switch (ID) { case Obj::MYSTICAL_GARDEN: info.resize(1); info[0].limiter.numOfGrants = 1; info[0].reward.resources.amin(0); if (rand.nextInt(1) == 0) { info[0].reward.resources[Res::GEMS] = 5; } else { info[0].reward.resources[Res::GOLD] = 500; } break; case Obj::WINDMILL: info.resize(1); info[0].reward.resources.amin(0); // 3-6 of any resource but wood and gold info[0].reward.resources[rand.nextInt(Res::MERCURY, Res::GEMS)] = rand.nextInt(3, 6); info[0].limiter.numOfGrants = 1; break; case Obj::WATER_WHEEL: info.resize(1); info[0].reward.resources.amin(0); info[0].reward.resources[Res::GOLD] = 500; info[0].limiter.numOfGrants = 1; break; } }
// ------------------------------------------------------ // Benchmark Random Generators // ------------------------------------------------------ double random_test_1(int a1, int a2) { CRandomGenerator rg; // test 1: draw uint32 // ---------------------------------------- const long N = 100000000; CTicTac tictac; for (long i = 0; i < N; i++) { rg.drawUniform32bit(); } return tictac.Tac() / N; }
double random_test_2(int a1, int a2) { CRandomGenerator rg; // test 2: drawUniform // ---------------------------------------- const long N = 100000000; CTicTac tictac; for (long i = 0; i < N; i++) { rg.drawUniform(0, 1); } return tictac.Tac() / N; }
double random_test_3(int a1, int a2) { CRandomGenerator rg; // test 3: drawGaussian1D_normalized // ---------------------------------------- const long N = 10000000; CTicTac tictac; for (long i = 0; i < N; i++) { rg.drawGaussian1D_normalized(); } return tictac.Tac() / N; }
double random_test_4(int a1, int a2) { CRandomGenerator rg; // test 4: drawGaussian1D // ---------------------------------------- const long N = 10000000; CTicTac tictac; for (long i = 0; i < N; i++) { rg.drawGaussian1D(5.0, 3.0); } return tictac.Tac() / N; }
void CBankInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const { //logGlobal->debugStream() << "Seed used to configure bank is " << rng.nextInt(); auto bank = dynamic_cast<CBank*>(object); bank->resetDuration = bankResetDuration; si32 totalChance = 0; for (auto & node : levels) totalChance += node["chance"].Float(); assert(totalChance != 0); si32 selectedChance = rng.nextInt(totalChance - 1); //logGlobal->debugStream() << "Selected chance for bank config is " << selectedChance; for (auto & node : levels) { if (selectedChance < node["chance"].Float()) { bank->setConfig(generateConfig(node, rng)); } else { selectedChance -= node["chance"].Float(); } } }
double random_test_6(int a1, int a2) { CRandomGenerator rg; double COVs[] = {6.0, -5.0, 2.0, -5.0, 3.0, 1.0, 2.0, 1.0, 7.0}; CMatrixDouble33 COV(COVs); // test 6: // ---------------------------------------- const long N = 100000; CTicTac tictac; CVectorDouble res; for (long i = 0; i < N; i++) { rg.drawGaussianMultivariate(res, COV); } return tictac.Tac() / N; }
double random_test_10(int a1, int a2) { CRandomGenerator rg; CVectorDouble vec(a1); rg.drawUniformVector(vec, 0.0, 1.0); // test 10: permute // ---------------------------------------- const long N = 10000; CVectorDouble vec2; CTicTac tictac; for (long i = 0; i < N; i++) { rg.permuteVector(vec, vec2); } return tictac.Tac() / N; }
double random_test_9(int a1, int a2) { CRandomGenerator rg; CMatrixTemplateNumeric<double> R(a1, a1); rg.drawGaussian1DMatrix(R, 0.0, 1.0); CMatrixTemplateNumeric<double> COV; COV.multiply_AAt(R); const size_t NSAMPS = 1000; // test 9: // ---------------------------------------- const long N = 1000; CTicTac tictac; std::vector<CVectorDouble> res; for (long i = 0; i < N; i++) { rg.drawGaussianMultivariateMany(res, NSAMPS, COV); } return tictac.Tac() / (N * NSAMPS); }
double random_test_8(int a1, int a2) { CRandomGenerator rg; CMatrixFixed<double, DIM, DIM> R; rg.drawGaussian1DMatrix(R, 0.0, 1.0); CMatrixFixed<double, DIM, DIM> COV; COV.matProductOf_AAt(R); const size_t NSAMPS = 1000; // test 8: // ---------------------------------------- const long N = 1000; CTicTac tictac; std::vector<CVectorDouble> res; for (long i = 0; i < N; i++) { rg.drawGaussianMultivariateMany(res, NSAMPS, COV); } return tictac.Tac() / (N * NSAMPS); }
/// Helper, selects random art class based on weights static int selectRandomArtClass(CRandomGenerator & rand, int treasure, int minor, int major, int relic) { int total = treasure + minor + major + relic; assert(total != 0); int hlp = rand.nextInt(total - 1); if(hlp < treasure) return CArtifact::ART_TREASURE; if(hlp < treasure + minor) return CArtifact::ART_MINOR; if(hlp < treasure + minor + major) return CArtifact::ART_MAJOR; return CArtifact::ART_RELIC; }
ui32 BattleInfo::calculateDmg( const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg, CRandomGenerator & rand ) { TDmgRange range = calculateDmgRange(attacker, defender, shooting, charge, lucky, unlucky, deathBlow, ballistaDoubleDmg); if(range.first != range.second) { int valuesToAverage[10]; int howManyToAv = std::min<ui32>(10, attacker->count); for (int g=0; g<howManyToAv; ++g) { valuesToAverage[g] = rand.nextInt(range.first, range.second); } return std::accumulate(valuesToAverage, valuesToAverage + howManyToAv, 0) / howManyToAv; } else return range.first; }
SecondarySkill CHeroClass::chooseSecSkill(const std::set<SecondarySkill> & possibles, CRandomGenerator & rand) const //picks secondary skill out from given possibilities { int totalProb = 0; for(auto & possible : possibles) { totalProb += secSkillProbability[possible]; } if (totalProb != 0) // may trigger if set contains only banned skills (0 probability) { auto ran = rand.nextInt(totalProb - 1); for(auto & possible : possibles) { ran -= secSkillProbability[possible]; if(ran < 0) { return possible; } } } // FIXME: select randomly? How H3 handles such rare situation? return *possibles.begin(); }
void CGQuestGuard::init(CRandomGenerator & rand) { blockVisit = true; quest->textOption = rand.nextInt(3, 5); quest->completedOption = rand.nextInt(4, 5); }
void CGPickable::initObj(CRandomGenerator & rand) { blockVisit = true; switch(ID) { case Obj::CAMPFIRE: { soundID = soundBase::experience; int givenRes = rand.nextInt(5); int givenAmm = rand.nextInt(4, 6); info.resize(1); info[0].reward.resources[givenRes] = givenAmm; info[0].reward.resources[Res::GOLD]= givenAmm * 100; info[0].message.addTxt(MetaString::ADVOB_TXT,23); info[0].reward.removeObject = true; break; } case Obj::FLOTSAM: { int type = rand.nextInt(3); soundID = soundBase::GENIE; switch(type) { case 0: info.resize(1); info[0].message.addTxt(MetaString::ADVOB_TXT, 51); info[0].reward.removeObject = true; break; case 1: { info.resize(1); info[0].reward.resources[Res::WOOD] = 5; info[0].message.addTxt(MetaString::ADVOB_TXT, 52); info[0].reward.removeObject = true; break; } case 2: { info.resize(1); info[0].reward.resources[Res::WOOD] = 5; info[0].reward.resources[Res::GOLD] = 200; info[0].message.addTxt(MetaString::ADVOB_TXT, 53); info[0].reward.removeObject = true; break; } case 3: { info.resize(1); info[0].reward.resources[Res::WOOD] = 10; info[0].reward.resources[Res::GOLD] = 500; info[0].message.addTxt(MetaString::ADVOB_TXT, 54); info[0].reward.removeObject = true; break; } } break; } case Obj::SEA_CHEST: { soundID = soundBase::chest; int hlp = rand.nextInt(99); if(hlp < 20) { info.resize(1); info[0].message.addTxt(MetaString::ADVOB_TXT, 116); info[0].reward.removeObject = true; } else if(hlp < 90) { info.resize(1); info[0].reward.resources[Res::GOLD] = 1500; info[0].message.addTxt(MetaString::ADVOB_TXT, 118); info[0].reward.removeObject = true; } else { info.resize(1); loadRandomArtifact(rand, info[0], 100, 0, 0, 0); info[0].reward.resources[Res::GOLD] = 1000; info[0].message.addTxt(MetaString::ADVOB_TXT, 117); info[0].message.addReplacement(MetaString::ART_NAMES, info[0].reward.artifacts.back()); info[0].reward.removeObject = true; } } break; case Obj::SHIPWRECK_SURVIVOR: { soundID = soundBase::experience; info.resize(1); loadRandomArtifact(rand, info[0], 55, 20, 20, 5); info[0].message.addTxt(MetaString::ADVOB_TXT, 125); info[0].message.addReplacement(MetaString::ART_NAMES, info[0].reward.artifacts.back()); info[0].reward.removeObject = true; } break; case Obj::TREASURE_CHEST: { int hlp = rand.nextInt(99); if(hlp >= 95) { soundID = soundBase::treasure; info.resize(1); loadRandomArtifact(rand, info[0], 100, 0, 0, 0); info[0].message.addTxt(MetaString::ADVOB_TXT,145); info[0].message.addReplacement(MetaString::ART_NAMES, info[0].reward.artifacts.back()); info[0].reward.removeObject = true; return; } else if (hlp >= 65) { soundID = soundBase::chest; onSelect.addTxt(MetaString::ADVOB_TXT,146); info.resize(2); info[0].reward.resources[Res::GOLD] = 2000; info[1].reward.gainedExp = 1500; info[0].reward.removeObject = true; info[1].reward.removeObject = true; } else if(hlp >= 33) { soundID = soundBase::chest; onSelect.addTxt(MetaString::ADVOB_TXT,146); info.resize(2); info[0].reward.resources[Res::GOLD] = 1500; info[1].reward.gainedExp = 1000; info[0].reward.removeObject = true; info[1].reward.removeObject = true; } else { soundID = soundBase::chest; onSelect.addTxt(MetaString::ADVOB_TXT,146); info.resize(2); info[0].reward.resources[Res::GOLD] = 1000; info[1].reward.gainedExp = 500; info[0].reward.removeObject = true; info[1].reward.removeObject = true; } } break; } }
void CGOnceVisitable::initObj(CRandomGenerator & rand) { switch(ID) { case Obj::CORPSE: { onEmpty.addTxt(MetaString::ADVOB_TXT, 38); soundID = soundBase::MYSTERY; blockVisit = true; if(rand.nextInt(99) < 20) { info.resize(1); loadRandomArtifact(rand, info[0], 10, 10, 10, 0); info[0].message.addTxt(MetaString::ADVOB_TXT, 37); info[0].limiter.numOfGrants = 1; } } break; case Obj::LEAN_TO: { soundID = soundBase::GENIE; onEmpty.addTxt(MetaString::ADVOB_TXT, 65); info.resize(1); int type = rand.nextInt(5); //any basic resource without gold int value = rand.nextInt(1, 4); info[0].reward.resources[type] = value; info[0].message.addTxt(MetaString::ADVOB_TXT, 64); info[0].limiter.numOfGrants = 1; } break; case Obj::WARRIORS_TOMB: { soundID = soundBase::GRAVEYARD; onSelect.addTxt(MetaString::ADVOB_TXT, 161); info.resize(2); loadRandomArtifact(rand, info[0], 30, 50, 25, 5); Bonus bonus(Bonus::ONE_BATTLE, Bonus::MORALE, Bonus::OBJECT, -3, ID); info[0].reward.bonuses.push_back(bonus); info[1].reward.bonuses.push_back(bonus); info[0].limiter.numOfGrants = 1; info[0].message.addTxt(MetaString::ADVOB_TXT, 162); info[0].message.addReplacement(VLC->arth->artifacts[info[0].reward.artifacts.back()]->Name()); info[1].message.addTxt(MetaString::ADVOB_TXT, 163); } break; case Obj::WAGON: { soundID = soundBase::GENIE; onVisited.addTxt(MetaString::ADVOB_TXT, 156); int hlp = rand.nextInt(99); if(hlp < 40) //minor or treasure art { info.resize(1); loadRandomArtifact(rand, info[0], 10, 10, 0, 0); info[0].limiter.numOfGrants = 1; info[0].message.addTxt(MetaString::ADVOB_TXT, 155); } else if(hlp < 90) //2 - 5 of non-gold resource { info.resize(1); int type = rand.nextInt(5); int value = rand.nextInt(2, 5); info[0].reward.resources[type] = value; info[0].limiter.numOfGrants = 1; info[0].message.addTxt(MetaString::ADVOB_TXT, 154); } // or nothing } break; } }
void CGVisitableOPH::initObj(CRandomGenerator & rand) { switch(ID) { case Obj::ARENA: soundID = soundBase::NOMAD; info.resize(2); info[0].reward.primary[PrimarySkill::ATTACK] = 2; info[1].reward.primary[PrimarySkill::DEFENSE] = 2; onSelect.addTxt(MetaString::ADVOB_TXT, 0); onVisited.addTxt(MetaString::ADVOB_TXT, 1); canRefuse = true; break; case Obj::MERCENARY_CAMP: info.resize(1); info[0].reward.primary[PrimarySkill::ATTACK] = 1; soundID = soundBase::NOMAD; info[0].message.addTxt(MetaString::ADVOB_TXT, 80); onVisited.addTxt(MetaString::ADVOB_TXT, 81); break; case Obj::MARLETTO_TOWER: info.resize(1); info[0].reward.primary[PrimarySkill::DEFENSE] = 1; soundID = soundBase::NOMAD; info[0].message.addTxt(MetaString::ADVOB_TXT, 39); onVisited.addTxt(MetaString::ADVOB_TXT, 40); break; case Obj::STAR_AXIS: info.resize(1); info[0].reward.primary[PrimarySkill::SPELL_POWER] = 1; soundID = soundBase::gazebo; info[0].message.addTxt(MetaString::ADVOB_TXT, 100); onVisited.addTxt(MetaString::ADVOB_TXT, 101); break; case Obj::GARDEN_OF_REVELATION: info.resize(1); info[0].reward.primary[PrimarySkill::KNOWLEDGE] = 1; soundID = soundBase::GETPROTECTION; info[0].message.addTxt(MetaString::ADVOB_TXT, 59); onVisited.addTxt(MetaString::ADVOB_TXT, 60); break; case Obj::LEARNING_STONE: info.resize(1); info[0].reward.gainedExp = 1000; soundID = soundBase::gazebo; info[0].message.addTxt(MetaString::ADVOB_TXT, 143); onVisited.addTxt(MetaString::ADVOB_TXT, 144); break; case Obj::TREE_OF_KNOWLEDGE: soundID = soundBase::gazebo; info.resize(1); canRefuse = true; info[0].reward.gainedLevels = 1; onVisited.addTxt(MetaString::ADVOB_TXT, 147); info.resize(1); switch (rand.nextInt(2)) { case 0: // free onSelect.addTxt(MetaString::ADVOB_TXT, 148); break; case 1: info[0].limiter.resources[Res::GOLD] = 2000; info[0].reward.resources[Res::GOLD] = -2000; onSelect.addTxt(MetaString::ADVOB_TXT, 149); onEmpty.addTxt(MetaString::ADVOB_TXT, 150); break; case 2: info[0].limiter.resources[Res::GEMS] = 10; info[0].reward.resources[Res::GEMS] = -10; onSelect.addTxt(MetaString::ADVOB_TXT, 151); onEmpty.addTxt(MetaString::ADVOB_TXT, 152); break; } break; case Obj::LIBRARY_OF_ENLIGHTENMENT: { onVisited.addTxt(MetaString::ADVOB_TXT, 67); onEmpty.addTxt(MetaString::ADVOB_TXT, 68); // Don't like this one but don't see any easier approach CVisitInfo visit; visit.reward.primary[PrimarySkill::ATTACK] = 2; visit.reward.primary[PrimarySkill::DEFENSE] = 2; visit.reward.primary[PrimarySkill::KNOWLEDGE] = 2; visit.reward.primary[PrimarySkill::SPELL_POWER] = 2; static_assert(SecSkillLevel::LEVELS_SIZE == 4, "Behavior of Library of Enlignment may not be correct"); for (int i=0; i<SecSkillLevel::LEVELS_SIZE; i++) { visit.limiter.minLevel = 10 - i * 2; visit.limiter.secondary[SecondarySkill::DIPLOMACY] = i; visit.message.addTxt(MetaString::ADVOB_TXT, 66); info.push_back(visit); } soundID = soundBase::gazebo; break; } case Obj::SCHOOL_OF_MAGIC: info.resize(2); info[0].reward.primary[PrimarySkill::SPELL_POWER] = 1; info[1].reward.primary[PrimarySkill::KNOWLEDGE] = 1; info[0].reward.resources[Res::GOLD] = -1000; info[1].reward.resources[Res::GOLD] = -1000; onSelect.addTxt(MetaString::ADVOB_TXT, 71); onVisited.addTxt(MetaString::ADVOB_TXT, 72); onEmpty.addTxt(MetaString::ADVOB_TXT, 73); soundID = soundBase::faerie; canRefuse = true; break; case Obj::SCHOOL_OF_WAR: info.resize(2); info[0].reward.primary[PrimarySkill::ATTACK] = 1; info[1].reward.primary[PrimarySkill::DEFENSE] = 1; info[0].reward.resources[Res::GOLD] = -1000; info[1].reward.resources[Res::GOLD] = -1000; onSelect.addTxt(MetaString::ADVOB_TXT, 158); onVisited.addTxt(MetaString::ADVOB_TXT, 159); onEmpty.addTxt(MetaString::ADVOB_TXT, 160); soundID = soundBase::MILITARY; canRefuse = true; break; } }
inline CMatrixTemplateNumeric<T> operator()() { do gen.drawUniformMatrix(tmp,T(-3.0),T(3.0)); while (tmp.isSingular(eps)); res.multiply_AAt(tmp); return res; }
MyMat operator()() { MyMat res(sz,sz); do gen.drawUniformMatrix(res,-10.0,10.0); while (res.isSingular(1e-4)); return res; }
void CGSeerHut::init(CRandomGenerator & rand) { seerName = *RandomGeneratorUtil::nextItem(VLC->generaltexth->seerNames, rand); quest->textOption = rand.nextInt(2); quest->completedOption = rand.nextInt(1, 3); }
inline vector<T> operator()() { gen.drawUniformVector(res,T(-3.0),T(3.0)); return res; }
void CRandomRewardObjectInfo::configureObject(CRewardableObject * object, CRandomGenerator & rng) const { std::map<si32, si32> thrownDice; for (const JsonNode & reward : parameters["rewards"].Vector()) { if (!reward["appearChance"].isNull()) { JsonNode chance = reward["appearChance"]; si32 diceID = chance["dice"].Float(); if (thrownDice.count(diceID) == 0) thrownDice[diceID] = rng.getIntRange(1, 100)(); if (!chance["min"].isNull()) { int min = chance["min"].Float(); if (min > thrownDice[diceID]) continue; } if (!chance["max"].isNull()) { int max = chance["max"].Float(); if (max < thrownDice[diceID]) continue; } } const JsonNode & limiter = reward["limiter"]; CVisitInfo info; // load limiter info.limiter.numOfGrants = JsonRandom::loadValue(limiter["numOfGrants"], rng); info.limiter.dayOfWeek = JsonRandom::loadValue(limiter["dayOfWeek"], rng); info.limiter.minLevel = JsonRandom::loadValue(limiter["minLevel"], rng); info.limiter.resources = JsonRandom::loadResources(limiter["resources"], rng); info.limiter.primary = JsonRandom::loadPrimary(limiter["primary"], rng); info.limiter.secondary = JsonRandom::loadSecondary(limiter["secondary"], rng); info.limiter.artifacts = JsonRandom::loadArtifacts(limiter["artifacts"], rng); info.limiter.creatures = JsonRandom::loadCreatures(limiter["creatures"], rng); info.reward.resources = JsonRandom::loadResources(reward["resources"], rng); info.reward.gainedExp = JsonRandom::loadValue(reward["gainedExp"], rng); info.reward.gainedLevels = JsonRandom::loadValue(reward["gainedLevels"], rng); info.reward.manaDiff = JsonRandom::loadValue(reward["manaPoints"], rng); info.reward.manaPercentage = JsonRandom::loadValue(reward["manaPercentage"], rng, -1); info.reward.movePoints = JsonRandom::loadValue(reward["movePoints"], rng); info.reward.movePercentage = JsonRandom::loadValue(reward["movePercentage"], rng, -1); //FIXME: compile this line on Visual //info.reward.bonuses = JsonRandom::loadBonuses(reward["bonuses"]); info.reward.primary = JsonRandom::loadPrimary(reward["primary"], rng); info.reward.secondary = JsonRandom::loadSecondary(reward["secondary"], rng); std::vector<SpellID> spells; for (size_t i=0; i<6; i++) IObjectInterface::cb->getAllowedSpells(spells, i); info.reward.artifacts = JsonRandom::loadArtifacts(reward["artifacts"], rng); info.reward.spells = JsonRandom::loadSpells(reward["spells"], rng, spells); info.reward.creatures = JsonRandom::loadCreatures(reward["creatures"], rng); info.message = loadMessage(reward["message"]); info.selectChance = JsonRandom::loadValue(reward["selectChance"], rng); } object->onSelect = loadMessage(parameters["onSelectMessage"]); object->onVisited = loadMessage(parameters["onVisitedMessage"]); object->onEmpty = loadMessage(parameters["onEmptyMessage"]); //TODO: visitMode and selectMode object->soundID = parameters["soundID"].Float(); object->resetDuration = parameters["resetDuration"].Float(); object->canRefuse =parameters["canRefuse"].Bool(); }
void CMapGenOptions::finalize(CRandomGenerator & rand) { logGlobal->info("RMG settings: players %d, teams %d, computer players %d, computer teams %d, water %d, monsters %d", static_cast<int>(getPlayerCount()), static_cast<int>(getTeamCount()), static_cast<int>(getCompOnlyPlayerCount()), static_cast<int>(getCompOnlyTeamCount()), static_cast<int>(getWaterContent()), static_cast<int>(getMonsterStrength())); if(!mapTemplate) { mapTemplate = getPossibleTemplate(rand); } assert(mapTemplate); if (getPlayerCount() == RANDOM_SIZE) { auto possiblePlayers = mapTemplate->getPlayers().getNumbers(); //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(); } if(teamCount == RANDOM_SIZE) { teamCount = rand.nextInt(getPlayerCount() - 1); if (teamCount == 1) teamCount = 0; } if(compOnlyPlayerCount == RANDOM_SIZE) { auto possiblePlayers = mapTemplate->getCpuPlayers().getNumbers(); compOnlyPlayerCount = *RandomGeneratorUtil::nextItem(possiblePlayers, rand); updateCompOnlyPlayers(); } if(compOnlyTeamCount == RANDOM_SIZE) { compOnlyTeamCount = rand.nextInt(std::max(compOnlyPlayerCount - 1, 0)); } if(waterContent == EWaterContent::RANDOM) { waterContent = static_cast<EWaterContent::EWaterContent>(rand.nextInt(EWaterContent::NONE, EWaterContent::ISLANDS)); } if(monsterStrength == EMonsterStrength::RANDOM) { monsterStrength = static_cast<EMonsterStrength::EMonsterStrength>(rand.nextInt(EMonsterStrength::GLOBAL_WEAK, EMonsterStrength::GLOBAL_STRONG)); } 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->trace("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->trace("Player %d: %s", player.second.getColor(), playerType); } setCompOnlyPlayerCount(cpuOnlyPlayers); //human players are set automaticlaly (?) logGlobal->info("Final player config: %d total, %d cpu-only", players.size(), (int)getCompOnlyPlayerCount()); }