12 [[nodiscard]] std::int64_t reserveForHighestDevelopedRent(
23 [[nodiscard]]
double monopolyFrequency(
27 const auto index =
static_cast<std::size_t
>(
group);
32 inline constexpr std::array<rules::board::SquareType, 28> MortgageOrder{
68 std::int64_t minCashOnHand,
69 std::int64_t moneyOwed)
noexcept
72 player >=
state.numberOfPlayers ||
76 auto liquid = cashOnly
77 ?
state.players[player].cash
79 std::int64_t payments{};
84 payments = minCashOnHand;
88 payments = std::max(payments, minCashOnHand);
92 payments = std::max(payments, minCashOnHand);
95 payments = reserveForHighestDevelopedRent(
state, player);
97 payments = std::max(payments, minCashOnHand);
104 payments = reserveForHighestDevelopedRent(
state, player);
107 payments = std::max(payments, minCashOnHand);
113 return std::max<std::int64_t>(0, liquid - payments);
120 std::int64_t minCashOnHand,
121 std::int64_t moneyOwed)
noexcept
127 auto simulated =
state;
134 simulated, player,
true, strategy, minCashOnHand, moneyOwed) !=
138 simulated, player,
false, strategy, minCashOnHand, moneyOwed);
146 std::int64_t minCashOnHand,
147 std::span<const std::int64_t> moneyOwed)
noexcept
153 player >=
state.numberOfPlayers || property >= SquareType::InJail ||
159 const auto debt = player < moneyOwed.size() ? moneyOwed[player] : 0;
163 reserve = std::max(reserve, minCashOnHand) - definition.
mortgageCost;
168 if (withHouses < propertyCost || withHouses - propertyCost < reserve)
181 if (liquid - propertyCost < reserve)
183 if (importanceOthers == StrategicPropertyImportance::GivesDirectMonopoly)
186 if (monopolyPlayer >=
state.numberOfPlayers)
188 const auto otherDebt = monopolyPlayer < moneyOwed.size() ? moneyOwed[monopolyPlayer] : 0;
190 state, monopolyPlayer,
true,
false, otherDebt);
191 if (otherLiquid < propertyCost)
192 return definition.
group <= SquareGroup::OrientalAvenue;
196 if (importanceUs == StrategicPropertyImportance::GivesDirectMonopoly)
198 if (definition.
group <= SquareGroup::OrientalAvenue)
201 if (monopolies.count == 0)
203 for (std::size_t monopolyIndex = 0; monopolyIndex < monopolies.count; ++monopolyIndex)
205 const auto representative = monopolies.representatives[monopolyIndex];
208 if (houses <
static_cast<std::int64_t
>(lots.count * 3))
211 const auto shortfall = propertyCost + reserve - liquid;
212 const auto last = monopolies.representatives[monopolies.count - 1];
213 if (
static_cast<double>(shortfall) >
227 if (importanceUs == StrategicPropertyImportance::GivesDirectMonopoly)
229 if (importanceOthers == StrategicPropertyImportance::AllowsTrade ||
230 importanceOthers == StrategicPropertyImportance::GivesDirectMonopoly)
233 if (definition.
group == SquareGroup::ParkPlace ||
234 definition.
group == SquareGroup::MediterraneanAvenue ||
235 definition.
group == SquareGroup::StJamesPlace)
237 if (importanceUs != StrategicPropertyImportance::NotImportant && !buy)
245 if (protectBare - propertyCost < reserve && !buy)
248 state, player, strategy, minCashOnHand, debt) < propertyCost)
256 std::int64_t moneyOwed)
noexcept
259 player >=
state.numberOfPlayers)
263 state, player,
false,
false, moneyOwed);
273 const auto representative = monopolies.representatives[
index];
276 const auto toThree =
static_cast<std::int64_t
>(lots.count * 3) - houses;
282 if (bestMetric <
static_cast<double>(definition.
rent[0]))
284 bestMetric =
static_cast<double>(definition.
rent[0]);
285 bestSquare = representative;
294 const auto representative = monopolies.representatives[
index];
297 static_cast<std::int64_t
>(lots.count * 3))
302 const auto frequency = monopolyFrequency(representative);
303 if (bestMetric < frequency)
305 bestMetric = frequency;
306 bestSquare = representative;
316 const auto representative = monopolies.representatives[
index];
319 static_cast<std::int64_t
>(lots.count *
state.options.housesPerHotel))
324 const auto frequency = monopolyFrequency(representative);
325 if (bestMetric < frequency)
327 bestMetric = frequency;
328 bestSquare = representative;
339 auto topHousesOnLot =
state.options.housesPerHotel;
340 if (
state.options.evenBuildRule)
342 const auto balancedTop =
static_cast<std::uint8_t
>(
344 static_cast<std::int64_t
>(lots.count) + 1);
345 if (balancedTop < topHousesOnLot)
346 topHousesOnLot = balancedTop;
352 const auto square = lots.squares[
index];
353 if (
state.squares[
static_cast<std::size_t
>(square)].houses < topHousesOnLot)
362 ++
state.squares[
static_cast<std::size_t
>(chosen)].houses;
365 state.players[player].cash -=
373 std::int64_t minCashOnHand,
374 std::int64_t moneyOwed)
noexcept
379 return SquareType::Go;
383 state, player,
false, strategy, minCashOnHand, moneyOwed);
385 const auto tryRange = [&](std::size_t begin, std::size_t endExclusive) {
388 const auto square =
static_cast<SquareType
>(
index);
391 if (!
runtime.mortgaged || bit == 0 || (owned & bit) == 0 ||
395 const auto rawCost =
static_cast<double>(
398 if (
static_cast<double>(excess) < rawCost)
402 state.players[player].cash -=
static_cast<std::int64_t
>(rawCost);
405 return SquareType::Go;
408 auto square = tryRange(
409 static_cast<std::size_t
>(SquareType::OrientalAvenue),
410 static_cast<std::size_t
>(SquareType::InJail));
411 if (square != SquareType::Go)
415 static_cast<std::size_t
>(SquareType::Go),
416 static_cast<std::size_t
>(SquareType::BalticAvenue) + 1);
424 std::int64_t minCashOnHand,
425 std::int64_t moneyOwed)
noexcept
430 return SquareType::Go;
433 state, player, strategy, minCashOnHand, moneyOwed);
434 if (
monopoly != SquareType::Go || onlyMonopolies)
439 state, player,
true, strategy, minCashOnHand, moneyOwed);
441 state, player, owned, excessCash);
442 if (square == SquareType::Go)
443 return SquareType::Go;
445 const auto rawCost =
static_cast<double>(
449 state.squares[
static_cast<std::size_t
>(square)].mortgaged =
false;
450 state.players[player].cash -=
static_cast<std::int64_t
>(rawCost);
458 std::int64_t minCashOnHand,
459 std::int64_t moneyOwed)
noexcept
466 auto simulated =
state;
476 simulated, player,
true, strategy, minCashOnHand, moneyOwed);
478 simulated, player,
false, strategy, minCashOnHand, moneyOwed);
480 for (std::size_t
index = 0;
483 const auto square =
static_cast<SquareType
>(
index);
488 const auto cost =
static_cast<std::int64_t
>(
492 if (available >=
cost)
502 std::int64_t minCashOnHand,
503 std::uint8_t housingPurchaseStrategy,
504 std::int64_t moneyOwed)
noexcept
509 state.options.housesPerHotel == 0)
518 if (monopolies.count == 0)
526 for (std::size_t
index = 0;
529 const auto square =
static_cast<SquareType
>(
index);
574 std::int64_t minCashOnHand,
575 std::uint8_t housingPurchaseStrategy,
576 std::int64_t moneyOwed)
noexcept
582 state.options.housesPerHotel == 0)
589 for (std::size_t
index = 0;
594 static_cast<SquareType
>(
index)};
612 ?
static_cast<int>(
state.options.housesPerHotel) - 1
613 :
static_cast<int>(
state.options.housesPerHotel);
615 std::array<SquareType, 8> monopolies{};
645 const auto baseRent =
static_cast<double>(
661 static_cast<int>(
lots.count * 3))
690 (
static_cast<int>(
state.options.housesPerHotel) - 1) *
691 static_cast<int>(
lots.count);
718 const auto square =
lots.squares[
index - 1];
719 if (
state.squares[
static_cast<std::size_t
>(square)].mortgaged)
724 if (
state.options.evenBuildRule)
727 static_cast<int>(
lots.count) + 1;
764 std::int64_t minCashOnHand,
767 std::int64_t moneyOwed)
noexcept
772 state.options.housesPerHotel == 0)
785 if (
owned.count == 0)
789 ?
static_cast<int>(
state.options.housesPerHotel) - 1
790 :
static_cast<int>(
state.options.housesPerHotel);
797 for (std::size_t
i = 0;
i <
lots.count; ++
i)
809 for (std::size_t
i = 0;
i <
owned.count; ++
i)
811 const auto rep =
owned.representatives[
i];
833 for (std::size_t
i = 0;
i <
owned.count; ++
i)
835 const auto rep =
owned.representatives[
i];
856 for (std::size_t
i = 0;
i <
owned.count; ++
i)
858 const auto rep =
owned.representatives[
i];
888 if (
state.options.evenBuildRule)
891 static_cast<int>(
lots.count) + 1;
896 for (std::size_t
i = 0;
i <
lots.count; ++
i)
898 const auto square =
lots.squares[
i];
902 const auto houses =
state.squares[
static_cast<std::size_t
>(square)].houses;
918 std::int64_t minCashOnHand,
919 std::int64_t moneyOwed)
noexcept
931 for (std::size_t
index = 0;
936 static_cast<SquareType
>(
index)};
946 const auto cash =
state.players[player].cash;
948 const auto tryMonopolyRange = [&](std::size_t begin, std::size_t endExclusive)
952 const auto square =
static_cast<SquareType
>(
index);
958 const auto rawCost =
static_cast<double>(
962 if (
static_cast<double>(cash) <
rawCost)
970 static_cast<std::size_t
>(SquareType::OrientalAvenue),
971 static_cast<std::size_t
>(SquareType::InJail));
975 static_cast<std::size_t
>(SquareType::Go),
976 static_cast<std::size_t
>(SquareType::BalticAvenue) + 1);
982 if (square == SquareType::Go)
984 const auto rawCost =
static_cast<double>(
986 if (
static_cast<double>(cash) <
rawCost)
996 player >=
state.numberOfPlayers)
1012 player >=
state.numberOfPlayers)
1013 return std::nullopt;
1024 const auto index =
static_cast<std::size_t
>(square);
1031 current <
state.numberOfPlayers; ++current)
1040 const auto electric =
static_cast<std::size_t
>(SquareType::ElectricCompany);
1041 const auto water =
static_cast<std::size_t
>(SquareType::WaterWorks);
1074 state, player, SquareGroup::Railroad,
false,
owned);
1076 state, player, SquareGroup::Utility,
false,
owned);
1078 std::int64_t
total{};
1079 for (std::size_t
index = 0;
1082 const auto square =
static_cast<SquareType
>(
index);
1109 total +=
static_cast<std::int64_t
>(
1130 const auto mortgage = [&](SquareType square) {
1131 const auto index =
static_cast<std::size_t
>(square);
1142 const auto index =
static_cast<std::size_t
>(square);
1159 if (
group == SquareGroup::Railroad ||
group == SquareGroup::Utility)
1163 state.options.mortgagedCountsInGroupRent,
owned);
1217 if (
raw >=
static_cast<std::size_t
>(SquareType::InJail))
1221 if (
lots.count == 0)
1231 const auto square =
lots.squares[
index];
1232 const auto squareIndex =
static_cast<std::size_t
>(square);
1255 player >=
state.numberOfPlayers)
1262 for (std::size_t
index = 0;
1268 static_cast<SquareType
>(
index)};
1273 for (std::size_t
index = 0;
1296 if (
state.players[player].currentSquare ==
1299 while (
state.players[player].cash < 0)
1329 if (
state.players[current].currentSquare ==
1330 static_cast<std::uint8_t
>(SquareType::OffBoard))
1343 config.minCashOnHand[current],
config.moneyOwed[current]) != SquareType::Go);
1348 if (
state.players[current].currentSquare ==
1349 static_cast<std::uint8_t
>(SquareType::OffBoard))
1353 config.minCashOnHand[current],
config.moneyOwed[current]) != SquareType::Go)
1360 if (
state.players[current].currentSquare ==
1361 static_cast<std::uint8_t
>(SquareType::OffBoard))
1363 while (
simulated.players[current].cash < 0)
1378 static_cast<double>(
simulated.numberOfPlayers - 1);
1379 chances[current] -=
static_cast<double>(
1381 chances[current] +=
static_cast<double>(
state.options.passingGoAmount);
1397 ?
config.cashLiquidAssetsDependence : 1.0;
1406 chances[current] +=
config.monopolyNotOwnedStageCashMultiplier *
1410 chances[current] +=
config.monopolyOwnedStageCashMultiplier *
1448 auto before =
state;
1452 if (
config.purchasingPlayer <
state.numberOfPlayers &&
1455 const auto index =
static_cast<std::size_t
>(
config.purchasingProperty);
1456 before.squares[
index].owner =
config.purchasingPlayer;
1457 after.squares[
index].owner =
config.purchasingPlayer;
1461 before, player,
config.winningChance);
1463 after, player,
config.winningChance);
1469 const auto debt =
config.winningChance.moneyOwed[player];
1472 for (std::size_t
deck = 0;
1475 if (before.cards[
deck].jailOwner == player)
1477 if (after.cards[
deck].jailOwner == player)
1483 config.propertyImportance,
config.winningChance.moneyOwed);
1486 propertyImportance *
config.tradeImportanceFactor;
1496 player >=
state.numberOfPlayers || property >= SquareType::InJail ||
1500 constexpr std::int64_t
Change = 10;
1503 const auto index =
static_cast<std::size_t
>(property);
1517 return current <
config.evaluation.winningChance.moneyOwed.size()
1518 ?
config.evaluation.winningChance.moneyOwed[current] : 0;
1539 for (std::size_t
deck = 0;
1550 proposal[player].propertiesReceived =
bit;
1555 config.evaluation.propertyImportance,
1556 config.evaluation.winningChance.moneyOwed);
1557 const double evaluation =
1560 propertyImportance *
config.evaluation.tradeImportanceFactor;
1572 player >=
state.numberOfPlayers || item >= SquareType::Count ||
1576 const auto debt =
config.evaluation.winningChance.moneyOwed[player];
1577 const auto strategy =
config.evaluation.winningChance.cashStrategy[player];
1578 const auto minCash =
config.evaluation.winningChance.minCashOnHand[player];
1587 std::int64_t mortgageCost{};
1588 std::int64_t purchaseCost{};
1591 if (item < SquareType::InJail)
1617 if (item < SquareType::InJail)
1627 ? (
static_cast<double>(
liquid) +
1629 config.monopolySuicideFactor) / 2.0
1634 const double remaining =
static_cast<double>(
1637 config.monopolySuicideFactor;
1638 bid *= 0.5 + (0.5 - remaining / 22.0 / 2.0);
1641 config.monopolySuicideFactor * 0.5;
1646 else if (owner == player)
1658 if (item < SquareType::InJail &&
bid <
static_cast<double>(mortgageCost))
1660 const auto floorBid = mortgageCost +
static_cast<std::int64_t
>(
bid) / 2;
1663 :
static_cast<double>(
liquid);
1666 if (item < SquareType::InJail &&
bid <
static_cast<double>(purchaseCost) &&
1671 bid =
static_cast<double>(purchaseCost);
1674 const std::int64_t
maximumBid =
static_cast<std::int64_t
>(
bid);
1683 std::span<const rules::PlayerNumber>
players,
1694 auto before =
state;
1698 if (
config.purchasingPlayer <
state.numberOfPlayers &&
1701 const auto index =
static_cast<std::size_t
>(
config.purchasingProperty);
1702 before.squares[
index].owner =
config.purchasingPlayer;
1703 after.squares[
index].owner =
config.purchasingPlayer;
1717 if (player >=
state.numberOfPlayers)
1730 const auto debt =
config.winningChance.moneyOwed[player];
1736 for (std::size_t
deck = 0;
1739 if (before.cards[
deck].jailOwner == player)
1741 if (after.cards[
deck].jailOwner == player)
1748 config.winningChance.moneyOwed);
1752 propertyImportance *
config.tradeImportanceFactor;
1759 std::span<const rules::PlayerNumber>
partners,
1764 std::span<const ai::trade::FutureImmunityRecord> immunities)
noexcept
1771 std::array<rules::PlayerNumber, rules::MaxPlayers>
participants{};
1780 std::array<std::int64_t, rules::MaxPlayers> cashGiven{};
1791 ?
config.minGiveMonopolyEvaluation
1792 :
config.minEvaluationThreshold;
1794 std::array<double, rules::MaxPlayers>
evaluations{};
1848 for (
const auto current :
partners)
1851 config.playerAttitude[current],
config.cashMultipliers);
1856 if (cashGiven[current] > 0)
1858 static_cast<double>(cashGiven[current]) -
1859 static_cast<double>(cashGiven[current]) *
factor);
1862 static_cast<double>(cashGiven[current]) -
1863 static_cast<double>(cashGiven[current]) /
factor);
1881 properties &=
~proposals[current].propertiesGiven;
1884 if (
config.localAIPlayer[current])
1885 canPay -=
config.evaluation.winningChance.moneyOwed[current];
1905 std::span<const rules::PlayerNumber>
partners,
1915 auto combined = properties[player];
1926 const auto square =
lots.squares[
index];
1927 const auto owner =
state.squares[
static_cast<std::size_t
>(square)].owner;
1928 if (owner == player)
1930 if (owner >=
state.numberOfPlayers)
1933 next[player].propertiesReceived |=
bit;
1934 next[owner].propertiesGiven |=
bit;
1946 config.fairTrade.evaluation.winningChance.moneyOwed[
partner]);
1965 auto available = properties[player];
1985 config.fairTrade.evaluation.winningChance.moneyOwed[
partner]))
2013 if (!
inputs.deriveOfferedGroups)
2020 std::array<rules::PlayerNumber, rules::MaxPlayers>
candidates{};
2038 double choice =
inputs.partnerRoll;
2039 std::size_t start{};
2060 auto available = properties[
target];
2064 static_cast<std::size_t
>(
inputs.wantedGroups[
index])];
2071 const auto owner =
state.squares[
2072 static_cast<std::size_t
>(
lots.squares[
lot])].owner;
2073 if (owner == player || owner >=
state.numberOfPlayers)
2095 for (std::size_t square = 0;
2104 if ((available &
bit) != 0)
2107 next[player].propertiesReceived |=
bit;
2117 auto available = properties[player];
2118 auto offeredGroups =
inputs.offeredGroups;
2119 if (
inputs.deriveOfferedGroups)
2124 config.fairTrade.evaluation.winningChance.moneyOwed[
target]),
2131 static_cast<std::size_t
>(offeredGroups[
index])];
2133 auto offered = available &
groupSet;
2139 next[player].propertiesGiven |= offered;
2147 next[player].propertiesGiven ^= offered;
2193 std::array<rules::PlayerNumber, rules::MaxPlayers>
candidates{};
2212 if (
inputs.shouldGiveAwayMonopoly)
2215 state, player,
config.fairTrade.evaluation.winningChance.moneyOwed);
2223 result.proposal = proposal;
2253 static_cast<std::size_t
>(
group)];
2266 std::span<const rules::PlayerNumber>(
2268 properties, proposal,
config))
2271 if (
inputs.importance == 0 ||
2275 state, player, player, proposal,
2276 config.fairTrade.evaluation) <
2277 config.fairTrade.minEvaluationThreshold)
2284 result.proposal = proposal;
2289 if (!
inputs.semiImportant)
2304 result.proposal = proposal;
2316 std::span<const ai::trade::FutureImmunityRecord> immunities)
noexcept
2320 player >=
state.numberOfPlayers ||
inputs.proposedPlayer >=
state.numberOfPlayers)
2323 if (
inputs.pendingActions != 0 || !
state.tradeInProgress ||
2339 if (
session.timesCounteredTrade >=
config.tradeCounterLimit)
2344 if (
session.timesCounteredTrade == 0 &&
2347 currentTrade[player],
config.numberTimesAllowPropertyTrade) != 0)
2352 if (
session.timesCounteredTrade == 0)
2354 session.propertyMemory,
inputs.proposedPlayer, currentTrade[player]);
2356 if (
inputs.counterRoll >
config.tradeCounterProbability &&
2363 state, player, player, currentTrade,
config.evaluation);
2364 if (
session.timesCounteredTrade != 0 &&
2365 result.evaluation <=
session.lastTradeEvaluation)
2370 session.lastTradeEvaluation = result.evaluation;
2373 if (
config.evaluation.purchasingPlayer <
state.numberOfPlayers &&
2376 config.evaluation.purchasingProperty)].owner =
config.evaluation.purchasingPlayer;
2379 if (result.preparation.tradePlayerCount < 1)
2384 if (result.preparation.tradePlayerCount == 1)
2386 const auto partner = result.preparation.tradePlayers[0];
2393 result.averageAttitude = result.preparation.totalAttitude /
2394 static_cast<double>(result.preparation.tradePlayerCount);
2395 if (result.averageAttitude < -1.0)
2396 result.averageAttitude = -1.0;
2407 std::span<const ai::trade::FutureImmunityRecord> immunities)
noexcept
2411 player >=
state.numberOfPlayers ||
2413 preflight.preparation.tradePlayerCount == 0 ||
2415 config.maxIterations == 0)
2433 const auto square =
static_cast<std::size_t
>(
evaluationConfig.purchasingProperty);
2449 result.propertyImportance = 0.0;
2454 if (result.evaluation >=
config.minEvaluationThreshold)
2466 0.0,
config.fairTrade.cashMultipliers);
2468 for (
const auto& record : importance)
2470 if (-result.propertyImportance < record.importance)
2475 false,
config.whatToTrade, 0.0,
2483 ++result.iterations;
2484 if (!
added || result.iterations >=
config.maxIterations)
2487 while (result.propertyImportance < 0.0);
2489 if (result.propertyImportance <
config.lowestPropertyImportanceForCounter &&
2490 result.evaluation <
config.minEvaluationThreshold)
2503 config.fairTrade.cashMultipliers);
2504 for (
const auto& record : importance)
2512 if (-result.propertyImportance < record.importance)
2553 const auto partners = std::span<const rules::PlayerNumber>(
2574 std::int64_t minCashOnHand,
2575 int maxHousesPerSquareForGiveAway,
2576 std::span<const std::int64_t> moneyOwed)
noexcept
2588 const auto debt = player < moneyOwed.size() ? moneyOwed[player] : 0;
2604 if (houses <=
static_cast<std::int64_t
>(
lots.count) *
2605 maxHousesPerSquareForGiveAway)
std::array< rules::PlayerNumber, rules::MaxPlayers > players
decision::EconomicActionPlan plan
constexpr std::uint8_t HouseBuyWithin12
EconomicActionPlan planBuyHouseAction(const rules::GameState &state, rules::PlayerNumber player, CashStrategy strategy, std::int64_t minCashOnHand, std::uint8_t housingPurchaseStrategy, std::int64_t moneyOwed) noexcept
CounterProposalPreflightResult counterProposalPreflight(const rules::GameState &state, rules::PlayerNumber player, const ai::trade::TradeProposalList ¤tTrade, const CounterProposalPreflightInputs &inputs, const CounterProposalPreflightConfig &config, CounterProposalSession &session, std::span< const ai::trade::FutureImmunityRecord > immunities) noexcept
EconomicActionPlan planDebtLiquidationStep(const rules::GameState &state, rules::PlayerNumber player, bool sellHouses) noexcept
@ ExpectedRentIncludingMonopolies
@ ExpectedRentExcludingMonopolies
bool hypotheticalBuyHouse(rules::GameState &state, rules::PlayerNumber player, std::int64_t moneyOwed) noexcept
bool shouldGiveAwayMonopoly(const rules::GameState &state, rules::PlayerNumber player, CashStrategy strategy, std::int64_t minCashOnHand, int maxHousesPerSquareForGiveAway, std::span< const std::int64_t > moneyOwed) noexcept
bool mortgageWorstProperty(rules::GameState &state, rules::PlayerNumber player, bool sellHouses, bool mortgageMonopoly) noexcept
bool buildSemiImportantTrade(const rules::GameState &state, rules::PlayerNumber player, std::span< const double > playerAttitudes, const ai::trade::PropertySets &properties, const SemiImportantTradeInputs &inputs, ai::trade::TradeProposalList &proposals, const MonopolyProposalConfig &config) noexcept
double evaluateTrade(const rules::GameState &state, rules::PlayerNumber player, rules::PlayerNumber strategyPlayer, const ai::trade::TradeProposalList &proposals, const TradeEvaluationConfig &config) noexcept
CounterProposalBalanceResult counterProposalBalance(const rules::GameState &state, rules::PlayerNumber player, const CounterProposalPreflightResult &preflight, ai::trade::TradeProposalList &proposals, const CounterProposalBalanceConfig &config, std::span< const ai::trade::FutureImmunityRecord > immunities) noexcept
HousePurchaseDecision shouldBuyHouse(const rules::GameState &state, rules::PlayerNumber player, CashStrategy strategy, std::int64_t minCashOnHand, std::uint8_t housingPurchaseStrategy, std::int64_t moneyOwed) noexcept
std::int64_t cashAvailableAfterHousing(const rules::GameState &state, rules::PlayerNumber player, CashStrategy strategy, std::int64_t minCashOnHand, std::int64_t moneyOwed) noexcept
bool buildMonopolyTrade(const rules::GameState &state, rules::PlayerNumber player, rules::board::SquareGroup group, std::span< const rules::PlayerNumber > partners, const ai::trade::PropertySets &properties, ai::trade::TradeProposalList &proposals, const MonopolyProposalConfig &config) noexcept
std::int64_t excessCashAvailable(const rules::GameState &state, rules::PlayerNumber player, bool cashOnly, CashStrategy strategy, std::int64_t minCashOnHand, std::int64_t moneyOwed) noexcept
std::int64_t tradeBidForProperty(const rules::GameState &state, rules::PlayerNumber player, rules::board::SquareType property, std::int64_t currentBid, rules::PlayerNumber currentBidder, const AuctionBidConfig &config) noexcept
bool shouldBuyProperty(const rules::GameState &state, rules::PlayerNumber player, rules::board::SquareType property, CashStrategy strategy, std::int64_t minCashOnHand, std::span< const std::int64_t > moneyOwed) noexcept
std::optional< rules::board::SquareType > chooseHousingAuctionSquare(const rules::GameState &state, rules::PlayerNumber player, HousingAuctionBuilding building, CashStrategy strategy, std::int64_t minCashOnHand, rules::board::PropertySet legalSquares, bool reservedBuilding, std::int64_t moneyOwed) noexcept
EconomicActionPlan planUnmortgagePropertyAction(const rules::GameState &state, rules::PlayerNumber player, CashStrategy strategy, std::int64_t minCashOnHand, std::int64_t moneyOwed) noexcept
std::int64_t bidForAuctionItem(const rules::GameState &state, rules::PlayerNumber player, rules::board::SquareType item, std::int64_t currentBid, rules::PlayerNumber currentBidder, const AuctionBidConfig &config, bool useTenDollarIncrement) noexcept
bool buildMonopolyForCash(const rules::GameState &state, rules::PlayerNumber player, rules::PlayerNumber firstPartner, const ai::trade::PropertySets &properties, ai::trade::TradeProposalList &proposals, const MonopolyProposalConfig &config) noexcept
std::optional< bool > chooseFractionTax(const rules::GameState &state, rules::PlayerNumber player) noexcept
double evaluateWinningChances(const rules::GameState &state, rules::PlayerNumber player, const WinningChanceConfig &config, std::span< double > savePlayerChances) noexcept
EconomicActionPlan planHouseSaleAction(const rules::GameState &state, rules::board::SquareType referenceSquare) noexcept
ProactiveTradeResult buildProactiveTrade(const rules::GameState &state, rules::PlayerNumber player, std::span< const double > playerAttitudes, const ai::trade::PropertySets &properties, const ProactiveTradeInputs &inputs, const MonopolyProposalConfig &config) noexcept
constexpr std::uint8_t CriticalHousingLevel
std::int64_t totalWorthWithFactors(const rules::GameState &state, rules::PlayerNumber player, const WorthFactors &factors) noexcept
bool shouldUnmortgageProperty(const rules::GameState &state, rules::PlayerNumber player, CashStrategy strategy, std::int64_t minCashOnHand, std::int64_t moneyOwed) noexcept
rules::board::SquareType hypotheticalUnmortgageProperty(rules::GameState &state, rules::PlayerNumber player, bool onlyMonopolies, CashStrategy strategy, std::int64_t minCashOnHand, std::int64_t moneyOwed) noexcept
void mortgageNegativeCashPlayers(rules::GameState &state) noexcept
constexpr std::uint8_t HouseBuyAtLeast3
std::optional< JailExitChoice > chooseJailExitChoice(const rules::GameState &state, rules::PlayerNumber player, bool canRollDoubles, bool canPayFee, bool canUseCard) noexcept
rules::board::SquareType hypotheticalUnmortgageMonopolyProperty(rules::GameState &state, rules::PlayerNumber player, CashStrategy strategy, std::int64_t minCashOnHand, std::int64_t moneyOwed) noexcept
void evaluateTradePlayerList(const rules::GameState &state, std::span< const rules::PlayerNumber > players, rules::PlayerNumber strategyPlayer, const ai::trade::TradeProposalList &proposals, bool givingMonopolyForCash, const TradeEvaluationConfig &config, std::span< double > evaluations) noexcept
bool makeTradeFair(const rules::GameState &state, rules::PlayerNumber player, std::span< const rules::PlayerNumber > partners, std::int64_t giveMost, bool givingMonopoly, ai::trade::TradeProposalList &proposals, const FairTradeConfig &config, std::span< const ai::trade::FutureImmunityRecord > immunities) noexcept
constexpr std::array< double, 8 > MonopolyAverageLandingFrequency
std::int64_t transferTax(const rules::GameState &state, rules::board::PropertySet properties) noexcept
void rememberTradedProperties(PropertyTradeMemory &memory, rules::PlayerNumber proposedPlayer, const TradeProposalRecord &proposal) noexcept
double cashMultiplier(double attitude, const CashMultiplierTable &multipliers) noexcept
PlayerPropertyAttitudeList createPlayerPropertyAttitudeList(const rules::GameState &state, rules::PlayerNumber player, const TradeProposalList &proposals, std::span< const double > playerAttitudes) noexcept
constexpr std::uint8_t TradeForCash
bool tradeIsProper(const rules::GameState &state, const TradeProposalList &proposals, std::span< const FutureImmunityRecord > immunities) noexcept
rules::board::PropertySet propertiesAlreadyTraded(const PropertyTradeMemory &memory, rules::PlayerNumber proposedPlayer, const TradeProposalRecord &proposal, int dangerLevel) noexcept
StrategicPropertyImportance
bool playerInvolvedInTrade(const TradeProposalRecord &proposal) noexcept
constexpr std::uint8_t TradeSomewhatImportant
std::array< rules::board::SquareGroup, 8 > orderMonopolyImportance(std::int64_t liquidAssets, MonopolySortOrder order, std::span< const std::uint32_t > randomKeys) noexcept
MonopolyTradeGroup findSmallestMonopolyTrade(rules::PlayerNumber player, rules::board::PropertySet monopoly, std::span< const rules::PlayerNumber > candidates, const PropertySets &properties) noexcept
constexpr std::uint8_t TradeDesperate
constexpr std::uint8_t TradeGiveMonopoly
TradeImportanceList createItemImportanceList(const rules::GameState &state, rules::PlayerNumber player, rules::PlayerNumber strategyPlayer, const PropertyImportanceConfig &config, double strategyAttitudeTowardPlayer, const CashMultiplierTable &multipliers) noexcept
bool addTypeProperty(const rules::GameState &before, const rules::GameState &after, rules::PlayerNumber player, rules::PlayerNumber strategyPlayer, rules::board::PropertySet &combinedProperties, TradeImportanceItem item, TradeProposalList &proposals, const PropertySets &properties, bool giveDescending, const WhatToTradeTable &whatToTrade, double strategyAttitudeTowardPlayer, std::int64_t playerMoneyOwed) noexcept
void makeTradeProper(const rules::GameState &state, TradeProposalList &proposals, std::span< const FutureImmunityRecord > immunities) noexcept
bool onlyPlayerHasMonopoly(const rules::GameState &state, rules::PlayerNumber player) noexcept
void applyTradeToState(rules::GameState &state, const TradeProposalList &proposals) noexcept
std::array< rules::board::PropertySet, rules::MaxPlayers > PropertySets
bool playerHasFutureOrImmunity(rules::PlayerNumber player, std::span< const FutureImmunityRecord > immunities) noexcept
std::array< TradeProposalRecord, rules::MaxPlayers > TradeProposalList
MonopolyTradeDecision shouldTradeForMonopoly(const rules::GameState &state, rules::PlayerNumber player) noexcept
double calculateTradePropertyImportance(const rules::GameState &before, const rules::GameState &after, rules::PlayerNumber player, rules::PlayerNumber strategyPlayer, const TradeProposalList &proposals, bool givingMonopolyAway, const PropertyImportanceConfig &config, std::span< const std::int64_t > moneyOwed) noexcept
constexpr std::size_t WhatToTradeEntries
bool hasMonopolyTrade(const rules::GameState &state, rules::PlayerNumber player, rules::PlayerNumber excludedPlayer) noexcept
rules::PlayerNumber findNonmonopolyPlayer(const rules::GameState &state, rules::PlayerNumber player, std::span< const std::int64_t > moneyOwed) noexcept
StrategicPropertyImportance strategicPropertyImportance(const rules::GameState &state, rules::board::SquareType property, rules::PlayerNumber excludedPlayer, rules::PlayerNumber includedPlayer, rules::PlayerNumber purchasingPlayer, rules::board::SquareType purchasingProperty) noexcept
double averageRentReceived(const rules::GameState &state, rules::PlayerNumber player, std::int64_t startSquare, bool dontCountDevelopedMonopolies, double cashCowMultiplier, rules::board::PropertySet propertiesOwned) noexcept
MonopolyStage monopolyStage(const rules::GameState &state, rules::PlayerNumber player) noexcept
bool someoneCloseToMonopoly(const rules::GameState &state, rules::PlayerNumber player, const MonopolyLots &monopoly, std::int64_t minDistance, std::int64_t maxDistance) noexcept
int housesOnMonopoly(const rules::GameState &state, SquareType square) noexcept
MonopolyLots monopolyLots(SquareType square) noexcept
std::uint8_t freeHouses(const rules::GameState &state) noexcept
int propertyCount(rules::board::PropertySet properties) noexcept
std::int64_t minimumCalculatedExpenses(const rules::GameState &state, rules::PlayerNumber player) noexcept
bool playerOwnsMonopoly(const rules::GameState &state, rules::PlayerNumber player, bool countBaltic) noexcept
rules::board::PropertySet monopolySet(SquareType square) noexcept
bool isCashCow(SquareType square) noexcept
bool testForMonopoly(rules::board::PropertySet properties, SquareType square) noexcept
bool ownsMonopoly(const rules::GameState &state, rules::PlayerNumber player, SquareType square, bool mortgageCounts) noexcept
SquareType findLowestRentProperty(const rules::GameState &state, rules::PlayerNumber player, rules::board::PropertySet properties) noexcept
int numberRailroadsUtilitiesOwned(const rules::GameState &state, rules::PlayerNumber player, SquareGroup group, bool mortgageCounts, rules::board::PropertySet propertiesOwned) noexcept
void testSellHouses(rules::GameState &state, const MonopolyLots &monopoly, SquareType testSquare) noexcept
std::int64_t mostLiquidAssets(const rules::GameState &state, rules::PlayerNumber excludedPlayer, bool countMonopolies, std::span< const std::int64_t > moneyOwed) noexcept
std::int64_t totalWorth(const rules::GameState &state, rules::PlayerNumber player) noexcept
int propertiesLeftToBuy(const rules::GameState &state) noexcept
std::int64_t liquidAssets(const rules::GameState &state, rules::PlayerNumber player, bool countHouses, bool countMonopolies, std::int64_t moneyOwed) noexcept
bool housingShortage(const rules::GameState &state, std::uint8_t criticalLevel) noexcept
constexpr std::array< rules::board::SquareType, 8 > ExpensiveMonopolySquares
std::int64_t liquidAssetsForProperties(const rules::GameState &state, rules::board::PropertySet properties, bool countHouses, bool countMonopolies) noexcept
rules::PlayerNumber firstOwnerInMonopoly(const rules::GameState &state, SquareType square) noexcept
bool playerCloseToProperty(const rules::GameState &state, rules::PlayerNumber ignorePlayer, SquareType property, std::int64_t minDistance, std::int64_t maxDistance) noexcept
HighestRentResult highestRentSquare(const rules::GameState &state, rules::PlayerNumber player) noexcept
MonopolyCollection monopoliesOwned(const rules::GameState &state, rules::PlayerNumber player, bool mortgageCounts) noexcept
bool anyMonopoly(const rules::GameState &state) noexcept
std::int64_t averageRentPaid(const rules::GameState &state, rules::PlayerNumber player, std::int64_t startSquare, bool considerDevelopedMonopolies, double cashCowMultiplier) noexcept
rules::PlayerNumber bestCurrentRent(const rules::GameState &state) noexcept
std::uint8_t freeHotels(const rules::GameState &state) noexcept
std::int64_t costUnmortgageMonopoly(const rules::GameState &state, SquareType square) noexcept
std::int64_t housesCanBuyOnMonopoly(const rules::GameState &state, SquareType square) noexcept
SquareType findHighestRentMortgaged(const rules::GameState &state, rules::PlayerNumber player, rules::board::PropertySet properties, std::int64_t topUnmortgageCost) noexcept
rules::board::PropertySet propertiesOwnedByPlayer(const rules::GameState &state, rules::PlayerNumber player) noexcept
bool ownsPropertyFromMonopoly(const rules::GameState &state, rules::PlayerNumber player, SquareType square) noexcept
rules::PlayerNumber mostExpensivePotentialIncome(const rules::GameState &state) noexcept
const SquareDefinition & definition(SquareType square)
std::uint32_t PropertySet
PropertySet propertyBit(SquareType square)
std::uint8_t PlayerNumber
constexpr PlayerNumber MaxPlayers
constexpr PlayerNumber NobodyPlayer
CounterProposalStatus status
std::int64_t housePurchaseCost
std::int64_t mortgageCost
std::int64_t purchaseCost
std::array< std::int64_t, RentStepCount > rent