/nix/store/i1aar97n7b4yf8rk94p66if25brfvvdx-gqvzl8a5pvrg3xj44q0msrndcripi8dk-source/src/statefunctions/gamestates/chi.cc
Line | Count | Source |
1 | | #include <array> |
2 | | #include <cstdint> |
3 | | #include <iostream> |
4 | | #include <memory> |
5 | | #include <vector> |
6 | | |
7 | | #include "statefunctions/router.h" |
8 | | #include "statefunctions/stateutilities.h" |
9 | | #include "types/event.h" |
10 | | #include "types/gamestate.h" |
11 | | #include "types/pieces.h" |
12 | | #include "types/piecetype.h" |
13 | | #include "types/sets.h" |
14 | | #include "types/statefunction.h" |
15 | | |
16 | | namespace mahjong { |
17 | | namespace { |
18 | 0 | Piece GetChiStart(const GameState& state, int player) { |
19 | 0 | if (CountPieces(state, player, state.pendingPiece - 2) > 0 && |
20 | 0 | CountPieces(state, player, state.pendingPiece - 1) > 0) { |
21 | 0 | return state.pendingPiece - 2; |
22 | 0 | } |
23 | 0 | if (CountPieces(state, player, state.pendingPiece - 1) > 0 && |
24 | 0 | CountPieces(state, player, state.pendingPiece + 1) > 0) { |
25 | 0 | return state.pendingPiece - 1; |
26 | 0 | } |
27 | 0 | if (CountPieces(state, player, state.pendingPiece + 1) > 0 && |
28 | 0 | CountPieces(state, player, state.pendingPiece + 2) > 0) { |
29 | 0 | return state.pendingPiece; |
30 | 0 | } |
31 | 0 | return kError; |
32 | 0 | } |
33 | | |
34 | 0 | std::unique_ptr<GameState> Chi(std::unique_ptr<GameState> state) { |
35 | | // only gives a single one of the chis |
36 | | // ui oof |
37 | 0 | const Piece chi_start = GetChiStart(*state, state->lastCaller); |
38 | 0 | if (chi_start == kError) { |
39 | 0 | std::cerr << "Failed to get start of Chi" << '\n'; |
40 | 0 | state->nextState = StateFunctionType::kError; |
41 | 0 | return state; |
42 | 0 | } |
43 | | |
44 | 0 | if (state->hands.at(state->currentPlayer).riichi && |
45 | 0 | state->hands.at(state->currentPlayer).discards.size() == |
46 | 0 | state->hands.at(state->currentPlayer).riichiPieceDiscard) { |
47 | 0 | state->hands.at(state->currentPlayer).riichiPieceDiscard++; |
48 | 0 | } |
49 | |
|
50 | 0 | state->hands.at(state->lastCaller).open = true; |
51 | 0 | state->currentPlayer = state->lastCaller; |
52 | |
|
53 | 0 | AlertPlayers( |
54 | 0 | *state, |
55 | 0 | Event{ |
56 | 0 | .type = Event::kChi, // type |
57 | 0 | .player = state->lastCaller, // player |
58 | 0 | .piece = static_cast<int16_t>(chi_start.toUint8_t()), // piece |
59 | 0 | .decision = false, // decision |
60 | 0 | }); |
61 | |
|
62 | 0 | state->hands.at(state->lastCaller).live.push_back(state->pendingPiece); |
63 | 0 | state->hands.at(state->lastCaller).sort(); |
64 | 0 | state->lastCall = state->turnNum; |
65 | 0 | state->concealedKan = false; |
66 | 0 | state->turnNum++; |
67 | |
|
68 | 0 | if (RemovePieces(*state, state->lastCaller, chi_start, /*count=*/1) != 1 || |
69 | 0 | RemovePieces(*state, state->lastCaller, chi_start + 1, /*count=*/1) != |
70 | 0 | 1 || |
71 | 0 | RemovePieces(*state, state->lastCaller, chi_start + 2, /*count=*/1) != |
72 | 0 | 1) { |
73 | 0 | std::cerr << "Not Enough Pieces to remove in Chi" << '\n'; |
74 | 0 | state->nextState = StateFunctionType::kError; |
75 | 0 | return state; |
76 | 0 | } |
77 | 0 | state->hands.at(state->lastCaller) |
78 | 0 | .melds.push_back({SetType::kChi, chi_start}); |
79 | |
|
80 | 0 | state->pendingPiece = AskForDiscard(*state); |
81 | |
|
82 | 0 | state->nextState = StateFunctionType::kDiscard; |
83 | 0 | return state; |
84 | 0 | } |
85 | | } // namespace |
86 | | |
87 | | REGISTER_ROUTE(Chi, StateFunctionType::kChi); |
88 | | } // namespace mahjong |