Skip to content

Commit

Permalink
Making std::sort 'stable' by getting rid of equal elements
Browse files Browse the repository at this point in the history
  • Loading branch information
seroperson committed Apr 28, 2023
1 parent f0832f0 commit 3bc7303
Show file tree
Hide file tree
Showing 22 changed files with 237 additions and 69 deletions.
8 changes: 7 additions & 1 deletion CvGameCoreDLL_Expansion2/CvAIOperation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,13 @@ int CvAIOperation::GrabUnitsFromTheReserves(CvPlot* pMusterPlot, CvPlot* pTarget
if (pLoopUnit->getDomainType() == DOMAIN_LAND && pLoopUnit->plot()->getArea() != pMusterPlot->getArea())
iTurnsToReachCheckpoint++;

choices.push_back(OptionWithScore<int>(pLoopUnit->GetID(), 10000 + pLoopUnit->GetPower() - iTurnsToReachCheckpoint * 30));
choices.push_back(
OptionWithScore<int>(
pLoopUnit->GetID(),
10000 + pLoopUnit->GetPower() - iTurnsToReachCheckpoint * 30,
pLoopUnit->GetID()
)
);
}
}

Expand Down
6 changes: 3 additions & 3 deletions CvGameCoreDLL_Expansion2/CvAStar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2822,7 +2822,7 @@ map<CvPlot*,SPath> CvPathFinder::GetMultiplePaths(const CvPlot* pStartPlot, vect
{
bool operator()(const CvPlot* lhs, const CvPlot* rhs) const { return lhs->GetPlotIndex() < rhs->GetPlotIndex(); }
};
std::stable_sort( vDestPlots.begin(), vDestPlots.end(), PrSortByPlotIndex() );
std::sort( vDestPlots.begin(), vDestPlots.end(), PrSortByPlotIndex() );

//there is no destination! the return value will always be false
CvAStar::FindPathWithCurrentConfiguration(pStartPlot->getX(),pStartPlot->getY(), -1, -1, data);
Expand Down Expand Up @@ -3639,7 +3639,7 @@ void ReachablePlots::createIndex()
lookup.reserve(storage.size());
for (size_t i = 0; i < storage.size(); i++)
lookup.push_back( make_pair(storage[i].iPlotIndex,i) );
stable_sort(lookup.begin(), lookup.end(), PairCompareFirst());
sort(lookup.begin(), lookup.end(), PairCompareFirst());
}

struct EqualRangeComparison
Expand Down Expand Up @@ -3678,7 +3678,7 @@ void ReachablePlots::insertWithIndex(const SMovePlot& plot)
{
lookup.push_back( make_pair(plot.iPlotIndex,storage.size()) );
storage.push_back(plot);
stable_sort(lookup.begin(), lookup.end(), PairCompareFirst());
sort(lookup.begin(), lookup.end(), PairCompareFirst());
}

FDataStream & operator >> (FDataStream & kStream, CvPathNode & node)
Expand Down
2 changes: 1 addition & 1 deletion CvGameCoreDLL_Expansion2/CvArmyAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ CvPlot* CvArmyAI::GetCenterOfMass(bool bClampToUnit, float* pfVarX, float* pfVar
return NULL;

//this sorts ascending!
std::stable_sort(vPlots.begin(),vPlots.end());
std::sort(vPlots.begin(),vPlots.end());
return vPlots.front().pPlot;
}
else
Expand Down
2 changes: 1 addition & 1 deletion CvGameCoreDLL_Expansion2/CvBarbarians.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1437,7 +1437,7 @@ UnitTypes CvBarbarians::GetRandomBarbarianUnitType(CvPlot* pPlot, UnitAITypes eP
}

if (iScore > 0)
candidates.push_back(OptionWithScore<UnitTypes>(eLoopUnit, iScore));
candidates.push_back(OptionWithScore<UnitTypes>(eLoopUnit, iScore, eLoopUnit));
}

