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; } }
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(); } } }
/// 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 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()); }
void CGQuestGuard::init(CRandomGenerator & rand) { blockVisit = true; quest->textOption = rand.nextInt(3, 5); quest->completedOption = rand.nextInt(4, 5); }
void CGSeerHut::init(CRandomGenerator & rand) { seerName = *RandomGeneratorUtil::nextItem(VLC->generaltexth->seerNames, rand); quest->textOption = rand.nextInt(2); quest->completedOption = rand.nextInt(1, 3); }
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; } }
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 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; } }