Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
IBarPropertyPlayback.cpp
Go to the documentation of this file.
2
3#include <memory>
4#include <utility>
5#include <variant>
6#include <vector>
7
8namespace monopoly::ibar
9{
12 const PropertyTitleInputs& inputs) noexcept
13 {
15 if (!inputs.available)
16 return plan;
17
19 {
20 for (int square = 0; square < static_cast<int>(rules::SquareCount); ++square)
21 {
22 const auto bit = layout::propertyBit(square);
23 if (bit != 0 && (set & bit) != 0)
24 {
25 plan.styles[static_cast<std::size_t>(square)] = style;
26 plan.visibleProperties |= bit;
27 }
28 }
29 };
30
31 switch (inputs.mode)
32 {
34 if (inputs.selectedDeed && *inputs.selectedDeed < rules::SquareCount)
35 {
36 const int square = *inputs.selectedDeed;
37 const auto bit = layout::propertyBit(square);
38 if (bit != 0)
39 {
40 plan.styles[static_cast<std::size_t>(square)] =
41 state.squares[static_cast<std::size_t>(square)].mortgaged
44 plan.visibleProperties = bit;
45 }
46 }
47 return plan;
48
49 case RuleMode::Build:
51 return plan;
52
53 case RuleMode::Sell:
56 return plan;
57
60 return plan;
61
63 {
64 auto set = inputs.unmortgageProperties;
65 if (inputs.projectedMode == RuleMode::FreeUnmortgage)
66 set &= ~inputs.freeUnmortgageProperties;
68 return plan;
69 }
70
72 applySet(inputs.freeUnmortgageProperties, PropertyTitleStyle::Mortgaged);
73 return plan;
74
77 applySet(inputs.placeBuildingProperties, PropertyTitleStyle::FullColour);
78 return plan;
79
80 default:
81 break;
82 }
83
84 for (int square = 0; square < static_cast<int>(rules::SquareCount); ++square)
85 {
86 const auto bit = layout::propertyBit(square);
87 if (bit == 0) continue;
88
89 const auto& property = state.squares[static_cast<std::size_t>(square)];
90 const bool fullColour =
91 (inputs.player < rules::MaxPlayers && property.owner == inputs.player) ||
92 (inputs.player == rules::BankPlayer && property.owner == rules::NobodyPlayer);
93
94 plan.styles[static_cast<std::size_t>(square)] = fullColour
95 ? (property.mortgaged ? PropertyTitleStyle::Mortgaged
98 plan.visibleProperties |= bit;
99 }
100
101 return plan;
102 }
103
104
106 int square, PropertyTitleStyle style) noexcept
107 {
108 const int index = layout::propertyIndex(square);
110 return data::EmptyDataId;
111
113 switch (style)
114 {
117 break;
120 break;
123 break;
124 default:
125 return data::EmptyDataId;
126 }
127
128 return data::packDataId(
130 static_cast<data::DataTag>(base + index));
131 }
132
133
134 std::expected<void, std::string> PropertyTitlePlayback::sync(
135 const PropertyTitlePlan& plan,
137 {
138 std::array<data::DataId, rules::SquareCount> desired{};
139 std::array<std::uint16_t, rules::SquareCount> desiredPriorities{};
140 std::array<std::shared_ptr<const sequence::SequenceProgram>, rules::SquareCount> programs{};
141 std::size_t requiredCommands = 0;
142
143 for (int square = 0; square < static_cast<int>(rules::SquareCount); ++square)
144 {
145 const auto index = static_cast<std::size_t>(square);
146 desired[index] = propertyTitleDataId(square, plan.styles[index]);
147 const int order = layout::propertyBarOrder(square);
148 desiredPriorities[index] = order < 0
150 : static_cast<std::uint16_t>(PropertyBasePriority + order % 3);
151
152 if (desired[index] == current_[index]) continue;
153 if (current_[index] != data::EmptyDataId) ++requiredCommands;
155 {
156 requiredCommands += 2;
158 playback.resources(), desired[index]);
159 if (!loaded)
160 return std::unexpected(loaded.error().detail);
161 programs[index] = std::move(*loaded);
162 }
163 }
164
166 playback.commands().pendingCount() >
168 {
169 return std::unexpected(
170 "sequence command queue cannot fit IBar property title transition");
171 }
172
173 std::vector<sequence::SequenceCommand> commands;
174 commands.reserve(requiredCommands);
175 for (int square = 0; square < static_cast<int>(rules::SquareCount); ++square)
176 {
177 const auto index = static_cast<std::size_t>(square);
178 if (desired[index] == current_[index]) continue;
179
180 if (current_[index] != data::EmptyDataId)
181 {
182 commands.push_back(sequence::StopSequenceCommand{
183 current_[index], priorities_[index], false});
184 }
185
187 {
188 commands.push_back(sequence::StartSequenceCommand{
190 const auto rect = layout::propertyRect(square);
191 commands.push_back(sequence::makeMoveXY(
193 }
194 }
195
196 for (auto& command : commands)
197 {
198 const auto queued = std::visit(
199 [&](auto value)
200 {
201 return playback.commands().enqueue(std::move(value));
202 },
203 std::move(command));
204 if (!queued)
205 return std::unexpected(
206 "validated IBar property title command rejected");
207 }
208
209 current_ = desired;
210 priorities_ = desiredPriorities;
211 return {};
212 }
213
214
216 int square, bool mortgaged) noexcept
217 {
218 const int index = layout::propertyIndex(square);
219 if (index < 0)
220 return data::EmptyDataId;
221
222 const auto base = mortgaged
225 return data::packDataId(
227 static_cast<data::DataTag>(base + index));
228 }
229
230
231 std::expected<void, std::string> BuyAuctionPopupPlayback::sync(
232 std::optional<std::uint8_t> desiredSquare,
236 {
239 desired = playback.deedDataId(*desiredSquare, true,
241
242 if (desired == currentDeed_)
243 return {};
244
245 bool nextOnLeft = true;
246 std::int32_t x = BuyAuctionPopupXRight;
248 {
249 if (view == display::Screen2D::Trade ||
251 {
253 nextOnLeft = false;
254 }
255 else if (((currentPlayerSquare % 10) % 3) != 0)
256 {
258 nextOnLeft = true;
259 }
260 else
261 {
263 nextOnLeft = false;
264 }
265 }
266
267 std::shared_ptr<const sequence::SequenceProgram> program;
269 {
270 auto loaded = playback.loadProgram(desired);
271 if (!loaded)
272 return std::unexpected(loaded.error());
273 program = std::move(*loaded);
274 }
275
276 std::vector<sequence::SequenceCommand> commands;
277 if (currentDeed_ != data::EmptyDataId)
278 {
279 commands.push_back(sequence::StopSequenceCommand{
280 currentDeed_, BuyAuctionPopupPriority, false});
281 }
283 {
284 commands.push_back(sequence::StartSequenceCommand{
285 std::move(program), BuyAuctionPopupPriority, {}});
286 commands.push_back(sequence::makeMoveXY(
288 }
289
290 if (commands.size() >
291 sequence::SequenceCommandQueue::Capacity - playback.commands().pendingCount())
292 {
293 return std::unexpected(
294 "sequence command queue cannot fit IBar Buy/Auction popup transition");
295 }
296
297 for (auto& command : commands)
298 {
299 const auto queued = std::visit(
300 [&](auto value)
301 {
302 return playback.commands().enqueue(std::move(value));
303 },
304 std::move(command));
305 if (!queued)
306 return std::unexpected(
307 "validated IBar Buy/Auction popup command rejected");
308 }
309
310 currentDeed_ = desired;
311 onLeft_ = nextOnLeft;
312 return {};
313 }
314
315
317 {
318 currentDeed_ = data::EmptyDataId;
319 onLeft_ = true;
320 }
321
322
323 std::expected<void, std::string> PropertyHoverPlayback::sync(
324 const rules::GameState& state,
327 std::uint64_t tick,
329 {
330 int nextCheckedSquare = checkedSquare_;
331 std::uint64_t nextHoverStartTick = hoverStartTick_;
333
334 const bool validHover =
335 currentMouseOver >= 0 &&
338 (titles.visibleProperties & layout::propertyBit(currentMouseOver)) != 0;
339
340 if (!validHover)
341 {
343 }
344 else if (currentMouseOver == checkedSquare_)
345 {
346 if (tick - hoverStartTick_ > PropertyHoverDelayTicks)
347 {
348 const auto index = static_cast<std::size_t>(currentMouseOver);
349 const auto style = titles.styles[index];
352 {
353 desired = playback.deedDataId(currentMouseOver,
354 !state.squares[index].mortgaged, propertyHoverDataId(
355 currentMouseOver, state.squares[index].mortgaged));
356 }
357 }
358 }
359 else
360 {
361 if (checkedSquare_ == -1)
362 nextHoverStartTick = tick;
364 }
365
366 if (desired == currentDeed_)
367 {
368 checkedSquare_ = nextCheckedSquare;
369 hoverStartTick_ = nextHoverStartTick;
370 return {};
371 }
372
373 std::shared_ptr<const sequence::SequenceProgram> program;
375 {
376 auto loaded = playback.loadProgram(desired);
377 if (!loaded)
378 return std::unexpected(loaded.error());
379 program = std::move(*loaded);
380 }
381
382 std::vector<sequence::SequenceCommand> commands;
383 if (currentDeed_ != data::EmptyDataId)
384 {
385 commands.push_back(sequence::StopSequenceCommand{
386 currentDeed_, PropertyHoverPriority, false});
387 }
389 {
390 commands.push_back(sequence::StartSequenceCommand{
391 std::move(program), PropertyHoverPriority, {}});
392 commands.push_back(sequence::makeMoveXY(
394 }
395
396 if (commands.size() >
397 sequence::SequenceCommandQueue::Capacity - playback.commands().pendingCount())
398 {
399 return std::unexpected(
400 "sequence command queue cannot fit IBar property hover transition");
401 }
402
403 for (auto& command : commands)
404 {
405 const auto queued = std::visit(
406 [&](auto value)
407 {
408 return playback.commands().enqueue(std::move(value));
409 },
410 std::move(command));
411 if (!queued)
412 return std::unexpected(
413 "validated IBar property hover command rejected");
414 }
415
416 checkedSquare_ = nextCheckedSquare;
417 hoverStartTick_ = nextHoverStartTick;
418 currentDeed_ = desired;
419 return {};
420 }
421
422
424 {
425 checkedSquare_ = -1;
426 hoverStartTick_ = 0;
427 currentDeed_ = data::EmptyDataId;
428 }
429
430
432 {
433 current_.fill(data::EmptyDataId);
434 priorities_.fill(PropertyBasePriority);
435 }
436}
decision::EconomicActionPlan plan
unsigned index
unsigned style
Rect rect
std::uint16_t value
Definition Timers.cpp:16
std::expected< void, std::string > sync(std::optional< std::uint8_t > desiredSquare, display::Screen2D view, int currentPlayerSquare, engine::SequencePlayback &playback)
std::expected< void, std::string > sync(const rules::GameState &state, const PropertyTitlePlan &titles, int currentMouseOver, std::uint64_t tick, engine::SequencePlayback &playback)
std::expected< void, std::string > sync(const PropertyTitlePlan &plan, engine::SequencePlayback &playback)
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::uint32_t DataId
Definition DataBanks.hpp:10
constexpr DataId EmptyDataId
Definition DataBanks.hpp:13
std::uint16_t DataTag
Definition DataBanks.hpp:11
constexpr DataId packDataId(std::uint16_t group, DataTag tag) noexcept
Definition DataBanks.hpp:39
constexpr bool isBoardVisible(Screen2D screen) noexcept
Definition Display.hpp:41
int propertyIndex(int square) noexcept
std::uint32_t PropertyMask
Rect propertyRect(int square) noexcept
PropertyMask propertyBit(int square) noexcept
int propertyBarOrder(int square) noexcept
constexpr std::uint16_t BuyAuctionPopupPriority
constexpr data::DataTag PropertyFullColourBaseTag
constexpr std::int32_t PropertyHoverX
constexpr data::DataTag PropertyMortgagedBaseTag
constexpr std::uint64_t PropertyHoverDelayTicks
data::DataId propertyTitleDataId(int square, PropertyTitleStyle style) noexcept
data::DataId propertyHoverDataId(int square, bool mortgaged) noexcept
PropertyTitlePlan planPropertyTitles(const rules::GameState &state, const PropertyTitleInputs &inputs) noexcept
constexpr std::int32_t BuyAuctionPopupXLeft
constexpr std::uint16_t PropertyBasePriority
constexpr data::DataTag PropertyLowColourBaseTag
constexpr std::int32_t BuyAuctionPopupXRight
constexpr data::DataTag PropertyHoverNormalBaseTag
State & state()
Definition IBar.cpp:1285
constexpr std::int32_t BuyAuctionPopupY
constexpr std::uint16_t PropertyHoverPriority
constexpr std::int32_t BuyAuctionPopupXTrade
constexpr std::int32_t PropertyHoverY
constexpr data::DataTag PropertyHoverMortgagedBaseTag
constexpr PlayerNumber BankPlayer
Definition RuleTypes.hpp:15
constexpr std::size_t SquareCount
Definition RuleTypes.hpp:24
constexpr PlayerNumber MaxPlayers
Definition RuleTypes.hpp:14
constexpr PlayerNumber NobodyPlayer
Definition RuleTypes.hpp:16
MoveSequenceCommand makeMoveXY(data::DataId dataId, std::uint16_t priority, std::int32_t x, std::int32_t y) noexcept