if (candidates.empty())
Expand Down
30 changes: 22 additions & 8 deletions CvGameCoreDLL_Expansion2/CvBuilderTaskingAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ BuilderDirective CvBuilderTaskingAI::EvaluateBuilder(CvUnit* pUnit, const map<Cv
}
}

stable_sort(m_aDirectives.begin(), m_aDirectives.end());
sort(m_aDirectives.begin(), m_aDirectives.end());
LogDirectives(pUnit);

//nothing found?
Expand Down Expand Up @@ -1023,7 +1023,9 @@ void CvBuilderTaskingAI::AddImprovingResourcesDirectives(CvUnit* pUnit, CvPlot*
LogInfo(strTemp, m_pPlayer);
}

m_aDirectives.push_back( OptionWithScore<BuilderDirective>(directive, iWeight));
m_aDirectives.push_back(
OptionWithScore<BuilderDirective>(directive, iWeight, pPlot->GetPlotIndex())
);
}
}
}
Expand Down Expand Up @@ -1258,7 +1260,9 @@ void CvBuilderTaskingAI::AddImprovingPlotsDirectives(CvUnit* pUnit, CvPlot* pPlo
LogInfo(strTemp, m_pPlayer);
}

m_aDirectives.push_back( OptionWithScore<BuilderDirective>(directive, iWeight));
m_aDirectives.push_back(
OptionWithScore<BuilderDirective>(directive, iWeight, pPlot->GetPlotIndex())
);
}
}

Expand Down Expand Up @@ -1332,7 +1336,9 @@ void CvBuilderTaskingAI::AddRemoveRouteDirectives(CvUnit* pUnit, CvPlot* pPlot,
LogInfo(strTemp, m_pPlayer);
}

m_aDirectives.push_back( OptionWithScore<BuilderDirective>(directive, iWeight));
m_aDirectives.push_back(
OptionWithScore<BuilderDirective>(directive, iWeight, pPlot->GetPlotIndex())
);
}

/// Adds a directive if the unit can construct a road in the plot
Expand Down Expand Up @@ -1393,7 +1399,9 @@ void CvBuilderTaskingAI::AddRouteDirectives(CvUnit* pUnit, CvPlot* pPlot, CvCity
LogInfo(strTemp, m_pPlayer);
}

m_aDirectives.push_back( OptionWithScore<BuilderDirective>(directive, iWeight));
m_aDirectives.push_back(
OptionWithScore<BuilderDirective>(directive, iWeight, pPlot->GetPlotIndex())
);
}

/// Determines if the builder should "chop" the feature in the tile
Expand Down Expand Up @@ -1590,7 +1598,9 @@ void CvBuilderTaskingAI::AddChopDirectives(CvUnit* pUnit, CvPlot* pPlot, CvCity*
//directive.m_iGoldCost = m_pPlayer->getBuildCost(pPlot, eChopBuild);
directive.m_sMoveTurnsAway = iMoveTurnsAway;

m_aDirectives.push_back( OptionWithScore<BuilderDirective>(directive, iWeight));
m_aDirectives.push_back(
OptionWithScore<BuilderDirective>(directive, iWeight, pPlot->GetPlotIndex())
);
}
}

Expand Down Expand Up @@ -1631,7 +1641,9 @@ void CvBuilderTaskingAI::AddRepairTilesDirectives(CvUnit* pUnit, CvPlot* pPlot,
//directive.m_iGoldCost = m_pPlayer->getBuildCost(pPlot, eChopBuild);
directive.m_sMoveTurnsAway = iMoveTurnsAway;

m_aDirectives.push_back( OptionWithScore<BuilderDirective>(directive, iWeight));
m_aDirectives.push_back(
OptionWithScore<BuilderDirective>(directive, iWeight, pPlot->GetPlotIndex())
);
}
}
// Everything means less than zero, hey
Expand Down Expand Up @@ -1661,7 +1673,9 @@ void CvBuilderTaskingAI::AddScrubFalloutDirectives(CvUnit* pUnit, CvPlot* pPlot,
directive.m_sX = pPlot->getX();
directive.m_sY = pPlot->getY();
directive.m_sMoveTurnsAway = iMoveTurnsAway;
m_aDirectives.push_back( OptionWithScore<BuilderDirective>(directive, iWeight));
m_aDirectives.push_back(
OptionWithScore<BuilderDirective>(directive, iWeight, pPlot->GetPlotIndex())
);
}
}

