Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
RuleBuildings.cpp
Go to the documentation of this file.
1#include "RuleBuildings.hpp"
2
3#include "LegacyTextIds.hpp"
4#include "Messaging.hpp"
5#include "PhaseStack.hpp"
6#include "RuleRejections.hpp"
7#include "RuleEconomy.hpp"
8#include "RuleResync.hpp"
10
11#include <algorithm>
12#include <cstddef>
13#include <cstdint>
14#include <limits>
15
17{
18 namespace
19 {
20 constexpr std::uint8_t BoardwalkSquare = 39;
21 constexpr std::uint8_t OffBoardSquare = 41;
22
23 void sendRestart()
24 {
29 );
30 }
31
32
33 void popAndRestart(
35 {
38 }
39
40
42 const actions::Message& message,
43 bool success)
44 {
49 static_cast<std::int64_t>(
50 message.action
51 ),
52 success ? 1 : 0,
53 message.fromPlayer,
54 0
55 );
56 }
57
58
59 void notifyError(
60 std::int64_t error,
61 std::int64_t argument,
62 PlayerNumber player,
63 std::uint8_t square)
64 {
69 error,
71 player,
72 square
73 );
74 }
75
76
77 bool quickBuyAllowed(
78 GamePhase phase)
79 {
80 switch (phase)
81 {
94 return true;
95
96 default:
97 return false;
98 }
99 }
100
101
102 bool quickSellAllowed(
103 GamePhase phase)
104 {
105 switch (phase)
106 {
119 return true;
120
121 default:
122 return false;
123 }
124 }
125
126
129 std::uint8_t squareNo)
130 {
133 static_cast<board::SquareType>(
135 )
136 ).group;
137
138 const PlayerNumber player =
141 ].owner;
142
143 std::int64_t cash = 0;
144
145
146 for (std::size_t i = 0;
147 i < SquareCount;
148 ++i)
149 {
150 if (
152 static_cast<board::SquareType>(
153 i
154 )
155 ).group != group)
156 {
157 continue;
158 }
159
160
161 const std::uint8_t houses =
162 state.squares[i].houses;
163
164 state.squares[i].houses = 0;
165
166
167 if (houses == 0)
168 {
169 continue;
170 }
171
172
177 i,
178 0,
180 );
181
182
183 cash +=
184 (
185 static_cast<std::int64_t>(
186 houses
187 ) *
189 static_cast<board::SquareType>(
190 i
191 )
192 ).housePurchaseCost
193 + 1
194 ) / 2;
195 }
196
197
198 if (cash == 0)
199 {
200 return;
201 }
202
203
205 state,
207 player,
208 cash,
209 true
210 );
211
212
218 player,
219 cash,
221 );
222 }
223
224
226 const GameState& state)
227 {
228 int houseCount = 0;
229
230 for (std::size_t i = 0;
231 i < SquareCount;
232 ++i)
233 {
234 const int houses =
235 state.squares[i].houses;
236
237 if (
238 houses <
240 {
241 houseCount += houses;
242 }
243 }
244
245 return houseCount;
246 }
247 }
248
249
251 {
252 // Undo state is owned by GameState and reset with that state.
253 }
254
255
257 const GameState& state,
259 std::uint8_t squareNo,
260 bool adding)
261 {
262 PlacementCheck result{};
263
264
265 if (squareNo >= SquareCount ||
267 {
268 result.error =
270
271 return result;
272 }
273
274
275 const GamePhase currentPhase =
278 : state.phaseStack[0].phase;
279
280
281 const bool noCharge =
282 currentPhase ==
284 currentPhase ==
286 currentPhase ==
288
289
292 static_cast<board::SquareType>(
294 )
295 );
296
297
299 predefined.group;
300
301
302 // ----------------------------------------------------
303 // Cash.
304 // ----------------------------------------------------
305
306 if (adding && !noCharge)
307 {
308 if (
309 predefined.housePurchaseCost >
312 ].cash)
313 {
314 result.error =
316
317 result.errorArgument =
318 predefined.housePurchaseCost;
319
320 return result;
321 }
322 }
323
324
325 // ----------------------------------------------------
326 // Terrain constructible.
327 // ----------------------------------------------------
328
329 if (
330 static_cast<std::uint8_t>(
332 ) >
333 static_cast<std::uint8_t>(
335 ))
336 {
337 result.error =
339
340 return result;
341 }
342
343
344 const SquareState& square =
347 ];
348
349
350 if (square.owner != purchaser)
351 {
352 result.error =
354
355 return result;
356 }
357
358
359 // ----------------------------------------------------
360 // Possession du groupe entier + aucune hypothèque.
361 // ----------------------------------------------------
362
363 int lowestHouses =
365
366 int highestHouses = 0;
367
368
369 for (std::size_t i = 0;
370 i < SquareCount;
371 ++i)
372 {
373 if (
375 static_cast<board::SquareType>(
376 i
377 )
378 ).group != monopolyGroup)
379 {
380 continue;
381 }
382
383
384 const SquareState& testSquare =
385 state.squares[i];
386
387
388 if (testSquare.owner != purchaser)
389 {
390 result.error =
392
393 return result;
394 }
395
396
397 if (testSquare.mortgaged)
398 {
399 result.error =
401
402 return result;
403 }
404
405
407 std::min(
409 static_cast<int>(
410 testSquare.houses
411 )
412 );
413
414
416 std::max(
418 static_cast<int>(
419 testSquare.houses
420 )
421 );
422 }
423
424
425 if (
426 adding &&
427 square.houses >=
429 {
430 result.error =
432
433 return result;
434 }
435
436
437 // ----------------------------------------------------
438 // Inventaire banque : 32 maisons / 12 hôtels par
439 // défaut.
440 // ----------------------------------------------------
441
442 int houseCount = 0;
443 int hotelCount = 0;
444
445
446 for (std::size_t i = 0;
447 i < SquareCount;
448 ++i)
449 {
450 const int houses =
451 state.squares[i].houses;
452
453
454 if (
455 houses <
457 {
458 houseCount += houses;
459 }
460 else
461 {
462 ++hotelCount;
463 }
464 }
465
466
467 const int freeHouses =
468 static_cast<int>(
470 ) -
472
473
474 const int freeHotels =
475 static_cast<int>(
477 ) -
479
480
481 // ----------------------------------------------------
482 // Ajouter.
483 // ----------------------------------------------------
484
485 if (adding)
486 {
487 if (
489 square.houses >
491 {
492 result.error =
494
495 result.errorArgument =
497
498 return result;
499 }
500
501
502 if (
503 square.houses >=
505 {
506 result.buildingAHotel = true;
507
508 if (freeHotels < 1)
509 {
510 result.error =
512
513 return result;
514 }
515
516
517 result.freeBuildings =
518 freeHotels;
519 }
520 else
521 {
522 result.buildingAHotel = false;
523
524 if (freeHouses < 1)
525 {
526 result.error =
528
529 return result;
530 }
531
532
533 result.freeBuildings =
534 freeHouses;
535 }
536 }
537
538 // ----------------------------------------------------
539 // Retirer.
540 // ----------------------------------------------------
541
542 else
543 {
544 if (
545 square.houses >=
547 {
548 result.buildingAHotel = true;
549
550
551 if (
552 currentPhase !=
554 freeHouses <
556 {
557 result.error =
560
561 result.errorArgument =
563
564 return result;
565 }
566
567
568 result.freeBuildings =
569 freeHotels;
570 }
571 else
572 {
573 result.buildingAHotel = false;
574
575
576 if (square.houses <= 0)
577 {
578 result.error =
580
581 return result;
582 }
583
584
585 if (
587 square.houses <
589 {
590 result.error =
592
593 result.errorArgument =
595
596 return result;
597 }
598
599
600 result.freeBuildings =
601 freeHouses;
602 }
603 }
604
605
606 return result;
607 }
608
609
611 const GameState& state,
612 bool hotel)
613 {
614 PlayerSet allowed = 0;
615
616
617 for (std::size_t squareNo = 0;
619 ++squareNo)
620 {
621 const PlayerNumber player =
624 ].owner;
625
626
627 if (player >= MaxPlayers)
628 {
629 continue;
630 }
631
632
633 if (
634 (
635 allowed &
636 (1u << player)
637 ) != 0)
638 {
639 continue;
640 }
641
642
643 const PlacementCheck check =
645 state,
646 player,
647 static_cast<std::uint8_t>(
649 ),
650 true
651 );
652
653
654 if (
655 check.error == 0 &&
656 check.buildingAHotel == hotel)
657 {
658 allowed |=
659 (1u << player);
660 }
661 }
662
663
664 return allowed;
665 }
666
667
669 const GameState& state)
670 {
671 if (
673 state.phaseStack[0].phase !=
675 {
676 return 0;
677 }
678
679
681
682
683 for (std::size_t squareNo = 0;
685 ++squareNo)
686 {
687 const PlacementCheck check =
689 state,
690 state.phaseStack[0].fromPlayer,
691 static_cast<std::uint8_t>(
693 ),
694 true
695 );
696
697
698 if (check.error != 0)
699 {
700 continue;
701 }
702
703
704 const bool wantsHotel =
705 state.phaseStack[0].amount > 0;
706
707
708 if (
709 check.buildingAHotel ==
711 {
712 legalSet |=
714 static_cast<board::SquareType>(
716 )
717 );
718 }
719 }
720
721
722 return legalSet;
723 }
724
725
728 std::uint8_t squareNo)
729 {
730 // BuildHouse() original.
731
732 ++state.squares[
734 ].houses;
735
736
741 squareNo,
744 ].houses,
746 );
747 }
748
749
752 const actions::Message& message)
753 {
754 const PlayerNumber player =
755 message.fromPlayer;
756
757
758 if (
759 message.numberA < 0 ||
760 message.numberA >
762 {
764
765 return;
766 }
767
768
769 const std::uint8_t squareNo =
770 static_cast<std::uint8_t>(
771 message.numberA
772 );
773
774
775 const GamePhase phase =
777 state
778 ).phase;
779
780
781 const bool quick =
782 message.numberD != 0;
783
784
785 if (quick)
786 {
787 if (!quickBuyAllowed(phase))
788 {
790
791 return;
792 }
793 }
794 else
795 {
796 if (
797 phase !=
799 phase !=
801 {
803
804 return;
805 }
806
807
808 if (
809 phase ==
811 player !=
813 state
814 ).fromPlayer)
815 {
817
818 return;
819 }
820
821
822 if (
823 phase ==
825 player !=
827 state
828 ).fromPlayer)
829 {
831
832 return;
833 }
834 }
835
836
837 const PlacementCheck check =
839 state,
840 player,
841 squareNo,
842 true
843 );
844
845
846 if (check.error != 0)
847 {
849 message,
850 false
851 );
852
853
855 check.error,
856 check.errorArgument,
857 player,
859 );
860
861 return;
862 }
863
864
865 // ----------------------------------------------------
866 // Bâtiment déjà acheté aux enchères :
867 // il faut placer le bon type.
868 // ----------------------------------------------------
869
870 if (
871 phase ==
874 state
875 ).amount !=
876 (
877 check.buildingAHotel
878 ? 1
879 : -1
880 ))
881 {
883 message,
884 false
885 );
886
887
889 legacy_text::
890 ErrorAuctionWrongBuilding,
891 0,
892 player,
894 );
895
896 return;
897 }
898
899
900 const PlayerSet allowed =
902 state,
903 check.buildingAHotel
904 );
905
906
907 const int shortageLevel =
908 check.buildingAHotel
911
912
913 // ----------------------------------------------------
914 // Pénurie.
915 // ----------------------------------------------------
916
917 if (
918 allowed !=
919 (1u << player) &&
920 phase !=
922 check.freeBuildings <=
924 {
926 message,
927 false
928 );
929
930
931 if (
932 phase ==
934 {
937 NotifyPlayerBuySellMort,
941 0,
942 0,
944 );
945 }
946
947
949 state,
950 GamePhase::
952 player,
953 squareNo,
954 check.buildingAHotel
955 ? check.freeBuildings
956 : -check.freeBuildings
957 );
958
959
962
963 // ActionBuyHouse() original :
964 // IgnoreWaitForEverybodyReady = FALSE.
966
967
968 sendRestart();
969
970 return;
971 }
972
973
974 // ----------------------------------------------------
975 // Achat normal.
976 // ----------------------------------------------------
977
979 message,
980 true
981 );
982
983
984 if (
985 phase !=
987 {
989 state,
990 player,
993 static_cast<board::SquareType>(
995 )
996 ).housePurchaseCost,
997 true
998 );
999 }
1000
1001
1003 state,
1004 squareNo
1005 );
1006
1007
1010 BankPlayer,
1011 AllPlayers,
1013 player,
1014 phase ==
1016 ? 0
1018 static_cast<board::SquareType>(
1019 squareNo
1020 )
1022 squareNo
1023 );
1024
1025
1026 if (
1027 phase ==
1029 {
1031 }
1032 }
1033
1034
1037 const actions::Message& message)
1038 {
1039 const PlayerNumber player =
1040 message.fromPlayer;
1041
1042
1043 if (
1044 message.numberA < 0 ||
1045 message.numberA >
1047 {
1048 rejections::wrongPhase(state, message);
1049
1050 return;
1051 }
1052
1053
1054 const std::uint8_t squareNo =
1055 static_cast<std::uint8_t>(
1056 message.numberA
1057 );
1058
1059
1060 const GamePhase phaseBefore =
1062 state
1063 ).phase;
1064
1065
1066 const bool quick =
1067 message.numberD != 0;
1068
1069
1070 if (quick)
1071 {
1072 if (
1075 ))
1076 {
1077 rejections::wrongPhase(state, message);
1078
1079 return;
1080 }
1081 }
1082 else
1083 {
1084 if (
1085 phaseBefore !=
1087 phaseBefore !=
1089 {
1090 rejections::wrongPhase(state, message);
1091
1092 return;
1093 }
1094
1095
1096 if (
1097 player !=
1099 state
1100 ).fromPlayer)
1101 {
1103
1104 return;
1105 }
1106 }
1107
1108
1109 // ----------------------------------------------------
1110 // Vente de tout le groupe.
1111 // ----------------------------------------------------
1112
1113 if (message.numberB != 0)
1114 {
1115 if (
1116 state.squares[
1117 squareNo
1118 ].owner != player)
1119 {
1121 message,
1122 false
1123 );
1124
1125
1127 legacy_text::
1128 ErrorBuildingOnUnowned,
1129 0,
1130 player,
1131 squareNo
1132 );
1133
1134 return;
1135 }
1136
1137
1139 message,
1140 true
1141 );
1142
1143
1145 state,
1146 squareNo
1147 );
1148
1149
1150 if (
1151 quick &&
1152 phaseBefore ==
1154 {
1155 sendRestart();
1156 }
1157
1158
1159 return;
1160 }
1161
1162
1163 // ----------------------------------------------------
1164 // Vente d'un seul bâtiment.
1165 // ----------------------------------------------------
1166
1169 state,
1170 player,
1171 squareNo,
1172 false
1173 );
1174
1175
1176 if (
1177 check.error ==
1178 legacy_text::
1179 ErrorBuildingNoBreakdownHouses &&
1180 phaseBefore !=
1182 {
1183 // Original :
1184 //
1185 // Push GF_DECOMPOSE_HOTEL,
1186 // SaveGameStateInCurrentPhase(),
1187 // puis la vente de l'hôtel continue quand même.
1188
1189 if (
1190 phaseBefore ==
1192 {
1195 NotifyPlayerBuySellMort,
1196 BankPlayer,
1197 AllPlayers,
1199 0,
1200 0,
1202 );
1203 }
1204
1205
1207 state,
1209 player,
1211 squareNo
1212 );
1213
1214
1216
1217
1218 sendRestart();
1219
1220
1221 // Dans GF_DECOMPOSE_HOTEL le manque de maisons
1222 // n'empêche plus la vente.
1223 check.error = 0;
1224 }
1225
1226
1227 if (check.error != 0)
1228 {
1230 message,
1231 false
1232 );
1233
1234
1236 check.error,
1237 check.errorArgument,
1238 player,
1239 squareNo
1240 );
1241
1242 return;
1243 }
1244
1245
1246 if (
1247 state.squares[
1248 squareNo
1249 ].houses == 0)
1250 {
1252 message,
1253 false
1254 );
1255
1256 return;
1257 }
1258
1259
1260 --state.squares[
1261 squareNo
1262 ].houses;
1263
1264
1266 message,
1267 true
1268 );
1269
1270
1271 const std::int64_t salePrice =
1272 (
1274 static_cast<board::SquareType>(
1275 squareNo
1276 )
1278 1
1279 ) / 2;
1280
1281
1283 state,
1284 BankPlayer,
1285 player,
1286 salePrice,
1287 true
1288 );
1289
1290
1293 BankPlayer,
1294 AllPlayers,
1295 squareNo,
1296 state.squares[
1297 squareNo
1298 ].houses,
1300 );
1301
1302
1305 BankPlayer,
1306 AllPlayers,
1308 player,
1309 salePrice,
1310 squareNo
1311 );
1312
1313
1314 // ----------------------------------------------------
1315 // Décomposition hôtel.
1316 // ----------------------------------------------------
1317
1318 if (
1320 state
1321 ).phase ==
1323 {
1324 const int houseCount =
1326 state
1327 );
1328
1329
1330 if (
1331 houseCount <=
1333 {
1335 }
1336 else
1337 {
1338 sendRestart();
1339 }
1340 }
1341
1342
1343 if (
1344 quick &&
1346 state
1347 ).phase ==
1349 {
1350 sendRestart();
1351 }
1352 }
1353
1354
1357 const actions::Message& message)
1358 {
1359 if (
1361 state
1362 ).phase !=
1364 {
1365 rejections::wrongPhase(state, message);
1366
1367 return;
1368 }
1369
1370
1371 if (
1372 message.fromPlayer !=
1374 state
1375 ).fromPlayer)
1376 {
1378
1379 return;
1380 }
1381
1382
1384 message,
1385 true
1386 );
1387
1388
1390 {
1392 }
1393
1394
1396 }
1397
1398
1401 const actions::Message& message)
1402 {
1403 // ActionPlayerBuySellMort().
1404
1405 const PlayerNumber player =
1406 message.fromPlayer;
1407
1408
1409 if (
1411 state
1412 ).phase ==
1414 {
1415 if (
1416 player ==
1418 state
1419 ).fromPlayer)
1420 {
1421 state.phaseStack[0].amount =
1422 message.numberB;
1423
1424
1426 message,
1427 true
1428 );
1429 }
1430 else
1431 {
1432 rejections::wrongPhase(state, message);
1433 }
1434
1435
1436 sendRestart();
1437 return;
1438 }
1439
1440
1441 if (
1442 player >=
1444 state.players[
1445 player
1446 ].currentSquare >=
1447 OffBoardSquare)
1448 {
1450
1451 return;
1452 }
1453
1454
1455 const GamePhase phase =
1457 state
1458 ).phase;
1459
1460
1461 bool allowed = false;
1462
1463
1464 switch (phase)
1465 {
1476 allowed = true;
1477 break;
1478
1479 default:
1480 break;
1481 }
1482
1483
1484 if (!allowed)
1485 {
1486 rejections::wrongPhase(state, message);
1487
1488 return;
1489 }
1490
1491
1493 message,
1494 true
1495 );
1496
1497
1499 state,
1501 player,
1503 message.numberB
1504 );
1505
1506
1507 sendRestart();
1508 }
1509
1510
1513 const actions::Message& message)
1514 {
1515 if (
1517 state
1518 ).phase !=
1520 {
1521 rejections::wrongPhase(state, message);
1522
1523 return;
1524 }
1525
1526
1527 if (
1528 message.fromPlayer !=
1530 state
1531 ).fromPlayer)
1532 {
1534
1535 return;
1536 }
1537
1538
1540 message,
1541 true
1542 );
1543
1544
1547 NotifyPlayerBuySellMort,
1548 BankPlayer,
1549 AllPlayers,
1551 0,
1552 0,
1554 );
1555
1556
1558 }
1559
1560
1563 {
1564 const PendingPhase phase =
1566 state
1567 );
1568
1569
1570 switch (phase.phase)
1571 {
1573 {
1574 const bool bankrupt =
1575 phase.fromPlayer >=
1577 state.players[
1578 phase.fromPlayer
1579 ].currentSquare >=
1580 OffBoardSquare;
1581
1582
1583 if (bankrupt)
1584 {
1587 NotifyPlayerBuySellMort,
1588 BankPlayer,
1589 AllPlayers,
1591 0,
1592 0,
1594 );
1595
1596
1598 return true;
1599 }
1600
1601
1602 std::int64_t cashOwing = 0;
1603
1606
1607
1608 if (
1610 state.phaseStack[1].phase ==
1612 state.phaseStack[1].fromPlayer ==
1613 phase.fromPlayer)
1614 {
1615 cashOwing =
1616 state.phaseStack[1].amount;
1617
1618 owedTo =
1619 state.phaseStack[1].toPlayer;
1620 }
1621
1622
1625 NotifyPlayerBuySellMort,
1626 BankPlayer,
1627 AllPlayers,
1628 phase.fromPlayer,
1629 phase.amount,
1630 cashOwing,
1631 owedTo
1632 );
1633
1634
1635 return true;
1636 }
1637
1638
1640 {
1641 const int count =
1643 state
1644 );
1645
1646
1649 NotifyDecomposeSale,
1650 BankPlayer,
1651 AllPlayers,
1652 phase.fromPlayer,
1653 count -
1655 );
1656
1657
1658 return true;
1659 }
1660
1661
1663 {
1664 const bool bankrupt =
1665 phase.fromPlayer >=
1667 state.players[
1668 phase.fromPlayer
1669 ].currentSquare >=
1670 OffBoardSquare;
1671
1672
1675 state
1676 );
1677
1678
1679 if (bankrupt ||
1680 legal == 0)
1681 {
1683 return true;
1684 }
1685
1686
1689 NotifyPlaceBuilding,
1690 BankPlayer,
1691 AllPlayers,
1692 phase.fromPlayer,
1693 phase.amount,
1694 legal
1695 );
1696
1697
1698 return true;
1699 }
1700
1701
1702 default:
1703 return false;
1704 }
1705 }
1706}
1707
1708
std::size_t count
std::uint16_t group
unsigned index
std::string error
constexpr std::int64_t ErrorBuildingOnNonProperty
constexpr std::int64_t ErrorBuildingAllSold
constexpr std::int64_t ErrorBuildingNoHouses
constexpr std::int64_t ErrorSellNoHouses
constexpr std::int64_t ErrorBuildingSold
constexpr std::int64_t ErrorBuildingOnUnowned
constexpr std::int64_t ErrorBuildingNotEven
constexpr std::int64_t ErrorBuildingNoHotels
constexpr std::int64_t ErrorBuildingMaxedOut
constexpr std::int64_t ErrorBuildingNeedsCash
constexpr std::int64_t ErrorBuildingNeedsMonopoly
constexpr std::int64_t ErrorBuildingBought
constexpr std::int64_t ErrorBuildingMortgaged
constexpr std::int64_t ErrorBuildingNoBreakdownHouses
bool sendAction(const actions::Message &message)
const SquareDefinition & definition(SquareType square)
std::uint32_t PropertySet
PropertySet propertyBit(SquareType square)
PlacementCheck testBuildingPlacement(const GameState &state, PlayerNumber purchaser, std::uint8_t squareNo, bool adding)
void actionBuyHouse(GameState &state, const actions::Message &message)
PlayerSet playersWhoCanBuyBuilding(const GameState &state, bool hotel)
void actionCancelDecomposition(GameState &state, const actions::Message &message)
void buildApprovedBuilding(GameState &state, std::uint8_t squareNo)
void actionPlayerDoneBuySellMortgage(GameState &state, const actions::Message &message)
bool restartBuildingPhase(GameState &state)
void actionPlayerBuySellMortgage(GameState &state, const actions::Message &message)
board::PropertySet placeBuildingLegalSquares(const GameState &state)
void actionSellBuildings(GameState &state, const actions::Message &message)
void blindlyTransferCash(GameState &state, PlayerNumber fromPlayer, PlayerNumber toPlayer, std::int64_t amount, bool sendAnimation)
bool pop(GameState &state)
const PendingPhase & current(const GameState &state)
void saveCurrent(GameState &state)
bool push(GameState &state, GamePhase phase, PlayerNumber fromPlayer, PlayerNumber toPlayer, std::int64_t amount)
bool restoreCurrent(GameState &state)
void wrongPlayer(const GameState &state, const actions::Message &message)
void wrongPhase(const GameState &state, const actions::Message &message)
void sendClientState(const GameState &state, PlayerNumber toPlayer, Cause cause)
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< SquareState, SquareCount > squares
std::array< PendingPhase, MaxPendingPhases > phaseStack
std::uint8_t numberOfPendingPhases
std::array< PlayerState, MaxPlayers > players