/nix/store/i1aar97n7b4yf8rk94p66if25brfvvdx-gqvzl8a5pvrg3xj44q0msrndcripi8dk-source/src/statefunctions/gamestates/discard.cc
Line | Count | Source |
1 | | #include <array> |
2 | | #include <cstdint> |
3 | | #include <iostream> |
4 | | #include <memory> |
5 | | #include <vector> |
6 | | |
7 | | #include "controllers/playercontroller.h" |
8 | | #include "statefunctions/decisionfunction.h" |
9 | | #include "statefunctions/router.h" |
10 | | #include "statefunctions/stateutilities.h" |
11 | | #include "types/event.h" |
12 | | #include "types/gamestate.h" |
13 | | #include "types/piecetype.h" |
14 | | #include "types/statefunction.h" |
15 | | #include "types/walls.h" |
16 | | |
17 | | namespace mahjong { |
18 | | |
19 | | namespace { |
20 | 11 | std::unique_ptr<GameState> Discard(std::unique_ptr<GameState> state) { |
21 | 11 | AlertPlayers(*state, Event{ |
22 | 11 | .type = Event::kDiscard, // type |
23 | 11 | .player = state->currentPlayer, // player |
24 | 11 | .piece = static_cast<int16_t>( |
25 | 11 | state->pendingPiece.toUint8_t()), // piece |
26 | 11 | .decision = false, // decision |
27 | 11 | }); |
28 | 11 | DiscardPiece(*state, state->currentPlayer, state->pendingPiece); |
29 | | |
30 | 11 | const std::vector<PossibleDecision> decisions = { |
31 | 11 | {.type = Event::kChi, .func = CanChi}, |
32 | 11 | {.type = Event::kPon, .func = CanPon}, |
33 | 11 | {.type = Event::kKan, .func = CanKan}, |
34 | 11 | {.type = Event::kRon, .func = CanRon}, |
35 | 11 | }; |
36 | | |
37 | 11 | std::array<bool, 4> need_decision = {false, false, false, false}; |
38 | 55 | for (int player = 0; player < 4; player++) { |
39 | 44 | if (player == state->currentPlayer) { |
40 | 11 | continue; |
41 | 11 | } |
42 | 132 | for (const auto& [decision, decisionIsPossible] : decisions) { |
43 | 132 | if (decisionIsPossible(*state, player)) { |
44 | 2 | need_decision.at(player) = true; |
45 | 2 | state->players.at(player).controller->ReceiveEvent(Event{ |
46 | 2 | .type = decision, // type |
47 | 2 | .player = state->currentPlayer, // player |
48 | 2 | .piece = |
49 | 2 | static_cast<int16_t>(state->pendingPiece.toUint8_t()), // piece |
50 | 2 | .decision = true, // decision |
51 | 2 | }); |
52 | 2 | } |
53 | 132 | } |
54 | 33 | } |
55 | | |
56 | 11 | Event decision = kDeclineEvent; |
57 | 55 | for (int i = 0; i < 4; i++) { |
58 | 44 | if (need_decision.at(i)) { |
59 | 2 | Event temp_decision = |
60 | 2 | GetValidDecisionOrThrow(*state, i, /*inHand=*/false); |
61 | 2 | if (temp_decision.type < decision.type) { // lower is higher priority |
62 | 1 | temp_decision.player = i; |
63 | 1 | temp_decision.piece = |
64 | 1 | static_cast<int16_t>(state->pendingPiece.toUint8_t()); |
65 | 1 | decision = temp_decision; |
66 | 1 | } |
67 | 2 | if (temp_decision.type == Event::kRon) { |
68 | 0 | state->hasRonned.at(i) = true; |
69 | 0 | } |
70 | 2 | } |
71 | 44 | } |
72 | | |
73 | 11 | if (decision.type == Event::kDecline && |
74 | 11 | state->walls.GetRemainingPieces() == 0) { |
75 | 0 | state->nextState = StateFunctionType::kExhaust; |
76 | 0 | return state; |
77 | 0 | } |
78 | | |
79 | 11 | if (decision.type != Event::kDecline) { |
80 | 1 | state->lastCaller = decision.player; |
81 | 1 | } |
82 | | |
83 | 11 | switch (decision.type) { |
84 | 10 | case Event::kDecline: |
85 | 10 | state->nextState = StateFunctionType::kDraw; |
86 | 10 | break; |
87 | 0 | case Event::kRon: |
88 | 0 | state->nextState = StateFunctionType::kRon; |
89 | 0 | break; |
90 | 0 | case Event::kChi: |
91 | 0 | state->nextState = StateFunctionType::kChi; |
92 | 0 | break; |
93 | 1 | case Event::kPon: |
94 | 1 | state->nextState = StateFunctionType::kPon; |
95 | 1 | break; |
96 | 0 | case Event::kKan: |
97 | 0 | state->nextState = StateFunctionType::kKan; |
98 | 0 | break; |
99 | 0 | default: |
100 | 0 | std::cerr << "Invalid Decision Type in Discard: " << decision.type |
101 | 0 | << '\n'; |
102 | 0 | state->nextState = StateFunctionType::kError; |
103 | 0 | break; |
104 | 11 | } |
105 | | |
106 | 11 | return state; |
107 | 11 | } |
108 | | } // namespace |
109 | | |
110 | | REGISTER_ROUTE(Discard, StateFunctionType::kDiscard); |
111 | | } // namespace mahjong |