Expand Down
2 changes: 1 addition & 1 deletion CvGameCoreDLL_Expansion2/CvCityStrategyAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ void CvCityStrategyAI::PrecalcYieldStats()
int iYieldPerPop100 = (iYield*100) / max(1, m_pCity->getPopulation());
int iDeviation = iYieldPerPop100 - (int)expectedYieldPerPop[iI];

deviations.push_back( OptionWithScore<YieldTypes>(eYield,iDeviation) );
deviations.push_back( OptionWithScore<YieldTypes>(eYield,iDeviation, eYield) );
}

//this sorts in descending order
Expand Down
16 changes: 14 additions & 2 deletions CvGameCoreDLL_Expansion2/CvDealAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4345,7 +4345,13 @@ void CvDealAI::DoAddStrategicResourceToThem(CvDeal* pDeal, PlayerTypes eThem, in
if (iItemValue == INT_MAX)
continue;

vOptions.push_back(OptionWithScore<TradeItem>(TradeItem(eResource, iResourceQuantity), iItemValue));
vOptions.push_back(
OptionWithScore<TradeItem>(
TradeItem(eResource, iResourceQuantity),
iItemValue,
eResource
)
);
}
}

Expand Down Expand Up @@ -4434,7 +4440,13 @@ void CvDealAI::DoAddStrategicResourceToUs(CvDeal* pDeal, PlayerTypes eThem, int&
if (iItemValue == INT_MAX)
continue;

vOptions.push_back(OptionWithScore<TradeItem>(TradeItem(eResource, iResourceQuantity), iItemValue));
vOptions.push_back(
OptionWithScore<TradeItem>(
TradeItem(eResource, iResourceQuantity),
iItemValue,
eResource
)
);
}
}

Expand Down
3 changes: 2 additions & 1 deletion CvGameCoreDLL_Expansion2/CvDllDatabaseUtility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,8 @@ struct OrderIndex
};
bool sortHotkeyPriority(const OrderIndex& orderIndex1, const OrderIndex& orderIndex2)
{
return (orderIndex1.m_iPriority > orderIndex2.m_iPriority);
return std::make_pair(orderIndex1.m_iPriority, orderIndex1.m_iIndex) >
std::make_pair(orderIndex2.m_iPriority, orderIndex2.m_iIndex);
}

template <class T>
Expand Down
6 changes: 4 additions & 2 deletions CvGameCoreDLL_Expansion2/CvGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9338,7 +9338,9 @@ UnitTypes CvGame::GetCsGiftSpawnUnitType(PlayerTypes ePlayer, bool bIncludeShips
continue;

// CUSTOMLOG("CS Gift considering unit type %i", eLoopUnit);
veUnitRankings.push_back( OptionWithScore<UnitTypes>(eLoopUnit, pkUnitInfo->GetPower()));
veUnitRankings.push_back(
OptionWithScore<UnitTypes>(eLoopUnit, pkUnitInfo->GetPower(), eLoopUnit)
);
}

// Choose from weighted unit types
Expand Down Expand Up @@ -9663,7 +9665,7 @@ UnitTypes CvGame::GetRandomUniqueUnitType(bool bIncludeCivsInGame, bool bInclude
if (pkUnitInfo->IsMinorCivGift())
iRandom += 5;

veUnitRankings.push_back( OptionWithScore<UnitTypes>(eLoopUnit, iRandom));
veUnitRankings.push_back( OptionWithScore<UnitTypes>(eLoopUnit, iRandom, eLoopUnit));
}
// we didn't find any candidates! try again with all UUs
if (veUnitRankings.size() <= 0)
Expand Down
8 changes: 6 additions & 2 deletions CvGameCoreDLL_Expansion2/CvGameCoreUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,8 +427,12 @@ struct OptionWithScore
{
T option;
int score;
OptionWithScore(const T& t, int s) : option(t), score(s) {}
bool operator<(const OptionWithScore& rhs) const { return score > rhs.score; } //sort descending!
std::pair<int, int> comparing;
OptionWithScore(const T& t, int s, int fallback) :
option(t),
score(s),
comparing(std::make_pair(s, fallback)) {}
bool operator<(const OptionWithScore& rhs) const { return comparing > rhs.comparing; } //sort descending!
};

