Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
TradeTokenPlayback.cpp
Go to the documentation of this file.
2
3#include "LegacyBitmap.hpp"
4#include "LegacySequence.hpp"
5#include "SequenceRuntime.hpp"
6
7#include <memory>
8#include <utility>
9#include <variant>
10#include <vector>
11
12namespace monopoly::tradeui
13{
14 namespace
15 {
16 struct TokenSpec
17 {
19 std::uint16_t priority{};
20 std::int32_t x{};
21 std::int32_t y{};
22 };
23
24 [[nodiscard]] std::expected<std::uint32_t, std::string>
25 anyBitmapWidth(const sequence::SequenceProgram& program)
26 {
27 const auto resources = program.resources();
28 if (!resources)
29 return std::unexpected("Trade token sequence has no resource snapshot");
30
31 for (const auto& description : program.descriptions())
32 {
33 if (!std::holds_alternative<data::SequenceBitmapData>(
34 description.record.data) ||
35 !description.contentsDataId)
36 continue;
37
38 const auto id = *description.contentsDataId;
39 const auto metadata = resources->data().metadata(id);
40 if (!metadata)
41 return std::unexpected(metadata.error().detail);
42 const auto bytes = resources->data().load(id);
43 if (!bytes)
44 return std::unexpected(bytes.error().detail);
45
47 {
49 if (!bitmap)
50 return std::unexpected(bitmap.error().detail);
51 if (bitmap->width <= 0)
52 return std::unexpected("Trade token bitmap width is invalid");
53 return static_cast<std::uint32_t>(bitmap->width);
54 }
55
57 {
58 const auto bitmap = data::inspectLegacyUap(**bytes);
59 if (!bitmap)
60 return std::unexpected(bitmap.error().detail);
61 if (bitmap->width == 0)
62 return std::unexpected("Trade token UAP width is invalid");
63 return bitmap->width;
64 }
65
66 return std::unexpected(
67 "Trade token 2D sequence content is not a bitmap");
68 }
69
70 return std::unexpected(
71 "Trade token sequence contains no bitmap record");
72 }
73
74 [[nodiscard]] std::expected<std::array<TokenSpec, 2>, std::string> desiredTokens(
75 const State& state,
76 const rules::GameState& gameState,
78 {
79 std::array<TokenSpec, 2> specs{{
82 }};
83
85 return specs;
86
87 const std::array players{state.playerA, state.playerB};
88 for (std::size_t index = 0; index < players.size(); ++index)
89 {
90 const auto player = players[index];
91 if (player >= rules::MaxPlayers)
92 continue;
93 const auto token = gameState.players[player].token;
95 return std::unexpected("Trade token index is out of range");
97 }
98 return specs;
99 }
100 }
101
102 std::expected<void, std::string> TokenPlayback::sync(
103 const State& state,
107 {
109 if (!desired) return std::unexpected(desired.error());
110 auto specs = *desired;
111 std::array<std::shared_ptr<const sequence::SequenceProgram>, 2> programs{};
112
113 for (std::size_t index = 0; index < specs.size(); ++index)
114 {
115 if (specs[index].id == data::EmptyDataId ||
116 specs[index].id == current_[index])
117 continue;
118
120 playback.resources(), specs[index].id);
121 if (!loaded)
122 return std::unexpected(loaded.error().detail);
123 programs[index] = std::move(*loaded);
124 }
125
126 if (specs[1].id != data::EmptyDataId &&
127 specs[1].id != current_[1])
128 {
129 const auto width = anyBitmapWidth(*programs[1]);
130 if (!width)
131 return std::unexpected(width.error());
132 if (*width > static_cast<std::uint32_t>(TradeTokenRightEdge))
133 return std::unexpected("Trade token bitmap is wider than right alignment edge");
134 specs[1].x = TradeTokenRightEdge - static_cast<std::int32_t>(*width);
135 }
136
137 std::vector<sequence::SequenceCommand> commands;
138
139 for (std::size_t index = 0; index < specs.size(); ++index)
140 {
141 if (specs[index].id == current_[index])
142 continue;
143
144 if (current_[index] != data::EmptyDataId)
145 {
146 commands.push_back(sequence::StopSequenceCommand{
147 current_[index], specs[index].priority, false});
148 }
149
150 if (specs[index].id != data::EmptyDataId)
151 {
152 commands.push_back(sequence::StartSequenceCommand{
154 commands.push_back(sequence::makeMoveXY(
156 specs[index].x, specs[index].y));
157 }
158 }
159
160 if (commands.size() > sequence::SequenceCommandQueue::Capacity -
161 playback.commands().pendingCount())
162 {
163 return std::unexpected(
164 "sequence command queue cannot fit Trade token transition");
165 }
166
167 for (auto& command : commands)
168 {
169 const auto queued = std::visit(
170 [&](auto value)
171 {
172 return playback.commands().enqueue(std::move(value));
173 },
174 std::move(command));
175 if (!queued)
176 return std::unexpected("validated Trade token command rejected");
177 }
178
179 for (std::size_t index = 0; index < specs.size(); ++index)
180 current_[index] = specs[index].id;
181 return {};
182 }
183}
std::array< rules::PlayerNumber, rules::MaxPlayers > players
LegacyBitmapMetadata metadata
std::vector< std::byte > bytes
std::uint16_t priority
std::uint32_t width
unsigned state
unsigned index
int token
std::uint16_t value
Definition Timers.cpp:16
static std::expected< std::shared_ptr< const SequenceProgram >, RuntimeError > load(const data::DataSource &source, data::DataId id, std::size_t offset=0, DescriptionLimits limits={})
std::expected< void, std::string > sync(const State &state, const rules::GameState &gameState, display::Screen2D desiredView, engine::SequencePlayback &playback)
std::uint32_t DataId
Definition DataBanks.hpp:10
constexpr DataId EmptyDataId
Definition DataBanks.hpp:13
std::expected< LegacyUapMetadata, BitmapError > inspectLegacyUap(std::span< const std::byte > bytes)
std::expected< LegacyBitmapMetadata, BitmapError > inspectLegacyBitmap(std::span< const std::byte > bytes)
constexpr std::size_t MaxTokens
Definition RuleTypes.hpp:30
constexpr PlayerNumber MaxPlayers
Definition RuleTypes.hpp:14
MoveSequenceCommand makeMoveXY(data::DataId dataId, std::uint16_t priority, std::int32_t x, std::int32_t y) noexcept
std::shared_ptr< const data::ResourceSnapshot > resources() noexcept
constexpr std::int32_t TradeTokenAX
constexpr data::DataId tradeTokenSequence(std::uint8_t token) noexcept
constexpr std::int32_t TradeTokenY
constexpr std::uint16_t TradeTokenBPriority
constexpr std::int32_t TradeTokenRightEdge
constexpr std::uint16_t TradeTokenAPriority