34 std::vector<RuleHit> ruleHits;
42 std::uint64_t pressSerial{};
78 return std::wstring(message.
stringA.data());
110 (!
name.empty() &&
name.back() ==
L'_' ? 1u : 0u);
116 if constexpr (
sizeof(
wchar_t) == 2)
121 name.push_back(
static_cast<wchar_t>(0xD800u + (
character >> 10u)));
122 name.push_back(
static_cast<wchar_t>(0xDC00u + (
character & 0x3FFu)));
127 name.push_back(
L'_');
135 for (std::size_t
i = 0;
i <
utf8.size();)
137 const auto first =
static_cast<std::uint8_t
>(
utf8[
i]);
138 std::uint32_t code{};
141 else if ((
first & 0xE0u) == 0xC0u) { code =
first & 0x1Fu;
count = 2; }
142 else if ((
first & 0xF0u) == 0xE0u) { code =
first & 0x0Fu;
count = 3; }
143 else if ((
first & 0xF8u) == 0xF0u) { code =
first & 0x07u;
count = 4; }
144 else { ++
i;
continue; }
147 for (std::size_t
j = 1;
j <
count; ++
j)
153 if (!
valid) { ++
i;
continue; }
155 (
count == 3 && code < 0x800u) || (
count == 4 && code < 0x10000u);
156 if (
overlong || code > 0x10FFFFu || (code >= 0xD800u && code <= 0xDFFFu))
174 if constexpr (
sizeof(
wchar_t) == 2)
184 name.push_back(
L'_');
202 static_cast<std::uint8_t
>(
215 static_cast<std::uint8_t
>(
226 if (resources && resources->language() && resources->language()->catalog)
230 const auto value = resources->language()->catalog->message(920 +
token);
319 .currentPlayerSetupPhase
326 .desiredPlayerSetupPhase
339 static_cast<std::uint8_t
>(
405 case Button::TokenGun:
410 case Button::TokenIron:
415 case Button::TokenThimble:
420 case Button::TokenCar:
425 case Button::TokenHorse:
430 case Button::TokenBarrow:
435 case Button::TokenDog:
440 case Button::TokenShip:
445 case Button::TokenMoneyBag:
450 case Button::TokenHat:
455 case Button::TokenShoe:
478 if (
button == Button::SelectPlayerMore)
482 if (
button >= Button::SelectPlayerCard1 &&
483 button <= Button::SelectPlayerCard8)
485 const std::size_t
slot =
486 static_cast<std::size_t
>(
487 static_cast<std::uint8_t
>(
button) -
488 static_cast<std::uint8_t
>(Button::SelectPlayerCard1));
501 std::uint8_t
token = 0;
524 Phase::StartAddRemove)
528 case Button::AddHuman:
529 case Button::AddComputer:
535 case Button::RemovePlayer:
541 case Button::StartGame:
544 uiState.numberOfPlayers >= 2 &&
557 button == Button::RulesOkay)
570 Button::EnterNameNext)
584 player <
uiState.numberOfPlayers;
606 if (current <
uiState.numberOfPlayers &&
641 switch (command.
type)
804 .desiredPlayerSetupPhase)
826 const int px =
static_cast<int>(
x),
py =
static_cast<int>(
y);
827 for (
const auto&
hit : ruleHits)
829 if (!
hit.rect.contains(
px,
py))
continue;
929 if (history.configured())
996 if (history.configured())
1112 static_cast<std::uint8_t
>(
1119 .startButtonPressed;
1125 .currentPlayerSetupPhase
1187 if (
auto result = history.open(std::move(
path)); !result)
return result;
1209 if (!assetRoot.is_absolute())
1210 return std::unexpected(
"custom board asset root must be absolute");
1253 ruleHits.assign(
hits.begin(),
hits.end());
1260 if (history.configured())
1263 std::vector<HistoryPlayer>
players;
1265 players.push_back({game.players[i].name,game.players[i].aiPlayerLevel,
1266 ui::localplayers::slotIsLocalPlayer(i)});
1267 if (
auto result=history.gameStarted(
players);!result)
1281 const auto&
winner=game.players[
static_cast<std::size_t
>(message.
numberA)];
1282 if (
auto result=history.gameOver(
winner.name,
static_cast<int>(message.
numberB),
winner.aiPlayerLevel);!result)
1296 static_cast<std::int64_t
>(
1303 static_cast<std::size_t
>(message.
numberA);
1312 static_cast<std::uint8_t
>(message.
numberB);
1315 static_cast<std::uint8_t
>(message.
numberC);
1318 static_cast<std::uint8_t
>(message.
numberD);
1335 std::clamp<std::int64_t>(
1338 static_cast<std::int64_t
>(
1350 static_cast<std::uint8_t
>(
count);
1476 static_cast<std::int64_t
>(
1543 const std::int64_t
x =
1546 const std::int64_t
y =
1725 const auto command =
std::array< rules::PlayerNumber, rules::MaxPlayers > players
std::atomic< float > left
std::atomic< float > right
std::vector< HistoryEntry > highScores() const
@ NotifyProposedConfiguration
const State & stateReadOnly() noexcept
void setBackdrop(Screen2D screen)
const State & stateReadOnly()
void playWarningSound() noexcept
void playPennybagsVoice(udsound::PennybagsVoice line, udsound::TokenVoiceClipPolicy policy, bool watchAfterStart) noexcept
void restoreRuleTracking() noexcept
bool startConfiguredNetwork()
bool sendAction(const actions::Message &message)
void visualPhaseStarted(ui::playersetup::Phase phase) noexcept
RenderState renderStateReadOnly()
void setPlaybackState(bool interactable, std::span< const RuleHit > hits, ui::playersetup::Rect restore, ui::playersetup::Rect shortGame)
bool consumeCustomBoardRequest() noexcept
std::expected< void, std::string > configureHistory(std::filesystem::path path)
const State & stateReadOnly()
void processLibraryMessage(const uimsg::Message &message)
std::expected< void, std::string > commitCustomBoard(std::filesystem::path assetRoot)
void playerButtonClicked(rules::PlayerNumber player)
void processMessage(const actions::Message &message)
void switchPhase(display::PlayerSetupPhase phase)
bool consumeLoadRequest() noexcept
bool acceptedConfigurationMessage(const GameOptions &options, PlayerNumber fromPlayer, bool interim, actions::Message &result)
void setShortGameRules(GameOptions &options)
void setStandardMonopolyRules(GameOptions &options)
bool applySetupRuleChoice(GameOptions &options, SetupRule rule, std::uint8_t choice) noexcept
constexpr PlayerNumber BankPlayer
std::uint8_t PlayerNumber
constexpr std::size_t MaxTokens
constexpr PlayerNumber MaxPlayers
constexpr PlayerNumber NobodyPlayer
std::shared_ptr< const data::ResourceSnapshot > resources() noexcept
bool requestRemoveLocalPlayer(const GameState &uiState, PlayerNumber player)
PlayerNumber currentUIPlayer()
PlayerNumber anyLocalPlayer(const GameState &uiState)
void setCurrentUIPlayerFromPlayerSet(const GameState &uiState, std::uint32_t playerSet)
bool slotIsLocalHumanPlayer(PlayerNumber slot)
bool requestAddLocalPlayer(const GameState &uiState, std::wstring_view name, std::uint8_t token, std::uint8_t colour, std::uint8_t aiLevel, bool takeOverAI)
constexpr std::uint8_t TokenCar
constexpr std::uint8_t TokenThimble
void setPlayerLogEntries(State &state, const rules::GameState &uiState, std::span< const std::wstring > entries)
constexpr std::uint8_t TokenHat
Command playerBarClicked(State &state, rules::PlayerNumber player)
constexpr std::uint8_t TokenShoe
Command clickButton(State &state, const GameState &uiState, Button button)
constexpr int MonetarySystemUs
constexpr std::uint8_t TokenIron
bool tokenAvailable(const GameState &uiState, std::uint8_t token)
constexpr std::uint8_t TokenGun
constexpr std::size_t PlayerHistoryPageSize
constexpr std::uint8_t TokenBarrow
void initialize(State &state, bool serverMode)
Command customRuleChoice(State &state, const GameState &, rules::options::SetupRule rule, std::uint8_t choice)
void requestPhase(State &state, const GameState &uiState, Phase requested)
constexpr std::uint8_t TokenHorse
constexpr std::uint8_t TokenShip
constexpr std::uint8_t TokenDog
void setTokenName(State &state, std::uint8_t token, std::wstring_view name)
constexpr std::uint8_t TokenMoneyBag
Button buttonAt(Phase phase, int x, int y, data::BoardEdition edition)
Update startPhase(State &state, display::PlayerSetupPhase phase, bool aiPlayer, std::uint8_t numberOfPlayers) noexcept
void resetPlayback(State &state) noexcept
const rules::GameState & ruleStateReadOnly()
rules::GameState & ruleState()
std::array< wchar_t, 80 > stringA
rules::PlayerNumber player
rules::options::SetupRule setupRule