template<class T>
Expand Down
4 changes: 3 additions & 1 deletion CvGameCoreDLL_Expansion2/CvHomelandAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6067,19 +6067,21 @@ SPatrolTarget::SPatrolTarget()
pTarget = NULL;
pWorstEnemy = NULL;
iThreatLevel = 0;
comparing = std::make_pair(iThreatLevel, 0);
}

SPatrolTarget::SPatrolTarget(CvPlot * target, CvPlot * neighbor, int iThreat)
{
pTarget = target;
pWorstEnemy = neighbor;
iThreatLevel = iThreat;
comparing = std::make_pair(iThreatLevel, pTarget->GetPlotIndex());
}

bool SPatrolTarget::operator<(const SPatrolTarget & rhs) const
{
//sort descending!
return iThreatLevel > rhs.iThreatLevel;
return comparing > rhs.comparing;
}

bool SPatrolTarget::operator==(const SPatrolTarget & rhs) const
Expand Down
1 change: 1 addition & 0 deletions CvGameCoreDLL_Expansion2/CvHomelandAI.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ struct SPatrolTarget {
CvPlot* pTarget;
CvPlot* pWorstEnemy; //may be null
int iThreatLevel;
std::pair<int, int> comparing;

SPatrolTarget();
SPatrolTarget(CvPlot* target, CvPlot* neighbor, int iThreat);
Expand Down
25 changes: 20 additions & 5 deletions CvGameCoreDLL_Expansion2/CvMilitaryAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,13 @@ size_t CvMilitaryAI::UpdateAttackTargets()
if (target.m_iApproachScore == 0)
continue;

vAttackOptions.push_back(OptionWithScore<CvAttackTarget>(target, ScoreAttackTarget(target)));
vAttackOptions.push_back(
OptionWithScore<CvAttackTarget>(
target,
ScoreAttackTarget(target),
target.m_iTargetPlotIndex
)
);

//and now the other way around
if (GET_PLAYER(eOtherPlayer).isMajorCiv())
Expand All @@ -820,7 +826,13 @@ size_t CvMilitaryAI::UpdateAttackTargets()
{
//do not try any advanced scoring, just use a basic approach/distance score
int iScore = (reverseTarget.m_iApproachScore * 10) / sqrti(it->second.length());
vDefenseOptions.push_back(OptionWithScore<CvAttackTarget>(reverseTarget, iScore));
vDefenseOptions.push_back(
OptionWithScore<CvAttackTarget>(
reverseTarget,
iScore,
reverseTarget.m_iTargetPlotIndex
)
);
}
}
}
Expand All @@ -842,7 +854,7 @@ size_t CvMilitaryAI::UpdateAttackTargets()
if (target.m_iApproachScore == 0)
continue;

vAttackOptions.push_back(OptionWithScore<CvAttackTarget>(target, ScoreAttackTarget(target)));
vAttackOptions.push_back(OptionWithScore<CvAttackTarget>(target, ScoreAttackTarget(target), target.m_iTargetPlotIndex));

