Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
RuleStartingOrder.cpp
Go to the documentation of this file.
2
3#include "LegacyTextIds.hpp"
4#include "Messaging.hpp"
5#include "PhaseStack.hpp"
6#include "RuleGameStart.hpp"
7
8#include <array>
9#include <cstddef>
10#include <cstdint>
11#include <utility>
12
14{
15 namespace
16 {
17 using PlayerSet = std::uint32_t;
18
19 constexpr std::uint8_t OffBoardSquare = 41;
20
21
23 const GameState& state)
24 {
25 for (PlayerNumber playerNo = 0;
27 ++playerNo)
28 {
29 const PlayerState& player =
31
32
38 player.token,
39 player.colour,
40 player.aiPlayerLevel,
41 player.name
42 );
43 }
44 }
45
46
49 {
50 // SortPlayersByRollHistory() original.
51
52 struct Order
53 {
54 PlayerNumber player = 0;
55 std::uint32_t rollHistory = 0;
56 };
57
58
59 std::array<Order, MaxPlayers>
61
62
63 std::array<PlayerState, MaxPlayers>
65 std::array<std::uint32_t, MaxPlayers> originalOwners{};
66
67
68 for (PlayerNumber playerNo = 0;
70 ++playerNo)
71 {
72 newPlayerOrder[playerNo].player =
74
75 newPlayerOrder[playerNo].rollHistory =
78 ].diceRollHistory;
79 }
80
81
82 // Bubble sort décroissant.
83 //
84 // Le test est strictement "<", ce qui conserve
85 // l'ordre existant en cas d'égalité résiduelle.
86
87 for (
88 int playerNo =
89 static_cast<int>(
91 ) - 1;
92
93 playerNo >= 1;
94
95 --playerNo)
96 {
97 for (
98 int otherNo = 0;
99
101
102 ++otherNo)
103 {
104 if (
106 otherNo
107 ].rollHistory <
109 otherNo + 1
110 ].rollHistory)
111 {
112 std::swap(
114 otherNo
115 ],
117 otherNo + 1
118 ]
119 );
120 }
121 }
122 }
123
124
125 for (PlayerNumber playerNo = 0;
127 ++playerNo)
128 {
132 }
133
134
135 for (PlayerNumber playerNo = 0;
137 ++playerNo)
138 {
143 ].player
144 ];
147 }
148
149
150 // Player records and their connection owners move together.
151
153 }
154 }
155
156
159 std::uint8_t dieA,
160 std::uint8_t dieB)
161 {
162 // Branche GF_PICKING_STARTING_ORDER
163 // de ActionRollDice().
164
165 if (
171 {
172 return;
173 }
174
175
176 state.dice[0] = dieA;
177 state.dice[1] = dieB;
178
179
180 const std::uint32_t total =
181 static_cast<std::uint32_t>(
182 dieA + dieB
183 );
184
185
186 std::uint32_t shiftValue =
189 ].diceRollHistory;
190
191
192 int i = 0;
193
194
195 // Exactement l'encodage 32 bits original :
196 //
197 // premier lancer dans le nibble le plus haut,
198 // puis les éventuels tie-breaks vers le bas.
199
200 while (
201 (shiftValue & 0xFu) == 0 &&
202 i < 32)
203 {
204 i += 4;
205 shiftValue >>= 4;
206 }
207
208
209 if (i >= 4)
210 {
213 ].diceRollHistory |=
214 (
215 total <<
216 (i - 4)
217 );
218 }
219
220
221 // Ce joueur a répondu au roll-off courant.
222
223 const std::uint32_t bit =
224 1u << state.currentPlayer;
225
226
227 state.phaseStack[0].fromPlayer =
228 static_cast<PlayerNumber>(
229 static_cast<std::uint32_t>(
230 state.phaseStack[0].fromPlayer
231 ) &
232 ~bit
233 );
234
235
240 );
241 }
242
243
246 {
247 // AskForStartingOrderDiceRolls() original.
248
249 if (
253 {
254 return;
255 }
256
257
258 // ----------------------------------------------------
259 // Un roll-off est déjà en cours :
260 // demander le prochain joueur du set.
261 // ----------------------------------------------------
262
263 if (
264 state.phaseStack[0].fromPlayer != 0)
265 {
266 const std::uint32_t waitingSet =
267 state.phaseStack[0].fromPlayer;
268
269
270 for (PlayerNumber playerNo = 0;
272 ++playerNo)
273 {
274 if (
275 (
276 waitingSet &
277 (1u << playerNo)
278 ) == 0)
279 {
280 continue;
281 }
282
283
285 playerNo;
286
287
293 OffBoardSquare
294 );
295
296
297 return;
298 }
299 }
300
301
302 // ----------------------------------------------------
303 // Chercher une égalité.
304 // ----------------------------------------------------
305
306 for (PlayerNumber playerNo = 0;
308 ++playerNo)
309 {
310 const std::uint32_t tieDieValue =
313 ].diceRollHistory;
314
315
316 int numberOfTiedPlayers = 0;
317
318 PlayerSet tiePlayerSet = 0;
319
320
321 for (PlayerNumber otherNo = 0;
323 ++otherNo)
324 {
325 const std::uint32_t dieValue =
327 otherNo
328 ].diceRollHistory;
329
330
331 if (dieValue ==
333 {
335
336 tiePlayerSet |=
337 1u << otherNo;
338 }
339 }
340
341
342 // Si le nibble bas est encore zéro,
343 // il reste de la place pour un nouveau tie-break.
344
345 if (
347 (tieDieValue & 0xFu) == 0)
348 {
349 state.phaseStack[0].fromPlayer =
350 static_cast<PlayerNumber>(
352 );
353
354
355 // Ordre exact de Rule.cpp :
356 // RESTART puis message tie-rolloff.
357
362 );
363
364
371 playerNo,
373 );
374
375
376 return;
377 }
378 }
379
380
381 // ----------------------------------------------------
382 // Ordre définitif.
383 // ----------------------------------------------------
384
386
387
388 // Puis StartGameInitialisation().
390 state
391 );
392 }
393}
unsigned index
constexpr std::int64_t ErrorTieRolloff
std::uint32_t playerOwner(rules::PlayerNumber player)
Definition Messaging.cpp:83
bool sendAction(const actions::Message &message)
void setPlayerOwner(rules::PlayerNumber player, std::uint32_t source)
Definition Messaging.cpp:76
void startGameAfterOrdering(GameState &state)
const PendingPhase & current(const GameState &state)
void recordDiceRoll(GameState &state, std::uint8_t dieA, std::uint8_t dieB)
constexpr PlayerNumber BankPlayer
Definition RuleTypes.hpp:15
std::uint8_t PlayerNumber
Definition RuleTypes.hpp:12
const GameState & state()
constexpr PlayerNumber AllPlayers
Definition RuleTypes.hpp:17
std::array< std::uint8_t, 2 > dice
std::array< PendingPhase, MaxPendingPhases > phaseStack
std::uint8_t numberOfPendingPhases
std::array< PlayerState, MaxPlayers > players