Reduce available command assembly overhead (#8759)

This commit is contained in:
2026-07-23 13:14:57 -07:00
committed by GitHub
parent 9b42eb90a0
commit 132cf36673
@@ -52,11 +52,22 @@ private:
const std::vector<std::shared_ptr<const CommandFactory>> commandFactories;
const PlayerSetupCommandFactory playerSetupCommandFactory;
struct PlayerCommandContext {
std::vector<PlayerId> allyPids;
PossibleChargees possibleChargees;
bool isAttacker;
bool cannotBecomeOutlaw;
};
static auto MakePlayerCommandContext(const GameStateW &gameState, PlayerId playerId)
-> PlayerCommandContext;
// AvailableCommands helpers for a single unit
void AddAvailableCommandsForOneUnit(
const GameStateW &gameState,
CommandList &commands,
const Unit *unit,
const PlayerCommandContext &playerContext,
bool onlyFollowUps) const;
public:
@@ -95,30 +106,39 @@ auto AvailableCommandsFactoryImpl::GetPlayerSetupCommands(
gameState,
reinforcementPositions);
return std::make_shared<CommandList>(previewCommands);
return std::make_shared<CommandList>(std::move(previewCommands));
}
auto AvailableCommandsFactoryImpl::MakePlayerCommandContext(
const GameStateW &gameState,
const PlayerId playerId) -> PlayerCommandContext {
PossibleChargees possibleChargees{};
possibleChargees.reserve(gameState->possible_chargee_ids()->size());
for (const UnitId chargeeId : *gameState->possible_chargee_ids()) {
if (chargeeId != -1) { possibleChargees.push_back(chargeeId); }
}
return PlayerCommandContext{
.allyPids = AlliedPids(gameState, playerId),
.possibleChargees = std::move(possibleChargees),
.isAttacker = IsAttacker(gameState, playerId),
.cannotBecomeOutlaw = CannotBecomeOutlaw(gameState, playerId)};
}
void AvailableCommandsFactoryImpl::AddAvailableCommandsForOneUnit(
const GameStateW &gameState,
CommandList &commands,
const Unit *unit,
const PlayerCommandContext &playerContext,
const bool onlyFollowUps) const {
const auto &battType = settings.GetBattalionType(unit->battalion().type());
const bool hasHero = unit->has_attached_hero();
const auto allyPids = AlliedPids(gameState, unit->player_id());
const bool isAttacker = IsAttacker(gameState, unit->player_id());
const bool cannotBecomeOutlaw = CannotBecomeOutlaw(gameState, unit->player_id());
const bool unitMovedIntoZoc = unit->has_moved_in_zoc();
const ActionPoints remainingActionPoints = unit->remaining_action_points();
const Coords &currentCoords = unit->location();
const bool isEligibleCharger = unit->unit_id() == gameState->eligible_charger_id();
std::vector<UnitId> possibleChargees{};
possibleChargees.reserve(gameState->possible_chargee_ids()->size());
for (const UnitId cid : *gameState->possible_chargee_ids()) {
if (cid != -1) { possibleChargees.push_back(cid); }
}
// Undead units cannot act until the commanding hero has controlled them
if (unit->commanding_unit_id() != -1) {
@@ -140,12 +160,12 @@ void AvailableCommandsFactoryImpl::AddAvailableCommandsForOneUnit(
.position = currentCoords,
.weatherFb = gameState->weather(),
.isEligibleCharger = isEligibleCharger,
.possibleChargees = possibleChargees,
.possibleChargees = playerContext.possibleChargees,
.hexMap = gameState->hex_map(),
.units = gameState->units(),
.allyPids = allyPids,
.isAttacker = isAttacker,
.cannotBecomeOutlaw = cannotBecomeOutlaw,
.allyPids = playerContext.allyPids,
.isAttacker = playerContext.isAttacker,
.cannotBecomeOutlaw = playerContext.cannotBecomeOutlaw,
.unitMovedIntoZoc = unitMovedIntoZoc};
for (const auto &commandFactory : commandFactories) {
@@ -184,7 +204,10 @@ void AvailableCommandsFactoryImpl::AddAvailableCommandsForOneUnit(
});
}
commands.insert(commands.end(), oneUnitCommands.begin(), oneUnitCommands.end());
commands.insert(
commands.end(),
std::make_move_iterator(oneUnitCommands.begin()),
std::make_move_iterator(oneUnitCommands.end()));
}
auto AvailableCommandsFactoryImpl::GetAvailableCommands(
@@ -196,7 +219,9 @@ auto AvailableCommandsFactoryImpl::GetAvailableCommands(
playerSetupCommandFactory
.AddAvailablePlayerSetupCommands(commands, playerId, gameState, reinforcementPositions);
if (!commands.empty()) return std::make_shared<CommandList>(commands);
if (!commands.empty()) return std::make_shared<CommandList>(std::move(commands));
const auto playerContext = MakePlayerCommandContext(gameState, playerId);
for (const Unit *unit : *gameState->units()) {
if (unit->status() != net::eagle0::shardok::storage::fb::UnitStatus_NORMAL_UNIT) continue;
@@ -205,6 +230,7 @@ auto AvailableCommandsFactoryImpl::GetAvailableCommands(
gameState,
commands,
unit,
playerContext,
/* onlyFollowUps=*/false);
}
@@ -229,10 +255,13 @@ auto AvailableCommandsFactoryImpl::GetAvailableCommands(
auto after = ApplyResults(copy, results, settings);
CommandList followUpCommands{};
const auto followUpPlayerContext =
MakePlayerCommandContext(after, after->units()->Get(actor)->player_id());
AddAvailableCommandsForOneUnit(
after,
followUpCommands,
after->units()->Get(actor),
followUpPlayerContext,
/* onlyFollowUps=*/true);
std::unordered_set<CommandType> followUpTypes{};
@@ -249,7 +278,7 @@ auto AvailableCommandsFactoryImpl::GetAvailableCommands(
}
if (commands.empty()) return nullptr;
return std::make_shared<CommandList>(commands);
return std::make_shared<CommandList>(std::move(commands));
}
} // namespace shardok