//and now the other way around
if (GET_PLAYER(eOtherPlayer).isMajorCiv())
Expand All @@ -857,7 +869,7 @@ size_t CvMilitaryAI::UpdateAttackTargets()
{
//do not try any advanced scoring, just use a basic approach/distance score
int iScore = (reverseTarget.m_iApproachScore * 10) / sqrti(it->second.length());
vDefenseOptions.push_back(OptionWithScore<CvAttackTarget>(reverseTarget, iScore));
vDefenseOptions.push_back(OptionWithScore<CvAttackTarget>(reverseTarget, iScore, reverseTarget.m_iTargetPlotIndex));
}
}
}
Expand Down Expand Up @@ -2509,7 +2521,10 @@ CvUnit* CvMilitaryAI::FindUselessShip()
//sort ships by experience: we want to scrap the veterans last ...
struct PrSortByExperience
{
bool operator()(const CvUnit* lhs, const CvUnit* rhs) const { return lhs->getExperienceTimes100() < rhs->getExperienceTimes100(); }
bool operator()(const CvUnit* lhs, const CvUnit* rhs) const {
return std::make_pair(lhs->getExperienceTimes100(), lhs->GetID()) <
std::make_pair(rhs->getExperienceTimes100(), rhs->GetID());
}
};
std::sort( candidates.begin(), candidates.end(), PrSortByExperience() );

Expand Down
7 changes: 4 additions & 3 deletions CvGameCoreDLL_Expansion2/CvPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5278,7 +5278,10 @@ vector<CvCity*> CvPlayer::GetThreatenedCities(bool bCoastalOnly)
vector<CvCity*> result;
struct SortByThreatLevel
{
bool operator()(const CvCity* lhs, const CvCity* rhs) const { return lhs->getThreatValue() > rhs->getThreatValue(); }
bool operator()(const CvCity* lhs, const CvCity* rhs) const {
return make_pair(lhs->getThreatValue(), lhs->GetID()) >
make_pair(rhs->getThreatValue(), rhs->GetID());
}
};

int iLoop = 0;
Expand Down Expand Up @@ -47194,7 +47197,6 @@ void CvPlayer::Serialize(Player& player, Visitor& visitor)
visitor(player.m_iAbleToAnnexCityStatesCount);
visitor(player.m_iOnlyTradeSameIdeology);
visitor(player.m_iSupplyFreeUnits);
visitor(player.m_aistrInstantYield);
visitor(player.m_abActiveContract);
visitor(player.m_iJFDReformCooldownRate);
visitor(player.m_iJFDGovernmentCooldownRate);
Expand Down Expand Up @@ -47317,7 +47319,6 @@ void CvPlayer::Serialize(Player& player, Visitor& visitor)
visitor(player.m_iNumFreePolicies);
visitor(player.m_iNumFreePoliciesEver);
visitor(player.m_iNumFreeTenets);
visitor(player.m_iLastSliceMoved);
visitor(player.m_uiStartTime);
visitor(player.m_bHasUUPeriod);
visitor(player.m_bNoNewWars);
Expand Down
6 changes: 3 additions & 3 deletions CvGameCoreDLL_Expansion2/CvPlayerAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -744,13 +744,13 @@ void CvPlayerAI::AI_considerAnnex()
iWeight += 3;

int iScore = iWeight * pCity->getYieldRateTimes100(YIELD_PRODUCTION, false);
options.push_back( OptionWithScore<CvCity*>(pCity,iScore) );
options.push_back( OptionWithScore<CvCity*>(pCity,iScore,pCity->GetID()) );
}

if (!options.empty())
{
//descending by default
std::stable_sort(options.begin(), options.end());
sort(options.begin(), options.end());

CvCity* pTargetCity = options.front().option;
if (pTargetCity)
Expand Down Expand Up @@ -1926,7 +1926,7 @@ CvPlot* CvPlayerAI::FindBestMerchantTargetPlotForCash(CvUnit* pMerchant)
}
}

std::stable_sort(vCandidates.begin(), vCandidates.end());
sort(vCandidates.begin(), vCandidates.end());

int iFlags = CvUnit::MOVEFLAG_NO_ENEMY_TERRITORY | CvUnit::MOVEFLAG_APPROX_TARGET_RING1 | CvUnit::MOVEFLAG_APPROX_TARGET_NATIVE_DOMAIN;
for (size_t i = 0; i < vCandidates.size(); i++)
Expand Down

0 comments on commit 3bc7303

Please sign in to comment.