Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
RuleCards.cpp
Go to the documentation of this file.
1#include "RuleCards.hpp"
2
3#include "BoardRules.hpp"
4#include "CardDeckRuntime.hpp"
5#include "LegacyTextIds.hpp"
6#include "Messaging.hpp"
7#include "PhaseStack.hpp"
8#include "RuleRejections.hpp"
9#include "RuleEconomy.hpp"
10
11#include <cstddef>
12#include <cstdint>
13#include <utility>
14
16{
17 namespace { BankPayoutObserver payoutObserver{}; }
19 namespace
20 {
21 constexpr std::uint8_t GoSquare = 0;
22 constexpr std::uint8_t ReadingRailroad = 5;
23 constexpr std::uint8_t StCharlesPlace = 11;
24 constexpr std::uint8_t ElectricCompany = 12;
25 constexpr std::uint8_t PennsylvaniaRailroad = 15;
26 constexpr std::uint8_t IllinoisAvenue = 24;
27 constexpr std::uint8_t BAndORailroad = 25;
28 constexpr std::uint8_t WaterWorks = 28;
29 constexpr std::uint8_t ShortLineRailroad = 35;
30 constexpr std::uint8_t Boardwalk = 39;
31 constexpr std::uint8_t InJail = 40;
32 constexpr std::uint8_t OffBoard = 41;
33
34
35 void sendRestart()
36 {
41 );
42 }
43
44
45 void popAndRestart(
46 GameState& state)
47 {
50 }
51
52
54 const actions::Message& message)
55 {
60 static_cast<std::int64_t>(
61 message.action
62 ),
63 1,
64 message.fromPlayer,
65 0
66 );
67 }
68
69
71 actions::Type type,
72 std::int64_t a,
73 std::int64_t b,
74 std::int64_t c,
75 std::int64_t d,
76 std::int64_t e)
77 {
78 actions::Message message{};
79
80 message.action = type;
81 message.fromPlayer = BankPlayer;
82 message.toPlayer = AllPlayers;
83
84 message.numberA = a;
85 message.numberB = b;
86 message.numberC = c;
87 message.numberD = d;
88 message.numberE = e;
89
90 messaging::sendAction(message);
91 }
92
93
95 const GameState& state,
96 PlayerNumber player,
97 int& houses,
98 int& hotels)
99 {
100 // RULE_CountHousesAndHotels() original.
101
102 houses = 0;
103 hotels = 0;
104
105
106 for (std::size_t squareNo = 0;
108 ++squareNo)
109 {
110 const board::SquareDefinition& predefined =
112 static_cast<board::SquareType>(
114 )
115 );
116
117
118 if (
119 static_cast<std::size_t>(
120 predefined.group
121 ) >=
123 {
124 continue;
125 }
126
127
128 if (
131 ].owner != player)
132 {
133 continue;
134 }
135
136
137 const int buildingCount =
140 ].houses;
141
142
143 if (
146 {
147 houses +=
149 }
150 else
151 {
152 ++hotels;
153 }
154 }
155 }
156
157
159 GameState& state,
160 PlayerNumber fromPlayer,
161 PlayerNumber toPlayer,
163 {
164 // TransferGetOutOfJail() original.
165
166 if (fromPlayer >= MaxPlayers)
167 {
168 fromPlayer =
170 }
171
172
173 if (toPlayer >= MaxPlayers)
174 {
175 toPlayer =
177 }
178
179
180 CardDeck& deck =
181 state.cards[
182 static_cast<std::size_t>(
184 )
185 ];
186
187
188 if (deck.jailOwner !=
189 fromPlayer)
190 {
191 return false;
192 }
193
194
195 // Lorsqu'un joueur rend la carte au paquet,
196 // elle retourne d'abord physiquement en bas.
197
198 if (
199 deck.jailOwner < MaxPlayers &&
200 toPlayer == NobodyPlayer)
201 {
203 state,
207 );
208 }
209
210
211 deck.jailOwner =
212 toPlayer;
213
214 deck.jailOfferedInTradeTo =
216
217
222 deck.jailOwner,
223 static_cast<std::int64_t>(
225 )
226 );
227
228
229 return true;
230 }
231
232
233 void moveForwards(
234 GameState& state,
235 std::uint8_t destination)
236 {
238 state,
240 0,
241 0,
242 0
243 );
244
245
251 );
252 }
253
254
255 void moveBackwards(
256 GameState& state,
257 std::uint8_t destination)
258 {
260 state,
262 0,
263 0,
264 0
265 );
266
267
273 );
274 }
275
276
277 void jumpTo(
278 GameState& state,
279 std::uint8_t destination)
280 {
282 state,
284 0,
285 0,
286 0
287 );
288
289
295 );
296 }
297
298
300 GameState& state,
301 std::int64_t perHouse,
302 std::int64_t perHotel)
303 {
304 int houseCount = 0;
305 int hotelCount = 0;
306
307
309 state,
313 );
314
315
316 const std::int64_t amount =
319
320
321 // End movement before debt activity stacks up.
323
324
326 state,
329 amount
330 );
331
332
334 state,
335 amount
336 );
337
338
339 // MESS_SendAction2() original :
340 //
341 // error id,
342 // amount,
343 // player,
344 // houseCount,
345 // hotelCount
346
350 amount,
354 );
355 }
356
357
359 GameState& state,
360 std::int64_t amountPerPlayer)
361 {
362 // COMMUNITY_GET_50_FROM_EACH_PLAYER.
363 //
364 // L'original parcourt les joueurs EN ARRIÈRE
365 // afin que l'ordre LIFO de phaseStack donne
366 // l'ordre voulu au paiement.
367
368 const PlayerNumber current =
370
371
373
374
376 current;
377
378
379 while (true)
380 {
381 if (other == 0)
382 {
383 other =
384 static_cast<PlayerNumber>(
386 );
387 }
388 else
389 {
390 --other;
391 }
392
393
394 if (other == current)
395 {
396 break;
397 }
398
399
400 if (
402 other
403 ].currentSquare <
404 OffBoard)
405 {
407 state,
408 other,
409 current,
411 );
412 }
413 }
414
415
416 sendRestart();
417 }
418
419
421 GameState& state,
422 std::int64_t amountPerPlayer)
423 {
424 // CHANCE_PAY_50_TO_EACH_PLAYER.
425
426 const PlayerNumber current =
428
429
431
432
434 current;
435
436
437 while (true)
438 {
439 if (other == 0)
440 {
441 other =
442 static_cast<PlayerNumber>(
444 );
445 }
446 else
447 {
448 --other;
449 }
450
451
452 if (other == current)
453 {
454 break;
455 }
456
457
458 if (
460 other
461 ].currentSquare <
462 OffBoard)
463 {
465 state,
466 current,
467 other,
469 );
470 }
471 }
472
473
474 sendRestart();
475 }
476
477
479 const GameState& state)
480 {
481 const std::uint8_t squareNo =
484 ].currentSquare;
485
486
489 static_cast<board::SquareType>(
491 )
492 ).group;
493
494
495 return
496 group ==
500 }
501 }
502
503
506 const actions::Message& message)
507 {
508 // ====================================================
509 // ActionCardSeen() original.
510 // ====================================================
511
512 if (
514 state
515 ).phase !=
517 {
519
520 return;
521 }
522
523
524 if (
525 message.fromPlayer !=
529 {
531
532 return;
533 }
534
535
536 PlayerState& player =
539 ];
540
541
542 const DeckType deck =
544 state
545 );
546
547
548 const CardType pickedCard =
550 state,
551 deck
552 );
553
554
556 message
557 );
558
559
565 static_cast<std::int64_t>(
566 deck
567 ),
568 static_cast<std::int64_t>(
570 ),
571 0
572 );
573
574
575 // Certaines cartes modifient une action qui se produit
576 // après le déplacement :
577 //
578 // - gare la plus proche, loyer double
579 // - compagnie la plus proche, lancer ×10
580
583
584
585 switch (pickedCard)
586 {
587 // =================================================
588 // COMMUNITY CHEST : argent reçu.
589 // =================================================
590
594 {
596 state,
599 100,
600 true
601 );
602
604 break;
605 }
606
607
609 {
611 state,
614 10,
615 true
616 );
617
619 break;
620 }
621
622
624 {
626 state,
629 200,
630 true
631 );
632
634
636 break;
637 }
638
639
641 {
643 state,
646 20,
647 true
648 );
649
651 break;
652 }
653
654
656 {
658 state,
661 45,
662 true
663 );
664
666 break;
667 }
668
669
671 {
673 state,
676 25,
677 true
678 );
679
681 break;
682 }
683
684
685 // =================================================
686 // CHANCE : argent reçu.
687 // =================================================
688
690 {
692 state,
695 150,
696 true
697 );
698
700 break;
701 }
702
703
705 {
707 state,
710 50,
711 true
712 );
713
715
717 break;
718 }
719
720
721 // =================================================
722 // GET OUT OF JAIL FREE.
723 // =================================================
724
727 {
728 transferGetOutOfJail(
729 state,
732 deck
733 );
734
736 break;
737 }
738
739
740 // =================================================
741 // Paiements à la banque.
742 // =================================================
743
745 {
747
749 state,
752 50
753 );
754
756 state,
757 50
758 );
759
760 break;
761 }
762
763
765 {
767
769 state,
772 150
773 );
774
776 state,
777 150
778 );
779
780 break;
781 }
782
783
785 {
787
789 state,
792 100
793 );
794
796 state,
797 100
798 );
799
800 break;
801 }
802
803
805 {
807
809 state,
812 15
813 );
814
816 state,
817 15
818 );
819
820 break;
821 }
822
823
824 // =================================================
825 // Réparations propriétés.
826 // =================================================
827
828 case CardType::
830 {
832 state,
833 40,
834 115
835 );
836
837 break;
838 }
839
840
841 case CardType::
843 {
845 state,
846 25,
847 100
848 );
849
850 break;
851 }
852
853
854 // =================================================
855 // Paiements entre joueurs.
856 // =================================================
857
858 case CardType::
860 {
862 state,
863 50
864 );
865
866 break;
867 }
868
869
870 case CardType::
872 {
874 state,
875 50
876 );
877
878 break;
879 }
880
881
882 // =================================================
883 // Prison.
884 // =================================================
885
886 case CardType::
888
889 case CardType::
891 {
892 jumpTo(
893 state,
894 InJail
895 );
896
897 break;
898 }
899
900
901 // =================================================
902 // GO.
903 // =================================================
904
905 case CardType::
907
908 case CardType::
910 {
911 jumpTo(
912 state,
914 );
915
916 break;
917 }
918
919
920 // =================================================
921 // Déplacements Chance.
922 // =================================================
923
924 case CardType::
926 {
928 state,
929 ReadingRailroad
930 );
931
932 break;
933 }
934
935
936 case CardType::
938 {
940 state,
941 StCharlesPlace
942 );
943
944 break;
945 }
946
947
948 case CardType::
950 {
952 state,
953 Boardwalk
954 );
955
956 break;
957 }
958
959
960 case CardType::
962 {
964 state,
965 IllinoisAvenue
966 );
967
968 break;
969 }
970
971
972 // =================================================
973 // Compagnie la plus proche.
974 // =================================================
975
976 case CardType::
978 {
979 std::uint8_t newSquare = 0;
980
981
982 if (
983 player.currentSquare >=
984 ElectricCompany &&
985 player.currentSquare <
986 WaterWorks)
987 {
988 newSquare =
989 WaterWorks;
990 }
991 else
992 {
993 newSquare =
994 ElectricCompany;
995 }
996
997
999 state,
1000 newSquare
1001 );
1002
1003 break;
1004 }
1005
1006
1007 // =================================================
1008 // Gare la plus proche + loyer double.
1009 // =================================================
1010
1011 case CardType::
1013
1014 case CardType::
1016 {
1017 std::uint8_t newSquare = 0;
1018
1019
1020 if (
1021 player.currentSquare >=
1022 ShortLineRailroad ||
1023 player.currentSquare <
1024 ReadingRailroad)
1025 {
1026 newSquare =
1027 ReadingRailroad;
1028 }
1029 else if (
1030 player.currentSquare <
1031 PennsylvaniaRailroad)
1032 {
1033 newSquare =
1034 PennsylvaniaRailroad;
1035 }
1036 else if (
1037 player.currentSquare <
1038 BAndORailroad)
1039 {
1040 newSquare =
1041 BAndORailroad;
1042 }
1043 else
1044 {
1045 newSquare =
1046 ShortLineRailroad;
1047 }
1048
1049
1051 state,
1052 newSquare
1053 );
1054
1055 break;
1056 }
1057
1058
1059 // =================================================
1060 // Reculez de trois cases.
1061 // =================================================
1062
1063 case CardType::
1065 {
1066 int newSquare =
1067 static_cast<int>(
1068 player.currentSquare
1069 ) - 3;
1070
1071
1072 if (newSquare < 0)
1073 {
1074 newSquare +=
1075 Boardwalk + 1;
1076 }
1077
1078
1080 state,
1081 static_cast<std::uint8_t>(
1082 newSquare
1083 )
1084 );
1085
1086 break;
1087 }
1088
1089
1090 // =================================================
1091 // Erreur de paquet / carte inconnue.
1092 // =================================================
1093
1094 case CardType::None:
1095 default:
1096 {
1099 BankPlayer,
1100 AllPlayers,
1102 static_cast<std::int64_t>(
1104 ),
1106 player.currentSquare
1107 );
1108
1109
1111 break;
1112 }
1113 }
1114
1115
1116 // ====================================================
1117 // ReturnCard() original.
1118 //
1119 // Toutes les cartes reviennent en bas du paquet SAUF
1120 // les deux cartes "Get Out of Jail Free", qui restent
1121 // hors paquet tant qu'un joueur les possède.
1122 // ====================================================
1123
1124 if (
1125 pickedCard !=
1127 pickedCard !=
1129 {
1131 state,
1133 );
1134 }
1135 }
1136}
std::uint16_t group
unsigned index
CardTag other
constexpr std::int64_t ErrorPropertyFees
constexpr std::int64_t ErrorUnimplementedCard
bool sendAction(const actions::Message &message)
const SquareDefinition & definition(SquareType square)
constexpr std::size_t MaxPropertyGroups
void returnToBottom(GameState &state, CardType card)
CardType dealFromTop(GameState &state, DeckType deck)
bool transferGetOutOfJail(GameState &state, PlayerNumber fromPlayer, PlayerNumber toPlayer, DeckType deckType)
void(*)(BankPayout) BankPayoutObserver
Definition RuleCards.hpp:9
void actionCardSeen(GameState &state, const actions::Message &message)
void setBankPayoutObserver(BankPayoutObserver observer) noexcept
Definition RuleCards.cpp:18
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 addMoneyToFreeParkingPot(GameState &state, std::int64_t amount)
bool pop(GameState &state)
const PendingPhase & current(const GameState &state)
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)
constexpr PlayerNumber BankPlayer
Definition RuleTypes.hpp:15
std::uint8_t PlayerNumber
Definition RuleTypes.hpp:12
constexpr std::size_t SquareCount
Definition RuleTypes.hpp:24
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 fromPlayer
Definition Actions.hpp:128
std::array< CardDeck, static_cast< std::size_t >(DeckType::Count) > cards
std::array< SquareState, SquareCount > squares
std::array< PlayerState, MaxPlayers > players