Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
BoardOwnershipHighlight.cpp
Go to the documentation of this file.
2
3#include "BoardGeometry.hpp"
4#include "BoardRules.hpp"
5#include "LegacyBitmap.hpp"
6
7#include <cmath>
8#include <numbers>
9#include <vector>
10
12{
13 int ownershipPropertyIndex(int square) noexcept
14 {
15 if (square < 0 || square >= static_cast<int>(rules::SquareCount))
16 return -1;
17 const auto type = static_cast<rules::board::SquareType>(square);
18 if (!rules::board::isOwnable(type)) return -1;
19 int result = 0;
20 for (int test = 0; test < square; ++test)
22 static_cast<rules::board::SquareType>(test)))
23 ++result;
24 return result;
25 }
26
28 {
29 constexpr int JustVisiting =
31 constexpr int FreeParking =
33 constexpr int GoToJail =
34 static_cast<int>(rules::board::SquareType::GoToJail);
35 constexpr int InJail =
36 static_cast<int>(rules::board::SquareType::InJail);
37 int tile = square == InJail ? JustVisiting : square;
38 if (tile < 0 || tile >= static_cast<int>(rules::SquareCount))
39 return sequence::identity3D();
40
41 const auto& point = boardgeometry::locations3D()[
42 static_cast<std::size_t>(tile)];
43 constexpr float horizontal = -19.0F;
44 constexpr float vertical = -8.0F;
45 float x{};
46 float z{};
47 float yaw{};
48 if (tile < JustVisiting)
49 {
50 x = point.x + vertical; z = point.z + horizontal; yaw = 0.0F;
51 }
52 else if (tile < FreeParking)
53 {
54 x = point.x + horizontal; z = point.z - vertical;
55 yaw = std::numbers::pi_v<float> / 2.0F;
56 }
57 else if (tile < GoToJail)
58 {
59 x = point.x - vertical; z = point.z - horizontal;
60 yaw = std::numbers::pi_v<float>;
61 }
62 else
63 {
64 x = point.x - horizontal; z = point.z + vertical;
65 yaw = -std::numbers::pi_v<float> / 2.0F;
66 }
69 }
70
71 std::expected<OwnershipHighlightPlan, std::string> planOwnershipHighlights(
73 bool board3DOn, pieces::BoardCameraView camera)
74 {
76 if (!display::isBoardVisible(view)) return result;
77
78 const bool use3D = board3DOn || view == display::Screen2D::Portfolio ||
80 const auto cameraIndex = static_cast<std::uint32_t>(camera);
81 if (!use3D && cameraIndex >=
82 static_cast<std::uint32_t>(pieces::BoardCameraView::Count))
83 return std::unexpected("ownership highlight camera is outside legacy 0..38 range");
84
85 for (std::size_t square = 0; square < rules::SquareCount; ++square)
86 {
87 const auto owner = state.squares[square].owner;
88 if (owner >= rules::MaxPlayers) continue;
89 const auto colour = state.players[owner].colour;
91 return std::unexpected("ownership highlight player colour is outside legacy 0..5 range");
92 const auto priority = static_cast<std::uint16_t>(
93 OwnershipPriorityBase + square);
94 const bool mortgaged = state.squares[square].mortgaged;
95
96 if (use3D)
97 {
98 const auto base = mortgaged
100 result[square] = OwnershipHighlight{
102 static_cast<data::DataTag>(base + colour)),
104 ownershipHighlight3DTransform(static_cast<int>(square))};
105 continue;
106 }
107
108 const int property = ownershipPropertyIndex(static_cast<int>(square));
109 if (property < 0)
110 return std::unexpected(
111 "2D ownership highlight encountered an owned non-ownable square");
112 const std::uint32_t offset = cameraIndex * Ownership2DPerCamera +
113 static_cast<std::uint32_t>(property) * OwnershipColours + colour;
114 const auto base = mortgaged
116 const auto tag = static_cast<std::uint32_t>(base) + offset;
117 if (tag > 0xFFFFU)
118 return std::unexpected("2D ownership highlight tag overflows DataTag");
119 result[square] = OwnershipHighlight{
121 data::LegacyGroupId::Board, static_cast<data::DataTag>(tag)),
123 }
124 return result;
125 }
126
127 std::expected<void, std::string> OwnershipHighlightPlayback::sync(
129 {
130 std::array<std::shared_ptr<const sequence::SequenceProgram>, rules::SquareCount> programs{};
131 std::array<sequence::SequenceTransform, rules::SquareCount> transforms{};
132 std::size_t requiredCommands{};
133
134 for (std::size_t square = 0; square < plan.size(); ++square)
135 {
136 const auto desired = plan[square] ? plan[square]->sequence : data::EmptyDataId;
137 if (desired == current_[square]) continue;
138 if (current_[square] != data::EmptyDataId) ++requiredCommands;
139 if (!plan[square]) continue;
140 requiredCommands += 2;
142 if (!loaded) return std::unexpected(loaded.error().detail);
143 programs[square] = std::move(*loaded);
144
146 {
147 transforms[square] = plan[square]->transform3D;
148 }
149 else
150 {
151 const auto bytes = playback.resources()->data().load(desired);
152 if (!bytes) return std::unexpected(bytes.error().detail);
153 const auto metadata = data::inspectLegacyUap(**bytes);
154 if (!metadata) return std::unexpected(metadata.error().detail);
156 metadata->originX, metadata->originY);
157 }
158 }
159
162 playback.commands().pendingCount())
163 return std::unexpected(
164 "sequence command queue cannot fit board ownership transition");
165
166 for (std::size_t square = 0; square < plan.size(); ++square)
167 {
168 const auto desired = plan[square] ? plan[square]->sequence : data::EmptyDataId;
169 if (desired == current_[square]) continue;
170 const auto priority = static_cast<std::uint16_t>(OwnershipPriorityBase + square);
171 if (current_[square] != data::EmptyDataId)
172 (void)playback.commands().enqueue(sequence::StopSequenceCommand{
173 current_[square], priority, false});
174 if (plan[square])
175 {
176 (void)playback.commands().enqueue(sequence::StartSequenceCommand{
177 programs[square], priority, {}});
178 (void)playback.commands().enqueue(sequence::makeMoveTheWorks(
179 desired, priority, transforms[square]));
180 }
181 }
182
183 for (std::size_t square = 0; square < plan.size(); ++square)
184 current_[square] = plan[square] ? plan[square]->sequence : data::EmptyDataId;
185 return {};
186 }
187
189 {
190 current_.fill(data::EmptyDataId);
191 }
192}
decision::EconomicActionPlan plan
std::size_t offset
LegacyBitmapMetadata metadata
std::vector< std::byte > bytes
std::uint16_t priority
unsigned state
unsigned index
int colour
Kind kind
float yaw
int z
std::expected< void, std::string > sync(const OwnershipHighlightPlan &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={})
constexpr data::DataTag Ownership3DMortgagedBaseTag
constexpr std::uint16_t OwnershipPriorityBase
int ownershipPropertyIndex(int square) noexcept
constexpr data::DataTag Ownership2DNormalBaseTag
constexpr std::uint32_t Ownership2DPerCamera
sequence::Matrix3D ownershipHighlight3DTransform(int square) noexcept
std::expected< OwnershipHighlightPlan, std::string > planOwnershipHighlights(const rules::GameState &state, display::Screen2D view, bool board3DOn, pieces::BoardCameraView camera)
std::array< std::optional< OwnershipHighlight >, rules::SquareCount > OwnershipHighlightPlan
constexpr data::DataTag Ownership2DMortgagedBaseTag
constexpr std::uint32_t OwnershipColours
constexpr data::DataTag Ownership3DNormalBaseTag
const std::array< Point3D, 42 > & locations3D()
constexpr DataId EmptyDataId
Definition DataBanks.hpp:13
std::uint16_t DataTag
Definition DataBanks.hpp:11
std::expected< LegacyUapMetadata, BitmapError > inspectLegacyUap(std::span< const std::byte > bytes)
constexpr DataId packDataId(std::uint16_t group, DataTag tag) noexcept
Definition DataBanks.hpp:39
constexpr bool isBoardVisible(Screen2D screen) noexcept
Definition Display.hpp:41
bool isOwnable(SquareType square)
constexpr std::size_t SquareCount
Definition RuleTypes.hpp:24
constexpr PlayerNumber MaxPlayers
Definition RuleTypes.hpp:14
MoveSequenceCommand makeMoveTheWorks(data::DataId dataId, std::uint16_t priority, SequenceTransform transform, bool wholeTree) noexcept
Matrix3D moveRySTxzTransform(float yaw, float scale, float x, float z) noexcept
Matrix3D identity3D() noexcept
SequenceTransform moveXYTransform(std::int32_t x, std::int32_t y) noexcept