Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
RuleAuction.cpp
Go to the documentation of this file.
1#include "RuleAuction.hpp"
2
3#include "BoardRules.hpp"
4#include "LegacyTextIds.hpp"
5#include "Messaging.hpp"
6#include "PhaseStack.hpp"
7#include "RuleRejections.hpp"
8#include "RuleBuildings.hpp"
9#include "RuleEconomy.hpp"
11
12#include <cstddef>
13#include <cstdint>
14
16{
17 namespace
18 {
19 constexpr std::uint8_t AuctionHouse = 40;
20 constexpr std::uint8_t AuctionHotel = 41;
21 constexpr std::uint8_t OffBoardSquare = 41;
22
23
24 void sendRestart()
25 {
30 );
31 }
32
33
34 void popAndRestart(
36 {
39 }
40
41
43 const actions::Message& message,
44 bool success)
45 {
48 NotifyActionCompleted,
51 static_cast<std::int64_t>(
52 message.action
53 ),
54 success ? 1 : 0,
55 message.fromPlayer
56 );
57 }
58
59
61 actions::Type action,
62 std::int64_t a,
63 std::int64_t b,
64 std::int64_t c,
65 std::int64_t d,
66 std::int64_t e)
67 {
68 actions::Message message{};
69
70 message.action = action;
71 message.fromPlayer = BankPlayer;
72 message.toPlayer = AllPlayers;
73
74 message.numberA = a;
75 message.numberB = b;
76 message.numberC = c;
77 message.numberD = d;
78 message.numberE = e;
79
80 messaging::sendAction(message);
81 }
82
83
84 buildings::PlayerSet playersAllowedToBid(
85 const GameState& state)
86 {
87 if (
89 state.phaseStack[0].phase !=
91 {
92 return 0;
93 }
94
95
96 if (
99 {
100 return
102 state,
106 );
107 }
108
109
111
112
113 for (PlayerNumber player = 0;
114 player < state.numberOfPlayers;
115 ++player)
116 {
117 if (
119 player
120 ].currentSquare <
121 OffBoardSquare)
122 {
123 allowed |=
124 (1u << player);
125 }
126 }
127
128
129 return allowed;
130 }
131
132
135 {
136 // Les deux hacks présents dans Rule.cpp
137 // sont désactivés dans ce build original.
138
141
143 static_cast<std::uint8_t>(
145 state
146 ).amount
147 );
148
151
153
154 // InitialiseAuctionDataAndRestart():
155 // IgnoreWaitForEverybodyReady = FALSE.
157
158
159 // WaitForEverybodyReady() est un mécanisme
160 // réseau. MESS est encore local uniquement,
161 // donc aucun faux handshake n'est injecté.
162
163 sendRestart();
164 }
165
166
167 void finishAuction(
169 {
170 const PlayerNumber winner =
172
173 const std::uint8_t item =
176
177 const std::int64_t price =
179
180
181 if (winner < MaxPlayers)
182 {
183 // ------------------------------------------------
184 // Propriété.
185 // ------------------------------------------------
186
187 if (item < AuctionHouse)
188 {
191 state,
192 item,
193 winner
194 );
195
196
198 state,
199 GamePhase::
201 0,
202 winner,
204 static_cast<
206 >(item)
207 )
208 );
209
210
212 state,
213 winner,
215 price
216 );
217
218
219 return;
220 }
221
222
223 // ------------------------------------------------
224 // Maison / hôtel.
225 //
226 // Le bâtiment est déjà retiré du stock
227 // logique pendant GF_PLACE_BUILDING :
228 // on demande d'abord où le placer, puis
229 // la dette d'enchère reste dessous.
230 // ------------------------------------------------
231
233
234
236 state,
237 winner,
239 price
240 );
241
242
244 state,
246 winner,
248 item == AuctionHotel
249 ? 1
250 : -1
251 );
252
253
254 sendRestart();
255
256 return;
257 }
258
259
260 // ----------------------------------------------------
261 // Personne n'a enchéri.
262 // ----------------------------------------------------
263
264 if (item < AuctionHouse)
265 {
266 SquareState& square =
267 state.squares[item];
268
269
270 const PlayerNumber oldOwner =
271 square.owner;
272
273
274 square.owner =
276
277 square.offeredInTradeTo =
279
280
283 NotifySquareOwnership,
286 item,
289 );
290 }
291
292
294 }
295
296
297 void tickAuction(
299 {
301
302
303 if (
306 {
307 return;
308 }
309
310
311 // Original :
312 // attend aussi que la queue soit vide.
313 if (
315 {
316 return;
317 }
318
319
321
323
324
332 0
333 );
334
335 if (
337 state,
339 NotifyAuctionGoing
340 ))
341 {
342 return;
343 }
344
345// WaitForEverybodyReady après "going once"
346 // est volontairement différé au port réseau.
347
348
349 if (
351 {
353 }
354 }
355
356
359 {
360 // ActionTick() original :
361 // synchroniser tout le monde AVANT de lancer
362 // le compte à rebours de pénurie.
363
364 if (
365 state.auction.tickCount == 0 &&
366 state.auction.goingCount == 0 &&
368 state,
370 NotifyHousingShortage
371 ))
372 {
373 return;
374 }
375
376
378
379
380 if (
383 {
384 return;
385 }
386
387
389
391
392
393 const PendingPhase shortage =
395
396
398 shortage.fromPlayer;
399
400
401 const std::uint8_t squareNo =
402 shortage.toPlayer;
403
404
405 const bool hotel =
406 shortage.amount > 0;
407
408
411 state,
412 hotel
413 );
414
415
416 // Source :
417 // s'il n'y a qu'un joueur capable d'acheter,
418 // inutile d'attendre plus longtemps.
419 if (
420 allowed ==
421 (1u << originalBuyer))
422 {
424 }
425
426
429 NotifyHousingShortage,
431 squareNo,
432 shortage.amount,
434 allowed
435 );
436
437
438 if (
440 {
441 return;
442 }
443
444
445 // Personne d'autre n'a demandé d'enchère :
446 // vente normale au demandeur initial.
447
448 const std::int64_t price =
450 static_cast<board::SquareType>(
452 )
454
455
457 state,
460 price,
461 true
462 );
463
464
466 state,
468 );
469
470
477 price,
479 );
480
481
483 }
484 }
485
486
489 const actions::Message& message)
490 {
491 if (
493 state
494 ).phase !=
496 {
498
499 return;
500 }
501
502
503 const PlayerNumber player =
504 message.fromPlayer;
505
506
507 if (
508 player >=
510 {
512
513 return;
514 }
515
516
518 playersAllowedToBid(
519 state
520 );
521
522
523 if (
524 (
525 allowed &
526 (1u << player)
527 ) == 0)
528 {
530
531 return;
532 }
533
534
535 // Le source confirme l'action même si l'offre
536 // n'est pas supérieure à l'offre actuelle.
538 message,
539 true
540 );
541
542
543 if (
544 message.numberA <=
546 {
547 return;
548 }
549
550
552 player;
553
555 message.numberA;
556
559
560
567 0,
568 allowed
569 );
570 }
571
572
575 const actions::Message& message)
576 {
577 if (
579 state
580 ).phase !=
581 GamePhase::
583 {
585
586 return;
587 }
588
589
590 const PendingPhase shortage =
592
593
594 const PlayerNumber player =
595 message.fromPlayer;
596
597
598 if (
599 player ==
600 shortage.fromPlayer)
601 {
603 message,
604 false
605 );
606
607
612 legacy_text::
613 ErrorBuildingAlreadyBuying,
614 0,
615 player,
616 shortage.toPlayer
617 );
618
619
620 return;
621 }
622
623
624 const bool hotel =
625 shortage.amount > 0;
626
627
630 state,
631 hotel
632 );
633
634
635 if (
636 player >= MaxPlayers ||
637 (
638 allowed &
639 (1u << player)
640 ) == 0)
641 {
643
644 return;
645 }
646
647
649 message,
650 true
651 );
652
653
655 state,
657 0,
658 0,
659 hotel
662 );
663
664
666 state
667 );
668 }
669
670
673 {
674 const PendingPhase phase =
676
677
678 switch (phase.phase)
679 {
681 {
684 NotifyNewHighBid,
689 0,
690 playersAllowedToBid(
691 state
692 )
693 );
694
695 if (
697 state,
699 NotifyNewHighBid
700 ))
701 {
702 return true;
703 }
704
705
706 return true;
707 }
708
709
710 case GamePhase::
712 {
715
716
719 NotifyHousingShortage,
720 phase.fromPlayer,
721 phase.toPlayer,
722 phase.amount,
723 0,
726 state,
727 phase.amount > 0
728 )
729 );
730
731
732 return true;
733 }
734
735
736 default:
737 return false;
738 }
739 }
740
741
744 {
745 if (
747 {
748 return;
749 }
750
751
752 switch (
754 state
755 ).phase)
756 {
759 break;
760
761
762 case GamePhase::
765 break;
766
767
768 default:
769 break;
770 }
771 }
772
773
776 {
777 // RULE_PropertySetOwnedByPlayer(BANK)
778 // puis RULE_BitSetToProperty(), qui prend
779 // la première propriété dans l'ordre des cases.
780
781 for (std::size_t squareNo = 0;
782 squareNo <= 39;
783 ++squareNo)
784 {
785 if (
788 ].owner != BankPlayer)
789 {
790 continue;
791 }
792
793
794 if (
796 static_cast<board::SquareType>(
798 )
799 ))
800 {
801 continue;
802 }
803
804
806 state,
808 0,
809 0,
811 );
812
813
815 state
816 );
817
818
819 return true;
820 }
821
822
823 return false;
824 }
825}
826
827
unsigned index
constexpr std::int64_t ErrorBuildingBought
std::size_t currentQueueSize()
bool sendAction(const actions::Message &message)
void actionBid(GameState &state, const actions::Message &message)
void actionStartHousingAuction(GameState &state, const actions::Message &message)
void onIdleTick(GameState &state)
bool restartAuctionPhase(GameState &state)
bool startPendingBankPropertyAuction(GameState &state)
const SquareDefinition & definition(SquareType square)
bool isOwnable(SquareType square)
PropertySet propertyBit(SquareType square)
PlayerSet playersWhoCanBuyBuilding(const GameState &state, bool hotel)
void buildApprovedBuilding(GameState &state, std::uint8_t squareNo)
void blindlyTransferCash(GameState &state, PlayerNumber fromPlayer, PlayerNumber toPlayer, std::int64_t amount, bool sendAnimation)
void stackDebt(GameState &state, PlayerNumber fromPlayer, PlayerNumber toPlayer, std::int64_t amount)
void stackDebtAndRestart(GameState &state, PlayerNumber fromPlayer, PlayerNumber toPlayer, std::int64_t amount)
void transferPropertyForSettlement(GameState &state, std::uint8_t squareNo, PlayerNumber toPlayer)
bool pop(GameState &state)
const PendingPhase & current(const GameState &state)
bool push(GameState &state, GamePhase phase, PlayerNumber fromPlayer, PlayerNumber toPlayer, std::int64_t amount)
void switchTo(GameState &state, GamePhase phase, PlayerNumber fromPlayer, PlayerNumber toPlayer, std::int64_t amount)
void wrongPlayer(const GameState &state, const actions::Message &message)
void wrongPhase(const GameState &state, const actions::Message &message)
bool beginWaitOnce(GameState &state, actions::Type hint)
constexpr PlayerNumber BankPlayer
Definition RuleTypes.hpp:15
std::uint8_t PlayerNumber
Definition RuleTypes.hpp:12
const GameState & state()
constexpr PlayerNumber MaxPlayers
Definition RuleTypes.hpp:14
constexpr PlayerNumber NobodyPlayer
Definition RuleTypes.hpp:16
constexpr PlayerNumber AllPlayers
Definition RuleTypes.hpp:17
rules::PlayerNumber toPlayer
Definition Actions.hpp:131
rules::PlayerNumber fromPlayer
Definition Actions.hpp:128
std::array< SquareState, SquareCount > squares
std::array< PendingPhase, MaxPendingPhases > phaseStack
std::uint8_t numberOfPendingPhases
std::array< PlayerState, MaxPlayers > players