18 const auto first =
text.find_first_not_of(
" \t\r\n");
19 if (
first == std::string_view::npos)
21 const auto last =
text.find_last_not_of(
" \t\r\n");
27 std::string result(
text);
38 std::istringstream
input{std::string(
text)};
39 std::vector<double> values;
42 values.push_back(
value);
47 std::span<const double> values,
52 if (values.size() >=
count)
54 return std::unexpected(
Error{
57 std::string(
key) +
": not enough numeric values"});
60 [[
nodiscard]] std::expected<trade::PropertyClassification, Error>
63 const int value =
static_cast<int>(
raw);
70 return std::unexpected(
Error{
73 "WHAT TO TRADE monopoly classification must be 0, 1, or 2"});
79 std::span<const double> values,
82 if (
key ==
"PLAYER ATTITUDE")
89 const auto scalar = [&](
double&
target) -> std::expected<void, Error> {
95 if (
key ==
"ATTITUDE LOST FOR REJECTING TRADE")
97 if (
key ==
"ATTITUDE LOST PER EVALUATION POINT WHEN OBSERVING")
99 if (
key ==
"ATTITUDE CHANGE PER TICK")
101 if (
key ==
"ATTITUDE NEUTRAL")
103 if (
key ==
"PROBABILITY OF COUNTERING TRADE")
105 if (
key ==
"BUYING STAGE CASH MULTIPLIER")
107 if (
key ==
"NO MONOPOLY STAGE CASH MULTIPLIER")
109 if (
key ==
"CASH LIQUID ASSETS DEPENDANCE")
111 if (
key ==
"MONOPOLY EXISTS BUT NOT OWNER CASH MULTIPLIER")
113 if (
key ==
"MONOPOLY WAR CASH MULTIPLIER")
115 if (
key ==
"ODDS OF WINNING FACTOR")
117 if (
key ==
"MAX WINNING FACTOR LOSS ACCEPTABLE IN TRADE")
119 if (
key ==
"CASH FACTOR")
121 if (
key ==
"PROPERTY STRATEGIC FACTOR")
123 if (
key ==
"MINIMUM EVALUATION TRADE BENEFIT")
125 if (
key ==
"MINIMUM EVALUATION WHEN GIVING A MONOPOLY FOR CASH")
127 if (
key ==
"MONOPOLY RECEIVED IMPORTANCE")
129 if (
key ==
"GIVING MONOPOLY IMPORTANCE")
131 if (
key ==
"BALTIC RECEIVED IMPORTANCE")
133 if (
key ==
"PROPERTY ALLOWS TRADE IMPORTANCE")
135 if (
key ==
"PROPERTY ALLOWS ANOTHER TRADE IMPORTANCE")
137 if (
key ==
"PROPERTY GIVEN WITH ONE UNOWNED IMPORTANCE")
139 if (
key ==
"PROPERTY GIVEN WITH TWO UNOWNED IMPORTANCE")
141 if (
key ==
"NEGATIVE PROPERTY IMPORTANCE CHANGE MULTIPLIER FOR OPPONENTS")
143 if (
key ==
"PROPOSE TRADE PROBABILITY")
145 if (
key ==
"MONOPOLY TRADE PROBABILITY")
147 if (
key ==
"PROPOSE MONOPOLY GIVE AWAY PROBABILITY")
149 if (
key ==
"MINIMUM EVALUATION IF FED UP")
151 if (
key ==
"MONOPOLY SUICIDE FACTOR")
153 if (
key ==
"LOWEST PROPERTY STRAT FACTOR FOR COUNTER PROPOSAL")
155 if (
key ==
"MINIMUM NON-MONOPOLY ATTITUDE")
158 if (
key ==
"TIME TO FORGET TRADE" ||
key ==
"MAX TRADES" ||
159 key ==
"TRADE COUNTER LIMIT" ||
key ==
"MINIMUM CASH ON HAND" ||
160 key ==
"BUYING HOUSE STRATEGY" ||
161 key ==
"MAXIMUMG HOUSES PER SQUARE FOR MONOPOLY GIVE AWAY" ||
162 key ==
"MINIMUM PAUSE FOR ACTION" ||
key ==
"MAXIMUM PAUSE FOR ACTION" ||
163 key ==
"PAUSE WHEN CONSIDERING TRADE" ||
key ==
"PATIENCE" ||
164 key ==
"NUMBER OF TIMES CONSIDER PROPERTY TRADE" ||
165 key ==
"TURNS BEFORE FORGETTING PROPERTY WAS TRADED")
169 const auto integer =
static_cast<std::int64_t
>(values[0]);
171 else if (
key ==
"MAX TRADES")
176 static_cast<std::uint8_t
>(std::clamp<std::int64_t>(
integer, 0, 3));
177 else if (
key ==
"MAXIMUMG HOUSES PER SQUARE FOR MONOPOLY GIVE AWAY")
182 else if (
key ==
"PATIENCE") profile.
patience =
static_cast<std::uint64_t
>(std::max<std::int64_t>(0,
integer));
183 else if (
key ==
"NUMBER OF TIMES CONSIDER PROPERTY TRADE")
189 if (
key ==
"CASH STRATEGY")
193 const int strategy =
static_cast<int>(values[0]);
200 if (
key ==
"PROPERTY FACTORS")
207 if (
key ==
"CASH COW FACTORS")
214 if (
key ==
"RAILROAD IMPORTANCE FACTORS")
219 std::copy_n(values.begin(),
target.size(),
target.begin());
222 if (
key ==
"UTILITY IMPORTANCE FACTORS")
227 std::copy_n(values.begin(),
target.size(),
target.begin());
230 if (
key ==
"MONOPOLY VETO IMPORTANCE VALUES")
235 std::copy_n(values.begin(),
target.size(),
target.begin());
254 entry.giveGroupTrades =
static_cast<std::uint8_t
>(std::clamp(values[1], 0.0, 6.0));
255 entry.giveCashCows =
static_cast<std::uint8_t
>(std::clamp(values[2], 0.0, 6.0));
256 entry.giveJunk =
static_cast<std::uint8_t
>(std::clamp(values[3], 0.0, 6.0));
257 entry.cashMultiplier = values[4];
266 if (
upperLine.find(
"GLOBAL SETTINGS") != std::string_view::npos)
268 if (
upperLine.find(
"STRATEGY FOR LEVEL 1") != std::string_view::npos)
270 if (
upperLine.find(
"STRATEGY FOR LEVEL 2") != std::string_view::npos)
272 if (
upperLine.find(
"STRATEGY FOR LEVEL 3") != std::string_view::npos)
278 std::expected<Profile, Error>
parse(std::string_view
text,
int level)
293 offset = end == std::string_view::npos ?
text.size() + 1 : end + 1;
306 if (
equals == std::string::npos)
316 return std::unexpected(
applied.error());
321 std::expected<Profile, Error>
load(
const std::filesystem::path&
path,
int level)
323 std::ifstream
input(
path, std::ios::binary);
335 static constexpr std::array<std::string_view, TokenProfileCount>
Names{
336 "Cannon.ai",
"RaceCar.ai",
"Dog.ai",
"TopHat.ai",
"Iron.ai",
337 "Horse.ai",
"Ship.ai",
"Boot.ai",
"Thimble.ai",
"Barrow.AI",
"Moneybag.ai"};
353 config.winningChance.minCashOnHand[player] =
profiles[player].minCashOnHand;
354 config.winningChance.moneyOwed[player] = context.moneyOwed[player];
356 config.winningChance.buyingStageCashMultiplier =
strategy.buyingStageCashMultiplier;
357 config.winningChance.noMonopolyStageCashMultiplier =
strategy.noMonopolyStageCashMultiplier;
358 config.winningChance.cashLiquidAssetsDependence =
strategy.cashLiquidAssetsDependence;
359 config.winningChance.monopolyNotOwnedStageCashMultiplier =
360 strategy.monopolyNotOwnedStageCashMultiplier;
361 config.winningChance.monopolyOwnedStageCashMultiplier =
362 strategy.monopolyOwnedStageCashMultiplier;
369 config.purchasingPlayer = context.purchasingPlayer;
370 config.purchasingProperty = context.purchasingProperty;
386 config.numberTimesAllowPropertyTrade =
strategy.numberTimesAllowPropertyTrade;
387 config.tradeCounterProbability =
strategy.tradeCounterProbability;
402 config.fairTrade.localAIPlayer = context.localAIPlayer;
405 config.fairTrade.minEvaluationThreshold =
strategy.minEvaluationThreshold;
406 config.fairTrade.minGiveMonopolyEvaluation =
strategy.minGiveMonopolyEvaluation;
409 config.lowestPropertyImportanceForCounter =
strategy.lowestPropertyImportanceForCounter;
425 config.fairTrade.localAIPlayer = context.localAIPlayer;
429 config.fairTrade.minEvaluationThreshold =
strategy.minEvaluationThreshold;
430 config.fairTrade.minGiveMonopolyEvaluation =
strategy.minGiveMonopolyEvaluation;
std::expected< Profile, Error > load(const std::filesystem::path &path, int level)
std::array< Profile, rules::MaxPlayers > ProfileSet
decision::CounterProposalBalanceConfig makeCounterBalanceConfig(const ProfileSet &profiles, rules::PlayerNumber strategyPlayer, const ConfigContext &context) noexcept
decision::MonopolyProposalConfig makeMonopolyProposalConfig(const ProfileSet &profiles, rules::PlayerNumber strategyPlayer, const ConfigContext &context) noexcept
decision::TradeEvaluationConfig makeTradeEvaluationConfig(const ProfileSet &profiles, rules::PlayerNumber strategyPlayer, const ConfigContext &context) noexcept
std::string_view tokenFileName(std::uint8_t token) noexcept
std::expected< Profile, Error > parse(std::string_view text, int level)
decision::CounterProposalPreflightConfig makeCounterPreflightConfig(const ProfileSet &profiles, rules::PlayerNumber strategyPlayer, const ConfigContext &context) noexcept
constexpr std::size_t WhatToTradeEntries
std::uint8_t PlayerNumber
constexpr PlayerNumber MaxPlayers
FairTradeConfig fairTrade
TradeEvaluationConfig evaluation
TradeEvaluationConfig evaluation
FairTradeConfig fairTrade
WinningChanceConfig winningChance
std::array< CashStrategy, rules::MaxPlayers > cashStrategy
std::array< double, 6 > cashCow
std::array< double, 8 > property
std::int64_t minCashOnHand
double cashLiquidAssetsDependence
int maxHousesPerSquareForGiveAway
decision::CashStrategy cashStrategy
int turnsToForgetPropertyTrade
std::int64_t timeForgetTrade
double monopolyTradeProbability
decision::WorthFactors worthFactors
double attitudeLostForRejectedTrade
double proposeTradeProbability
double minEvaluationIfFedUp
double minimumNonmonopolyTradeAttitude
double monopolyOwnedStageCashMultiplier
std::uint8_t housingPurchaseStrategy
double proposeMonopolyGiveAwayProbability
std::array< double, rules::MaxPlayers > playerAttitude
double lowestPropertyImportanceForCounter
double noMonopolyStageCashMultiplier
double tradeImportanceFactor
double tradeCounterProbability
trade::WhatToTradeTable whatToTrade
trade::PropertyImportanceConfig propertyImportance
double minGiveMonopolyEvaluation
double monopolySuicideFactor
int numberTimesAllowPropertyTrade
double attitudeTickChange
double balticReceivedImportance
double attitudeChangeTradeObserving
double minEvaluationThreshold
double buyingStageCashMultiplier
double monopolyNotOwnedStageCashMultiplier
double negativePropertyImportanceChangeMultiplier
double propertyAllowMoreTradeImportance
double propertyOneUnownedImportance
std::array< double, 9 > monopolyVetoImportance
double monopolyReceivedImportance
std::array< double, 4 > railroadImportance
double givingMonopolyImportance
double propertyAllowTradeImportance
std::array< double, 2 > utilityImportance
double propertyTwoUnownedImportance