Skip to content

Commit

Permalink
use custom std::minstd_rand based RNG for AI
Browse files Browse the repository at this point in the history
  • Loading branch information
wichern committed Feb 8, 2025
1 parent 7f20e8d commit 244e436
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 16 deletions.
10 changes: 5 additions & 5 deletions libs/s25main/ai/aijh/AIConstruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
#include "addons/const_addons.h"
#include "ai/AIInterface.h"
#include "ai/aijh/AIPlayerJH.h"
#include "ai/random.h"
#include "buildings/noBuildingSite.h"
#include "buildings/nobBaseMilitary.h"
#include "buildings/nobBaseWarehouse.h"
#include "buildings/nobMilitary.h"
#include "buildings/nobUsual.h"
#include "helpers/containerUtils.h"
#include "random/Random.h"
#include "nodeObjs/noFlag.h"
#include "nodeObjs/noRoadNode.h"
#include "gameTypes/BuildingQuality.h"
Expand Down Expand Up @@ -467,10 +467,10 @@ helpers::OptionalEnum<BuildingType> AIConstruction::ChooseMilitaryBuilding(const

const Inventory& inventory = aii.GetInventory();
uint8_t playerId = aii.GetPlayerId();
if((RANDOM.Rand(RANDOM_CONTEXT2(playerId), 3) == 0 || inventory.people[Job::Private] < 15)
if((AI::randomValue<int>(0, 3) == 0 || inventory.people[Job::Private] < 15)
&& (inventory.goods[GoodType::Stones] > 6 || bldPlanner.GetNumBuildings(BuildingType::Quarry) > 0))
bld = BuildingType::Guardhouse;
if(aijh.getAIInterface().isHarborPosClose(pt, 19) && RANDOM.Rand(RANDOM_CONTEXT2(playerId), 10) != 0
if(aijh.getAIInterface().isHarborPosClose(pt, 19) && AI::randomValue<int>(0, 10) != 0
&& aijh.ggs.isEnabled(AddonId::SEA_ATTACK))
{
if(aii.CanBuildBuildingtype(BuildingType::Watchtower))
Expand All @@ -481,7 +481,7 @@ helpers::OptionalEnum<BuildingType> AIConstruction::ChooseMilitaryBuilding(const
{
if(aijh.UpdateUpgradeBuilding() < 0 && bldPlanner.GetNumBuildingSites(biggestBld) < 1
&& (inventory.goods[GoodType::Stones] > 20 || bldPlanner.GetNumBuildings(BuildingType::Quarry) > 0)
&& RANDOM.Rand(RANDOM_CONTEXT2(playerId), 10) != 0)
&& AI::randomValue<int>(0, 10) != 0)
{
return biggestBld;
}
Expand All @@ -495,7 +495,7 @@ helpers::OptionalEnum<BuildingType> AIConstruction::ChooseMilitaryBuilding(const
// Prüfen ob Feind in der Nähe
if(milBld->GetPlayer() != playerId && distance < 35)
{
int randmil = RANDOM.Rand(RANDOM_CONTEXT2(playerId), std::numeric_limits<int>::max());
int randmil = AI::randomValue<int>(0, std::numeric_limits<int>::max());
bool buildCatapult = randmil % 8 == 0 && aii.CanBuildCatapult()
&& bldPlanner.GetNumAdditionalBuildingsWanted(BuildingType::Catapult) > 0;
// another catapult within "min" radius? ->dont build here!
Expand Down
19 changes: 8 additions & 11 deletions libs/s25main/ai/aijh/AIPlayerJH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "RttrForeachPt.h"
#include "addons/const_addons.h"
#include "ai/AIEvents.h"
#include "ai/random.h"
#include "boost/filesystem/fstream.hpp"
#include "buildings/noBuildingSite.h"
#include "buildings/nobHarborBuilding.h"
Expand All @@ -26,7 +27,6 @@
#include "notifications/RoadNote.h"
#include "notifications/ShipNote.h"
#include "pathfinding/PathConditionRoad.h"
#include "random/Random.h"
#include "nodeObjs/noAnimal.h"
#include "nodeObjs/noFlag.h"
#include "nodeObjs/noShip.h"
Expand All @@ -40,7 +40,6 @@
#include <algorithm>
#include <array>
#include <memory>
#include <random>
#include <stdexcept>
#include <type_traits>

Expand Down Expand Up @@ -345,7 +344,7 @@ void AIPlayerJH::PlanNewBuildings(const unsigned gf)
DistributeGoodsByBlocking(GoodType::Boards, 30);
DistributeGoodsByBlocking(GoodType::Stones, 50);
// go to the picked random warehouse and try to build around it
int randomStore = RANDOM.Rand(RANDOM_CONTEXT2(playerId), storehouses.size());
int randomStore = AI::randomValue<int>(0, storehouses.size());
auto it = storehouses.begin();
std::advance(it, randomStore);
const MapPoint whPos = (*it)->GetPos();
Expand All @@ -366,7 +365,7 @@ void AIPlayerJH::PlanNewBuildings(const unsigned gf)
const std::list<nobMilitary*>& militaryBuildings = aii.GetMilitaryBuildings();
if(militaryBuildings.empty())
return;
int randomMiliBld = RANDOM.Rand(RANDOM_CONTEXT2(playerId), militaryBuildings.size());
int randomMiliBld = AI::randomValue<int>(0, militaryBuildings.size());
auto it2 = militaryBuildings.begin();
std::advance(it2, randomMiliBld);
MapPoint bldPos = (*it2)->GetPos();
Expand Down Expand Up @@ -1210,7 +1209,7 @@ void AIPlayerJH::HandleExpedition(const noShip* ship)
aii.FoundColony(ship);
else
{
const unsigned offset = RANDOM.Rand(RANDOM_CONTEXT2(playerId), helpers::MaxEnumValue_v<ShipDirection>);
const unsigned offset = AI::randomValue<unsigned>(0, helpers::MaxEnumValue_v<ShipDirection>);
for(auto dir : helpers::EnumRange<ShipDirection>{})
{
dir = ShipDirection((rttr::enum_cast(dir) + offset) % helpers::MaxEnumValue_v<ShipDirection>);
Expand Down Expand Up @@ -1255,7 +1254,7 @@ void AIPlayerJH::HandleTreeChopped(const MapPoint pt)

UpdateNodesAround(pt, 3);

if(RANDOM.Rand(RANDOM_CONTEXT2(playerId), 2) == 0)
if(AI::randomValue<int>(0, 2) == 0)
AddMilitaryBuildJob(pt);
else // if (random % 12 == 0)
AddBuildJob(BuildingType::Woodcutter, pt);
Expand Down Expand Up @@ -1537,7 +1536,7 @@ void AIPlayerJH::TryToAttack()
// We skip the current building with a probability of limit/numMilBlds
// -> For twice the number of blds as the limit we will most likely skip every 2nd building
// This way we check roughly (at most) limit buildings but avoid any preference for one building over an other
if(static_cast<unsigned>(RANDOM.Rand(RANDOM_CONTEXT2(playerId), static_cast<int>(numMilBlds))) > limit)
if(AI::randomValue<unsigned>(0, numMilBlds) > limit)
continue;

if(milBld->GetFrontierDistance() == FrontierDistance::Far) // inland building? -> skip it
Expand Down Expand Up @@ -1570,7 +1569,7 @@ void AIPlayerJH::TryToAttack()

// shuffle everything but headquarters and harbors without any troops in them
std::shuffle(potentialTargets.begin() + hq_or_harbor_without_soldiers, potentialTargets.end(),
std::mt19937(RANDOM.Rand(RANDOM_CONTEXT2(playerId), 2048)));
std::mt19937(AI::randomValue<unsigned>(0, 2048)));

// check for each potential attacking target the number of available attacking soldiers
for(const nobBaseMilitary* target : potentialTargets)
Expand Down Expand Up @@ -1704,9 +1703,7 @@ void AIPlayerJH::TrySeaAttack()
unsigned skip = 0;
if(searcharoundharborspots.size() > 15)
skip =
std::max<int>(
RANDOM.Rand(RANDOM_CONTEXT2(playerId), static_cast<int>(searcharoundharborspots.size() / 15 + 1) * 15), 1)
- 1;
std::max<int>(AI::randomValue<int>(0, static_cast<int>(searcharoundharborspots.size() / 15 + 1) * 15), 1) - 1;
for(unsigned i = skip; i < searcharoundharborspots.size() && limit > 0; i++)
{
limit--;
Expand Down
16 changes: 16 additions & 0 deletions libs/s25main/ai/random.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (C) 2005 - 2025 Settlers Freaks (sf-team at siedler25.org)
//
// SPDX-License-Identifier: GPL-2.0-or-later

#include "ai/random.h"

namespace AI {

std::minstd_rand& getRandomGenerator()
{
std::random_device rnd_dev;
static std::minstd_rand rng(rnd_dev());
return rng;
}

} // namespace AI
20 changes: 20 additions & 0 deletions libs/s25main/ai/random.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (C) 2005 - 2025 Settlers Freaks (sf-team at siedler25.org)
//
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "helpers/random.h"
#include <random>

namespace AI {

std::minstd_rand& getRandomGenerator();

template<typename T>
T randomValue(T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max())
{
return helpers::randomValue(getRandomGenerator(), min, max);
}

} // namespace AI

0 comments on commit 244e436

Please sign in to comment.