From 3f002b04ac4667525ba45701ea4059ebe6d398bd Mon Sep 17 00:00:00 2001 From: alice Date: Sun, 24 Aug 2025 19:47:16 -0700 Subject: [PATCH 01/14] Change Walls Class to static and include members directly in state. --- src/scoring/scoring.cc | 3 +- src/scoring/yakus/bottomofthesea.cc | 3 +- src/scoring/yakus/fullyconcealedhand.cc | 3 +- src/statefunctions/decisionfunction.cc | 6 +- src/statefunctions/gamestates/discard.cc | 2 +- src/statefunctions/gamestates/draw.cc | 3 +- src/statefunctions/gamestates/replacement.cc | 4 +- src/statefunctions/gamestates/roundstart.cc | 6 +- src/types/gamestate.h | 8 +- src/types/settings.h | 9 +- src/types/typeprinter.cc | 33 +++---- src/types/walls.cc | 94 +++++++------------- src/types/walls.h | 23 ++--- tests/rules/basic_rules.test.cc | 11 +-- tests/setup.test.cc | 2 +- tests/yakus/concealedhand.test.cc | 5 +- tests/yakus/underthesea.test.cc | 9 +- 17 files changed, 96 insertions(+), 128 deletions(-) diff --git a/src/scoring/scoring.cc b/src/scoring/scoring.cc index 4a0016c4..eb7e7a95 100644 --- a/src/scoring/scoring.cc +++ b/src/scoring/scoring.cc @@ -14,6 +14,7 @@ #include "types/piecetype.h" #include "types/score.h" #include "types/sets.h" +#include "types/walls.h" namespace mahjong { @@ -95,7 +96,7 @@ Score scoreHand(const GameState& state, int player) { } } - for (const auto& dora : state.walls.GetDoras()) { + for (const auto& dora : Walls::GetDoras(state)) { for (const auto& p : state.hands.at(player).live) { if (p == dora) { branchscore.han++; diff --git a/src/scoring/yakus/bottomofthesea.cc b/src/scoring/yakus/bottomofthesea.cc index df20a5d9..e24f164d 100644 --- a/src/scoring/yakus/bottomofthesea.cc +++ b/src/scoring/yakus/bottomofthesea.cc @@ -5,12 +5,13 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/walls.h" #include "types/yaku.h" namespace mahjong::yaku { bool isBottomOfTheSea(const GameState& state, int /*player*/, const std::vector& /*branch*/) { - return state.walls.GetRemainingPieces() == 0; + return Walls::GetRemainingPieces(state) == 0; } REGISTER_YAKU({ diff --git a/src/scoring/yakus/fullyconcealedhand.cc b/src/scoring/yakus/fullyconcealedhand.cc index 342a22f3..dcc2c2d4 100644 --- a/src/scoring/yakus/fullyconcealedhand.cc +++ b/src/scoring/yakus/fullyconcealedhand.cc @@ -5,13 +5,14 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/walls.h" #include "types/yaku.h" namespace mahjong::yaku { bool isFullyConcealedHand(const GameState& state, int player, const std::vector& /*branch*/) { return state.currentPlayer == player && !state.hands.at(player).open && - state.walls.GetRemainingPieces() > 0; + Walls::GetRemainingPieces(state) > 0; } REGISTER_YAKU({ diff --git a/src/statefunctions/decisionfunction.cc b/src/statefunctions/decisionfunction.cc index 506c4a7f..0cfd94a0 100644 --- a/src/statefunctions/decisionfunction.cc +++ b/src/statefunctions/decisionfunction.cc @@ -56,7 +56,7 @@ bool CanRon(const GameState& state, int player) { } bool CanKan(const GameState& state, int player) { - if (state.walls.GetRemainingPieces() == 0) { + if (Walls::GetRemainingPieces(state) == 0) { return false; } if (state.hands.at(player).riichi) { @@ -102,7 +102,7 @@ bool CanTsumo(const GameState& state, int player) { } bool CanConvertedKan(const GameState& state, int player) { - if (state.walls.GetRemainingPieces() == 0) { + if (Walls::GetRemainingPieces(state) == 0) { return false; } return std::any_of(state.hands.at(player).melds.begin(), @@ -113,7 +113,7 @@ bool CanConvertedKan(const GameState& state, int player) { } bool CanConcealedKan(const GameState& state, int player) { - if (state.walls.GetRemainingPieces() == 0) { + if (Walls::GetRemainingPieces(state) == 0) { return false; } // TODO(#19): Allow riichi concealed kan under the right conditions diff --git a/src/statefunctions/gamestates/discard.cc b/src/statefunctions/gamestates/discard.cc index 67ae2a25..66aaa6f3 100644 --- a/src/statefunctions/gamestates/discard.cc +++ b/src/statefunctions/gamestates/discard.cc @@ -71,7 +71,7 @@ std::unique_ptr Discard(std::unique_ptr state) { } if (decision.type == Event::kDecline && - state->walls.GetRemainingPieces() == 0) { + Walls::GetRemainingPieces(*state) == 0) { state->nextState = StateFunctionType::kExhaust; return state; } diff --git a/src/statefunctions/gamestates/draw.cc b/src/statefunctions/gamestates/draw.cc index f5c55ad6..24131dfc 100644 --- a/src/statefunctions/gamestates/draw.cc +++ b/src/statefunctions/gamestates/draw.cc @@ -4,7 +4,6 @@ #include "statefunctions/router.h" #include "types/gamestate.h" -#include "types/piecetype.h" #include "types/statefunction.h" #include "types/walls.h" @@ -13,7 +12,7 @@ namespace { std::unique_ptr Draw(std::unique_ptr state) { state->currentPlayer = (state->currentPlayer + 1) % 4; state->turnNum++; - state->pendingPiece = state->walls.TakePiece(); + state->pendingPiece = Walls::TakePiece(*state); state->hands.at(state->currentPlayer).live.push_back(state->pendingPiece); state->hands.at(state->currentPlayer).sort(); state->nextState = StateFunctionType::kPlayerHand; diff --git a/src/statefunctions/gamestates/replacement.cc b/src/statefunctions/gamestates/replacement.cc index d9c04297..de0189d8 100644 --- a/src/statefunctions/gamestates/replacement.cc +++ b/src/statefunctions/gamestates/replacement.cc @@ -14,7 +14,7 @@ namespace mahjong { namespace { std::unique_ptr Replacement(std::unique_ptr state) { - const Piece draw = state->walls.TakeReplacementTile(); + const Piece draw = Walls::TakeReplacementTile(*state); state->hands.at(state->currentPlayer).live.push_back(draw); state->hands.at(state->currentPlayer).sort(); state->pendingPiece = draw; @@ -24,7 +24,7 @@ std::unique_ptr Replacement(std::unique_ptr state) { .type = Event::kDora, // type .player = -1, // player .piece = static_cast( - state->walls.GetDoras().back().toUint8_t()), // piece + Walls::GetDoras(*state).back().toUint8_t()), // piece .decision = false, // decision }); diff --git a/src/statefunctions/gamestates/roundstart.cc b/src/statefunctions/gamestates/roundstart.cc index cf604dca..523162dc 100644 --- a/src/statefunctions/gamestates/roundstart.cc +++ b/src/statefunctions/gamestates/roundstart.cc @@ -18,9 +18,9 @@ namespace mahjong { namespace { std::unique_ptr RoundStart(std::unique_ptr state) { - state->walls = Walls(state->g); + Walls::New(*state); for (size_t i = 0; i < 4; i++) { - auto hand = state->walls.TakeHand(); + auto hand = Walls::TakeHand(*state); state->players.at(i).controller->RoundStart( hand, static_cast((i + 3 * (state->roundNum % 4)) % 4), (state->roundNum > 3) ? kSouth : kEast); @@ -32,7 +32,7 @@ std::unique_ptr RoundStart(std::unique_ptr state) { .type = Event::kDora, // type .player = -1, // player .piece = static_cast( - state->walls.GetDoras()[0].toUint8_t()), // piece + Walls::GetDoras(*state)[0].toUint8_t()), // piece .decision = false, // decision }); diff --git a/src/types/gamestate.h b/src/types/gamestate.h index 2dd24668..7b582051 100644 --- a/src/types/gamestate.h +++ b/src/types/gamestate.h @@ -3,12 +3,12 @@ #include #include +#include "statefunction.h" #include "types/hand.h" #include "types/piecetype.h" #include "types/player.h" #include "types/settings.h" #include "types/statefunction.h" -#include "types/walls.h" namespace mahjong { @@ -23,11 +23,15 @@ struct GameState { bool concealedKan = false; uint64_t seed = 0; std::mt19937_64 g; + int doraCount = 1; Piece pendingPiece = Piece(Piece::Type::kError); StateFunctionType prevState; StateFunctionType currState; StateFunctionType nextState; - Walls walls; + std::array livingWall; + int livingWallIndex = 0; + std::array deadWall; + int deadWallIndex = 0; std::array scores = {}; std::array hasRonned = {}; std::array hands = {}; diff --git a/src/types/settings.h b/src/types/settings.h index 1378d14a..96d1f3f5 100644 --- a/src/types/settings.h +++ b/src/types/settings.h @@ -1,9 +1,8 @@ #pragma once +#include #include #include -#include "types/piecetype.h" - namespace mahjong { // TODO(#24): Support 3 player mahjong @@ -11,6 +10,12 @@ constexpr int kNumPlayers = 4; // TODO(#25): Support configuring parts of scoring constexpr int kStartingPoints = 25000; +constexpr int kTileCount = 136; +constexpr int kReplacementCount = kNumPlayers == 4 ? 4 : 8; +constexpr int kDoraCount = 5; +constexpr int kDeadWallCount = (2 * kDoraCount) + kReplacementCount; +constexpr int kLivingWallCount = kTileCount - kDeadWallCount; + struct GameSettings { std::vector seatControllers; uint64_t seed = 0; diff --git a/src/types/typeprinter.cc b/src/types/typeprinter.cc index 5f42a530..81b87ac2 100644 --- a/src/types/typeprinter.cc +++ b/src/types/typeprinter.cc @@ -15,7 +15,6 @@ #include "types/meld.h" #include "types/piecetype.h" #include "types/player.h" -#include "types/walls.h" std::ostream& operator<<(std::ostream& os, const mahjong::Event& e) { os << "{type: " << e.typeToStr(); @@ -48,7 +47,20 @@ std::ostream& operator<<(std::ostream& os, const mahjong::GameState& state) { for (size_t i = 0; i < state.players.size(); i++) { os << "player[" << i << "]: " << state.players.at(i) << '\n'; } - os << state.walls << '\n'; + os << "{ doraCount: " << state.doraCount; + os << " livingWall: [" << '\n'; + for (const auto& piece : state.livingWall) { + os << piece.toStr() << ", "; + } + os << "]" << '\n'; + os << " livingWallIndex: " << state.livingWallIndex; + os << " deadWall: [" << '\n'; + for (const auto& piece : state.deadWall) { + os << piece.toStr() << ", "; + } + os << "]" << '\n'; + os << " DeadWallIndex: " << state.deadWallIndex; + os << "}" << '\n'; return os; } @@ -99,23 +111,6 @@ std::ostream& operator<<(std::ostream& os, const mahjong::Meld& meld) { return os; } -std::ostream& operator<<(std::ostream& os, const mahjong::Walls& walls) { - os << "{ doraCount: " << walls.doraCount; - os << " replacements: " << walls.replacements; - os << " livingWalls: [" << '\n'; - for (const auto& piece : walls.livingWalls) { - os << piece.toStr() << ", "; - } - os << "]" << '\n'; - os << " deadWall: [" << '\n'; - for (const auto& piece : walls.deadWall) { - os << piece.toStr() << ", "; - } - os << "]" << '\n'; - os << "}"; - return os; -} - std::ostream& operator<<(std::ostream& os, const mahjong::Player& player) { os << "{ controller: " << ((player.controller != nullptr) ? player.controller->Name() diff --git a/src/types/walls.cc b/src/types/walls.cc index a1584711..90bb4718 100644 --- a/src/types/walls.cc +++ b/src/types/walls.cc @@ -3,11 +3,12 @@ #include #include #include -#include #include +#include "types/gamestate.h" #include "types/pieces.h" #include "types/piecetype.h" +#include "types/settings.h" namespace mahjong { @@ -22,99 +23,68 @@ const std::vector kPieceSet = { kGreenDragon, kRedDragon, kEastWind, kSouthWind, kNorthWind, kWestWind}; -Walls::Walls() { - std::random_device rd; - std::mt19937_64 g(rd()); - - for (int i = 0; i < 4; i++) { - livingWalls.insert(livingWalls.end(), kPieceSet.begin(), kPieceSet.end()); - } - std::shuffle(livingWalls.begin(), livingWalls.end(), g); - - std::move(livingWalls.begin(), livingWalls.begin() + 14, - std::back_inserter(deadWall)); - for (size_t i = 0; i < 14; i++) { - livingWalls.erase(livingWalls.begin()); - } -} - -Walls::Walls(std::mt19937_64& g) { - const std::vector wall; +void Walls::New(GameState& state) { + std::vector living_walls; + living_walls.reserve(kPieceSet.size() * 4); for (int i = 0; i < 4; i++) { - livingWalls.insert(livingWalls.end(), kPieceSet.begin(), kPieceSet.end()); + living_walls.insert(living_walls.end(), kPieceSet.begin(), kPieceSet.end()); } - std::shuffle(livingWalls.begin(), livingWalls.end(), g); + std::shuffle(living_walls.begin(), living_walls.end(), state.g); - std::move(livingWalls.begin(), livingWalls.begin() + 14, - std::back_inserter(deadWall)); - for (size_t i = 0; i < 14; i++) { - livingWalls.erase(livingWalls.begin()); + for (int i = 0; i < kLivingWallCount; ++i) { + state.livingWall[i] = living_walls[i]; } -} - -Walls::Walls(std::vector wall) { - std::swap(livingWalls, wall); - std::move(livingWalls.rbegin(), livingWalls.rbegin() + 14, - std::back_inserter(deadWall)); - for (size_t i = 0; i < 14; i++) { - livingWalls.pop_back(); + for (int i = 0; i < kDeadWallCount; ++i) { + state.deadWall[i] = living_walls[kLivingWallCount + i]; } } -Piece Walls::TakePiece() { - if (!livingWalls.empty()) { - const Piece p = livingWalls.front(); - livingWalls.erase(livingWalls.begin()); - return p; +Piece Walls::TakePiece(GameState& state) { + if (state.livingWallIndex == kLivingWallCount) { + return kError; } - return kError; + const Piece p = state.livingWall[state.livingWallIndex++]; + return p; } -std::vector Walls::TakeHand() { - if (livingWalls.size() < 13) { +std::vector Walls::TakeHand(GameState& state) { + if (state.livingWallIndex + 13 == kLivingWallCount) { return {}; } std::vector hand; - std::move(livingWalls.begin(), livingWalls.begin() + 13, - std::back_inserter(hand)); + hand.resize(13); for (size_t i = 0; i < 13; i++) { - livingWalls.erase(livingWalls.begin()); + hand[i] = state.livingWall[state.livingWallIndex++]; } return hand; } -Piece Walls::TakeReplacementTile() { - if (livingWalls.empty()) { +Piece Walls::TakeReplacementTile(GameState& state) { + if (state.deadWallIndex == kReplacementCount) { return kError; } - if (replacements < 1) { - return kError; - } - replacements--; - const Piece p = deadWall.front(); - deadWall.erase(deadWall.begin()); - deadWall.push_back(livingWalls.back()); - doraCount++; - livingWalls.pop_back(); + const Piece p = state.deadWall[state.deadWallIndex++]; + state.livingWallIndex++; + state.doraCount++; return p; } -std::vector Walls::GetDoras() const { +std::vector Walls::GetDoras(const GameState& state) { std::vector doras; - std::copy_n(deadWall.begin() + replacements, doraCount, + std::copy_n(state.deadWall.begin() + kReplacementCount, state.doraCount, std::back_inserter(doras)); return doras; } -std::vector Walls::GetUraDoras() const { +std::vector Walls::GetUraDoras(const GameState& state) { std::vector doras; - std::copy_n(deadWall.begin() + replacements + doraCount, doraCount, - std::back_inserter(doras)); + std::copy_n(state.deadWall.begin() + kReplacementCount + kDoraCount, + state.doraCount, std::back_inserter(doras)); return doras; } -int Walls::GetRemainingPieces() const { - return livingWalls.size(); +int Walls::GetRemainingPieces(const GameState& state) { + return kLivingWallCount - state.livingWallIndex; } } // namespace mahjong diff --git a/src/types/walls.h b/src/types/walls.h index f6a4c338..6f8001fd 100644 --- a/src/types/walls.h +++ b/src/types/walls.h @@ -1,24 +1,19 @@ #pragma once -#include #include #include "types/piecetype.h" +#include "piecetype.h" +#include "types/gamestate.h" namespace mahjong { class Walls { public: - explicit Walls(); - explicit Walls(std::mt19937_64& g); - explicit Walls(std::vector wall); - std::vector livingWalls; - std::vector deadWall; - int doraCount = 1; - int replacements = 4; - Piece TakePiece(); - std::vector TakeHand(); - Piece TakeReplacementTile(); - [[nodiscard]] std::vector GetDoras() const; - [[nodiscard]] std::vector GetUraDoras() const; - [[nodiscard]] int GetRemainingPieces() const; + static void New(GameState& state); + static Piece TakePiece(GameState& state); + static std::vector TakeHand(GameState& state); + static Piece TakeReplacementTile(GameState& state); + [[nodiscard]] static std::vector GetDoras(const GameState& state); + [[nodiscard]] static std::vector GetUraDoras(const GameState& state); + [[nodiscard]] static int GetRemainingPieces(const GameState& state); }; } // namespace mahjong diff --git a/tests/rules/basic_rules.test.cc b/tests/rules/basic_rules.test.cc index b8ae57bc..d42f7bd4 100644 --- a/tests/rules/basic_rules.test.cc +++ b/tests/rules/basic_rules.test.cc @@ -8,6 +8,7 @@ #include "types/gamestate.h" #include "types/settings.h" #include "types/statefunction.h" +#include "types/walls.h" #include "utils/gamestate_utils.h" namespace mahjong { @@ -53,11 +54,11 @@ TEST(RoundSetup, wall) { EXPECT_EQ(state->seed, 12345); // Check that walls were initialized correctly - EXPECT_EQ(state->walls.livingWalls.size(), 70); - EXPECT_EQ(state->walls.deadWall.size(), 14); + EXPECT_EQ(Walls::GetRemainingPieces(*state), 70); + EXPECT_EQ(state->deadWallIndex, 0); // Check that dora indicator is set - EXPECT_EQ(state->walls.GetDoras().size(), 1); + EXPECT_EQ(Walls::GetDoras(*state).size(), 1); } TEST(TurnOrder, initialPlayer) { @@ -103,7 +104,7 @@ TEST(DrawMechanics, drawIncreasesTileCount) { EXPECT_EQ(state->hands[i].live.size(), 13); } - const int walls_before = state->walls.GetRemainingPieces(); + const int walls_before = Walls::GetRemainingPieces(*state); // First player draws state = AdvanceGameState(std::move(state)); @@ -118,7 +119,7 @@ TEST(DrawMechanics, drawIncreasesTileCount) { } // Wall should have one less tile - EXPECT_EQ(state->walls.GetRemainingPieces(), walls_before - 1); + EXPECT_EQ(Walls::GetRemainingPieces(*state), walls_before - 1); } TEST(StateMachine, earlyGameTransitions) { diff --git a/tests/setup.test.cc b/tests/setup.test.cc index 4b8bb06a..d43bd923 100644 --- a/tests/setup.test.cc +++ b/tests/setup.test.cc @@ -35,7 +35,7 @@ TEST(Setup, DoraIndicator) { } ASSERT_NO_THROW(state = Router::Instance().Route( StateFunctionType::kRoundStart)(std::move(state))); - EXPECT_EQ(state->walls.GetDoras().size(), 1); + EXPECT_EQ(Walls::GetDoras(*state).size(), 1); } TEST(Setup, Dealing) { diff --git a/tests/yakus/concealedhand.test.cc b/tests/yakus/concealedhand.test.cc index f885fdfc..a3b23c49 100644 --- a/tests/yakus/concealedhand.test.cc +++ b/tests/yakus/concealedhand.test.cc @@ -2,12 +2,11 @@ #include #include -#include #include "scoring/yakus/fullyconcealedhand.h" #include "types/gamestate.h" #include "types/hand.h" -#include "types/walls.h" +#include "types/settings.h" #include "utils/handformer.h" namespace mahjong::yaku { @@ -45,7 +44,7 @@ TEST(isFullyConcealedHand, MustHavePiecesRemainingInWall) { game_state.currentPlayer = 0; // Empty the Wall - game_state.walls.livingWalls.clear(); + game_state.livingWallIndex = kLivingWallCount; EXPECT_FALSE(isFullyConcealedHand(game_state, 0)); } diff --git a/tests/yakus/underthesea.test.cc b/tests/yakus/underthesea.test.cc index 74d3d979..61cecdf7 100644 --- a/tests/yakus/underthesea.test.cc +++ b/tests/yakus/underthesea.test.cc @@ -2,15 +2,12 @@ #include #include -#include -#include #include "analysis/analysis.h" #include "analysis/handnode.h" #include "scoring/yakus/bottomofthesea.h" #include "types/gamestate.h" -#include "types/hand.h" -#include "types/walls.h" +#include "types/settings.h" #include "utils/handformer.h" namespace mahjong::yaku { @@ -18,7 +15,7 @@ namespace mahjong::yaku { TEST(isBottomOfTheSea, 1Han) { auto game_state = GameState(); game_state.hands[0] = Hand(HandFromNotation("123m789m111z999s55z")); - game_state.walls.livingWalls.clear(); + game_state.livingWallIndex = kLivingWallCount; auto root = breakdownHand(game_state.hands.at(0).live); @@ -34,7 +31,7 @@ TEST(isBottomOfTheSea, 1Han) { TEST(isBottomOfTheSea, 1HanRonned) { auto game_state = GameState(); game_state.hands[0] = Hand(HandFromNotation("123m789m111z999s55z")); - game_state.walls.livingWalls.clear(); + game_state.livingWallIndex = kLivingWallCount; game_state.hasRonned[0] = true; auto root = breakdownHand(game_state.hands.at(0).live); From e2dfa21f229ccf9ccdd4176e41b79760711eb06c Mon Sep 17 00:00:00 2001 From: alice Hartley Date: Tue, 26 Aug 2025 13:11:41 -0700 Subject: [PATCH 02/14] Embed Player directly. --- src/api/gamestate.cc | 2 +- src/statefunctions/gamestates/discard.cc | 3 +-- src/statefunctions/gamestates/gameend.cc | 5 ++--- src/statefunctions/gamestates/gamestart.cc | 5 ++--- src/statefunctions/gamestates/kandiscard.cc | 3 +-- src/statefunctions/gamestates/playerhand.cc | 3 +-- src/statefunctions/gamestates/roundend.cc | 9 ++++----- src/statefunctions/gamestates/roundstart.cc | 3 +-- src/statefunctions/statecontroller.cc | 5 ++--- src/statefunctions/stateutilities.cc | 7 +++---- src/types/CMakeLists.txt | 1 - src/types/gamestate.h | 6 +++--- src/types/player.h | 14 -------------- src/types/typeprinter.cc | 16 ++++++---------- tests/api/game_control.test.cc | 8 +++----- tests/rules/basic_rules.test.cc | 2 +- tests/setup.test.cc | 4 ++-- tests/utils/gamestate_utils.cc | 10 +++++----- tests/utils/gamestate_utils.test.cc | 2 +- 19 files changed, 39 insertions(+), 69 deletions(-) delete mode 100644 src/types/player.h diff --git a/src/api/gamestate.cc b/src/api/gamestate.cc index 6a5003d4..e531763e 100644 --- a/src/api/gamestate.cc +++ b/src/api/gamestate.cc @@ -141,7 +141,7 @@ CObservedGameState ObserveGameState(mahjong::GameState* state) { // Player data for (int i = 0; i < 4; i++) { observed.scores[i] = state->scores[i]; - observed.points[i] = state->players[i].points; + observed.points[i] = state->points[i]; observed.hasRonned[i] = state->hasRonned[i]; // Convert Hand to CHand diff --git a/src/statefunctions/gamestates/discard.cc b/src/statefunctions/gamestates/discard.cc index 66aaa6f3..3208c394 100644 --- a/src/statefunctions/gamestates/discard.cc +++ b/src/statefunctions/gamestates/discard.cc @@ -4,7 +4,6 @@ #include #include -#include "controllers/playercontroller.h" #include "statefunctions/decisionfunction.h" #include "statefunctions/router.h" #include "statefunctions/stateutilities.h" @@ -42,7 +41,7 @@ std::unique_ptr Discard(std::unique_ptr state) { for (const auto& [decision, decisionIsPossible] : decisions) { if (decisionIsPossible(*state, player)) { need_decision.at(player) = true; - state->players.at(player).controller->ReceiveEvent(Event{ + state->players.at(player)->ReceiveEvent(Event{ .type = decision, // type .player = state->currentPlayer, // player .piece = diff --git a/src/statefunctions/gamestates/gameend.cc b/src/statefunctions/gamestates/gameend.cc index d7b178e8..509a1d2c 100644 --- a/src/statefunctions/gamestates/gameend.cc +++ b/src/statefunctions/gamestates/gameend.cc @@ -4,7 +4,6 @@ #include "statefunctions/router.h" #include "types/event.h" #include "types/gamestate.h" -#include "types/player.h" #include "types/statefunction.h" namespace mahjong { @@ -12,8 +11,8 @@ namespace mahjong { namespace { std::unique_ptr GameEnd(std::unique_ptr state) { for (auto& player : state->players) { - player.controller->ReceiveEvent(kEndEvent); - player.controller.reset(); + player->ReceiveEvent(kEndEvent); + player.reset(); } return state; } diff --git a/src/statefunctions/gamestates/gamestart.cc b/src/statefunctions/gamestates/gamestart.cc index a978d141..5c446657 100644 --- a/src/statefunctions/gamestates/gamestart.cc +++ b/src/statefunctions/gamestates/gamestart.cc @@ -1,7 +1,6 @@ #include #include -#include "controllers/playercontroller.h" #include "statefunctions/router.h" #include "types/gamestate.h" #include "types/settings.h" @@ -12,8 +11,8 @@ namespace mahjong { namespace { std::unique_ptr GameStart(std::unique_ptr state) { for (int i = 0; i < 4; i++) { - state->players.at(i).points = kStartingPoints; - state->players.at(i).controller->GameStart(i); + state->points[i] = kStartingPoints; + state->players[i]->GameStart(i); } state->g.seed(state->seed); state->nextState = StateFunctionType::kRoundStart; diff --git a/src/statefunctions/gamestates/kandiscard.cc b/src/statefunctions/gamestates/kandiscard.cc index 11619c85..e287d034 100644 --- a/src/statefunctions/gamestates/kandiscard.cc +++ b/src/statefunctions/gamestates/kandiscard.cc @@ -2,7 +2,6 @@ #include #include -#include "controllers/playercontroller.h" #include "statefunctions/decisionfunction.h" #include "statefunctions/router.h" #include "statefunctions/stateutilities.h" @@ -23,7 +22,7 @@ std::unique_ptr KanDiscard(std::unique_ptr state) { if (CanRon(*state, player)) { need_decision.at(player) = true; state->players.at(state->currentPlayer) - .controller->ReceiveEvent(Event{ + ->ReceiveEvent(Event{ .type = Event::kRon, // type .player = state->currentPlayer, // player .piece = static_cast( diff --git a/src/statefunctions/gamestates/playerhand.cc b/src/statefunctions/gamestates/playerhand.cc index 4bd2a513..923d4cf7 100644 --- a/src/statefunctions/gamestates/playerhand.cc +++ b/src/statefunctions/gamestates/playerhand.cc @@ -4,7 +4,6 @@ #include #include -#include "controllers/playercontroller.h" #include "statefunctions/decisionfunction.h" #include "statefunctions/router.h" #include "statefunctions/stateutilities.h" @@ -32,7 +31,7 @@ std::unique_ptr PlayerHand(std::unique_ptr state) { if (decisionIsPossible(*state, state->currentPlayer)) { decision_asked = true; state->players.at(state->currentPlayer) - .controller->ReceiveEvent(Event{ + ->ReceiveEvent(Event{ .type = decision, // type .player = state->currentPlayer, // player .piece = static_cast( diff --git a/src/statefunctions/gamestates/roundend.cc b/src/statefunctions/gamestates/roundend.cc index 7beef2cf..50718b50 100644 --- a/src/statefunctions/gamestates/roundend.cc +++ b/src/statefunctions/gamestates/roundend.cc @@ -29,12 +29,11 @@ std::unique_ptr RoundEnd(std::unique_ptr state) { std::vector winners; int highscore = -100000; for (int i = 0; i < 4; i++) { - if (state->players.at(i).points + state->scores.at(i) > highscore) { - highscore = state->players.at(i).points + state->scores.at(i); + if (state->points[i] + state->scores.at(i) > highscore) { + highscore = state->points[i] + state->scores.at(i); winners.clear(); winners.push_back(i); - } else if (state->players.at(i).points + state->scores.at(i) == - highscore) { + } else if (state->points[i] + state->scores.at(i) == highscore) { winners.push_back(i); } } @@ -50,7 +49,7 @@ std::unique_ptr RoundEnd(std::unique_ptr state) { .player = i, .piece = static_cast(state->scores.at(i) / 100), .decision = false}); - state->players.at(i).points += state->scores.at(i); + state->points[i] += state->scores.at(i); } state->scores = {}; diff --git a/src/statefunctions/gamestates/roundstart.cc b/src/statefunctions/gamestates/roundstart.cc index 523162dc..02ed0106 100644 --- a/src/statefunctions/gamestates/roundstart.cc +++ b/src/statefunctions/gamestates/roundstart.cc @@ -4,7 +4,6 @@ #include #include -#include "controllers/playercontroller.h" #include "statefunctions/router.h" #include "statefunctions/stateutilities.h" #include "types/event.h" @@ -21,7 +20,7 @@ std::unique_ptr RoundStart(std::unique_ptr state) { Walls::New(*state); for (size_t i = 0; i < 4; i++) { auto hand = Walls::TakeHand(*state); - state->players.at(i).controller->RoundStart( + state->players.at(i)->RoundStart( hand, static_cast((i + 3 * (state->roundNum % 4)) % 4), (state->roundNum > 3) ? kSouth : kEast); state->hands.at(i) = Hand(hand); diff --git a/src/statefunctions/statecontroller.cc b/src/statefunctions/statecontroller.cc index 6f9a65c6..2ee0a069 100644 --- a/src/statefunctions/statecontroller.cc +++ b/src/statefunctions/statecontroller.cc @@ -42,9 +42,8 @@ void ExitGame(int game) { std::unique_ptr InitGameState(const GameSettings& settings) { auto state = std::make_unique(); for (int i = 0; i < 4; i++) { - state->players.at(i).controller = - ControllerManager::Instance().NewController( - settings.seatControllers.at(i)); + state->players.at(i) = ControllerManager::Instance().NewController( + settings.seatControllers.at(i)); } if (settings.seed != 0U) { state->seed = settings.seed; diff --git a/src/statefunctions/stateutilities.cc b/src/statefunctions/stateutilities.cc index 7e7a101c..c355584a 100644 --- a/src/statefunctions/stateutilities.cc +++ b/src/statefunctions/stateutilities.cc @@ -12,7 +12,6 @@ #include "types/event.h" #include "types/gamestate.h" #include "types/piecetype.h" -#include "types/player.h" #include "types/winds.h" namespace mahjong { @@ -25,7 +24,7 @@ Wind GetSeat(int round, int player) { void AlertPlayers(const GameState& state, Event e) { e.decision = false; for (const auto& player : state.players) { - player.controller->ReceiveEvent(e); + player->ReceiveEvent(e); } } @@ -61,7 +60,7 @@ void DiscardPiece(GameState& state, int player, Piece p) { Piece AskForDiscard(const GameState& state) { state.players.at(state.currentPlayer) - .controller->ReceiveEvent(Event{ + ->ReceiveEvent(Event{ .type = Event::kDiscard, // type .player = state.currentPlayer, // player .piece = 0, // piece @@ -98,7 +97,7 @@ Event GetValidDecisionOrThrow(const GameState& state, int player, bool inHand) { throw 0xBAD22222; } i++; - decision = state.players.at(player).controller->RetrieveDecision(); + decision = state.players.at(player)->RetrieveDecision(); valid = ValidateDecision(state, player, decision, inHand); } return decision; diff --git a/src/types/CMakeLists.txt b/src/types/CMakeLists.txt index 5fb3d06e..8f337895 100644 --- a/src/types/CMakeLists.txt +++ b/src/types/CMakeLists.txt @@ -12,7 +12,6 @@ target_sources( "meld.h" "pieces.h" "piecetype.h" - "player.h" "score.h" "settings.h" "statefunction.h" diff --git a/src/types/gamestate.h b/src/types/gamestate.h index 7b582051..9442553c 100644 --- a/src/types/gamestate.h +++ b/src/types/gamestate.h @@ -3,10 +3,9 @@ #include #include -#include "statefunction.h" +#include "controllers/playercontroller.h" #include "types/hand.h" #include "types/piecetype.h" -#include "types/player.h" #include "types/settings.h" #include "types/statefunction.h" @@ -35,7 +34,8 @@ struct GameState { std::array scores = {}; std::array hasRonned = {}; std::array hands = {}; - std::array players = {}; + std::array, kNumPlayers> players = {}; + std::array points = {}; }; } // namespace mahjong diff --git a/src/types/player.h b/src/types/player.h deleted file mode 100644 index 65a5f3ce..00000000 --- a/src/types/player.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include -#include - -#include "controllers/playercontroller.h" - -namespace mahjong { - -struct Player { - int points; - std::unique_ptr controller; -}; - -}; // namespace mahjong diff --git a/src/types/typeprinter.cc b/src/types/typeprinter.cc index 81b87ac2..e15d8ed3 100644 --- a/src/types/typeprinter.cc +++ b/src/types/typeprinter.cc @@ -14,7 +14,6 @@ #include "types/hand.h" #include "types/meld.h" #include "types/piecetype.h" -#include "types/player.h" std::ostream& operator<<(std::ostream& os, const mahjong::Event& e) { os << "{type: " << e.typeToStr(); @@ -45,7 +44,12 @@ std::ostream& operator<<(std::ostream& os, const mahjong::GameState& state) { } os << "players: " << '\n'; for (size_t i = 0; i < state.players.size(); i++) { - os << "player[" << i << "]: " << state.players.at(i) << '\n'; + os << "player[" << i << "]: "; + os << "{ controller: " + << ((state.players[i] != nullptr) ? state.players[i]->Name() + : "NULLPTR"); + os << " points: " << state.points[i]; + os << '\n'; } os << "{ doraCount: " << state.doraCount; os << " livingWall: [" << '\n'; @@ -110,11 +114,3 @@ std::ostream& operator<<(std::ostream& os, const mahjong::Meld& meld) { os << ", start: " << meld.start.toStr() << "}"; return os; } - -std::ostream& operator<<(std::ostream& os, const mahjong::Player& player) { - os << "{ controller: " - << ((player.controller != nullptr) ? player.controller->Name() - : "NULLPTR"); - os << " points: " << player.points; - return os; -} diff --git a/tests/api/game_control.test.cc b/tests/api/game_control.test.cc index 06d15f1a..01710a36 100644 --- a/tests/api/game_control.test.cc +++ b/tests/api/game_control.test.cc @@ -7,7 +7,6 @@ #include "api/gamestate.h" #include "api/types.h" -#include "controllers/playercontroller.h" #include "types/gamestate.h" #include "types/hand.h" #include "types/piecetype.h" @@ -37,8 +36,7 @@ TEST(Api, SettingsConversion) { EXPECT_EQ(state->seed, settings.seed); EXPECT_EQ(state->players.size(), settings.num_controllers); for (uint64_t i = 0; i < state->players.size(); ++i) { - EXPECT_EQ(state->players[i].controller->Name(), - settings.seat_controllers[i]); + EXPECT_EQ(state->players[i]->Name(), settings.seat_controllers[i]); } api::FreeGameState(state); } @@ -86,7 +84,7 @@ TEST(Api, ObserveGameState) { // Check arrays are properly sized and initialized for (int i = 0; i < 4; i++) { EXPECT_EQ(observed.scores[i], state->scores[i]); - EXPECT_EQ(observed.points[i], state->players[i].points); + EXPECT_EQ(observed.points[i], state->points[i]); EXPECT_EQ(observed.hasRonned[i], state->hasRonned[i]); } @@ -127,7 +125,7 @@ TEST(Api, ObserveGameStateAfterAdvancement) { // Check points are copied for (int i = 0; i < 4; i++) { - EXPECT_EQ(observed.points[i], state->players[i].points); + EXPECT_EQ(observed.points[i], state->points[i]); } api::FreeGameState(state); diff --git a/tests/rules/basic_rules.test.cc b/tests/rules/basic_rules.test.cc index d42f7bd4..3c3bdf4d 100644 --- a/tests/rules/basic_rules.test.cc +++ b/tests/rules/basic_rules.test.cc @@ -29,7 +29,7 @@ TEST(GameSetup, playerScore) { EXPECT_EQ(state->currState, StateFunctionType::kGameStart); // All players have the expected starting points for (int i = 0; i < kNumPlayers; i++) { - EXPECT_EQ(state->players[i].points, kStartingPoints); + EXPECT_EQ(state->points[i], kStartingPoints); } } diff --git a/tests/setup.test.cc b/tests/setup.test.cc index d43bd923..87aba0ab 100644 --- a/tests/setup.test.cc +++ b/tests/setup.test.cc @@ -31,7 +31,7 @@ TEST(Setup, PrevalentWind) { TEST(Setup, DoraIndicator) { std::unique_ptr state = std::make_unique(); for (int i = 0; i < 4; i++) { - state->players[i].controller = std::make_unique(); + state->players[i] = std::make_unique(); } ASSERT_NO_THROW(state = Router::Instance().Route( StateFunctionType::kRoundStart)(std::move(state))); @@ -41,7 +41,7 @@ TEST(Setup, DoraIndicator) { TEST(Setup, Dealing) { std::unique_ptr state = std::make_unique(); for (int i = 0; i < 4; i++) { - state->players[i].controller = std::make_unique(); + state->players[i] = std::make_unique(); } ASSERT_NO_THROW(state = Router::Instance().Route( StateFunctionType::kRoundStart)(std::move(state))); diff --git a/tests/utils/gamestate_utils.cc b/tests/utils/gamestate_utils.cc index 4dec921d..96066945 100644 --- a/tests/utils/gamestate_utils.cc +++ b/tests/utils/gamestate_utils.cc @@ -53,7 +53,7 @@ std::unique_ptr CreateTestGameState(uint64_t seed) { auto state = std::make_unique(); state->seed = seed; for (int i = 0; i < kNumPlayers; i++) { - state->players[i].controller = std::make_unique(); + state->players[i] = std::make_unique(); } state->nextState = StateFunctionType::kGameStart; return state; @@ -71,19 +71,19 @@ std::unique_ptr InitializeTestRound( std::min(playerControllers.size(), static_cast(kNumPlayers)); for (size_t i = 0; i < num_players; i++) { if (playerControllers[i]) { - state->players[i].controller = std::move(playerControllers[i]); + state->players[i] = std::move(playerControllers[i]); } else { - state->players[i].controller = std::make_unique(); + state->players[i] = std::make_unique(); } } // Fill remaining players with default controllers for (size_t i = num_players; i < kNumPlayers; i++) { - state->players[i].controller = std::make_unique(); + state->players[i] = std::make_unique(); } } else { // All players get default fake controllers for (int i = 0; i < kNumPlayers; i++) { - state->players[i].controller = std::make_unique(); + state->players[i] = std::make_unique(); } } diff --git a/tests/utils/gamestate_utils.test.cc b/tests/utils/gamestate_utils.test.cc index 329603a1..9aceb382 100644 --- a/tests/utils/gamestate_utils.test.cc +++ b/tests/utils/gamestate_utils.test.cc @@ -44,7 +44,7 @@ TEST(GameStateUtils, InitializeTestRoundDefault) { // All players are filled with a controller for (int i = 0; i < kNumPlayers; i++) { - EXPECT_NE(state->players[i].controller, nullptr); + EXPECT_NE(state->players[i], nullptr); } // Draw occurred From b785beab29802d1c1c08babaa64ad7982227698a Mon Sep 17 00:00:00 2001 From: alice Hartley Date: Tue, 26 Aug 2025 16:37:54 -0700 Subject: [PATCH 03/14] Move hand into gamestate.h --- src/statefunctions/decisionfunction.cc | 1 - src/statefunctions/gamestates/chi.cc | 1 - src/statefunctions/gamestates/draw.cc | 1 - src/statefunctions/gamestates/kan.cc | 1 - src/statefunctions/gamestates/pon.cc | 1 - src/statefunctions/gamestates/replacement.cc | 1 - src/statefunctions/gamestates/ron.cc | 1 - src/statefunctions/gamestates/roundstart.cc | 3 +-- src/types/CMakeLists.txt | 1 - src/types/gamestate.h | 12 ++++++++- src/types/hand.h | 26 -------------------- src/types/typeprinter.cc | 1 - src/types/typeprinter.h | 2 +- tests/api/game_control.test.cc | 1 - tests/game_play.test.cc | 3 +-- tests/yakus/afterkan.test.cc | 7 +++--- tests/yakus/allpon.test.cc | 9 +++---- tests/yakus/allsimples.test.cc | 7 +++--- tests/yakus/allterminalsandhonors.test.cc | 7 +++--- tests/yakus/blessingofman.test.cc | 9 +++---- tests/yakus/concealedhand.test.cc | 9 +++---- tests/yakus/concealedpon.test.cc | 11 ++++----- tests/yakus/dragonpon.test.cc | 13 +++++----- tests/yakus/fullflush.test.cc | 11 ++++----- tests/yakus/halfflush.test.cc | 9 +++---- tests/yakus/littlethreedragons.test.cc | 7 +++--- tests/yakus/mixedtriplechi.test.cc | 7 +++--- tests/yakus/outsidehand.test.cc | 9 +++---- tests/yakus/pinfu.test.cc | 9 +++---- tests/yakus/puredoublechi.test.cc | 7 +++--- tests/yakus/purestraight.test.cc | 7 +++--- tests/yakus/riichi.test.cc | 9 +++---- tests/yakus/robbingkan.test.cc | 5 ++-- tests/yakus/sevenpairs.test.cc | 7 +++--- tests/yakus/terminalinsets.test.cc | 7 +++--- tests/yakus/triplekan.test.cc | 9 +++---- tests/yakus/triplepon.test.cc | 5 ++-- tests/yakus/twicepuredoublechi.test.cc | 7 +++--- tests/yakus/underthesea.test.cc | 6 ++--- tests/yakus/windpons.test.cc | 17 ++++++------- 40 files changed, 107 insertions(+), 159 deletions(-) delete mode 100644 src/types/hand.h diff --git a/src/statefunctions/decisionfunction.cc b/src/statefunctions/decisionfunction.cc index 0cfd94a0..317890ff 100644 --- a/src/statefunctions/decisionfunction.cc +++ b/src/statefunctions/decisionfunction.cc @@ -27,7 +27,6 @@ bool CanRon(const GameState& state, int player) { // Build the theoretical hand auto& tmp_state = const_cast(state); tmp_state.hands.at(player).live.push_back(state.pendingPiece); - tmp_state.hands.at(player).sort(); // If this Ron is occurring due to a concealed kan discard, if (state.concealedKan) { diff --git a/src/statefunctions/gamestates/chi.cc b/src/statefunctions/gamestates/chi.cc index d8b01d1f..4cad84ae 100644 --- a/src/statefunctions/gamestates/chi.cc +++ b/src/statefunctions/gamestates/chi.cc @@ -60,7 +60,6 @@ std::unique_ptr Chi(std::unique_ptr state) { }); state->hands.at(state->lastCaller).live.push_back(state->pendingPiece); - state->hands.at(state->lastCaller).sort(); state->lastCall = state->turnNum; state->concealedKan = false; state->turnNum++; diff --git a/src/statefunctions/gamestates/draw.cc b/src/statefunctions/gamestates/draw.cc index 24131dfc..b167c58c 100644 --- a/src/statefunctions/gamestates/draw.cc +++ b/src/statefunctions/gamestates/draw.cc @@ -14,7 +14,6 @@ std::unique_ptr Draw(std::unique_ptr state) { state->turnNum++; state->pendingPiece = Walls::TakePiece(*state); state->hands.at(state->currentPlayer).live.push_back(state->pendingPiece); - state->hands.at(state->currentPlayer).sort(); state->nextState = StateFunctionType::kPlayerHand; return state; } diff --git a/src/statefunctions/gamestates/kan.cc b/src/statefunctions/gamestates/kan.cc index 3b75e01d..901f3036 100644 --- a/src/statefunctions/gamestates/kan.cc +++ b/src/statefunctions/gamestates/kan.cc @@ -33,7 +33,6 @@ std::unique_ptr Kan(std::unique_ptr state) { state->hands.at(state->lastCaller).open = true; state->currentPlayer = state->lastCaller; state->hands.at(state->lastCaller).live.push_back(state->pendingPiece); - state->hands.at(state->lastCaller).sort(); state->lastCall = state->turnNum; state->concealedKan = false; state->turnNum++; diff --git a/src/statefunctions/gamestates/pon.cc b/src/statefunctions/gamestates/pon.cc index 6628e23c..25f39b83 100644 --- a/src/statefunctions/gamestates/pon.cc +++ b/src/statefunctions/gamestates/pon.cc @@ -34,7 +34,6 @@ std::unique_ptr Pon(std::unique_ptr state) { state->currentPlayer = state->lastCaller; state->hands.at(state->lastCaller).live.push_back(state->pendingPiece); - state->hands.at(state->lastCaller).sort(); state->lastCall = state->turnNum; state->concealedKan = false; state->turnNum++; diff --git a/src/statefunctions/gamestates/replacement.cc b/src/statefunctions/gamestates/replacement.cc index de0189d8..95c1b07b 100644 --- a/src/statefunctions/gamestates/replacement.cc +++ b/src/statefunctions/gamestates/replacement.cc @@ -16,7 +16,6 @@ namespace { std::unique_ptr Replacement(std::unique_ptr state) { const Piece draw = Walls::TakeReplacementTile(*state); state->hands.at(state->currentPlayer).live.push_back(draw); - state->hands.at(state->currentPlayer).sort(); state->pendingPiece = draw; AlertPlayers(*state, diff --git a/src/statefunctions/gamestates/ron.cc b/src/statefunctions/gamestates/ron.cc index ccc24046..203e9821 100644 --- a/src/statefunctions/gamestates/ron.cc +++ b/src/statefunctions/gamestates/ron.cc @@ -16,7 +16,6 @@ namespace mahjong { namespace { std::unique_ptr Ron(std::unique_ptr state) { state->hands.at(state->lastCaller).live.push_back(state->pendingPiece); - state->hands.at(state->lastCaller).sort(); std::array basic_points = {}; if (state->hands.at(state->currentPlayer).riichi && diff --git a/src/statefunctions/gamestates/roundstart.cc b/src/statefunctions/gamestates/roundstart.cc index 02ed0106..452fb004 100644 --- a/src/statefunctions/gamestates/roundstart.cc +++ b/src/statefunctions/gamestates/roundstart.cc @@ -8,7 +8,6 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/statefunction.h" #include "types/walls.h" #include "types/winds.h" @@ -23,7 +22,7 @@ std::unique_ptr RoundStart(std::unique_ptr state) { state->players.at(i)->RoundStart( hand, static_cast((i + 3 * (state->roundNum % 4)) % 4), (state->roundNum > 3) ? kSouth : kEast); - state->hands.at(i) = Hand(hand); + state->hands.at(i).live = hand; } AlertPlayers(*state, diff --git a/src/types/CMakeLists.txt b/src/types/CMakeLists.txt index 8f337895..93bd26bb 100644 --- a/src/types/CMakeLists.txt +++ b/src/types/CMakeLists.txt @@ -8,7 +8,6 @@ target_sources( FILES "event.h" "gamestate.h" - "hand.h" "meld.h" "pieces.h" "piecetype.h" diff --git a/src/types/gamestate.h b/src/types/gamestate.h index 9442553c..ee41d364 100644 --- a/src/types/gamestate.h +++ b/src/types/gamestate.h @@ -4,13 +4,23 @@ #include #include "controllers/playercontroller.h" -#include "types/hand.h" +#include "types/meld.h" #include "types/piecetype.h" #include "types/settings.h" #include "types/statefunction.h" namespace mahjong { +struct Hand { + std::vector live; + std::vector melds; + std::vector discards; + bool open = false; + bool riichi = false; + size_t riichiPieceDiscard = -1; + int riichiRound = -1; +}; + struct GameState { int currentPlayer = -1; int turnNum = -1; diff --git a/src/types/hand.h b/src/types/hand.h deleted file mode 100644 index 69476c81..00000000 --- a/src/types/hand.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include -#include -#include -#include - -#include "types/meld.h" -#include "types/piecetype.h" - -namespace mahjong { - -class Hand { - public: - Hand() = default; - explicit Hand(std::vector live) : live(std::move(std::move(live))) {} - void sort() { std::ranges::sort(live); } - std::vector live; - std::vector melds; - std::vector discards; - bool open = false; - bool riichi = false; - size_t riichiPieceDiscard = -1; - int riichiRound = -1; -}; - -} // namespace mahjong diff --git a/src/types/typeprinter.cc b/src/types/typeprinter.cc index e15d8ed3..a02fc854 100644 --- a/src/types/typeprinter.cc +++ b/src/types/typeprinter.cc @@ -11,7 +11,6 @@ #include "controllers/playercontroller.h" #include "types/event.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/meld.h" #include "types/piecetype.h" diff --git a/src/types/typeprinter.h b/src/types/typeprinter.h index 30ecc47b..ef36eff5 100644 --- a/src/types/typeprinter.h +++ b/src/types/typeprinter.h @@ -5,7 +5,7 @@ namespace mahjong { struct Event; struct GameState; -class Hand; +struct Hand; class Node; struct Meld; class Walls; diff --git a/tests/api/game_control.test.cc b/tests/api/game_control.test.cc index 01710a36..136d1b62 100644 --- a/tests/api/game_control.test.cc +++ b/tests/api/game_control.test.cc @@ -8,7 +8,6 @@ #include "api/gamestate.h" #include "api/types.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/piecetype.h" namespace { diff --git a/tests/game_play.test.cc b/tests/game_play.test.cc index 96e45639..669894f1 100644 --- a/tests/game_play.test.cc +++ b/tests/game_play.test.cc @@ -5,7 +5,6 @@ #include "scoring/scoring.h" #include "statefunctions/decisionfunction.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/pieces.h" #include "types/piecetype.h" #include "utils/handformer.h" @@ -14,7 +13,7 @@ namespace mahjong { TEST(GamePlay, Furiten) { auto state = GameState(); - state.hands[0] = Hand(HandFromNotation("123m456p234678s44m")); + state.hands[0].live = HandFromNotation("123m456p234678s44m"); state.hands[0].open = false; EXPECT_TRUE(isComplete(state, 0)); state.pendingPiece = Piece(kFourPin); diff --git a/tests/yakus/afterkan.test.cc b/tests/yakus/afterkan.test.cc index 1fe6e965..33d91c5a 100644 --- a/tests/yakus/afterkan.test.cc +++ b/tests/yakus/afterkan.test.cc @@ -8,7 +8,6 @@ #include "analysis/handnode.h" #include "scoring/yakus/afterakan.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/statefunction.h" #include "utils/handformer.h" @@ -16,7 +15,7 @@ namespace mahjong::yaku { TEST(isAfterAKan, 1Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m789m1111z999s55z")); + game_state.hands[0].live = HandFromNotation("123m789m1111z999s55z"); game_state.currentPlayer = 0; game_state.prevState = StateFunctionType::kReplacement; @@ -34,7 +33,7 @@ TEST(isAfterAKan, 1Han) { TEST(isAfterAKan, DoesntApply) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m789m1111z999s55z")); + game_state.hands[0].live = HandFromNotation("123m789m1111z999s55z"); game_state.currentPlayer = 0; game_state.prevState = StateFunctionType::kPon; @@ -52,7 +51,7 @@ TEST(isAfterAKan, DoesntApply) { TEST(isAfterAKan, WrongPlayer) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m789m1111z999s55z")); + game_state.hands[0].live = HandFromNotation("123m789m1111z999s55z"); game_state.currentPlayer = 2; game_state.prevState = StateFunctionType::kReplacement; diff --git a/tests/yakus/allpon.test.cc b/tests/yakus/allpon.test.cc index 40cd0392..a134d54e 100644 --- a/tests/yakus/allpon.test.cc +++ b/tests/yakus/allpon.test.cc @@ -9,7 +9,6 @@ #include "analysis/handnode.h" #include "scoring/yakus/allpons.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" @@ -20,7 +19,7 @@ namespace mahjong::yaku { TEST(isAllPons, 2Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m222p888s666z44m")); + game_state.hands[0].live = HandFromNotation("111m222p888s666z44m"); auto root = breakdownHand(game_state.hands.at(0).live); @@ -40,7 +39,7 @@ TEST(isAllPons, WithKans) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m222p666z44m")); + game_state.hands[0].live = HandFromNotation("111m222p666z44m"); game_state.hands[0].melds = {meld}; game_state.hands[0].open = true; @@ -62,7 +61,7 @@ TEST(isAllPons, ConcealedKan) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m222p666z44m")); + game_state.hands[0].live = HandFromNotation("111m222p666z44m"); game_state.hands[0].melds = {meld}; game_state.hands[0].open = false; @@ -79,7 +78,7 @@ TEST(isAllPons, ConcealedKan) { TEST(isAllPons, BadHand) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m222p666z789m44m")); + game_state.hands[0].live = HandFromNotation("111m222p666z789m44m"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); diff --git a/tests/yakus/allsimples.test.cc b/tests/yakus/allsimples.test.cc index 41d9d483..f40f3a57 100644 --- a/tests/yakus/allsimples.test.cc +++ b/tests/yakus/allsimples.test.cc @@ -9,14 +9,13 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" -#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { TEST(isAllSimples, 1Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("222m333p444s555p88m")); + game_state.hands[0].live = HandFromNotation("222m333p444s555p88m"); auto root = breakdownHand(game_state.hands.at(0).live); @@ -31,7 +30,7 @@ TEST(isAllSimples, 1Han) { TEST(isAllSimples, BadHandHonors) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("222m333p444s111z88m")); + game_state.hands[0].live = HandFromNotation("222m333p444s111z88m"); auto root = breakdownHand(game_state.hands.at(0).live); @@ -46,7 +45,7 @@ TEST(isAllSimples, BadHandHonors) { TEST(isAllSimples, BadHandTerminals) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("222m333p444s111m88m")); + game_state.hands[0].live = HandFromNotation("222m333p444s111m88m"); auto root = breakdownHand(game_state.hands.at(0).live); diff --git a/tests/yakus/allterminalsandhonors.test.cc b/tests/yakus/allterminalsandhonors.test.cc index 30c4da92..77c8f761 100644 --- a/tests/yakus/allterminalsandhonors.test.cc +++ b/tests/yakus/allterminalsandhonors.test.cc @@ -10,7 +10,6 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" @@ -21,7 +20,7 @@ namespace mahjong::yaku { TEST(isAllTerminalsAndHonors, 2Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("222z111p111m999s66z")); + game_state.hands[0].live = HandFromNotation("222z111p111m999s66z"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -37,7 +36,7 @@ TEST(isAllTerminalsAndHonors, 2Han) { TEST(isAllTerminalsAndHonors, BadHand) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("222z111p111m888s66z")); + game_state.hands[0].live = HandFromNotation("222z111p111m888s66z"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -58,7 +57,7 @@ TEST(isAllTerminalsAndHonors, CanBeOpen) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("222z111m999s66z")); + game_state.hands[0].live = HandFromNotation("222z111m999s66z"); game_state.hands[0].open = true; game_state.hands[0].melds = {meld}; diff --git a/tests/yakus/blessingofman.test.cc b/tests/yakus/blessingofman.test.cc index 571eada4..0f35b8d4 100644 --- a/tests/yakus/blessingofman.test.cc +++ b/tests/yakus/blessingofman.test.cc @@ -9,13 +9,12 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" -#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { TEST(isBlessingOfMan, 5Han) { auto game_state = GameState(); - game_state.hands[3] = Hand(HandFromNotation("123m123p444m111z55m")); + game_state.hands[3].live = HandFromNotation("123m123p444m111z55m"); game_state.hands[3].open = false; game_state.turnNum = 1; @@ -38,7 +37,7 @@ TEST(isBlessingOfMan, 5Han) { TEST(isBlessingOfMan, MustBeARon) { auto game_state = GameState(); - game_state.hands[3] = Hand(HandFromNotation("123m123p444m111z55m")); + game_state.hands[3].live = HandFromNotation("123m123p444m111z55m"); game_state.hands[3].open = false; game_state.turnNum = 3; @@ -61,7 +60,7 @@ TEST(isBlessingOfMan, MustBeARon) { TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m123p444m111z55m")); + game_state.hands[0].live = HandFromNotation("123m123p444m111z55m"); game_state.hands[0].open = false; game_state.turnNum = 2; @@ -84,7 +83,7 @@ TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { TEST(isBlessingOfMan, NoCalledMustHaveOccured) { auto game_state = GameState(); - game_state.hands[3] = Hand(HandFromNotation("123m123p444m111z55m")); + game_state.hands[3].live = HandFromNotation("123m123p444m111z55m"); game_state.hands[3].open = false; game_state.turnNum = 1; diff --git a/tests/yakus/concealedhand.test.cc b/tests/yakus/concealedhand.test.cc index a3b23c49..7f7ca288 100644 --- a/tests/yakus/concealedhand.test.cc +++ b/tests/yakus/concealedhand.test.cc @@ -5,14 +5,13 @@ #include "scoring/yakus/fullyconcealedhand.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/settings.h" #include "utils/handformer.h" namespace mahjong::yaku { TEST(isFullyConcealedHand, 1Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("555m555p555s111z44m")); + game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); game_state.hands[0].open = false; game_state.currentPlayer = 0; @@ -21,7 +20,7 @@ TEST(isFullyConcealedHand, 1Han) { TEST(isFullyConcealedHand, MustTsumo) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("555m555p555s111z44m")); + game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); game_state.hands[0].open = false; game_state.currentPlayer = 1; @@ -30,7 +29,7 @@ TEST(isFullyConcealedHand, MustTsumo) { TEST(isFullyConcealedHand, MustBeClosedHand) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("555m555p555s111z44m")); + game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); game_state.hands[0].open = true; game_state.currentPlayer = 0; @@ -39,7 +38,7 @@ TEST(isFullyConcealedHand, MustBeClosedHand) { TEST(isFullyConcealedHand, MustHavePiecesRemainingInWall) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("555m555p555s111z44m")); + game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); game_state.hands[0].open = false; game_state.currentPlayer = 0; diff --git a/tests/yakus/concealedpon.test.cc b/tests/yakus/concealedpon.test.cc index 4f13e3ee..4370fe90 100644 --- a/tests/yakus/concealedpon.test.cc +++ b/tests/yakus/concealedpon.test.cc @@ -9,7 +9,6 @@ #include "analysis/handnode.h" #include "scoring/yakus/threeconcealedpons.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" @@ -19,7 +18,7 @@ namespace mahjong::yaku { TEST(isThreeConcealedPons, 2Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m111p111s666z44m")); + game_state.hands[0].live = HandFromNotation("111m111p111s666z44m"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -39,7 +38,7 @@ TEST(isThreeConcealedPons, PonsMustBeConcealed) { meld.start = Piece(kTwoBamboo); auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m111p111s44m")); + game_state.hands[0].live = HandFromNotation("111m111p111s44m"); game_state.hands[0].melds.push_back(meld); game_state.hands[0].open = true; @@ -60,7 +59,7 @@ TEST(isThreeConcealedPons, CanHaveAdditionalOpenPon) { meld.start = Piece(kTwoBamboo); auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m111p111s44m")); + game_state.hands[0].live = HandFromNotation("111m111p111s44m"); game_state.hands[0].melds.push_back(meld); game_state.hands[0].open = true; @@ -81,7 +80,7 @@ TEST(isThreeConcealedPons, PonsMustBeConcealedNegative) { meld.start = Piece(kOneBamboo); auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m111p234s44m")); + game_state.hands[0].live = HandFromNotation("111m111p234s44m"); game_state.hands[0].melds.push_back(meld); game_state.hands[0].open = true; @@ -98,7 +97,7 @@ TEST(isThreeConcealedPons, PonsMustBeConcealedNegative) { TEST(isThreeConcealedPons, BadHand) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m111p234567s44m")); + game_state.hands[0].live = HandFromNotation("111m111p234567s44m"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); diff --git a/tests/yakus/dragonpon.test.cc b/tests/yakus/dragonpon.test.cc index 9d95487b..258ae63e 100644 --- a/tests/yakus/dragonpon.test.cc +++ b/tests/yakus/dragonpon.test.cc @@ -8,14 +8,13 @@ #include "analysis/handnode.h" #include "scoring/yakus/honorpon.h" #include "types/gamestate.h" -#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { TEST(isWindOrDragonPon, WhiteDragon) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m555z11z")); + game_state.hands[0].live = HandFromNotation("123m456m555z11z"); auto root = breakdownHand(game_state.hands.at(0).live); @@ -30,7 +29,7 @@ TEST(isWindOrDragonPon, WhiteDragon) { TEST(isWindOrDragonPon, GreenDragon) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m666z11z")); + game_state.hands[0].live = HandFromNotation("123m456m666z11z"); auto root = breakdownHand(game_state.hands.at(0).live); @@ -45,7 +44,7 @@ TEST(isWindOrDragonPon, GreenDragon) { TEST(isWindOrDragonPon, RedDragon) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m777z11z")); + game_state.hands[0].live = HandFromNotation("123m456m777z11z"); auto root = breakdownHand(game_state.hands.at(0).live); @@ -60,7 +59,7 @@ TEST(isWindOrDragonPon, RedDragon) { TEST(isWindOrDragonPon, Kan) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m7777z11z")); + game_state.hands[0].live = HandFromNotation("123m456m7777z11z"); auto root = breakdownHand(game_state.hands.at(0).live); @@ -75,7 +74,7 @@ TEST(isWindOrDragonPon, Kan) { TEST(isWindOrDragonPon, CanWhenOpen) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m777z11z")); + game_state.hands[0].live = HandFromNotation("123m456m777z11z"); game_state.hands[0].open = true; auto root = breakdownHand(game_state.hands.at(0).live); @@ -91,7 +90,7 @@ TEST(isWindOrDragonPon, CanWhenOpen) { TEST(isWindOrDragonPon, BadHand) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m222p11p")); + game_state.hands[0].live = HandFromNotation("123m456m222p11p"); auto root = breakdownHand(game_state.hands.at(0).live); diff --git a/tests/yakus/fullflush.test.cc b/tests/yakus/fullflush.test.cc index 2fc2f669..dc6888ae 100644 --- a/tests/yakus/fullflush.test.cc +++ b/tests/yakus/fullflush.test.cc @@ -10,7 +10,6 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" @@ -26,7 +25,7 @@ TEST(isFullFlush, 5Han) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m222m345m99m")); + game_state.hands[0].live = HandFromNotation("111m222m345m99m"); game_state.hands[0].open = true; game_state.hands[0].melds = {meld}; @@ -43,7 +42,7 @@ TEST(isFullFlush, 5Han) { TEST(isFullFlush, 6Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m222m345m666m99m")); + game_state.hands[0].live = HandFromNotation("111m222m345m666m99m"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -59,7 +58,7 @@ TEST(isFullFlush, 6Han) { TEST(isFullFlush, BadHandHonors) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m222m111z666m99m")); + game_state.hands[0].live = HandFromNotation("111m222m111z666m99m"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -75,7 +74,7 @@ TEST(isFullFlush, BadHandHonors) { TEST(isFullFlush, BadHandSuit) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m222m111p666m99m")); + game_state.hands[0].live = HandFromNotation("111m222m111p666m99m"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -91,7 +90,7 @@ TEST(isFullFlush, BadHandSuit) { TEST(isFullFlush, BadHandFullFlushHonors) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111z222z333z444z55z")); + game_state.hands[0].live = HandFromNotation("111z222z333z444z55z"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); diff --git a/tests/yakus/halfflush.test.cc b/tests/yakus/halfflush.test.cc index ad990f14..0e0e318f 100644 --- a/tests/yakus/halfflush.test.cc +++ b/tests/yakus/halfflush.test.cc @@ -10,7 +10,6 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" @@ -26,7 +25,7 @@ TEST(isHalfFlush, 2Han) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("11m234m111z222z")); + game_state.hands[0].live = HandFromNotation("11m234m111z222z"); game_state.hands[0].open = true; game_state.hands[0].melds = {meld}; @@ -43,7 +42,7 @@ TEST(isHalfFlush, 2Han) { TEST(isHalfFlush, 3Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("11m234m777m111z222z")); + game_state.hands[0].live = HandFromNotation("11m234m777m111z222z"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -64,7 +63,7 @@ TEST(isHalfFlush, BadHand) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("11m234m111p222z")); + game_state.hands[0].live = HandFromNotation("11m234m111p222z"); game_state.hands[0].open = true; game_state.hands[0].melds = {meld}; @@ -86,7 +85,7 @@ TEST(isHalfFlush, FullFlushIncompatible) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("11m234m888m777m")); + game_state.hands[0].live = HandFromNotation("11m234m888m777m"); game_state.hands[0].open = true; game_state.hands[0].melds = {meld}; diff --git a/tests/yakus/littlethreedragons.test.cc b/tests/yakus/littlethreedragons.test.cc index f5814caa..d20802f4 100644 --- a/tests/yakus/littlethreedragons.test.cc +++ b/tests/yakus/littlethreedragons.test.cc @@ -10,7 +10,6 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" @@ -21,7 +20,7 @@ namespace mahjong::yaku { TEST(isLittleThreeDragons, 2Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("555z666z111m222p77z")); + game_state.hands[0].live = HandFromNotation("555z666z111m222p77z"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -42,7 +41,7 @@ TEST(isLittleThreeDragons, WhenOpen) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("666z111m222p77z")); + game_state.hands[0].live = HandFromNotation("666z111m222p77z"); game_state.hands[0].open = true; game_state.hands[0].melds = {meld}; @@ -64,7 +63,7 @@ TEST(isLittleThreeDragons, BadHand) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("666z111m222p77s")); + game_state.hands[0].live = HandFromNotation("666z111m222p77s"); game_state.hands[0].open = true; game_state.hands[0].melds = {meld}; diff --git a/tests/yakus/mixedtriplechi.test.cc b/tests/yakus/mixedtriplechi.test.cc index 6211099d..bc74aa13 100644 --- a/tests/yakus/mixedtriplechi.test.cc +++ b/tests/yakus/mixedtriplechi.test.cc @@ -9,14 +9,13 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" -#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { TEST(isMixedTripleChi, Open) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123p123m123s555p11z")); + game_state.hands[0].live = HandFromNotation("123p123m123s555p11z"); game_state.hands[0].open = true; auto root = breakdownHand(game_state.hands.at(0).live); @@ -32,7 +31,7 @@ TEST(isMixedTripleChi, Open) { TEST(isMixedTripleChi, Closed) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123p123m123s555p11z")); + game_state.hands[0].live = HandFromNotation("123p123m123s555p11z"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -48,7 +47,7 @@ TEST(isMixedTripleChi, Closed) { TEST(isMixedTripleChi, BadHand) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123p123p123s555p11z")); + game_state.hands[0].live = HandFromNotation("123p123p123s555p11z"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); diff --git a/tests/yakus/outsidehand.test.cc b/tests/yakus/outsidehand.test.cc index ffc78bb1..358da80e 100644 --- a/tests/yakus/outsidehand.test.cc +++ b/tests/yakus/outsidehand.test.cc @@ -9,14 +9,13 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" -#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { TEST(isOutsideHand, Open) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m789m111z999s55z")); + game_state.hands[0].live = HandFromNotation("123m789m111z999s55z"); game_state.hands[0].open = true; auto root = breakdownHand(game_state.hands.at(0).live); @@ -32,7 +31,7 @@ TEST(isOutsideHand, Open) { TEST(isOutsideHand, Closed) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m789m111z999s55z")); + game_state.hands[0].live = HandFromNotation("123m789m111z999s55z"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -48,7 +47,7 @@ TEST(isOutsideHand, Closed) { TEST(isOutsideHand, NoChi) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m111p111s999m66z")); + game_state.hands[0].live = HandFromNotation("111m111p111s999m66z"); auto root = breakdownHand(game_state.hands.at(0).live); @@ -63,7 +62,7 @@ TEST(isOutsideHand, NoChi) { TEST(isOutsideHand, BadHand) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m234p111s999m66z")); + game_state.hands[0].live = HandFromNotation("111m234p111s999m66z"); auto root = breakdownHand(game_state.hands.at(0).live); diff --git a/tests/yakus/pinfu.test.cc b/tests/yakus/pinfu.test.cc index 9f8bbfd6..eaefabe9 100644 --- a/tests/yakus/pinfu.test.cc +++ b/tests/yakus/pinfu.test.cc @@ -9,7 +9,6 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/pieces.h" #include "types/piecetype.h" #include "utils/handformer.h" @@ -18,7 +17,7 @@ namespace mahjong::yaku { TEST(isPinfu, 1Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456p234678s44m")); + game_state.hands[0].live = HandFromNotation("123m456p234678s44m"); game_state.hands[0].open = false; game_state.pendingPiece = Piece(kFourPin); @@ -35,7 +34,7 @@ TEST(isPinfu, 1Han) { TEST(isPinfu, BadHand) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m555p234678s44m")); + game_state.hands[0].live = HandFromNotation("123m555p234678s44m"); game_state.hands[0].open = false; game_state.pendingPiece = Piece(kTwoBamboo); @@ -52,7 +51,7 @@ TEST(isPinfu, BadHand) { TEST(isPinfu, CantBeOpen) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456p234678s44m")); + game_state.hands[0].live = HandFromNotation("123m456p234678s44m"); game_state.hands[0].open = true; game_state.pendingPiece = Piece(kFourPin); @@ -69,7 +68,7 @@ TEST(isPinfu, CantBeOpen) { TEST(isPinfu, NeedTwoWait) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456p234678s44m")); + game_state.hands[0].live = HandFromNotation("123m456p234678s44m"); game_state.hands[0].open = false; game_state.pendingPiece = Piece(kFivePin); diff --git a/tests/yakus/puredoublechi.test.cc b/tests/yakus/puredoublechi.test.cc index 14e3be84..4dbe3d01 100644 --- a/tests/yakus/puredoublechi.test.cc +++ b/tests/yakus/puredoublechi.test.cc @@ -9,14 +9,13 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" -#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { TEST(isPureDoubleChi, 1Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("234m234m555p888s88p")); + game_state.hands[0].live = HandFromNotation("234m234m555p888s88p"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -32,7 +31,7 @@ TEST(isPureDoubleChi, 1Han) { TEST(isPureDoubleChi, BadHand) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("234m123m555p888s88p")); + game_state.hands[0].live = HandFromNotation("234m123m555p888s88p"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -48,7 +47,7 @@ TEST(isPureDoubleChi, BadHand) { TEST(isPureDoubleChi, MustBeConcealed) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("234m234m555p888s88p")); + game_state.hands[0].live = HandFromNotation("234m234m555p888s88p"); game_state.hands[0].open = true; auto root = breakdownHand(game_state.hands.at(0).live); diff --git a/tests/yakus/purestraight.test.cc b/tests/yakus/purestraight.test.cc index 231818be..291ecd2f 100644 --- a/tests/yakus/purestraight.test.cc +++ b/tests/yakus/purestraight.test.cc @@ -9,14 +9,13 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" -#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { TEST(isPureStraight, Open) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m789m555p11z")); + game_state.hands[0].live = HandFromNotation("123m456m789m555p11z"); game_state.hands[0].open = true; auto root = breakdownHand(game_state.hands.at(0).live); @@ -32,7 +31,7 @@ TEST(isPureStraight, Open) { TEST(isPureStraight, Closed) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m789m555p11z")); + game_state.hands[0].live = HandFromNotation("123m456m789m555p11z"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -48,7 +47,7 @@ TEST(isPureStraight, Closed) { TEST(isPureStraight, BadHand) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m999m555p11z")); + game_state.hands[0].live = HandFromNotation("123m456m999m555p11z"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); diff --git a/tests/yakus/riichi.test.cc b/tests/yakus/riichi.test.cc index 8297afc3..631dd5ae 100644 --- a/tests/yakus/riichi.test.cc +++ b/tests/yakus/riichi.test.cc @@ -8,14 +8,13 @@ #include "scoring/yakus/doubleriichi.h" #include "scoring/yakus/ippatsu.h" #include "types/gamestate.h" -#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { TEST(isRiichi, Riichi) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("555m555p555s111z44m")); + game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); game_state.hands[0].riichi = true; game_state.hands[0].riichiRound = 7; @@ -27,7 +26,7 @@ TEST(isRiichi, Riichi) { TEST(isRiichi, Ippatsu) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("555m555p555s111z44m")); + game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); game_state.hands[0].riichi = true; game_state.hands[0].riichiRound = 14; @@ -39,7 +38,7 @@ TEST(isRiichi, Ippatsu) { TEST(isRiichi, DoubleRiichi) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("555m555p555s111z44m")); + game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); game_state.hands[0].riichi = true; game_state.hands[0].riichiRound = 1; @@ -51,7 +50,7 @@ TEST(isRiichi, DoubleRiichi) { TEST(isRiichi, NoRiichi) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("555m555p555s111z44m")); + game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); game_state.hands[0].riichi = false; game_state.turnNum = 2; diff --git a/tests/yakus/robbingkan.test.cc b/tests/yakus/robbingkan.test.cc index 3e0949c7..35a1b7a8 100644 --- a/tests/yakus/robbingkan.test.cc +++ b/tests/yakus/robbingkan.test.cc @@ -8,7 +8,6 @@ #include "analysis/handnode.h" #include "scoring/yakus/robbingakan.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/statefunction.h" #include "utils/handformer.h" @@ -16,7 +15,7 @@ namespace mahjong::yaku { TEST(isRobbingAKan, 1Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m789m1111z999s55z")); + game_state.hands[0].live = HandFromNotation("123m789m1111z999s55z"); game_state.hasRonned[0] = true; game_state.nextState = StateFunctionType::kKanDiscard; @@ -33,7 +32,7 @@ TEST(isRobbingAKan, 1Han) { TEST(isRobbingAKan, DoesntApply) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m789m1111z999s55z")); + game_state.hands[0].live = HandFromNotation("123m789m1111z999s55z"); game_state.hasRonned[0] = true; game_state.nextState = StateFunctionType::kPon; diff --git a/tests/yakus/sevenpairs.test.cc b/tests/yakus/sevenpairs.test.cc index 5c1c0dbc..b30b208a 100644 --- a/tests/yakus/sevenpairs.test.cc +++ b/tests/yakus/sevenpairs.test.cc @@ -9,14 +9,13 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" -#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { TEST(isSevenPairs, 2Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("11m22p33s44z55m11z66z")); + game_state.hands[0].live = HandFromNotation("11m22p33s44z55m11z66z"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -32,7 +31,7 @@ TEST(isSevenPairs, 2Han) { TEST(isSevenPairs, MustBeConcealed) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("11m22p33s44z55m11z66z")); + game_state.hands[0].live = HandFromNotation("11m22p33s44z55m11z66z"); game_state.hands[0].open = true; auto root = breakdownHand(game_state.hands.at(0).live); @@ -48,7 +47,7 @@ TEST(isSevenPairs, MustBeConcealed) { TEST(isSevenPairs, UniquePairsOnly) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("1111m22p33s44z11z66z")); + game_state.hands[0].live = HandFromNotation("1111m22p33s44z11z66z"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); diff --git a/tests/yakus/terminalinsets.test.cc b/tests/yakus/terminalinsets.test.cc index bb354420..649ee6dd 100644 --- a/tests/yakus/terminalinsets.test.cc +++ b/tests/yakus/terminalinsets.test.cc @@ -9,7 +9,6 @@ #include "analysis/handnode.h" #include "scoring/yakus/terminalsinallsets.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" @@ -25,7 +24,7 @@ TEST(isTerminalsInAllSets, 2Han) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m789m111p11s")); + game_state.hands[0].live = HandFromNotation("123m789m111p11s"); game_state.hands[0].open = true; game_state.hands[0].melds = {meld}; @@ -42,7 +41,7 @@ TEST(isTerminalsInAllSets, 2Han) { TEST(isTerminalsInAllSets, 3Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m789m111p789p11s")); + game_state.hands[0].live = HandFromNotation("123m789m111p789p11s"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -63,7 +62,7 @@ TEST(isTerminalsInAllSets, BadHand) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m789m222p11s")); + game_state.hands[0].live = HandFromNotation("123m789m222p11s"); game_state.hands[0].open = true; game_state.hands[0].melds = {meld}; diff --git a/tests/yakus/triplekan.test.cc b/tests/yakus/triplekan.test.cc index 2d7e5c24..867d6d43 100644 --- a/tests/yakus/triplekan.test.cc +++ b/tests/yakus/triplekan.test.cc @@ -9,7 +9,6 @@ #include "analysis/handnode.h" #include "scoring/yakus/threekans.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" @@ -33,7 +32,7 @@ TEST(isThreeKans, 2Han) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("666z22m")); + game_state.hands[0].live = HandFromNotation("666z22m"); game_state.hands[0].melds = {meld_a, meld_b, meld_c}; game_state.hands[0].open = true; @@ -67,7 +66,7 @@ TEST(isThreeKans, WithOtherMelds) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("22m")); + game_state.hands[0].live = HandFromNotation("22m"); game_state.hands[0].melds = {meld_a, meld_b, meld_c, meld_d}; game_state.hands[0].open = true; @@ -93,7 +92,7 @@ TEST(isThreeKans, BadHand) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("777p666z22m")); + game_state.hands[0].live = HandFromNotation("777p666z22m"); game_state.hands[0].melds = {meld_a, meld_b}; game_state.hands[0].open = true; @@ -123,7 +122,7 @@ TEST(isThreeKans, AllConcealed) { }; auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("666z22m")); + game_state.hands[0].live = HandFromNotation("666z22m"); game_state.hands[0].melds = {meld_a, meld_b, meld_c}; game_state.hands[0].open = false; diff --git a/tests/yakus/triplepon.test.cc b/tests/yakus/triplepon.test.cc index 4c1d0805..db9e0efa 100644 --- a/tests/yakus/triplepon.test.cc +++ b/tests/yakus/triplepon.test.cc @@ -9,14 +9,13 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" -#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { TEST(isTriplePon, 2Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m111p111s666z44m")); + game_state.hands[0].live = HandFromNotation("111m111p111s666z44m"); auto root = breakdownHand(game_state.hands.at(0).live); @@ -31,7 +30,7 @@ TEST(isTriplePon, 2Han) { TEST(isTriplePon, BadHand) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("111m111p222m666z44m")); + game_state.hands[0].live = HandFromNotation("111m111p222m666z44m"); auto root = breakdownHand(game_state.hands.at(0).live); diff --git a/tests/yakus/twicepuredoublechi.test.cc b/tests/yakus/twicepuredoublechi.test.cc index d8ab809a..e8f97649 100644 --- a/tests/yakus/twicepuredoublechi.test.cc +++ b/tests/yakus/twicepuredoublechi.test.cc @@ -9,14 +9,13 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" -#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { TEST(isTwicePureDoubleChi, 3Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("789p789p234m234m11z")); + game_state.hands[0].live = HandFromNotation("789p789p234m234m11z"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); @@ -32,7 +31,7 @@ TEST(isTwicePureDoubleChi, 3Han) { TEST(isTwicePureDoubleChi, MustBeConcealed) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("789p789p234m234m11z")); + game_state.hands[0].live = HandFromNotation("789p789p234m234m11z"); game_state.hands[0].open = true; auto root = breakdownHand(game_state.hands.at(0).live); @@ -48,7 +47,7 @@ TEST(isTwicePureDoubleChi, MustBeConcealed) { TEST(isTwicePureDoubleChi, BadHand) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("789p789p234m567m11z")); + game_state.hands[0].live = HandFromNotation("789p789p234m567m11z"); game_state.hands[0].open = false; auto root = breakdownHand(game_state.hands.at(0).live); diff --git a/tests/yakus/underthesea.test.cc b/tests/yakus/underthesea.test.cc index 61cecdf7..b5a6b8e7 100644 --- a/tests/yakus/underthesea.test.cc +++ b/tests/yakus/underthesea.test.cc @@ -14,7 +14,7 @@ namespace mahjong::yaku { TEST(isBottomOfTheSea, 1Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m789m111z999s55z")); + game_state.hands[0].live = HandFromNotation("123m789m111z999s55z"); game_state.livingWallIndex = kLivingWallCount; auto root = breakdownHand(game_state.hands.at(0).live); @@ -30,7 +30,7 @@ TEST(isBottomOfTheSea, 1Han) { TEST(isBottomOfTheSea, 1HanRonned) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m789m111z999s55z")); + game_state.hands[0].live = HandFromNotation("123m789m111z999s55z"); game_state.livingWallIndex = kLivingWallCount; game_state.hasRonned[0] = true; @@ -47,7 +47,7 @@ TEST(isBottomOfTheSea, 1HanRonned) { TEST(isBottomOfTheSea, DoesntApply) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m789m111z999s55z")); + game_state.hands[0].live = HandFromNotation("123m789m111z999s55z"); auto root = breakdownHand(game_state.hands.at(0).live); diff --git a/tests/yakus/windpons.test.cc b/tests/yakus/windpons.test.cc index f8c6946a..94d8b720 100644 --- a/tests/yakus/windpons.test.cc +++ b/tests/yakus/windpons.test.cc @@ -8,14 +8,13 @@ #include "analysis/handnode.h" #include "scoring/yakus/honorpon.h" #include "types/gamestate.h" -#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { TEST(isWindOrDragonPon, SeatWind) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m444z55z")); + game_state.hands[0].live = HandFromNotation("123m456m444z55z"); game_state.roundNum = 1; auto root = breakdownHand(game_state.hands.at(0).live); @@ -34,7 +33,7 @@ TEST(isWindOrDragonPon, SeatWind) { TEST(isWindOrDragonPon, SeatWindKan) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m4444z55z")); + game_state.hands[0].live = HandFromNotation("123m456m4444z55z"); game_state.roundNum = 1; auto root = breakdownHand(game_state.hands.at(0).live); @@ -50,7 +49,7 @@ TEST(isWindOrDragonPon, SeatWindKan) { TEST(isWindOrDragonPon, PrevalentWind) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m111z55z")); + game_state.hands[0].live = HandFromNotation("123m456m111z55z"); game_state.roundNum = 1; auto root = breakdownHand(game_state.hands.at(0).live); @@ -66,7 +65,7 @@ TEST(isWindOrDragonPon, PrevalentWind) { TEST(isWindOrDragonPon, PrevalentWindKan) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m1111z55z")); + game_state.hands[0].live = HandFromNotation("123m456m1111z55z"); game_state.roundNum = 1; auto root = breakdownHand(game_state.hands.at(0).live); @@ -82,7 +81,7 @@ TEST(isWindOrDragonPon, PrevalentWindKan) { TEST(isWindOrDragonPon, Dealer2Han) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m111z55z")); + game_state.hands[0].live = HandFromNotation("123m456m111z55z"); game_state.roundNum = 0; auto root = breakdownHand(game_state.hands.at(0).live); @@ -99,7 +98,7 @@ TEST(isWindOrDragonPon, Dealer2Han) { TEST(isWindOrDragonPon, Dealer2HanKan) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m1111z55z")); + game_state.hands[0].live = HandFromNotation("123m456m1111z55z"); game_state.roundNum = 0; auto root = breakdownHand(game_state.hands.at(0).live); @@ -116,7 +115,7 @@ TEST(isWindOrDragonPon, Dealer2HanKan) { TEST(isWindOrDragonPon, NotSeatOrPrevalent) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m222z55z")); + game_state.hands[0].live = HandFromNotation("123m456m222z55z"); game_state.roundNum = 0; auto root = breakdownHand(game_state.hands.at(0).live); @@ -133,7 +132,7 @@ TEST(isWindOrDragonPon, NotSeatOrPrevalent) { TEST(isWindOrDragonPon, NoWind) { auto game_state = GameState(); - game_state.hands[0] = Hand(HandFromNotation("123m456m666m55z")); + game_state.hands[0].live = HandFromNotation("123m456m666m55z"); game_state.roundNum = 0; auto root = breakdownHand(game_state.hands.at(0).live); From af215ecd149d11aa8604104c6ac03b2f5fce2b8c Mon Sep 17 00:00:00 2001 From: alice Hartley Date: Wed, 27 Aug 2025 13:46:35 -0700 Subject: [PATCH 04/14] Update Meld to use std::array. --- src/api/gamestate.cc | 2 +- src/scoring/scoring.cc | 31 ++++----- src/scoring/yakus/allgreen.cc | 8 ++- src/scoring/yakus/allhonors.cc | 7 ++- src/scoring/yakus/allpons.cc | 7 ++- src/scoring/yakus/allsimples.cc | 7 ++- src/scoring/yakus/allterminals.cc | 7 ++- src/scoring/yakus/allterminalsandhonors.cc | 7 ++- src/scoring/yakus/bigfourwinds.cc | 5 +- src/scoring/yakus/bigthreedragons.cc | 5 +- src/scoring/yakus/fourconcealedpon.cc | 5 +- src/scoring/yakus/fourkans.cc | 5 +- src/scoring/yakus/fullflush.cc | 11 ++-- src/scoring/yakus/halfflush.cc | 11 ++-- src/scoring/yakus/honorpon.cc | 5 +- src/scoring/yakus/littlefourwinds.cc | 5 +- src/scoring/yakus/littlethreedragons.cc | 5 +- src/scoring/yakus/maxbranches.cc | 36 ++++++----- src/scoring/yakus/mixedtriplechi.cc | 17 ++--- src/scoring/yakus/outsidehand.cc | 10 +-- src/scoring/yakus/purestraight.cc | 17 ++--- src/scoring/yakus/terminalsinallsets.cc | 10 +-- src/scoring/yakus/threeconcealedpons.cc | 5 +- src/scoring/yakus/threekans.cc | 5 +- src/scoring/yakus/triplepon.cc | 17 ++--- src/statefunctions/decisionfunction.cc | 5 +- src/statefunctions/gamestates/chi.cc | 13 ++-- src/statefunctions/gamestates/concealedkan.cc | 9 ++- src/statefunctions/gamestates/convertedkan.cc | 9 +-- src/statefunctions/gamestates/kan.cc | 12 ++-- src/statefunctions/gamestates/pon.cc | 10 ++- src/types/gamestate.h | 7 ++- src/types/typeprinter.cc | 13 ++-- tests/api/game_control.test.cc | 2 +- tests/rules/calls.test.cc | 2 +- tests/yakus/allpon.test.cc | 38 +++++------ tests/yakus/allterminalsandhonors.test.cc | 27 ++++---- tests/yakus/concealedpon.test.cc | 63 ++++++++++--------- tests/yakus/fullflush.test.cc | 42 +++++++------ tests/yakus/halfflush.test.cc | 46 +++++++------- tests/yakus/littlethreedragons.test.cc | 33 +++++----- tests/yakus/terminalinsets.test.cc | 34 +++++----- tests/yakus/triplekan.test.cc | 40 +++++++----- 43 files changed, 355 insertions(+), 300 deletions(-) diff --git a/src/api/gamestate.cc b/src/api/gamestate.cc index e531763e..4d1f2d4e 100644 --- a/src/api/gamestate.cc +++ b/src/api/gamestate.cc @@ -156,7 +156,7 @@ CObservedGameState ObserveGameState(mahjong::GameState* state) { } // Melds - const int meld_count = static_cast(cpp_hand.melds.size()); + const int meld_count = cpp_hand.meld_count; c_hand.meldCount = std::min(meld_count, kMaxMeldsPerHand); for (int j = 0; j < c_hand.meldCount; j++) { c_hand.melds[j].type = static_cast(cpp_hand.melds[j].type); diff --git a/src/scoring/scoring.cc b/src/scoring/scoring.cc index eb7e7a95..6357893d 100644 --- a/src/scoring/scoring.cc +++ b/src/scoring/scoring.cc @@ -59,7 +59,8 @@ const int kFuRounding = 10; } // namespace Score scoreHand(const GameState& state, int player) { - auto root = breakdownHand(state.hands.at(player).live); + const Hand& hand = state.hands[player]; + auto root = breakdownHand(hand.live); Score s; s.han = 0; s.yakuman = 0; @@ -76,7 +77,7 @@ Score scoreHand(const GameState& state, int player) { } for (const auto& yaku : Yakus::Instance().GetYakus()) { - if (yaku.type == Yaku::kClosed && state.hands[player].open) { + if (yaku.type == Yaku::kClosed && hand.open) { continue; } if (!yaku.is_yaku_func(state, player, branch)) { @@ -88,7 +89,7 @@ Score scoreHand(const GameState& state, int player) { branchscore.han += yaku.value; break; case Yaku::kBonusWhenClosed: - branchscore.han += yaku.value + (state.hands[player].open ? 0 : 1); + branchscore.han += yaku.value + (hand.open ? 0 : 1); break; case Yaku::kYakuman: branchscore.yakuman++; @@ -97,20 +98,20 @@ Score scoreHand(const GameState& state, int player) { } for (const auto& dora : Walls::GetDoras(state)) { - for (const auto& p : state.hands.at(player).live) { + for (const auto& p : hand.live) { if (p == dora) { branchscore.han++; } } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.start == dora) { + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].start == dora) { branchscore.han++; } - if (meld.type == SetType::kChi) { - if (meld.start + 1 == dora) { + if (hand.melds[i].type == SetType::kChi) { + if (hand.melds[i].start + 1 == dora) { branchscore.han++; } - if (meld.start + 2 == dora) { + if (hand.melds[i].start + 2 == dora) { branchscore.han++; } } @@ -178,9 +179,10 @@ int getFu(const GameState& state, int player, } else if (!state.hasRonned.at(player)) { fu += kSelfdraw; } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.type == SetType::kKan) { - if (!meld.start.isHonor() && !meld.start.isTerminal()) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].type == SetType::kKan) { + if (!hand.melds[i].start.isHonor() && !hand.melds[i].start.isTerminal()) { fu += open ? kSimplekan : kCsimplekan; } else { fu += open ? kTermHonorkan : kCtermHonorkan; @@ -251,8 +253,9 @@ bool isOpenPinfu(const GameState& state, int player, } } } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.type > SetType::kChi) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].type > SetType::kChi) { return false; } } diff --git a/src/scoring/yakus/allgreen.cc b/src/scoring/yakus/allgreen.cc index edb7633f..5643557b 100644 --- a/src/scoring/yakus/allgreen.cc +++ b/src/scoring/yakus/allgreen.cc @@ -10,13 +10,15 @@ namespace mahjong::yaku { bool isAllGreen(const GameState& state, int player, const std::vector& /*branch*/) { - for (const auto& piece : state.hands.at(player).live) { + const Hand& hand = state.hands[player]; + for (const auto& piece : hand.live) { if (!piece.isGreen()) { return false; } } - for (const auto& meld : state.hands.at(player).melds) { - if (!meld.start.isGreen()) { + + for (int i = 0; i < hand.meld_count; ++i) { + if (!hand.melds[i].start.isGreen()) { return false; } } diff --git a/src/scoring/yakus/allhonors.cc b/src/scoring/yakus/allhonors.cc index 12831fe8..44d60c55 100644 --- a/src/scoring/yakus/allhonors.cc +++ b/src/scoring/yakus/allhonors.cc @@ -10,13 +10,14 @@ namespace mahjong::yaku { bool isAllHonors(const GameState& state, int player, const std::vector& /*branch*/) { - for (const auto& piece : state.hands.at(player).live) { + const Hand& hand = state.hands[player]; + for (const auto& piece : hand.live) { if (!piece.isHonor()) { return false; } } - for (const auto& meld : state.hands.at(player).melds) { - if (!meld.start.isHonor()) { + for (int i = 0; i < hand.meld_count; ++i) { + if (!hand.melds[i].start.isHonor()) { return false; } } diff --git a/src/scoring/yakus/allpons.cc b/src/scoring/yakus/allpons.cc index 341d70b4..09d7842b 100644 --- a/src/scoring/yakus/allpons.cc +++ b/src/scoring/yakus/allpons.cc @@ -17,9 +17,10 @@ bool isAllPons(const GameState& state, int player, pons++; } } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.type == SetType::kKan || meld.type == SetType::kPon || - meld.type == SetType::kConcealedKan) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].type == SetType::kKan || hand.melds[i].type == SetType::kPon || + hand.melds[i].type == SetType::kConcealedKan) { pons++; } } diff --git a/src/scoring/yakus/allsimples.cc b/src/scoring/yakus/allsimples.cc index 7e114557..32901782 100644 --- a/src/scoring/yakus/allsimples.cc +++ b/src/scoring/yakus/allsimples.cc @@ -10,13 +10,14 @@ namespace mahjong::yaku { bool isAllSimples(const GameState& state, int player, const std::vector& /*branch*/) { - for (const auto& piece : state.hands.at(player).live) { + const Hand& hand = state.hands[player]; + for (const auto& piece : hand.live) { if (piece.isHonor() || piece.isTerminal()) { return false; } } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.start.isHonor() || meld.start.isTerminal()) { + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].start.isHonor() || hand.melds[i].start.isTerminal()) { return false; } } diff --git a/src/scoring/yakus/allterminals.cc b/src/scoring/yakus/allterminals.cc index 026b0aed..8c9d7674 100644 --- a/src/scoring/yakus/allterminals.cc +++ b/src/scoring/yakus/allterminals.cc @@ -10,13 +10,14 @@ namespace mahjong::yaku { bool isAllTerminals(const GameState& state, int player, const std::vector& /*branch*/) { - for (const auto& piece : state.hands.at(player).live) { + const Hand& hand = state.hands[player]; + for (const auto& piece : hand.live) { if (!piece.isTerminal()) { return false; } } - for (const auto& meld : state.hands.at(player).melds) { - if (!meld.start.isTerminal()) { + for (int i = 0; i < hand.meld_count; ++i) { + if (!hand.melds[i].start.isTerminal()) { return false; } } diff --git a/src/scoring/yakus/allterminalsandhonors.cc b/src/scoring/yakus/allterminalsandhonors.cc index d03bf8e1..103309f4 100644 --- a/src/scoring/yakus/allterminalsandhonors.cc +++ b/src/scoring/yakus/allterminalsandhonors.cc @@ -11,13 +11,14 @@ namespace mahjong::yaku { bool isAllTerminalsAndHonors( const GameState& state, int player, const std::vector& /*branch*/) { - for (const auto& piece : state.hands.at(player).live) { + const Hand& hand = state.hands[player]; + for (const auto& piece : hand.live) { if (!piece.isHonor() && !piece.isTerminal()) { return false; } } - for (const auto& meld : state.hands.at(player).melds) { - if (!meld.start.isHonor() && !meld.start.isTerminal()) { + for (int i = 0; i < hand.meld_count; ++i) { + if (!hand.melds[i].start.isHonor() && !hand.melds[i].start.isTerminal()) { return false; } } diff --git a/src/scoring/yakus/bigfourwinds.cc b/src/scoring/yakus/bigfourwinds.cc index fdb83e61..736255cd 100644 --- a/src/scoring/yakus/bigfourwinds.cc +++ b/src/scoring/yakus/bigfourwinds.cc @@ -27,8 +27,9 @@ bool isBigFourWinds(const GameState& state, int player, } pons++; } - for (const auto& meld : state.hands.at(player).melds) { - switch (meld.start.toUint8_t()) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + switch (hand.melds[i].start.toUint8_t()) { case Piece::Type::kEastWind: case Piece::Type::kSouthWind: case Piece::Type::kWestWind: diff --git a/src/scoring/yakus/bigthreedragons.cc b/src/scoring/yakus/bigthreedragons.cc index 29520a3f..3701d935 100644 --- a/src/scoring/yakus/bigthreedragons.cc +++ b/src/scoring/yakus/bigthreedragons.cc @@ -26,8 +26,9 @@ bool isBigThreeDragons(const GameState& state, int player, } pons++; } - for (const auto& meld : state.hands.at(player).melds) { - switch (meld.start.toUint8_t()) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + switch (hand.melds[i].start.toUint8_t()) { case Piece::Type::kRedDragon: case Piece::Type::kGreenDragon: case Piece::Type::kWhiteDragon: diff --git a/src/scoring/yakus/fourconcealedpon.cc b/src/scoring/yakus/fourconcealedpon.cc index b9a86725..54fd7d2d 100644 --- a/src/scoring/yakus/fourconcealedpon.cc +++ b/src/scoring/yakus/fourconcealedpon.cc @@ -20,8 +20,9 @@ bool isFourConcealedPon(const GameState& state, int player, concealed_pons++; } } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.type == SetType::kConcealedKan) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].type == SetType::kConcealedKan) { concealed_pons++; } } diff --git a/src/scoring/yakus/fourkans.cc b/src/scoring/yakus/fourkans.cc index 096b73bd..f50e7969 100644 --- a/src/scoring/yakus/fourkans.cc +++ b/src/scoring/yakus/fourkans.cc @@ -12,8 +12,9 @@ namespace mahjong::yaku { bool isFourKans(const GameState& state, int player, const std::vector& /*branch*/) { int kans = 0; - for (const auto& meld : state.hands.at(player).melds) { - if (meld.type >= SetType::kKan) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].type >= SetType::kKan) { kans++; } } diff --git a/src/scoring/yakus/fullflush.cc b/src/scoring/yakus/fullflush.cc index 1a41fcc6..f4c52e74 100644 --- a/src/scoring/yakus/fullflush.cc +++ b/src/scoring/yakus/fullflush.cc @@ -10,17 +10,18 @@ namespace mahjong::yaku { bool isFullFlush(const GameState& state, int player, const std::vector& /*branch*/) { - if (state.hands.at(player).live.front().isHonor()) { + const Hand& hand = state.hands[player]; + if (hand.live.front().isHonor()) { return false; } - const int suit = state.hands.at(player).live.front().getSuit(); - for (const auto& piece : state.hands.at(player).live) { + const int suit = hand.live.front().getSuit(); + for (const auto& piece : hand.live) { if (piece.getSuit() != suit) { return false; } } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.start.getSuit() != suit) { + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].start.getSuit() != suit) { return false; } } diff --git a/src/scoring/yakus/halfflush.cc b/src/scoring/yakus/halfflush.cc index 2996cbc8..0cfc896b 100644 --- a/src/scoring/yakus/halfflush.cc +++ b/src/scoring/yakus/halfflush.cc @@ -11,9 +11,10 @@ namespace mahjong::yaku { bool isHalfFlush(const GameState& state, int player, const std::vector& /*branch*/) { - const int suit = state.hands.at(player).live.front().getSuit(); + const Hand& hand = state.hands[player]; + const int suit = hand.live.front().getSuit(); bool honors = false; - for (const auto& piece : state.hands.at(player).live) { + for (const auto& piece : hand.live) { if (piece.isHonor()) { honors = true; continue; @@ -22,12 +23,12 @@ bool isHalfFlush(const GameState& state, int player, return false; } } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.start.isHonor()) { + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].start.isHonor()) { honors = true; continue; } - if (suit != meld.start.getSuit()) { + if (suit != hand.melds[i].start.getSuit()) { return false; } } diff --git a/src/scoring/yakus/honorpon.cc b/src/scoring/yakus/honorpon.cc index 1f76759c..c5b2eb13 100644 --- a/src/scoring/yakus/honorpon.cc +++ b/src/scoring/yakus/honorpon.cc @@ -22,8 +22,9 @@ bool findPon(const GameState& state, int player, return true; } } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.type >= SetType::kPon && meld.start == piece) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].type >= SetType::kPon && hand.melds[i].start == piece) { return true; } } diff --git a/src/scoring/yakus/littlefourwinds.cc b/src/scoring/yakus/littlefourwinds.cc index 2ca76dc8..fa299dea 100644 --- a/src/scoring/yakus/littlefourwinds.cc +++ b/src/scoring/yakus/littlefourwinds.cc @@ -35,8 +35,9 @@ bool isLittleFourWinds(const GameState& state, int player, if (!pair) { return false; } - for (const auto& meld : state.hands.at(player).melds) { - switch (meld.start.toUint8_t()) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + switch (hand.melds[i].start.toUint8_t()) { case Piece::Type::kEastWind: case Piece::Type::kSouthWind: case Piece::Type::kWestWind: diff --git a/src/scoring/yakus/littlethreedragons.cc b/src/scoring/yakus/littlethreedragons.cc index b73f9cf4..09ee1999 100644 --- a/src/scoring/yakus/littlethreedragons.cc +++ b/src/scoring/yakus/littlethreedragons.cc @@ -32,8 +32,9 @@ bool isLittleThreeDragons(const GameState& state, int player, if (!pair) { return false; } - for (const auto& meld : state.hands.at(player).melds) { - switch (meld.start.toUint8_t()) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + switch (hand.melds[i].start.toUint8_t()) { case Piece::Type::kRedDragon: case Piece::Type::kGreenDragon: case Piece::Type::kWhiteDragon: diff --git a/src/scoring/yakus/maxbranches.cc b/src/scoring/yakus/maxbranches.cc index c591ed07..ed31fb73 100644 --- a/src/scoring/yakus/maxbranches.cc +++ b/src/scoring/yakus/maxbranches.cc @@ -10,11 +10,13 @@ namespace mahjong::yaku { bool isMaxBranches(const GameState& state, int player, const std::vector& /*branch*/) { - const int start = state.hands.at(player).live[0].getPieceNum(); - const int suit = state.hands.at(player).live[0].getSuit(); + const Hand& hand = state.hands[player]; + const int start = hand.live[0].getPieceNum(); + const int suit = hand.live[0].getSuit(); std::array sets = {}; const std::array final = {3, 3, 2, 2, 2, 2}; - for (const auto& piece : state.hands.at(player).live) { + + for (const auto& piece : hand.live) { if (piece.getSuit() != suit) { return false; } @@ -23,28 +25,28 @@ bool isMaxBranches(const GameState& state, int player, } sets.at(piece.getPieceNum() - start)++; } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.start.getSuit() != suit) { + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].start.getSuit() != suit) { return false; } - if (meld.start.getPieceNum() < start || - meld.start.getPieceNum() > start + 3) { + if (hand.melds[i].start.getPieceNum() < start || + hand.melds[i].start.getPieceNum() > start + 3) { return false; } - if (meld.type >= SetType::kKan) { - if (meld.start.getPieceNum() != start && - meld.start.getPieceNum() != start + 1) { + if (hand.melds[i].type >= SetType::kKan) { + if (hand.melds[i].start.getPieceNum() != start && + hand.melds[i].start.getPieceNum() != start + 1) { return false; } - sets.at(meld.start.getPieceNum() - start) += 3; + sets.at(hand.melds[i].start.getPieceNum() - start) += 3; } - if (meld.type == SetType::kPon) { - sets.at(meld.start.getPieceNum() - start) += 3; + if (hand.melds[i].type == SetType::kPon) { + sets.at(hand.melds[i].start.getPieceNum() - start) += 3; } - if (meld.type == SetType::kChi) { - sets.at(meld.start.getPieceNum() - start)++; - sets.at(meld.start.getPieceNum() - start + 1)++; - sets.at(meld.start.getPieceNum() - start + 2)++; + if (hand.melds[i].type == SetType::kChi) { + sets.at(hand.melds[i].start.getPieceNum() - start)++; + sets.at(hand.melds[i].start.getPieceNum() - start + 1)++; + sets.at(hand.melds[i].start.getPieceNum() - start + 2)++; } } for (int i = 0; i < 6; i++) { diff --git a/src/scoring/yakus/mixedtriplechi.cc b/src/scoring/yakus/mixedtriplechi.cc index ad0fba5b..115254e5 100644 --- a/src/scoring/yakus/mixedtriplechi.cc +++ b/src/scoring/yakus/mixedtriplechi.cc @@ -29,16 +29,17 @@ bool isMixedTripleChi(const GameState& state, int player, } } } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.type == SetType::kChi) { - if (meld.start.getSuit() == Piece::Type::kBambooSuit) { - bamboo_chi.at(meld.start.getPieceNum()) = true; + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].type == SetType::kChi) { + if (hand.melds[i].start.getSuit() == Piece::Type::kBambooSuit) { + bamboo_chi.at(hand.melds[i].start.getPieceNum()) = true; } - if (meld.start.getSuit() == Piece::Type::kCharacterSuit) { - char_chi.at(meld.start.getPieceNum()) = true; + if (hand.melds[i].start.getSuit() == Piece::Type::kCharacterSuit) { + char_chi.at(hand.melds[i].start.getPieceNum()) = true; } - if (meld.start.getSuit() == Piece::Type::kPinSuit) { - pin_chi.at(meld.start.getPieceNum()) = true; + if (hand.melds[i].start.getSuit() == Piece::Type::kPinSuit) { + pin_chi.at(hand.melds[i].start.getPieceNum()) = true; } } } diff --git a/src/scoring/yakus/outsidehand.cc b/src/scoring/yakus/outsidehand.cc index 4057202b..5a839c68 100644 --- a/src/scoring/yakus/outsidehand.cc +++ b/src/scoring/yakus/outsidehand.cc @@ -27,15 +27,17 @@ bool isOutsideHand(const GameState& state, int player, } } } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.type == SetType::kChi) { - if (meld.start.isTerminal() || (meld.start + 2).isTerminal()) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].type == SetType::kChi) { + if (hand.melds[i].start.isTerminal() || + (hand.melds[i].start + 2).isTerminal()) { chi = true; } else { return false; } } else { - if (!meld.start.isTerminal() && !meld.start.isHonor()) { + if (!hand.melds[i].start.isTerminal() && !hand.melds[i].start.isHonor()) { return false; } } diff --git a/src/scoring/yakus/purestraight.cc b/src/scoring/yakus/purestraight.cc index 8bfad632..488a979d 100644 --- a/src/scoring/yakus/purestraight.cc +++ b/src/scoring/yakus/purestraight.cc @@ -41,25 +41,26 @@ bool isPureStraight(const GameState& state, int player, } } } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.type == SetType::kChi) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].type == SetType::kChi) { int ind = 0; - if (meld.start.getPieceNum() == k_firstchistart) { + if (hand.melds[i].start.getPieceNum() == k_firstchistart) { ind = 0; - } else if (meld.start.getPieceNum() == k_secondchistart) { + } else if (hand.melds[i].start.getPieceNum() == k_secondchistart) { ind = 1; - } else if (meld.start.getPieceNum() == k_thirdchistart) { + } else if (hand.melds[i].start.getPieceNum() == k_thirdchistart) { ind = 2; } else { continue; } - if (meld.start.getSuit() == Piece::Type::kBambooSuit) { + if (hand.melds[i].start.getSuit() == Piece::Type::kBambooSuit) { bamboo_chi.at(ind) = true; } - if (meld.start.getSuit() == Piece::Type::kCharacterSuit) { + if (hand.melds[i].start.getSuit() == Piece::Type::kCharacterSuit) { char_chi.at(ind) = true; } - if (meld.start.getSuit() == Piece::Type::kPinSuit) { + if (hand.melds[i].start.getSuit() == Piece::Type::kPinSuit) { pin_chi.at(ind) = true; } } diff --git a/src/scoring/yakus/terminalsinallsets.cc b/src/scoring/yakus/terminalsinallsets.cc index 19aff3cb..f9067655 100644 --- a/src/scoring/yakus/terminalsinallsets.cc +++ b/src/scoring/yakus/terminalsinallsets.cc @@ -30,12 +30,14 @@ bool isTerminalsInAllSets(const GameState& state, int player, break; } } - for (const auto& meld : state.hands.at(player).melds) { - switch (meld.type) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + switch (hand.melds[i].type) { case SetType::kSingle: return false; case SetType::kChi: - if (!meld.start.isTerminal() && !(meld.start + 2).isTerminal()) { + if (!hand.melds[i].start.isTerminal() && + !(hand.melds[i].start + 2).isTerminal()) { return false; } break; @@ -43,7 +45,7 @@ bool isTerminalsInAllSets(const GameState& state, int player, case SetType::kKan: case SetType::kConcealedKan: case SetType::kPon: - if (!meld.start.isTerminal()) { + if (!hand.melds[i].start.isTerminal()) { return false; } break; diff --git a/src/scoring/yakus/threeconcealedpons.cc b/src/scoring/yakus/threeconcealedpons.cc index 9be856c3..1565395a 100644 --- a/src/scoring/yakus/threeconcealedpons.cc +++ b/src/scoring/yakus/threeconcealedpons.cc @@ -17,8 +17,9 @@ bool isThreeConcealedPons(const GameState& state, int player, concealed_pons++; } } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.type == SetType::kConcealedKan) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].type == SetType::kConcealedKan) { concealed_pons++; } } diff --git a/src/scoring/yakus/threekans.cc b/src/scoring/yakus/threekans.cc index b22f233c..1bda22a9 100644 --- a/src/scoring/yakus/threekans.cc +++ b/src/scoring/yakus/threekans.cc @@ -12,8 +12,9 @@ namespace mahjong::yaku { bool isThreeKans(const GameState& state, int player, const std::vector& /*branch*/) { int kans = 0; - for (const auto& meld : state.hands.at(player).melds) { - if (meld.type >= SetType::kKan) { + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].type >= SetType::kKan) { kans++; } } diff --git a/src/scoring/yakus/triplepon.cc b/src/scoring/yakus/triplepon.cc index 462e8844..b0c33e85 100644 --- a/src/scoring/yakus/triplepon.cc +++ b/src/scoring/yakus/triplepon.cc @@ -28,16 +28,17 @@ bool isTriplePon(const GameState& state, int player, } } } - for (const auto& meld : state.hands.at(player).melds) { - if (meld.type >= SetType::kPon) { - if (meld.start.getSuit() == Piece::Type::kBambooSuit) { - bamboo_pon.at(meld.start.getPieceNum() - 1) = true; + const Hand& hand = state.hands[player]; + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].type >= SetType::kPon) { + if (hand.melds[i].start.getSuit() == Piece::Type::kBambooSuit) { + bamboo_pon.at(hand.melds[i].start.getPieceNum() - 1) = true; } - if (meld.start.getSuit() == Piece::Type::kCharacterSuit) { - char_pon.at(meld.start.getPieceNum() - 1) = true; + if (hand.melds[i].start.getSuit() == Piece::Type::kCharacterSuit) { + char_pon.at(hand.melds[i].start.getPieceNum() - 1) = true; } - if (meld.start.getSuit() == Piece::Type::kPinSuit) { - pin_pon.at(meld.start.getPieceNum() - 1) = true; + if (hand.melds[i].start.getSuit() == Piece::Type::kPinSuit) { + pin_pon.at(hand.melds[i].start.getPieceNum() - 1) = true; } } } diff --git a/src/statefunctions/decisionfunction.cc b/src/statefunctions/decisionfunction.cc index 317890ff..c1b73ccf 100644 --- a/src/statefunctions/decisionfunction.cc +++ b/src/statefunctions/decisionfunction.cc @@ -104,8 +104,9 @@ bool CanConvertedKan(const GameState& state, int player) { if (Walls::GetRemainingPieces(state) == 0) { return false; } - return std::any_of(state.hands.at(player).melds.begin(), - state.hands.at(player).melds.end(), [&](auto meld) { + const Hand& hand = state.hands.at(player); + return std::any_of(hand.melds.begin(), hand.melds.begin() + hand.meld_count, + [&](auto meld) { return meld.type == SetType::kPon && CountPieces(state, player, meld.start) == 1; }); diff --git a/src/statefunctions/gamestates/chi.cc b/src/statefunctions/gamestates/chi.cc index 4cad84ae..7b824d32 100644 --- a/src/statefunctions/gamestates/chi.cc +++ b/src/statefunctions/gamestates/chi.cc @@ -8,6 +8,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" #include "types/sets.h" @@ -47,7 +48,9 @@ std::unique_ptr Chi(std::unique_ptr state) { state->hands.at(state->currentPlayer).riichiPieceDiscard++; } - state->hands.at(state->lastCaller).open = true; + Hand& hand = state->hands.at(state->lastCaller); + + hand.open = true; state->currentPlayer = state->lastCaller; AlertPlayers( @@ -59,7 +62,7 @@ std::unique_ptr Chi(std::unique_ptr state) { .decision = false, // decision }); - state->hands.at(state->lastCaller).live.push_back(state->pendingPiece); + hand.live.push_back(state->pendingPiece); state->lastCall = state->turnNum; state->concealedKan = false; state->turnNum++; @@ -73,8 +76,10 @@ std::unique_ptr Chi(std::unique_ptr state) { state->nextState = StateFunctionType::kError; return state; } - state->hands.at(state->lastCaller) - .melds.push_back({SetType::kChi, chi_start}); + hand.melds[hand.meld_count++] = Meld{ + .type = SetType::kChi, + .start = chi_start, + }; state->pendingPiece = AskForDiscard(*state); diff --git a/src/statefunctions/gamestates/concealedkan.cc b/src/statefunctions/gamestates/concealedkan.cc index 819d2528..b7e8843c 100644 --- a/src/statefunctions/gamestates/concealedkan.cc +++ b/src/statefunctions/gamestates/concealedkan.cc @@ -2,12 +2,12 @@ #include #include #include -#include #include "statefunctions/router.h" #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/meld.h" #include "types/piecetype.h" #include "types/sets.h" #include "types/statefunction.h" @@ -29,8 +29,11 @@ std::unique_ptr ConcealedKan(std::unique_ptr state) { state->nextState = StateFunctionType::kError; return state; } - state->hands.at(state->currentPlayer) - .melds.push_back({SetType::kConcealedKan, state->pendingPiece}); + Hand& hand = state->hands.at(state->currentPlayer); + hand.melds[hand.meld_count++] = Meld{ + .type = SetType::kConcealedKan, + .start = state->pendingPiece, + }; state->concealedKan = true; state->nextState = StateFunctionType::kKanDiscard; return state; diff --git a/src/statefunctions/gamestates/convertedkan.cc b/src/statefunctions/gamestates/convertedkan.cc index 92a46442..4b480883 100644 --- a/src/statefunctions/gamestates/convertedkan.cc +++ b/src/statefunctions/gamestates/convertedkan.cc @@ -7,7 +7,6 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" -#include "types/meld.h" #include "types/piecetype.h" #include "types/sets.h" #include "types/statefunction.h" @@ -29,9 +28,11 @@ std::unique_ptr ConvertedKan(std::unique_ptr state) { return state; } state->concealedKan = false; - for (auto& meld : state->hands.at(state->currentPlayer).melds) { - if (meld.type == SetType::kPon && meld.start == state->pendingPiece) { - meld.type = SetType::kKan; + Hand& hand = state->hands.at(state->currentPlayer); + for (int i = 0; i < hand.meld_count; ++i) { + if (hand.melds[i].type == SetType::kPon && + hand.melds[i].start == state->pendingPiece) { + hand.melds[i].type = SetType::kKan; state->nextState = StateFunctionType::kKanDiscard; return state; } diff --git a/src/statefunctions/gamestates/kan.cc b/src/statefunctions/gamestates/kan.cc index 901f3036..2d22254f 100644 --- a/src/statefunctions/gamestates/kan.cc +++ b/src/statefunctions/gamestates/kan.cc @@ -8,6 +8,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/meld.h" #include "types/piecetype.h" #include "types/sets.h" #include "types/statefunction.h" @@ -30,9 +31,10 @@ std::unique_ptr Kan(std::unique_ptr state) { state->hands.at(state->currentPlayer).riichiPieceDiscard++; } - state->hands.at(state->lastCaller).open = true; + Hand& hand = state->hands.at(state->lastCaller); + hand.open = true; state->currentPlayer = state->lastCaller; - state->hands.at(state->lastCaller).live.push_back(state->pendingPiece); + hand.live.push_back(state->pendingPiece); state->lastCall = state->turnNum; state->concealedKan = false; state->turnNum++; @@ -43,8 +45,10 @@ std::unique_ptr Kan(std::unique_ptr state) { state->nextState = StateFunctionType::kError; return state; } - state->hands.at(state->lastCaller) - .melds.push_back({SetType::kKan, state->pendingPiece}); + hand.melds[hand.meld_count++] = Meld{ + .type = SetType::kKan, + .start = state->pendingPiece, + }; state->nextState = StateFunctionType::kKanDiscard; return state; diff --git a/src/statefunctions/gamestates/pon.cc b/src/statefunctions/gamestates/pon.cc index 25f39b83..173a3c45 100644 --- a/src/statefunctions/gamestates/pon.cc +++ b/src/statefunctions/gamestates/pon.cc @@ -8,6 +8,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/meld.h" #include "types/piecetype.h" #include "types/sets.h" #include "types/statefunction.h" @@ -32,8 +33,9 @@ std::unique_ptr Pon(std::unique_ptr state) { state->hands.at(state->currentPlayer).riichiPieceDiscard++; } + Hand& hand = state->hands.at(state->lastCaller); state->currentPlayer = state->lastCaller; - state->hands.at(state->lastCaller).live.push_back(state->pendingPiece); + hand.live.push_back(state->pendingPiece); state->lastCall = state->turnNum; state->concealedKan = false; state->turnNum++; @@ -44,8 +46,10 @@ std::unique_ptr Pon(std::unique_ptr state) { state->nextState = StateFunctionType::kError; return state; } - state->hands.at(state->lastCaller) - .melds.push_back({SetType::kPon, state->pendingPiece}); + hand.melds[hand.meld_count++] = Meld{ + .type = SetType::kPon, + .start = state->pendingPiece, + }; state->pendingPiece = AskForDiscard(*state); diff --git a/src/types/gamestate.h b/src/types/gamestate.h index ee41d364..e7ab9c3b 100644 --- a/src/types/gamestate.h +++ b/src/types/gamestate.h @@ -12,13 +12,14 @@ namespace mahjong { struct Hand { - std::vector live; - std::vector melds; - std::vector discards; bool open = false; bool riichi = false; size_t riichiPieceDiscard = -1; int riichiRound = -1; + int meld_count = 0; + std::vector live; + std::array melds; + std::vector discards; }; struct GameState { diff --git a/src/types/typeprinter.cc b/src/types/typeprinter.cc index a02fc854..82143704 100644 --- a/src/types/typeprinter.cc +++ b/src/types/typeprinter.cc @@ -11,7 +11,6 @@ #include "controllers/playercontroller.h" #include "types/event.h" #include "types/gamestate.h" -#include "types/meld.h" #include "types/piecetype.h" std::ostream& operator<<(std::ostream& os, const mahjong::Event& e) { @@ -79,8 +78,10 @@ std::ostream& operator<<(std::ostream& os, const mahjong::Hand& hand) { } os << "]" << '\n'; os << "melds: [" << '\n'; - for (const auto& meld : hand.melds) { - os << meld << ", "; + for (int i = 0; i < hand.meld_count; ++i) { + os << "{ type: " << hand.melds[i].typeToStr(); + os << ", start: " << hand.melds[i].start.toStr() << "}"; + os << ", "; } os << "]" << '\n'; os << "discards: [" << '\n'; @@ -107,9 +108,3 @@ std::ostream& operator<<(std::ostream& os, const mahjong::Node& node) { os << '\n'; return os; } - -std::ostream& operator<<(std::ostream& os, const mahjong::Meld& meld) { - os << "{ type: " << meld.typeToStr(); - os << ", start: " << meld.start.toStr() << "}"; - return os; -} diff --git a/tests/api/game_control.test.cc b/tests/api/game_control.test.cc index 136d1b62..6e2b9650 100644 --- a/tests/api/game_control.test.cc +++ b/tests/api/game_control.test.cc @@ -161,7 +161,7 @@ TEST(Api, ObserveGameStateHandsAndDiscards) { } // Check melds - EXPECT_EQ(c_hand.meldCount, static_cast(cpp_hand.melds.size())); + EXPECT_EQ(c_hand.meldCount, cpp_hand.meld_count); for (int meld = 0; meld < c_hand.meldCount; meld++) { EXPECT_EQ(static_cast(c_hand.melds[meld].type), static_cast(cpp_hand.melds[meld].type)); diff --git a/tests/rules/calls.test.cc b/tests/rules/calls.test.cc index be8519fe..080f8c1d 100644 --- a/tests/rules/calls.test.cc +++ b/tests/rules/calls.test.cc @@ -69,7 +69,7 @@ TEST(Calls, AcceptPon) { // - State should be kDiscard (Player 1 needs to discard) EXPECT_EQ(state->currentPlayer, 1); EXPECT_EQ(state->currState, StateFunctionType::kDiscard); - EXPECT_EQ(state->hands[1].melds.size(), 1); + EXPECT_EQ(state->hands[1].meld_count, 1); EXPECT_EQ(state->hands[1].melds[0].type, SetType::kPon); EXPECT_EQ(state->hands[1].melds[0].start, Piece(Piece::kNineBamboo)); diff --git a/tests/yakus/allpon.test.cc b/tests/yakus/allpon.test.cc index a134d54e..719ee952 100644 --- a/tests/yakus/allpon.test.cc +++ b/tests/yakus/allpon.test.cc @@ -19,9 +19,10 @@ namespace mahjong::yaku { TEST(isAllPons, 2Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m222p888s666z44m"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m222p888s666z44m"); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllPons(game_state, 0, branch)) { @@ -33,17 +34,16 @@ TEST(isAllPons, 2Han) { } TEST(isAllPons, WithKans) { - const Meld meld = { + auto game_state = GameState(); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m222p666z44m"); + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kKan, .start = Piece(kFivePin), }; + hand.open = true; - auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m222p666z44m"); - game_state.hands[0].melds = {meld}; - game_state.hands[0].open = true; - - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllPons(game_state, 0, branch)) { @@ -55,17 +55,16 @@ TEST(isAllPons, WithKans) { } TEST(isAllPons, ConcealedKan) { - const Meld meld = { + auto game_state = GameState(); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m222p666z44m"); + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kConcealedKan, .start = Piece(kFivePin), }; + hand.open = false; - auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m222p666z44m"); - game_state.hands[0].melds = {meld}; - game_state.hands[0].open = false; - - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllPons(game_state, 0, branch)) { @@ -78,10 +77,11 @@ TEST(isAllPons, ConcealedKan) { TEST(isAllPons, BadHand) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m222p666z789m44m"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m222p666z789m44m"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllPons(game_state, 0, branch)) { diff --git a/tests/yakus/allterminalsandhonors.test.cc b/tests/yakus/allterminalsandhonors.test.cc index 77c8f761..8da2b134 100644 --- a/tests/yakus/allterminalsandhonors.test.cc +++ b/tests/yakus/allterminalsandhonors.test.cc @@ -20,10 +20,11 @@ namespace mahjong::yaku { TEST(isAllTerminalsAndHonors, 2Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("222z111p111m999s66z"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("222z111p111m999s66z"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllTerminalsAndHonors(game_state, 0, branch)) { @@ -36,10 +37,11 @@ TEST(isAllTerminalsAndHonors, 2Han) { TEST(isAllTerminalsAndHonors, BadHand) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("222z111p111m888s66z"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("222z111p111m888s66z"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllTerminalsAndHonors(game_state, 0, branch)) { @@ -51,17 +53,16 @@ TEST(isAllTerminalsAndHonors, BadHand) { } TEST(isAllTerminalsAndHonors, CanBeOpen) { - const Meld meld = { + auto game_state = GameState(); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("222z111m999s66z"); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kNinePin), }; - auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("222z111m999s66z"); - game_state.hands[0].open = true; - game_state.hands[0].melds = {meld}; - - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllTerminalsAndHonors(game_state, 0, branch)) { diff --git a/tests/yakus/concealedpon.test.cc b/tests/yakus/concealedpon.test.cc index 4370fe90..6104890a 100644 --- a/tests/yakus/concealedpon.test.cc +++ b/tests/yakus/concealedpon.test.cc @@ -11,17 +11,17 @@ #include "types/gamestate.h" #include "types/meld.h" #include "types/pieces.h" -#include "types/piecetype.h" #include "types/sets.h" #include "utils/handformer.h" namespace mahjong::yaku { TEST(isThreeConcealedPons, 2Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m111p111s666z44m"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m111p111s666z44m"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, 0, branch)) { @@ -33,16 +33,16 @@ TEST(isThreeConcealedPons, 2Han) { } TEST(isThreeConcealedPons, PonsMustBeConcealed) { - auto meld = Meld(); - meld.type = SetType::kChi; - meld.start = Piece(kTwoBamboo); - auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m111p111s44m"); - game_state.hands[0].melds.push_back(meld); - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m111p111s44m"); + hand.melds[hand.meld_count++] = Meld{ + .type = SetType::kChi, + .start = kTwoBamboo, + }; + hand.open = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, 0, branch)) { @@ -54,16 +54,16 @@ TEST(isThreeConcealedPons, PonsMustBeConcealed) { } TEST(isThreeConcealedPons, CanHaveAdditionalOpenPon) { - auto meld = Meld(); - meld.type = SetType::kPon; - meld.start = Piece(kTwoBamboo); - auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m111p111s44m"); - game_state.hands[0].melds.push_back(meld); - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m111p111s44m"); + hand.melds[hand.meld_count++] = Meld{ + .type = SetType::kPon, + .start = kTwoBamboo, + }; + hand.open = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, 0, branch)) { @@ -75,16 +75,16 @@ TEST(isThreeConcealedPons, CanHaveAdditionalOpenPon) { } TEST(isThreeConcealedPons, PonsMustBeConcealedNegative) { - auto meld = Meld(); - meld.type = SetType::kPon; - meld.start = Piece(kOneBamboo); - auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m111p234s44m"); - game_state.hands[0].melds.push_back(meld); - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m111p234s44m"); + hand.melds[hand.meld_count++] = Meld{ + .type = SetType::kPon, + .start = kOneBamboo, + }; + hand.open = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, 0, branch)) { @@ -97,10 +97,11 @@ TEST(isThreeConcealedPons, PonsMustBeConcealedNegative) { TEST(isThreeConcealedPons, BadHand) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m111p234567s44m"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m111p234567s44m"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, 0, branch)) { diff --git a/tests/yakus/fullflush.test.cc b/tests/yakus/fullflush.test.cc index dc6888ae..ffb44e73 100644 --- a/tests/yakus/fullflush.test.cc +++ b/tests/yakus/fullflush.test.cc @@ -19,17 +19,17 @@ namespace mahjong::yaku { TEST(isFullFlush, 5Han) { - const Meld meld = { + auto game_state = GameState(); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m222m345m99m"); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; + ; - auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m222m345m99m"); - game_state.hands[0].open = true; - game_state.hands[0].melds = {meld}; - - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, 0, branch)) { @@ -42,10 +42,11 @@ TEST(isFullFlush, 5Han) { TEST(isFullFlush, 6Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m222m345m666m99m"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m222m345m666m99m"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, 0, branch)) { @@ -58,10 +59,11 @@ TEST(isFullFlush, 6Han) { TEST(isFullFlush, BadHandHonors) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m222m111z666m99m"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m222m111z666m99m"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, 0, branch)) { @@ -74,10 +76,11 @@ TEST(isFullFlush, BadHandHonors) { TEST(isFullFlush, BadHandSuit) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m222m111p666m99m"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m222m111p666m99m"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, 0, branch)) { @@ -90,10 +93,11 @@ TEST(isFullFlush, BadHandSuit) { TEST(isFullFlush, BadHandFullFlushHonors) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111z222z333z444z55z"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111z222z333z444z55z"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, 0, branch)) { diff --git a/tests/yakus/halfflush.test.cc b/tests/yakus/halfflush.test.cc index 0e0e318f..c9c01c80 100644 --- a/tests/yakus/halfflush.test.cc +++ b/tests/yakus/halfflush.test.cc @@ -19,17 +19,16 @@ namespace mahjong::yaku { TEST(isHalfFlush, 2Han) { - const Meld meld = { + auto game_state = GameState(); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("11m234m111z222z"); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("11m234m111z222z"); - game_state.hands[0].open = true; - game_state.hands[0].melds = {meld}; - - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isHalfFlush(game_state, 0, branch)) { @@ -42,10 +41,11 @@ TEST(isHalfFlush, 2Han) { TEST(isHalfFlush, 3Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("11m234m777m111z222z"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("11m234m777m111z222z"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isHalfFlush(game_state, 0, branch)) { @@ -57,17 +57,16 @@ TEST(isHalfFlush, 3Han) { } TEST(isHalfFlush, BadHand) { - const Meld meld = { + auto game_state = GameState(); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("11m234m111p222z"); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("11m234m111p222z"); - game_state.hands[0].open = true; - game_state.hands[0].melds = {meld}; - - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isHalfFlush(game_state, 0, branch)) { @@ -79,17 +78,16 @@ TEST(isHalfFlush, BadHand) { } TEST(isHalfFlush, FullFlushIncompatible) { - const Meld meld = { + auto game_state = GameState(); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("11m234m888m777m"); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("11m234m888m777m"); - game_state.hands[0].open = true; - game_state.hands[0].melds = {meld}; - - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isHalfFlush(game_state, 0, branch)) { diff --git a/tests/yakus/littlethreedragons.test.cc b/tests/yakus/littlethreedragons.test.cc index d20802f4..df45f62a 100644 --- a/tests/yakus/littlethreedragons.test.cc +++ b/tests/yakus/littlethreedragons.test.cc @@ -20,10 +20,11 @@ namespace mahjong::yaku { TEST(isLittleThreeDragons, 2Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("555z666z111m222p77z"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("555z666z111m222p77z"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isLittleThreeDragons(game_state, 0, branch)) { @@ -35,17 +36,16 @@ TEST(isLittleThreeDragons, 2Han) { } TEST(isLittleThreeDragons, WhenOpen) { - const Meld meld = { + auto game_state = GameState(); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("666z111m222p77z"); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kWhiteDragon), }; - auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("666z111m222p77z"); - game_state.hands[0].open = true; - game_state.hands[0].melds = {meld}; - - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isLittleThreeDragons(game_state, 0, branch)) { @@ -57,17 +57,16 @@ TEST(isLittleThreeDragons, WhenOpen) { } TEST(isLittleThreeDragons, BadHand) { - const Meld meld = { + auto game_state = GameState(); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("666z111m222p77s"); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kWhiteDragon), }; - auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("666z111m222p77s"); - game_state.hands[0].open = true; - game_state.hands[0].melds = {meld}; - - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isLittleThreeDragons(game_state, 0, branch)) { diff --git a/tests/yakus/terminalinsets.test.cc b/tests/yakus/terminalinsets.test.cc index 649ee6dd..2221d2d9 100644 --- a/tests/yakus/terminalinsets.test.cc +++ b/tests/yakus/terminalinsets.test.cc @@ -18,17 +18,16 @@ namespace mahjong::yaku { TEST(isTerminalsInAllSets, 2Han) { - const Meld meld = { + auto game_state = GameState(); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m789m111p11s"); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kChi, .start = Piece(kSevenPin), }; - auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m789m111p11s"); - game_state.hands[0].open = true; - game_state.hands[0].melds = {meld}; - - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTerminalsInAllSets(game_state, 0, branch)) { @@ -41,10 +40,11 @@ TEST(isTerminalsInAllSets, 2Han) { TEST(isTerminalsInAllSets, 3Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m789m111p789p11s"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m789m111p789p11s"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTerminalsInAllSets(game_state, 0, branch)) { @@ -56,17 +56,17 @@ TEST(isTerminalsInAllSets, 3Han) { } TEST(isTerminalsInAllSets, BadHand) { - const Meld meld = { + auto game_state = GameState(); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m789m222p11s"); + hand.open = true; + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kChi, .start = Piece(kSevenPin), }; - auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m789m222p11s"); - game_state.hands[0].open = true; - game_state.hands[0].melds = {meld}; - - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTerminalsInAllSets(game_state, 0, branch)) { diff --git a/tests/yakus/triplekan.test.cc b/tests/yakus/triplekan.test.cc index 867d6d43..03eee6e4 100644 --- a/tests/yakus/triplekan.test.cc +++ b/tests/yakus/triplekan.test.cc @@ -32,11 +32,13 @@ TEST(isThreeKans, 2Han) { }; auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("666z22m"); - game_state.hands[0].melds = {meld_a, meld_b, meld_c}; - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("666z22m"); + hand.melds = {meld_a, meld_b, meld_c}; + hand.meld_count = 3; + hand.open = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeKans(game_state, 0, branch)) { @@ -66,11 +68,13 @@ TEST(isThreeKans, WithOtherMelds) { }; auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("22m"); - game_state.hands[0].melds = {meld_a, meld_b, meld_c, meld_d}; - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("22m"); + hand.melds = {meld_a, meld_b, meld_c, meld_d}; + hand.meld_count = 4; + hand.open = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeKans(game_state, 0, branch)) { @@ -92,11 +96,13 @@ TEST(isThreeKans, BadHand) { }; auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("777p666z22m"); - game_state.hands[0].melds = {meld_a, meld_b}; - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("777p666z22m"); + hand.melds = {meld_a, meld_b}; + hand.meld_count = 2; + hand.open = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeKans(game_state, 0, branch)) { @@ -122,11 +128,13 @@ TEST(isThreeKans, AllConcealed) { }; auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("666z22m"); - game_state.hands[0].melds = {meld_a, meld_b, meld_c}; - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("666z22m"); + hand.melds = {meld_a, meld_b, meld_c}; + hand.meld_count = 3; + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeKans(game_state, 0, branch)) { From c042f5573fd906ed065cf6b5ff2db13c159292a0 Mon Sep 17 00:00:00 2001 From: alice Hartley Date: Wed, 27 Aug 2025 13:48:15 -0700 Subject: [PATCH 05/14] Clean up tests. --- src/analysis/analysis.cc | 2 +- src/analysis/analysis.h | 2 +- src/analysis/util.cc | 2 +- src/analysis/util.h | 2 +- src/scoring/yakus/ninegates.cc | 7 +++-- src/scoring/yakus/thirteenorphans.cc | 6 ++-- tests/yakus/afterkan.test.cc | 15 ++++++---- tests/yakus/allsimples.test.cc | 15 ++++++---- tests/yakus/blessingofman.test.cc | 28 ++++++++++-------- tests/yakus/concealedhand.test.cc | 20 +++++++------ tests/yakus/dragonpon.test.cc | 32 ++++++++++++--------- tests/yakus/mixedtriplechi.test.cc | 21 ++++++++------ tests/yakus/outsidehand.test.cc | 24 +++++++++------- tests/yakus/pinfu.test.cc | 28 ++++++++++-------- tests/yakus/puredoublechi.test.cc | 21 ++++++++------ tests/yakus/purestraight.test.cc | 21 ++++++++------ tests/yakus/riichi.test.cc | 26 ++++++++++------- tests/yakus/robbingkan.test.cc | 10 ++++--- tests/yakus/sevenpairs.test.cc | 21 ++++++++------ tests/yakus/triplepon.test.cc | 10 ++++--- tests/yakus/twicepuredoublechi.test.cc | 21 ++++++++------ tests/yakus/underthesea.test.cc | 15 ++++++---- tests/yakus/windpons.test.cc | 40 +++++++++++++++----------- 23 files changed, 227 insertions(+), 162 deletions(-) diff --git a/src/analysis/analysis.cc b/src/analysis/analysis.cc index e648f56e..26720c36 100644 --- a/src/analysis/analysis.cc +++ b/src/analysis/analysis.cc @@ -7,7 +7,7 @@ #include "analysis/handnode.h" #include "analysis/handtree.h" -#include "types/hand.h" +#include "types/gamestate.h" #include "types/meld.h" #include "types/piecetype.h" #include "types/sets.h" diff --git a/src/analysis/analysis.h b/src/analysis/analysis.h index fd2b100f..e9d17478 100644 --- a/src/analysis/analysis.h +++ b/src/analysis/analysis.h @@ -3,7 +3,7 @@ #include #include "analysis/handnode.h" -#include "types/hand.h" +#include "types/gamestate.h" #include "types/piecetype.h" namespace mahjong { diff --git a/src/analysis/util.cc b/src/analysis/util.cc index 930df1b3..fbb495d9 100644 --- a/src/analysis/util.cc +++ b/src/analysis/util.cc @@ -6,7 +6,7 @@ #include #include "analysis/analysis.h" -#include "types/hand.h" +#include "types/gamestate.h" #include "types/pieces.h" #include "types/piecetype.h" #include "types/sets.h" diff --git a/src/analysis/util.h b/src/analysis/util.h index f72f9af3..257f2e6f 100644 --- a/src/analysis/util.h +++ b/src/analysis/util.h @@ -3,7 +3,7 @@ #include #include "analysis/analysis.h" -#include "types/hand.h" +#include "types/gamestate.h" #include "types/piecetype.h" #include "types/sets.h" diff --git a/src/scoring/yakus/ninegates.cc b/src/scoring/yakus/ninegates.cc index 73fee0cc..8b4db4a7 100644 --- a/src/scoring/yakus/ninegates.cc +++ b/src/scoring/yakus/ninegates.cc @@ -12,13 +12,14 @@ namespace mahjong::yaku { bool isNineGates(const GameState& state, int player, const std::vector& branch) { - if (state.hands.at(player).open) { + const Hand& hand = state.hands[player]; + if (hand.open) { return false; } if (!isFullFlush(state, player, branch)) { return false; } - if (state.hands.at(player).open) { + if (hand.open) { return false; } std::map pieces; @@ -26,7 +27,7 @@ bool isNineGates(const GameState& state, int player, pieces.at(i) = 0; } bool duplicate = false; - for (const auto& piece : state.hands.at(player).live) { + for (const auto& piece : hand.live) { if (pieces.contains(piece.getPieceNum())) { if ((pieces[piece.getPieceNum()] != 0) && !piece.isTerminal()) { if (duplicate) { diff --git a/src/scoring/yakus/thirteenorphans.cc b/src/scoring/yakus/thirteenorphans.cc index aa8c0a39..f700537b 100644 --- a/src/scoring/yakus/thirteenorphans.cc +++ b/src/scoring/yakus/thirteenorphans.cc @@ -13,7 +13,8 @@ namespace mahjong::yaku { bool isThirteenOrphans(const GameState& state, int player, const std::vector& /*branch*/) { - if (state.hands.at(player).open) { + const Hand& hand = state.hands[player]; + if (hand.open) { return false; } std::map pieces = { @@ -23,7 +24,8 @@ bool isThirteenOrphans(const GameState& state, int player, {kNorthWind, false}, {kRedDragon, false}, {kWhiteDragon, false}, {kGreenDragon, false}}; bool duplicate = false; - for (const auto& piece : state.hands.at(player).live) { + + for (const auto& piece : hand.live) { if (pieces.contains(piece)) { if (pieces[piece]) { duplicate = true; diff --git a/tests/yakus/afterkan.test.cc b/tests/yakus/afterkan.test.cc index 33d91c5a..43904d2e 100644 --- a/tests/yakus/afterkan.test.cc +++ b/tests/yakus/afterkan.test.cc @@ -15,12 +15,13 @@ namespace mahjong::yaku { TEST(isAfterAKan, 1Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m789m1111z999s55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m789m1111z999s55z"); game_state.currentPlayer = 0; game_state.prevState = StateFunctionType::kReplacement; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAfterAKan(game_state, 0, branch)) { @@ -33,12 +34,13 @@ TEST(isAfterAKan, 1Han) { TEST(isAfterAKan, DoesntApply) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m789m1111z999s55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m789m1111z999s55z"); game_state.currentPlayer = 0; game_state.prevState = StateFunctionType::kPon; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAfterAKan(game_state, 0, branch)) { @@ -51,12 +53,13 @@ TEST(isAfterAKan, DoesntApply) { TEST(isAfterAKan, WrongPlayer) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m789m1111z999s55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m789m1111z999s55z"); game_state.currentPlayer = 2; game_state.prevState = StateFunctionType::kReplacement; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAfterAKan(game_state, 0, branch)) { diff --git a/tests/yakus/allsimples.test.cc b/tests/yakus/allsimples.test.cc index f40f3a57..7d4e7279 100644 --- a/tests/yakus/allsimples.test.cc +++ b/tests/yakus/allsimples.test.cc @@ -15,9 +15,10 @@ namespace mahjong::yaku { TEST(isAllSimples, 1Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("222m333p444s555p88m"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("222m333p444s555p88m"); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllSimples(game_state, 0, branch)) { @@ -30,9 +31,10 @@ TEST(isAllSimples, 1Han) { TEST(isAllSimples, BadHandHonors) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("222m333p444s111z88m"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("222m333p444s111z88m"); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllSimples(game_state, 0, branch)) { @@ -45,9 +47,10 @@ TEST(isAllSimples, BadHandHonors) { TEST(isAllSimples, BadHandTerminals) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("222m333p444s111m88m"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("222m333p444s111m88m"); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllSimples(game_state, 0, branch)) { diff --git a/tests/yakus/blessingofman.test.cc b/tests/yakus/blessingofman.test.cc index 0f35b8d4..38dfb0bb 100644 --- a/tests/yakus/blessingofman.test.cc +++ b/tests/yakus/blessingofman.test.cc @@ -14,8 +14,9 @@ namespace mahjong::yaku { TEST(isBlessingOfMan, 5Han) { auto game_state = GameState(); - game_state.hands[3].live = HandFromNotation("123m123p444m111z55m"); - game_state.hands[3].open = false; + Hand& hand = game_state.hands[3]; + hand.live = HandFromNotation("123m123p444m111z55m"); + hand.open = false; game_state.turnNum = 1; @@ -24,7 +25,7 @@ TEST(isBlessingOfMan, 5Han) { game_state.hasRonned[3] = true; - auto root = breakdownHand(game_state.hands.at(3).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBlessingOfMan(game_state, 3, branch)) { @@ -37,8 +38,9 @@ TEST(isBlessingOfMan, 5Han) { TEST(isBlessingOfMan, MustBeARon) { auto game_state = GameState(); - game_state.hands[3].live = HandFromNotation("123m123p444m111z55m"); - game_state.hands[3].open = false; + Hand& hand = game_state.hands[3]; + hand.live = HandFromNotation("123m123p444m111z55m"); + hand.open = false; game_state.turnNum = 3; @@ -47,7 +49,7 @@ TEST(isBlessingOfMan, MustBeARon) { game_state.hasRonned[3] = false; - auto root = breakdownHand(game_state.hands.at(3).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBlessingOfMan(game_state, 3, branch)) { @@ -60,8 +62,9 @@ TEST(isBlessingOfMan, MustBeARon) { TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m123p444m111z55m"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m123p444m111z55m"); + hand.open = false; game_state.turnNum = 2; @@ -70,7 +73,7 @@ TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { game_state.hasRonned[0] = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBlessingOfMan(game_state, 0, branch)) { @@ -83,8 +86,9 @@ TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { TEST(isBlessingOfMan, NoCalledMustHaveOccured) { auto game_state = GameState(); - game_state.hands[3].live = HandFromNotation("123m123p444m111z55m"); - game_state.hands[3].open = false; + Hand& hand = game_state.hands[3]; + hand.live = HandFromNotation("123m123p444m111z55m"); + hand.open = false; game_state.turnNum = 1; @@ -92,7 +96,7 @@ TEST(isBlessingOfMan, NoCalledMustHaveOccured) { game_state.hasRonned[3] = true; - auto root = breakdownHand(game_state.hands.at(3).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBlessingOfMan(game_state, 3, branch)) { diff --git a/tests/yakus/concealedhand.test.cc b/tests/yakus/concealedhand.test.cc index 7f7ca288..31ce7fc3 100644 --- a/tests/yakus/concealedhand.test.cc +++ b/tests/yakus/concealedhand.test.cc @@ -11,8 +11,9 @@ namespace mahjong::yaku { TEST(isFullyConcealedHand, 1Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("555m555p555s111z44m"); + hand.open = false; game_state.currentPlayer = 0; EXPECT_TRUE(isFullyConcealedHand(game_state, 0)); @@ -20,8 +21,9 @@ TEST(isFullyConcealedHand, 1Han) { TEST(isFullyConcealedHand, MustTsumo) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("555m555p555s111z44m"); + hand.open = false; game_state.currentPlayer = 1; EXPECT_FALSE(isFullyConcealedHand(game_state, 0)); @@ -29,8 +31,9 @@ TEST(isFullyConcealedHand, MustTsumo) { TEST(isFullyConcealedHand, MustBeClosedHand) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("555m555p555s111z44m"); + hand.open = true; game_state.currentPlayer = 0; EXPECT_FALSE(isFullyConcealedHand(game_state, 0)); @@ -38,8 +41,9 @@ TEST(isFullyConcealedHand, MustBeClosedHand) { TEST(isFullyConcealedHand, MustHavePiecesRemainingInWall) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("555m555p555s111z44m"); + hand.open = false; game_state.currentPlayer = 0; // Empty the Wall diff --git a/tests/yakus/dragonpon.test.cc b/tests/yakus/dragonpon.test.cc index 258ae63e..7a0aa2af 100644 --- a/tests/yakus/dragonpon.test.cc +++ b/tests/yakus/dragonpon.test.cc @@ -14,9 +14,10 @@ namespace mahjong::yaku { TEST(isWindOrDragonPon, WhiteDragon) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m555z11z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m555z11z"); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isWhiteDragon(game_state, 0, branch)) { @@ -29,9 +30,10 @@ TEST(isWindOrDragonPon, WhiteDragon) { TEST(isWindOrDragonPon, GreenDragon) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m666z11z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m666z11z"); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isGreenDragon(game_state, 0, branch)) { @@ -44,9 +46,10 @@ TEST(isWindOrDragonPon, GreenDragon) { TEST(isWindOrDragonPon, RedDragon) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m777z11z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m777z11z"); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRedDragon(game_state, 0, branch)) { @@ -59,9 +62,10 @@ TEST(isWindOrDragonPon, RedDragon) { TEST(isWindOrDragonPon, Kan) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m7777z11z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m7777z11z"); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRedDragon(game_state, 0, branch)) { @@ -74,10 +78,11 @@ TEST(isWindOrDragonPon, Kan) { TEST(isWindOrDragonPon, CanWhenOpen) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m777z11z"); - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m777z11z"); + hand.open = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRedDragon(game_state, 0, branch)) { @@ -90,9 +95,10 @@ TEST(isWindOrDragonPon, CanWhenOpen) { TEST(isWindOrDragonPon, BadHand) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m222p11p"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m222p11p"); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isGreenDragon(game_state, 0, branch)) { diff --git a/tests/yakus/mixedtriplechi.test.cc b/tests/yakus/mixedtriplechi.test.cc index bc74aa13..84f34e5e 100644 --- a/tests/yakus/mixedtriplechi.test.cc +++ b/tests/yakus/mixedtriplechi.test.cc @@ -15,10 +15,11 @@ namespace mahjong::yaku { TEST(isMixedTripleChi, Open) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123p123m123s555p11z"); - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123p123m123s555p11z"); + hand.open = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isMixedTripleChi(game_state, 0, branch)) { @@ -31,10 +32,11 @@ TEST(isMixedTripleChi, Open) { TEST(isMixedTripleChi, Closed) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123p123m123s555p11z"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123p123m123s555p11z"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isMixedTripleChi(game_state, 0, branch)) { @@ -47,10 +49,11 @@ TEST(isMixedTripleChi, Closed) { TEST(isMixedTripleChi, BadHand) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123p123p123s555p11z"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123p123p123s555p11z"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isMixedTripleChi(game_state, 0, branch)) { diff --git a/tests/yakus/outsidehand.test.cc b/tests/yakus/outsidehand.test.cc index 358da80e..331aaaa2 100644 --- a/tests/yakus/outsidehand.test.cc +++ b/tests/yakus/outsidehand.test.cc @@ -15,10 +15,11 @@ namespace mahjong::yaku { TEST(isOutsideHand, Open) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m789m111z999s55z"); - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m789m111z999s55z"); + hand.open = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isOutsideHand(game_state, 0, branch)) { @@ -31,10 +32,11 @@ TEST(isOutsideHand, Open) { TEST(isOutsideHand, Closed) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m789m111z999s55z"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m789m111z999s55z"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isOutsideHand(game_state, 0, branch)) { @@ -47,9 +49,10 @@ TEST(isOutsideHand, Closed) { TEST(isOutsideHand, NoChi) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m111p111s999m66z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m111p111s999m66z"); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isOutsideHand(game_state, 0, branch)) { @@ -62,9 +65,10 @@ TEST(isOutsideHand, NoChi) { TEST(isOutsideHand, BadHand) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m234p111s999m66z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m234p111s999m66z"); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isOutsideHand(game_state, 0, branch)) { diff --git a/tests/yakus/pinfu.test.cc b/tests/yakus/pinfu.test.cc index eaefabe9..54e62386 100644 --- a/tests/yakus/pinfu.test.cc +++ b/tests/yakus/pinfu.test.cc @@ -17,11 +17,12 @@ namespace mahjong::yaku { TEST(isPinfu, 1Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456p234678s44m"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456p234678s44m"); + hand.open = false; game_state.pendingPiece = Piece(kFourPin); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPinfu(game_state, 0, branch)) { @@ -34,11 +35,12 @@ TEST(isPinfu, 1Han) { TEST(isPinfu, BadHand) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m555p234678s44m"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m555p234678s44m"); + hand.open = false; game_state.pendingPiece = Piece(kTwoBamboo); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPinfu(game_state, 0, branch)) { @@ -51,11 +53,12 @@ TEST(isPinfu, BadHand) { TEST(isPinfu, CantBeOpen) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456p234678s44m"); - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456p234678s44m"); + hand.open = true; game_state.pendingPiece = Piece(kFourPin); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPinfu(game_state, 0, branch)) { @@ -68,11 +71,12 @@ TEST(isPinfu, CantBeOpen) { TEST(isPinfu, NeedTwoWait) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456p234678s44m"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456p234678s44m"); + hand.open = false; game_state.pendingPiece = Piece(kFivePin); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPinfu(game_state, 0, branch)) { diff --git a/tests/yakus/puredoublechi.test.cc b/tests/yakus/puredoublechi.test.cc index 4dbe3d01..3ca8f572 100644 --- a/tests/yakus/puredoublechi.test.cc +++ b/tests/yakus/puredoublechi.test.cc @@ -15,10 +15,11 @@ namespace mahjong::yaku { TEST(isPureDoubleChi, 1Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("234m234m555p888s88p"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("234m234m555p888s88p"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureDoubleChi(game_state, 0, branch)) { @@ -31,10 +32,11 @@ TEST(isPureDoubleChi, 1Han) { TEST(isPureDoubleChi, BadHand) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("234m123m555p888s88p"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("234m123m555p888s88p"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureDoubleChi(game_state, 0, branch)) { @@ -47,10 +49,11 @@ TEST(isPureDoubleChi, BadHand) { TEST(isPureDoubleChi, MustBeConcealed) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("234m234m555p888s88p"); - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("234m234m555p888s88p"); + hand.open = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureDoubleChi(game_state, 0, branch)) { diff --git a/tests/yakus/purestraight.test.cc b/tests/yakus/purestraight.test.cc index 291ecd2f..68190781 100644 --- a/tests/yakus/purestraight.test.cc +++ b/tests/yakus/purestraight.test.cc @@ -15,10 +15,11 @@ namespace mahjong::yaku { TEST(isPureStraight, Open) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m789m555p11z"); - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m789m555p11z"); + hand.open = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureStraight(game_state, 0, branch)) { @@ -31,10 +32,11 @@ TEST(isPureStraight, Open) { TEST(isPureStraight, Closed) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m789m555p11z"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m789m555p11z"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureStraight(game_state, 0, branch)) { @@ -47,10 +49,11 @@ TEST(isPureStraight, Closed) { TEST(isPureStraight, BadHand) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m999m555p11z"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m999m555p11z"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureStraight(game_state, 0, branch)) { diff --git a/tests/yakus/riichi.test.cc b/tests/yakus/riichi.test.cc index 631dd5ae..1e12dff8 100644 --- a/tests/yakus/riichi.test.cc +++ b/tests/yakus/riichi.test.cc @@ -14,10 +14,11 @@ namespace mahjong::yaku { TEST(isRiichi, Riichi) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); - game_state.hands[0].riichi = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("555m555p555s111z44m"); + hand.riichi = true; - game_state.hands[0].riichiRound = 7; + hand.riichiRound = 7; game_state.turnNum = 15; game_state.lastCall = 2; @@ -26,10 +27,11 @@ TEST(isRiichi, Riichi) { TEST(isRiichi, Ippatsu) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); - game_state.hands[0].riichi = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("555m555p555s111z44m"); + hand.riichi = true; - game_state.hands[0].riichiRound = 14; + hand.riichiRound = 14; game_state.turnNum = 15; game_state.lastCall = 2; @@ -38,10 +40,11 @@ TEST(isRiichi, Ippatsu) { TEST(isRiichi, DoubleRiichi) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); - game_state.hands[0].riichi = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("555m555p555s111z44m"); + hand.riichi = true; - game_state.hands[0].riichiRound = 1; + hand.riichiRound = 1; game_state.turnNum = 2; game_state.lastCall = -1; @@ -50,8 +53,9 @@ TEST(isRiichi, DoubleRiichi) { TEST(isRiichi, NoRiichi) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("555m555p555s111z44m"); - game_state.hands[0].riichi = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("555m555p555s111z44m"); + hand.riichi = false; game_state.turnNum = 2; game_state.lastCall = -1; diff --git a/tests/yakus/robbingkan.test.cc b/tests/yakus/robbingkan.test.cc index 35a1b7a8..6f9ee4d1 100644 --- a/tests/yakus/robbingkan.test.cc +++ b/tests/yakus/robbingkan.test.cc @@ -15,11 +15,12 @@ namespace mahjong::yaku { TEST(isRobbingAKan, 1Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m789m1111z999s55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m789m1111z999s55z"); game_state.hasRonned[0] = true; game_state.nextState = StateFunctionType::kKanDiscard; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRobbingAKan(game_state, 0, branch)) { @@ -32,11 +33,12 @@ TEST(isRobbingAKan, 1Han) { TEST(isRobbingAKan, DoesntApply) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m789m1111z999s55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m789m1111z999s55z"); game_state.hasRonned[0] = true; game_state.nextState = StateFunctionType::kPon; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRobbingAKan(game_state, 0, branch)) { diff --git a/tests/yakus/sevenpairs.test.cc b/tests/yakus/sevenpairs.test.cc index b30b208a..abef246e 100644 --- a/tests/yakus/sevenpairs.test.cc +++ b/tests/yakus/sevenpairs.test.cc @@ -15,10 +15,11 @@ namespace mahjong::yaku { TEST(isSevenPairs, 2Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("11m22p33s44z55m11z66z"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("11m22p33s44z55m11z66z"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSevenPairs(game_state, 0, branch)) { @@ -31,10 +32,11 @@ TEST(isSevenPairs, 2Han) { TEST(isSevenPairs, MustBeConcealed) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("11m22p33s44z55m11z66z"); - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("11m22p33s44z55m11z66z"); + hand.open = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSevenPairs(game_state, 0, branch)) { @@ -47,10 +49,11 @@ TEST(isSevenPairs, MustBeConcealed) { TEST(isSevenPairs, UniquePairsOnly) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("1111m22p33s44z11z66z"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("1111m22p33s44z11z66z"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSevenPairs(game_state, 0, branch)) { diff --git a/tests/yakus/triplepon.test.cc b/tests/yakus/triplepon.test.cc index db9e0efa..6d81cb06 100644 --- a/tests/yakus/triplepon.test.cc +++ b/tests/yakus/triplepon.test.cc @@ -15,9 +15,10 @@ namespace mahjong::yaku { TEST(isTriplePon, 2Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m111p111s666z44m"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m111p111s666z44m"); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTriplePon(game_state, 0, branch)) { @@ -30,9 +31,10 @@ TEST(isTriplePon, 2Han) { TEST(isTriplePon, BadHand) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("111m111p222m666z44m"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("111m111p222m666z44m"); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTriplePon(game_state, 0, branch)) { diff --git a/tests/yakus/twicepuredoublechi.test.cc b/tests/yakus/twicepuredoublechi.test.cc index e8f97649..0b052fd0 100644 --- a/tests/yakus/twicepuredoublechi.test.cc +++ b/tests/yakus/twicepuredoublechi.test.cc @@ -15,10 +15,11 @@ namespace mahjong::yaku { TEST(isTwicePureDoubleChi, 3Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("789p789p234m234m11z"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("789p789p234m234m11z"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTwicePureDoubleChi(game_state, 0, branch)) { @@ -31,10 +32,11 @@ TEST(isTwicePureDoubleChi, 3Han) { TEST(isTwicePureDoubleChi, MustBeConcealed) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("789p789p234m234m11z"); - game_state.hands[0].open = true; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("789p789p234m234m11z"); + hand.open = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTwicePureDoubleChi(game_state, 0, branch)) { @@ -47,10 +49,11 @@ TEST(isTwicePureDoubleChi, MustBeConcealed) { TEST(isTwicePureDoubleChi, BadHand) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("789p789p234m567m11z"); - game_state.hands[0].open = false; + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("789p789p234m567m11z"); + hand.open = false; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTwicePureDoubleChi(game_state, 0, branch)) { diff --git a/tests/yakus/underthesea.test.cc b/tests/yakus/underthesea.test.cc index b5a6b8e7..2226e34a 100644 --- a/tests/yakus/underthesea.test.cc +++ b/tests/yakus/underthesea.test.cc @@ -14,10 +14,11 @@ namespace mahjong::yaku { TEST(isBottomOfTheSea, 1Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m789m111z999s55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m789m111z999s55z"); game_state.livingWallIndex = kLivingWallCount; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBottomOfTheSea(game_state, 0, branch)) { @@ -30,11 +31,12 @@ TEST(isBottomOfTheSea, 1Han) { TEST(isBottomOfTheSea, 1HanRonned) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m789m111z999s55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m789m111z999s55z"); game_state.livingWallIndex = kLivingWallCount; game_state.hasRonned[0] = true; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBottomOfTheSea(game_state, 0, branch)) { @@ -47,9 +49,10 @@ TEST(isBottomOfTheSea, 1HanRonned) { TEST(isBottomOfTheSea, DoesntApply) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m789m111z999s55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m789m111z999s55z"); - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBottomOfTheSea(game_state, 0, branch)) { diff --git a/tests/yakus/windpons.test.cc b/tests/yakus/windpons.test.cc index 94d8b720..960e6958 100644 --- a/tests/yakus/windpons.test.cc +++ b/tests/yakus/windpons.test.cc @@ -14,10 +14,11 @@ namespace mahjong::yaku { TEST(isWindOrDragonPon, SeatWind) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m444z55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m444z55z"); game_state.roundNum = 1; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); auto branches = Node::AsBranchVectors(root.get()); @@ -33,10 +34,11 @@ TEST(isWindOrDragonPon, SeatWind) { TEST(isWindOrDragonPon, SeatWindKan) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m4444z55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m4444z55z"); game_state.roundNum = 1; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, 0, branch)) { @@ -49,10 +51,11 @@ TEST(isWindOrDragonPon, SeatWindKan) { TEST(isWindOrDragonPon, PrevalentWind) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m111z55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m111z55z"); game_state.roundNum = 1; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPrevalentWind(game_state, 0, branch)) { @@ -65,10 +68,11 @@ TEST(isWindOrDragonPon, PrevalentWind) { TEST(isWindOrDragonPon, PrevalentWindKan) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m1111z55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m1111z55z"); game_state.roundNum = 1; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPrevalentWind(game_state, 0, branch)) { @@ -81,10 +85,11 @@ TEST(isWindOrDragonPon, PrevalentWindKan) { TEST(isWindOrDragonPon, Dealer2Han) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m111z55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m111z55z"); game_state.roundNum = 0; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, 0, branch) && @@ -98,10 +103,11 @@ TEST(isWindOrDragonPon, Dealer2Han) { TEST(isWindOrDragonPon, Dealer2HanKan) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m1111z55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m1111z55z"); game_state.roundNum = 0; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, 0, branch) && @@ -115,10 +121,11 @@ TEST(isWindOrDragonPon, Dealer2HanKan) { TEST(isWindOrDragonPon, NotSeatOrPrevalent) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m222z55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m222z55z"); game_state.roundNum = 0; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, 0, branch) || @@ -132,10 +139,11 @@ TEST(isWindOrDragonPon, NotSeatOrPrevalent) { TEST(isWindOrDragonPon, NoWind) { auto game_state = GameState(); - game_state.hands[0].live = HandFromNotation("123m456m666m55z"); + Hand& hand = game_state.hands[0]; + hand.live = HandFromNotation("123m456m666m55z"); game_state.roundNum = 0; - auto root = breakdownHand(game_state.hands.at(0).live); + auto root = breakdownHand(hand.live); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, 0, branch) || From eb95ef4fc974fb47b33531d62c483aebc1e4e8ee Mon Sep 17 00:00:00 2001 From: alice Hartley Date: Wed, 27 Aug 2025 20:01:35 -0700 Subject: [PATCH 06/14] Convert hand discards to std::array. --- src/api/gamestate.cc | 3 +-- src/api/types.h | 2 +- src/statefunctions/gamestates/chi.cc | 2 +- src/statefunctions/gamestates/kan.cc | 2 +- src/statefunctions/gamestates/pon.cc | 2 +- src/statefunctions/gamestates/riichi.cc | 2 +- src/statefunctions/gamestates/ron.cc | 2 +- src/statefunctions/stateutilities.cc | 2 +- src/types/gamestate.h | 5 +++-- src/types/settings.h | 1 + tests/api/game_control.test.cc | 2 +- tests/rules/basic_rules.test.cc | 4 ++-- 12 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/api/gamestate.cc b/src/api/gamestate.cc index 4d1f2d4e..08fe3ba4 100644 --- a/src/api/gamestate.cc +++ b/src/api/gamestate.cc @@ -166,8 +166,7 @@ CObservedGameState ObserveGameState(mahjong::GameState* state) { // Discards const auto& discards = cpp_hand.discards; - const int discards_size = static_cast(discards.size()); - c_hand.discardCount = std::min(discards_size, kMaxDiscardsPerPlayer); + c_hand.discardCount = cpp_hand.discards_count; for (auto j = 0; j < c_hand.discardCount; j++) { c_hand.discards[j] = static_cast(discards[j].toUint8_t()); } diff --git a/src/api/types.h b/src/api/types.h index 3b99198d..dead6169 100644 --- a/src/api/types.h +++ b/src/api/types.h @@ -9,7 +9,7 @@ extern "C" { static const int kMaxLiveHandSize = 14; // Maximum 14 pieces (13 + 1 drawn) static const int kMaxMeldsPerHand = 4; // Maximum 4 melds possible static const int kMaxDiscardsPerPlayer = - 21; // Maximum 21 discards per player ((136 - 13*4 hands) / 4) + 27; // Flow interruption from calls can allow the max discards to go up to 27. using CPiece = int; using CWind = int; diff --git a/src/statefunctions/gamestates/chi.cc b/src/statefunctions/gamestates/chi.cc index 7b824d32..11ff37b3 100644 --- a/src/statefunctions/gamestates/chi.cc +++ b/src/statefunctions/gamestates/chi.cc @@ -43,7 +43,7 @@ std::unique_ptr Chi(std::unique_ptr state) { } if (state->hands.at(state->currentPlayer).riichi && - state->hands.at(state->currentPlayer).discards.size() == + state->hands.at(state->currentPlayer).discards_count == state->hands.at(state->currentPlayer).riichiPieceDiscard) { state->hands.at(state->currentPlayer).riichiPieceDiscard++; } diff --git a/src/statefunctions/gamestates/kan.cc b/src/statefunctions/gamestates/kan.cc index 2d22254f..4910a4af 100644 --- a/src/statefunctions/gamestates/kan.cc +++ b/src/statefunctions/gamestates/kan.cc @@ -26,7 +26,7 @@ std::unique_ptr Kan(std::unique_ptr state) { }); if (state->hands.at(state->currentPlayer).riichi && - state->hands.at(state->currentPlayer).discards.size() == + state->hands.at(state->currentPlayer).discards_count == state->hands.at(state->currentPlayer).riichiPieceDiscard) { state->hands.at(state->currentPlayer).riichiPieceDiscard++; } diff --git a/src/statefunctions/gamestates/pon.cc b/src/statefunctions/gamestates/pon.cc index 173a3c45..b998c416 100644 --- a/src/statefunctions/gamestates/pon.cc +++ b/src/statefunctions/gamestates/pon.cc @@ -28,7 +28,7 @@ std::unique_ptr Pon(std::unique_ptr state) { }); if (state->hands.at(state->currentPlayer).riichi && - state->hands.at(state->currentPlayer).discards.size() == + state->hands.at(state->currentPlayer).discards_count == state->hands.at(state->currentPlayer).riichiPieceDiscard) { state->hands.at(state->currentPlayer).riichiPieceDiscard++; } diff --git a/src/statefunctions/gamestates/riichi.cc b/src/statefunctions/gamestates/riichi.cc index 66959a58..aa977cd3 100644 --- a/src/statefunctions/gamestates/riichi.cc +++ b/src/statefunctions/gamestates/riichi.cc @@ -31,7 +31,7 @@ std::unique_ptr Riichi(std::unique_ptr state) { state->hands.at(state->currentPlayer).riichiRound = state->turnNum; state->hands.at(state->currentPlayer).riichiPieceDiscard = - state->hands.at(state->currentPlayer).discards.size(); + state->hands.at(state->currentPlayer).discards_count; state->hands.at(state->currentPlayer).riichi = true; state->riichiSticks++; diff --git a/src/statefunctions/gamestates/ron.cc b/src/statefunctions/gamestates/ron.cc index 203e9821..0ba0bad8 100644 --- a/src/statefunctions/gamestates/ron.cc +++ b/src/statefunctions/gamestates/ron.cc @@ -19,7 +19,7 @@ std::unique_ptr Ron(std::unique_ptr state) { std::array basic_points = {}; if (state->hands.at(state->currentPlayer).riichi && - state->hands.at(state->currentPlayer).discards.size() == + state->hands.at(state->currentPlayer).discards_count == state->hands.at(state->currentPlayer).riichiPieceDiscard) { state->riichiSticks--; state->hands.at(state->currentPlayer).riichi = false; diff --git a/src/statefunctions/stateutilities.cc b/src/statefunctions/stateutilities.cc index c355584a..07788b88 100644 --- a/src/statefunctions/stateutilities.cc +++ b/src/statefunctions/stateutilities.cc @@ -55,7 +55,7 @@ uint8_t RemovePieces(GameState& state, int player, Piece p, uint8_t count) { // Discard an instance of piece p from given players hand void DiscardPiece(GameState& state, int player, Piece p) { RemovePieces(state, player, p, /*count=*/1); - state.hands.at(player).discards.push_back(p); + state.hands[player].discards[state.hands[player].discards_count++] = p; } Piece AskForDiscard(const GameState& state) { diff --git a/src/types/gamestate.h b/src/types/gamestate.h index e7ab9c3b..59c4fcf5 100644 --- a/src/types/gamestate.h +++ b/src/types/gamestate.h @@ -14,12 +14,13 @@ namespace mahjong { struct Hand { bool open = false; bool riichi = false; - size_t riichiPieceDiscard = -1; + int riichiPieceDiscard = -1; int riichiRound = -1; int meld_count = 0; std::vector live; std::array melds; - std::vector discards; + std::array discards; + int discards_count = 0; }; struct GameState { diff --git a/src/types/settings.h b/src/types/settings.h index 96d1f3f5..612c41e9 100644 --- a/src/types/settings.h +++ b/src/types/settings.h @@ -15,6 +15,7 @@ constexpr int kReplacementCount = kNumPlayers == 4 ? 4 : 8; constexpr int kDoraCount = 5; constexpr int kDeadWallCount = (2 * kDoraCount) + kReplacementCount; constexpr int kLivingWallCount = kTileCount - kDeadWallCount; +constexpr int kMaxDiscardCount = 27; struct GameSettings { std::vector seatControllers; diff --git a/tests/api/game_control.test.cc b/tests/api/game_control.test.cc index 6e2b9650..359f83e8 100644 --- a/tests/api/game_control.test.cc +++ b/tests/api/game_control.test.cc @@ -171,7 +171,7 @@ TEST(Api, ObserveGameStateHandsAndDiscards) { } // Check discards using CHand structure - EXPECT_EQ(c_hand.discardCount, static_cast(cpp_hand.discards.size())); + EXPECT_EQ(c_hand.discardCount, static_cast(cpp_hand.discards_count)); for (int discard = 0; discard < c_hand.discardCount; discard++) { EXPECT_EQ( c_hand.discards[discard], diff --git a/tests/rules/basic_rules.test.cc b/tests/rules/basic_rules.test.cc index 3c3bdf4d..a882cd4b 100644 --- a/tests/rules/basic_rules.test.cc +++ b/tests/rules/basic_rules.test.cc @@ -149,7 +149,7 @@ TEST(DiscardMechanics, discardDecreasesTileCount) { EXPECT_EQ(state->currState, StateFunctionType::kPlayerHand); EXPECT_EQ(state->nextState, StateFunctionType::kDiscard); - const int discards_before = state->hands[0].discards.size(); + const int discards_before = state->hands[0].discards_count; state = AdvanceGameState(std::move(state)); EXPECT_EQ(state->currState, StateFunctionType::kDiscard); @@ -157,7 +157,7 @@ TEST(DiscardMechanics, discardDecreasesTileCount) { EXPECT_EQ(state->hands[0].live.size(), 13); // Discard pile should have increased - EXPECT_EQ(state->hands[0].discards.size(), discards_before + 1); + EXPECT_EQ(state->hands[0].discards_count, discards_before + 1); } } // namespace mahjong From d6da8ee6238e9f4b33f054a75586202f60d5e3a6 Mon Sep 17 00:00:00 2001 From: alice Hartley Date: Tue, 2 Sep 2025 20:03:52 -0700 Subject: [PATCH 07/14] [WIP] Change hand.live to use std::array --- src/analysis/analysis.cc | 7 +++-- src/analysis/analysis.h | 2 +- src/analysis/handtree.h | 3 ++ src/analysis/util.cc | 10 ++++-- src/api/gamestate.cc | 2 +- src/api/types.h | 3 +- src/scoring/scoring.cc | 7 +++-- src/scoring/yakus/allgreen.cc | 2 +- src/scoring/yakus/allhonors.cc | 2 +- src/scoring/yakus/allpons.cc | 3 +- src/scoring/yakus/allsimples.cc | 2 +- src/scoring/yakus/allterminals.cc | 2 +- src/scoring/yakus/allterminalsandhonors.cc | 2 +- src/scoring/yakus/fullflush.cc | 6 ++-- src/scoring/yakus/halfflush.cc | 4 +-- src/scoring/yakus/maxbranches.cc | 2 +- src/scoring/yakus/ninegates.cc | 2 +- src/scoring/yakus/pinfu.cc | 3 +- src/scoring/yakus/thirteenorphans.cc | 2 +- src/statefunctions/decisionfunction.cc | 22 ++++++------- src/statefunctions/gamestates/chi.cc | 3 +- src/statefunctions/gamestates/draw.cc | 4 +-- src/statefunctions/gamestates/kan.cc | 4 +-- src/statefunctions/gamestates/pon.cc | 4 +-- src/statefunctions/gamestates/replacement.cc | 3 +- src/statefunctions/gamestates/riichi.cc | 8 ++--- src/statefunctions/gamestates/ron.cc | 12 +++---- src/statefunctions/gamestates/roundstart.cc | 4 ++- src/statefunctions/stateutilities.cc | 33 ++++++++++---------- src/types/gamestate.h | 7 ++++- src/types/typeprinter.cc | 2 +- src/types/walls.h | 2 +- tests/api/game_control.test.cc | 3 +- tests/can_chi.test.cc | 3 ++ tests/count_pieces.test.cc | 1 + tests/discard_piece.test.cc | 4 ++- tests/game_play.test.cc | 7 +++-- tests/remove_pieces.test.cc | 13 +++++--- tests/rules/basic_rules.test.cc | 12 +++---- tests/rules/calls.test.cc | 20 +++++++----- tests/setup.test.cc | 2 +- tests/utils/gamestate_utils.test.cc | 4 +-- tests/utils/handformer.cc | 7 +++++ tests/utils/handformer.h | 2 ++ tests/yakus/afterkan.test.cc | 12 +++---- tests/yakus/allpon.test.cc | 17 +++++----- tests/yakus/allsimples.test.cc | 12 +++---- tests/yakus/allterminalsandhonors.test.cc | 13 ++++---- tests/yakus/blessingofman.test.cc | 16 +++++----- tests/yakus/concealedhand.test.cc | 8 ++--- tests/yakus/concealedpon.test.cc | 21 ++++++------- tests/yakus/dragonpon.test.cc | 24 +++++++------- tests/yakus/fullflush.test.cc | 22 ++++++------- tests/yakus/halfflush.test.cc | 17 +++++----- tests/yakus/littlethreedragons.test.cc | 13 ++++---- tests/yakus/mixedtriplechi.test.cc | 12 +++---- tests/yakus/outsidehand.test.cc | 16 +++++----- tests/yakus/pinfu.test.cc | 16 +++++----- tests/yakus/puredoublechi.test.cc | 12 +++---- tests/yakus/purestraight.test.cc | 12 +++---- tests/yakus/riichi.test.cc | 8 ++--- tests/yakus/robbingkan.test.cc | 8 ++--- tests/yakus/sevenpairs.test.cc | 12 +++---- tests/yakus/terminalinsets.test.cc | 13 ++++---- tests/yakus/triplekan.test.cc | 17 +++++----- tests/yakus/triplepon.test.cc | 8 ++--- tests/yakus/twicepuredoublechi.test.cc | 12 +++---- tests/yakus/underthesea.test.cc | 12 +++---- tests/yakus/windpons.test.cc | 32 +++++++++---------- 69 files changed, 320 insertions(+), 297 deletions(-) diff --git a/src/analysis/analysis.cc b/src/analysis/analysis.cc index 26720c36..b0e936af 100644 --- a/src/analysis/analysis.cc +++ b/src/analysis/analysis.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -41,7 +42,7 @@ std::vector AnalyzeHand(const Hand& hand, const bool only_complete) { } } std::vector branches; - const std::unique_ptr root = breakdownHand(hand.live); + const std::unique_ptr root = breakdownHand(hand.live_range()); for (const auto& branch_vec : Node::AsBranchVectors(root.get())) { branches.push_back(base_branch); Branch& branch = branches.back(); @@ -73,11 +74,11 @@ std::vector AnalyzeHand(const Hand& hand, const bool only_complete) { return branches; } -std::unique_ptr breakdownHand(const std::vector& pieces) { +std::unique_ptr breakdownHand(const std::span& pieces) { Breakdown b; b.rootNode = std::make_unique(/*id=*/b.id++); b.currentNode = b.rootNode.get(); - b.pieces = pieces; + b.pieces = std::vector(pieces.begin(), pieces.end()); countPieces(&b); std::ranges::sort(b.pieces); auto [begin, end] = std::ranges::unique(b.pieces); diff --git a/src/analysis/analysis.h b/src/analysis/analysis.h index e9d17478..b0eea3e2 100644 --- a/src/analysis/analysis.h +++ b/src/analysis/analysis.h @@ -17,6 +17,6 @@ struct Branch { bool complete = true; }; -std::unique_ptr breakdownHand(const std::vector& pieces); +std::unique_ptr breakdownHand(const std::span& pieces); std::vector AnalyzeHand(const Hand& hand, bool only_complete = false); } // namespace mahjong diff --git a/src/analysis/handtree.h b/src/analysis/handtree.h index 96ccfd96..8850c34f 100644 --- a/src/analysis/handtree.h +++ b/src/analysis/handtree.h @@ -4,7 +4,9 @@ #include "analysis/handnode.h" #include "types/piecetype.h" + namespace mahjong { + struct Breakdown { std::unique_ptr rootNode; Node* currentNode{}; @@ -12,6 +14,7 @@ struct Breakdown { std::map counts; std::map possibilities; std::vector pieces; + int pieces_size; }; void driver(Breakdown* b); diff --git a/src/analysis/util.cc b/src/analysis/util.cc index fbb495d9..0d38eca2 100644 --- a/src/analysis/util.cc +++ b/src/analysis/util.cc @@ -54,7 +54,7 @@ std::vector completeSet(const Piece a, const Piece b) { std::vector getWaits(const Hand& hand) { // 13, 10, 7, 4, 1 are possible piece counts for non-melded tiles - if (hand.live.empty() || hand.live.size() % 3 != 1) { + if (hand.live_count == 0 || hand.live_count % 3 != 1) { return {}; } constexpr int kMaxSingles = 2; @@ -75,13 +75,17 @@ std::vector getWaits(const Hand& hand) { std::vector getWaits(const Hand& hand, const Piece& piece) { Hand new_hand = hand; - new_hand.live.erase(std::ranges::find(new_hand.live, piece)); + // This will move all pieces matching piece to the end of the array, but + // we will only decrease the count by 1 so only a single piece will be + // removed. + std::ranges::remove(new_hand.live, piece); + new_hand.live_count--; return getWaits(new_hand); } std::map> getPossibleWaits(const Hand& hand) { // 14, 11, 8, 5, 2 are the possible piece counts for non-melded tiles. - if (hand.live.empty() || hand.live.size() % 3 != 2) { + if (hand.live_count == 0 || hand.live_count % 3 != 2) { return {}; } constexpr int kMaxSingles = 3; diff --git a/src/api/gamestate.cc b/src/api/gamestate.cc index 08fe3ba4..6aaf539c 100644 --- a/src/api/gamestate.cc +++ b/src/api/gamestate.cc @@ -149,7 +149,7 @@ CObservedGameState ObserveGameState(mahjong::GameState* state) { CHand& c_hand = observed.hands[i]; // Live pieces - const int live_piece_count = static_cast(cpp_hand.live.size()); + const int live_piece_count = static_cast(cpp_hand.live_count); c_hand.livePieceCount = std::min(live_piece_count, kMaxLiveHandSize); for (int j = 0; j < c_hand.livePieceCount; j++) { c_hand.livePieces[j] = static_cast(cpp_hand.live[j].toUint8_t()); diff --git a/src/api/types.h b/src/api/types.h index dead6169..2683306f 100644 --- a/src/api/types.h +++ b/src/api/types.h @@ -9,7 +9,8 @@ extern "C" { static const int kMaxLiveHandSize = 14; // Maximum 14 pieces (13 + 1 drawn) static const int kMaxMeldsPerHand = 4; // Maximum 4 melds possible static const int kMaxDiscardsPerPlayer = - 27; // Flow interruption from calls can allow the max discards to go up to 27. + 27; // Flow interruption from calls can allow the max discards to go up + // to 27. using CPiece = int; using CWind = int; diff --git a/src/scoring/scoring.cc b/src/scoring/scoring.cc index 6357893d..325a4a17 100644 --- a/src/scoring/scoring.cc +++ b/src/scoring/scoring.cc @@ -60,7 +60,7 @@ const int kFuRounding = 10; Score scoreHand(const GameState& state, int player) { const Hand& hand = state.hands[player]; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); Score s; s.han = 0; s.yakuman = 0; @@ -98,7 +98,7 @@ Score scoreHand(const GameState& state, int player) { } for (const auto& dora : Walls::GetDoras(state)) { - for (const auto& p : hand.live) { + for (const auto& p : hand.live_range()) { if (p == dora) { branchscore.han++; } @@ -263,7 +263,8 @@ bool isOpenPinfu(const GameState& state, int player, } bool isComplete(const GameState& state, int player) { - auto root = breakdownHand(state.hands.at(player).live); + const Hand& hand = state.hands[player]; + auto root = breakdownHand(hand.live_range()); if (!root->IsComplete() && !yaku::isThirteenOrphans(state, player)) { return false; } diff --git a/src/scoring/yakus/allgreen.cc b/src/scoring/yakus/allgreen.cc index 5643557b..caec6a4b 100644 --- a/src/scoring/yakus/allgreen.cc +++ b/src/scoring/yakus/allgreen.cc @@ -11,7 +11,7 @@ namespace mahjong::yaku { bool isAllGreen(const GameState& state, int player, const std::vector& /*branch*/) { const Hand& hand = state.hands[player]; - for (const auto& piece : hand.live) { + for (const auto& piece : hand.live_range()) { if (!piece.isGreen()) { return false; } diff --git a/src/scoring/yakus/allhonors.cc b/src/scoring/yakus/allhonors.cc index 44d60c55..d7f73388 100644 --- a/src/scoring/yakus/allhonors.cc +++ b/src/scoring/yakus/allhonors.cc @@ -11,7 +11,7 @@ namespace mahjong::yaku { bool isAllHonors(const GameState& state, int player, const std::vector& /*branch*/) { const Hand& hand = state.hands[player]; - for (const auto& piece : hand.live) { + for (const auto& piece : hand.live_range()) { if (!piece.isHonor()) { return false; } diff --git a/src/scoring/yakus/allpons.cc b/src/scoring/yakus/allpons.cc index 09d7842b..b867307f 100644 --- a/src/scoring/yakus/allpons.cc +++ b/src/scoring/yakus/allpons.cc @@ -19,7 +19,8 @@ bool isAllPons(const GameState& state, int player, } const Hand& hand = state.hands[player]; for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].type == SetType::kKan || hand.melds[i].type == SetType::kPon || + if (hand.melds[i].type == SetType::kKan || + hand.melds[i].type == SetType::kPon || hand.melds[i].type == SetType::kConcealedKan) { pons++; } diff --git a/src/scoring/yakus/allsimples.cc b/src/scoring/yakus/allsimples.cc index 32901782..5cac7c88 100644 --- a/src/scoring/yakus/allsimples.cc +++ b/src/scoring/yakus/allsimples.cc @@ -11,7 +11,7 @@ namespace mahjong::yaku { bool isAllSimples(const GameState& state, int player, const std::vector& /*branch*/) { const Hand& hand = state.hands[player]; - for (const auto& piece : hand.live) { + for (const auto& piece : hand.live_range()) { if (piece.isHonor() || piece.isTerminal()) { return false; } diff --git a/src/scoring/yakus/allterminals.cc b/src/scoring/yakus/allterminals.cc index 8c9d7674..ce48285e 100644 --- a/src/scoring/yakus/allterminals.cc +++ b/src/scoring/yakus/allterminals.cc @@ -11,7 +11,7 @@ namespace mahjong::yaku { bool isAllTerminals(const GameState& state, int player, const std::vector& /*branch*/) { const Hand& hand = state.hands[player]; - for (const auto& piece : hand.live) { + for (const auto& piece : hand.live_range()) { if (!piece.isTerminal()) { return false; } diff --git a/src/scoring/yakus/allterminalsandhonors.cc b/src/scoring/yakus/allterminalsandhonors.cc index 103309f4..4cdb580a 100644 --- a/src/scoring/yakus/allterminalsandhonors.cc +++ b/src/scoring/yakus/allterminalsandhonors.cc @@ -12,7 +12,7 @@ bool isAllTerminalsAndHonors( const GameState& state, int player, const std::vector& /*branch*/) { const Hand& hand = state.hands[player]; - for (const auto& piece : hand.live) { + for (const auto& piece : hand.live_range()) { if (!piece.isHonor() && !piece.isTerminal()) { return false; } diff --git a/src/scoring/yakus/fullflush.cc b/src/scoring/yakus/fullflush.cc index f4c52e74..d301da09 100644 --- a/src/scoring/yakus/fullflush.cc +++ b/src/scoring/yakus/fullflush.cc @@ -11,11 +11,11 @@ namespace mahjong::yaku { bool isFullFlush(const GameState& state, int player, const std::vector& /*branch*/) { const Hand& hand = state.hands[player]; - if (hand.live.front().isHonor()) { + if (hand.live[0].isHonor()) { return false; } - const int suit = hand.live.front().getSuit(); - for (const auto& piece : hand.live) { + const int suit = hand.live[0].getSuit(); + for (const auto& piece : hand.live_range()) { if (piece.getSuit() != suit) { return false; } diff --git a/src/scoring/yakus/halfflush.cc b/src/scoring/yakus/halfflush.cc index 0cfc896b..0744c075 100644 --- a/src/scoring/yakus/halfflush.cc +++ b/src/scoring/yakus/halfflush.cc @@ -12,9 +12,9 @@ namespace mahjong::yaku { bool isHalfFlush(const GameState& state, int player, const std::vector& /*branch*/) { const Hand& hand = state.hands[player]; - const int suit = hand.live.front().getSuit(); + const int suit = hand.live[0].getSuit(); bool honors = false; - for (const auto& piece : hand.live) { + for (const auto& piece : hand.live_range()) { if (piece.isHonor()) { honors = true; continue; diff --git a/src/scoring/yakus/maxbranches.cc b/src/scoring/yakus/maxbranches.cc index ed31fb73..5ed6b535 100644 --- a/src/scoring/yakus/maxbranches.cc +++ b/src/scoring/yakus/maxbranches.cc @@ -16,7 +16,7 @@ bool isMaxBranches(const GameState& state, int player, std::array sets = {}; const std::array final = {3, 3, 2, 2, 2, 2}; - for (const auto& piece : hand.live) { + for (const auto& piece : hand.live_range()) { if (piece.getSuit() != suit) { return false; } diff --git a/src/scoring/yakus/ninegates.cc b/src/scoring/yakus/ninegates.cc index 8b4db4a7..f5eaf11a 100644 --- a/src/scoring/yakus/ninegates.cc +++ b/src/scoring/yakus/ninegates.cc @@ -27,7 +27,7 @@ bool isNineGates(const GameState& state, int player, pieces.at(i) = 0; } bool duplicate = false; - for (const auto& piece : hand.live) { + for (const auto& piece : hand.live_range()) { if (pieces.contains(piece.getPieceNum())) { if ((pieces[piece.getPieceNum()] != 0) && !piece.isTerminal()) { if (duplicate) { diff --git a/src/scoring/yakus/pinfu.cc b/src/scoring/yakus/pinfu.cc index 4ad90b19..c9d05fc2 100644 --- a/src/scoring/yakus/pinfu.cc +++ b/src/scoring/yakus/pinfu.cc @@ -14,7 +14,8 @@ namespace mahjong::yaku { bool isPinfu(const GameState& state, int player, const std::vector& branch) { - if (state.hands.at(player).open) { + const Hand& hand = state.hands.at(player); + if (hand.open) { return false; } for (const auto* node : branch) { diff --git a/src/scoring/yakus/thirteenorphans.cc b/src/scoring/yakus/thirteenorphans.cc index f700537b..9509dd96 100644 --- a/src/scoring/yakus/thirteenorphans.cc +++ b/src/scoring/yakus/thirteenorphans.cc @@ -25,7 +25,7 @@ bool isThirteenOrphans(const GameState& state, int player, {kGreenDragon, false}}; bool duplicate = false; - for (const auto& piece : hand.live) { + for (const auto& piece : hand.live_range()) { if (pieces.contains(piece)) { if (pieces[piece]) { duplicate = true; diff --git a/src/statefunctions/decisionfunction.cc b/src/statefunctions/decisionfunction.cc index c1b73ccf..f4b2ebb6 100644 --- a/src/statefunctions/decisionfunction.cc +++ b/src/statefunctions/decisionfunction.cc @@ -2,13 +2,13 @@ #include #include -#include #include "analysis/util.h" #include "scoring/scoring.h" #include "scoring/yakus/thirteenorphans.h" #include "statefunctions/stateutilities.h" #include "types/gamestate.h" +#include "types/pieces.h" #include "types/piecetype.h" #include "types/sets.h" #include "types/walls.h" @@ -26,31 +26,26 @@ bool CanRon(const GameState& state, int player) { // Build the theoretical hand auto& tmp_state = const_cast(state); - tmp_state.hands.at(player).live.push_back(state.pendingPiece); + auto& tmp_hand = tmp_state.hands[player]; + tmp_hand.live[tmp_hand.live_count++] = state.pendingPiece; // If this Ron is occurring due to a concealed kan discard, if (state.concealedKan) { // If it happens to be a ron for a thirteen orphans, // it's allowed and you can ron if (yaku::isThirteenOrphans(state, player)) { - tmp_state.hands.at(player).live.erase( - std::find(state.hands.at(player).live.begin(), - state.hands.at(player).live.end(), state.pendingPiece)); + tmp_hand.live[--tmp_hand.live_count] = kError; return true; } // otherwise, you can't - tmp_state.hands.at(player).live.erase( - std::find(state.hands.at(player).live.begin(), - state.hands.at(player).live.end(), state.pendingPiece)); + tmp_hand.live[--tmp_hand.live_count] = kError; return false; } // if not a concealed kan, check if it's complete const bool can_ron = isComplete(state, player); - tmp_state.hands.at(player).live.erase( - std::find(state.hands.at(player).live.begin(), - state.hands.at(player).live.end(), state.pendingPiece)); + tmp_hand.live[--tmp_hand.live_count] = kError; return can_ron; } @@ -124,10 +119,11 @@ bool CanConcealedKan(const GameState& state, int player) { } bool CanRiichi(const GameState& state, int player) { - if (state.hands.at(player).riichi) { + const Hand& hand = state.hands[player]; + if (hand.riichi) { return false; } - if (state.hands.at(player).open) { + if (hand.open) { return false; } return !getPossibleWaits(state.hands[player]).empty(); diff --git a/src/statefunctions/gamestates/chi.cc b/src/statefunctions/gamestates/chi.cc index 11ff37b3..597c4326 100644 --- a/src/statefunctions/gamestates/chi.cc +++ b/src/statefunctions/gamestates/chi.cc @@ -2,7 +2,6 @@ #include #include #include -#include #include "statefunctions/router.h" #include "statefunctions/stateutilities.h" @@ -62,7 +61,7 @@ std::unique_ptr Chi(std::unique_ptr state) { .decision = false, // decision }); - hand.live.push_back(state->pendingPiece); + hand.live[hand.live_count++] = state->pendingPiece; state->lastCall = state->turnNum; state->concealedKan = false; state->turnNum++; diff --git a/src/statefunctions/gamestates/draw.cc b/src/statefunctions/gamestates/draw.cc index b167c58c..dfafde03 100644 --- a/src/statefunctions/gamestates/draw.cc +++ b/src/statefunctions/gamestates/draw.cc @@ -1,6 +1,5 @@ #include #include -#include #include "statefunctions/router.h" #include "types/gamestate.h" @@ -13,7 +12,8 @@ std::unique_ptr Draw(std::unique_ptr state) { state->currentPlayer = (state->currentPlayer + 1) % 4; state->turnNum++; state->pendingPiece = Walls::TakePiece(*state); - state->hands.at(state->currentPlayer).live.push_back(state->pendingPiece); + Hand& hand = state->hands[state->currentPlayer]; + hand.live[hand.live_count++] = state->pendingPiece; state->nextState = StateFunctionType::kPlayerHand; return state; } diff --git a/src/statefunctions/gamestates/kan.cc b/src/statefunctions/gamestates/kan.cc index 4910a4af..21878aa4 100644 --- a/src/statefunctions/gamestates/kan.cc +++ b/src/statefunctions/gamestates/kan.cc @@ -2,7 +2,6 @@ #include #include #include -#include #include "statefunctions/router.h" #include "statefunctions/stateutilities.h" @@ -34,13 +33,12 @@ std::unique_ptr Kan(std::unique_ptr state) { Hand& hand = state->hands.at(state->lastCaller); hand.open = true; state->currentPlayer = state->lastCaller; - hand.live.push_back(state->pendingPiece); state->lastCall = state->turnNum; state->concealedKan = false; state->turnNum++; if (RemovePieces(*state, state->lastCaller, state->pendingPiece, - /*count=*/4) != 4) { + /*count=*/3) != 3) { std::cerr << "Not Enough Pieces to remove in kan" << '\n'; state->nextState = StateFunctionType::kError; return state; diff --git a/src/statefunctions/gamestates/pon.cc b/src/statefunctions/gamestates/pon.cc index b998c416..8c844e22 100644 --- a/src/statefunctions/gamestates/pon.cc +++ b/src/statefunctions/gamestates/pon.cc @@ -2,7 +2,6 @@ #include #include #include -#include #include "statefunctions/router.h" #include "statefunctions/stateutilities.h" @@ -35,13 +34,12 @@ std::unique_ptr Pon(std::unique_ptr state) { Hand& hand = state->hands.at(state->lastCaller); state->currentPlayer = state->lastCaller; - hand.live.push_back(state->pendingPiece); state->lastCall = state->turnNum; state->concealedKan = false; state->turnNum++; if (RemovePieces(*state, state->lastCaller, state->pendingPiece, - /*count=*/3) != 3) { + /*count=*/2) != 2) { std::cerr << "Not enough pieces to remove in Pon" << '\n'; state->nextState = StateFunctionType::kError; return state; diff --git a/src/statefunctions/gamestates/replacement.cc b/src/statefunctions/gamestates/replacement.cc index 95c1b07b..58cd906d 100644 --- a/src/statefunctions/gamestates/replacement.cc +++ b/src/statefunctions/gamestates/replacement.cc @@ -15,7 +15,8 @@ namespace mahjong { namespace { std::unique_ptr Replacement(std::unique_ptr state) { const Piece draw = Walls::TakeReplacementTile(*state); - state->hands.at(state->currentPlayer).live.push_back(draw); + Hand& hand = state->hands.at(state->currentPlayer); + hand.live[hand.live_count++] = draw; state->pendingPiece = draw; AlertPlayers(*state, diff --git a/src/statefunctions/gamestates/riichi.cc b/src/statefunctions/gamestates/riichi.cc index aa977cd3..88492d25 100644 --- a/src/statefunctions/gamestates/riichi.cc +++ b/src/statefunctions/gamestates/riichi.cc @@ -29,10 +29,10 @@ std::unique_ptr Riichi(std::unique_ptr state) { .decision = false, // decision }); - state->hands.at(state->currentPlayer).riichiRound = state->turnNum; - state->hands.at(state->currentPlayer).riichiPieceDiscard = - state->hands.at(state->currentPlayer).discards_count; - state->hands.at(state->currentPlayer).riichi = true; + Hand& hand = state->hands[state->currentPlayer]; + hand.riichiRound = state->turnNum; + hand.riichiPieceDiscard = hand.discards_count; + hand.riichi = true; state->riichiSticks++; state->nextState = StateFunctionType::kDiscard; diff --git a/src/statefunctions/gamestates/ron.cc b/src/statefunctions/gamestates/ron.cc index 0ba0bad8..6d38ab6b 100644 --- a/src/statefunctions/gamestates/ron.cc +++ b/src/statefunctions/gamestates/ron.cc @@ -1,7 +1,6 @@ #include #include #include -#include #include "scoring/scoring.h" #include "statefunctions/router.h" @@ -15,14 +14,15 @@ namespace mahjong { namespace { std::unique_ptr Ron(std::unique_ptr state) { - state->hands.at(state->lastCaller).live.push_back(state->pendingPiece); + Hand& caller_hand = state->hands[state->lastCaller]; + caller_hand.live[caller_hand.live_count++] = state->pendingPiece; std::array basic_points = {}; - if (state->hands.at(state->currentPlayer).riichi && - state->hands.at(state->currentPlayer).discards_count == - state->hands.at(state->currentPlayer).riichiPieceDiscard) { + Hand& curr_hand = state->hands[state->currentPlayer]; + if (curr_hand.riichi && + curr_hand.discards_count == curr_hand.riichiPieceDiscard) { state->riichiSticks--; - state->hands.at(state->currentPlayer).riichi = false; + curr_hand.riichi = false; } for (int player = 0; player < 4; player++) { if (state->hasRonned.at(player)) { diff --git a/src/statefunctions/gamestates/roundstart.cc b/src/statefunctions/gamestates/roundstart.cc index 452fb004..cd13f181 100644 --- a/src/statefunctions/gamestates/roundstart.cc +++ b/src/statefunctions/gamestates/roundstart.cc @@ -1,3 +1,4 @@ +#include #include #include #include @@ -22,7 +23,8 @@ std::unique_ptr RoundStart(std::unique_ptr state) { state->players.at(i)->RoundStart( hand, static_cast((i + 3 * (state->roundNum % 4)) % 4), (state->roundNum > 3) ? kSouth : kEast); - state->hands.at(i).live = hand; + state->hands[i].live_count = hand.size(); + std::ranges::move(hand, state->hands[i].live.begin()); } AlertPlayers(*state, diff --git a/src/statefunctions/stateutilities.cc b/src/statefunctions/stateutilities.cc index 07788b88..eb647a6b 100644 --- a/src/statefunctions/stateutilities.cc +++ b/src/statefunctions/stateutilities.cc @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include "controllers/playercontroller.h" #include "statefunctions/decisionfunction.h" @@ -30,25 +30,24 @@ void AlertPlayers(const GameState& state, Event e) { // Count number of piece p that are in given players hands uint8_t CountPieces(const GameState& state, int player, Piece p) { - return std::count(state.hands.at(player).live.begin(), - state.hands.at(player).live.end(), p); + const Hand& hand = state.hands.at(player); + return std::ranges::count(hand.live_range(), p); } // Remove an instance of piece p from given players hand uint8_t RemovePieces(GameState& state, int player, Piece p, uint8_t count) { - count = std::min(CountPieces(state, player, p), count); + Hand& hand = state.hands.at(player); uint8_t removed = 0; - state.hands.at(player).live.erase( - std::remove_if(state.hands.at(player).live.begin(), - state.hands.at(player).live.end(), - [&](Piece _p) { - if (count > removed && p == _p) { - removed++; - return true; - } - return false; - }), - state.hands.at(player).live.end()); + count = std::min(CountPieces(state, player, p), count); + const auto match_piece = [&](Piece _p) { + if (count > removed && p == _p) { + removed++; + return true; + } + return false; + }; + std::ranges::remove_if(hand.live, match_piece); + hand.live_count -= removed; return removed; } @@ -81,8 +80,8 @@ Event GetValidDecisionOrThrow(const GameState& state, int player, bool inHand) { Event replacement_decision = decision; replacement_decision.type = inHand ? Event::kDiscard : Event::kDecline; if (inHand) { - replacement_decision.piece = static_cast( - state.hands.at(player).live.back().toUint8_t()); + replacement_decision.piece = + state.hands[player].live_range().back().toUint8_t(); } if (ValidateDecision(state, player, replacement_decision, inHand)) { return replacement_decision; diff --git a/src/types/gamestate.h b/src/types/gamestate.h index 59c4fcf5..99b75020 100644 --- a/src/types/gamestate.h +++ b/src/types/gamestate.h @@ -2,6 +2,7 @@ #include #include #include +#include #include "controllers/playercontroller.h" #include "types/meld.h" @@ -17,10 +18,14 @@ struct Hand { int riichiPieceDiscard = -1; int riichiRound = -1; int meld_count = 0; - std::vector live; + std::array live; + int live_count = 13; std::array melds; std::array discards; int discards_count = 0; + [[nodiscard]] std::ranges::subrange live_range() const { + return std::ranges::subrange(live.begin(), live.begin() + live_count); + } }; struct GameState { diff --git a/src/types/typeprinter.cc b/src/types/typeprinter.cc index 82143704..83c35638 100644 --- a/src/types/typeprinter.cc +++ b/src/types/typeprinter.cc @@ -73,7 +73,7 @@ std::ostream& operator<<(std::ostream& os, const mahjong::Hand& hand) { os << " riichiRound: " << hand.riichiRound; os << " live: [" << '\n'; ; - for (const auto& piece : hand.live) { + for (const auto& piece : hand.live_range()) { os << piece.toStr() << ", "; } os << "]" << '\n'; diff --git a/src/types/walls.h b/src/types/walls.h index 6f8001fd..6a72ae13 100644 --- a/src/types/walls.h +++ b/src/types/walls.h @@ -1,9 +1,9 @@ #pragma once #include -#include "types/piecetype.h" #include "piecetype.h" #include "types/gamestate.h" +#include "types/piecetype.h" namespace mahjong { class Walls { diff --git a/tests/api/game_control.test.cc b/tests/api/game_control.test.cc index 359f83e8..43353620 100644 --- a/tests/api/game_control.test.cc +++ b/tests/api/game_control.test.cc @@ -3,7 +3,6 @@ #include #include #include -#include #include "api/gamestate.h" #include "api/types.h" @@ -148,7 +147,7 @@ TEST(Api, ObserveGameStateHandsAndDiscards) { const mahjong::Hand& cpp_hand = state->hands[player]; // Check live pieces - EXPECT_EQ(c_hand.livePieceCount, static_cast(cpp_hand.live.size())); + EXPECT_EQ(c_hand.livePieceCount, static_cast(cpp_hand.live_count)); for (int piece = 0; piece < api::kMaxLiveHandSize; piece++) { if (piece < c_hand.livePieceCount) { EXPECT_EQ(c_hand.livePieces[piece], diff --git a/tests/can_chi.test.cc b/tests/can_chi.test.cc index fdcb319a..18258d9f 100644 --- a/tests/can_chi.test.cc +++ b/tests/can_chi.test.cc @@ -14,6 +14,7 @@ TEST(CanChi, EastShouldChiOnNorth) { state.pendingPiece = kOneCharacter; state.currentPlayer = 3; state.hands[0].live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; + state.hands[0].live_count = 3; EXPECT_TRUE(CanChi(state, 0)); state.pendingPiece = kTwoCharacter; EXPECT_TRUE(CanChi(state, 0)); @@ -28,6 +29,7 @@ TEST(CanChi, EastShouldNotChiOnSouth) { state.pendingPiece = kOneCharacter; state.currentPlayer = 1; state.hands[0].live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; + state.hands[0].live_count = 3; EXPECT_FALSE(CanChi(state, 0)); } @@ -36,6 +38,7 @@ TEST(CanChi, NoChiOnHonor) { state.pendingPiece = kOneCharacter; state.currentPlayer = 3; state.hands[0].live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; + state.hands[0].live_count = 3; state.pendingPiece = kWhiteDragon; EXPECT_FALSE(CanChi(state, 0)); } diff --git a/tests/count_pieces.test.cc b/tests/count_pieces.test.cc index ebe5364f..7752fdb4 100644 --- a/tests/count_pieces.test.cc +++ b/tests/count_pieces.test.cc @@ -12,6 +12,7 @@ namespace mahjong { TEST(CountPieces, CountPieces) { GameState state; state.hands[0].live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + state.hands[0].live_count = 4; EXPECT_EQ(CountPieces(state, 0, kOneCharacter), 1); EXPECT_EQ(CountPieces(state, 0, kFourPin), 1); diff --git a/tests/discard_piece.test.cc b/tests/discard_piece.test.cc index 8e376a24..86d1afa0 100644 --- a/tests/discard_piece.test.cc +++ b/tests/discard_piece.test.cc @@ -12,6 +12,7 @@ namespace mahjong { TEST(DiscardPiece, DiscardsCorrectPiece) { GameState state; state.hands[0].live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + state.hands[0].live_count = 4; DiscardPiece(state, 0, kOneCharacter); EXPECT_EQ(state.hands[0].discards[0], kOneCharacter); @@ -20,9 +21,10 @@ TEST(DiscardPiece, DiscardsCorrectPiece) { TEST(DiscardPiece, DoesntDiscardInCorrectPiece) { GameState state; state.hands[0].live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + state.hands[0].live_count = 4; DiscardPiece(state, 0, kGreenDragon); - EXPECT_EQ(state.hands[0].live.size(), 4); + EXPECT_EQ(state.hands[0].live_count, 4); } } // namespace mahjong diff --git a/tests/game_play.test.cc b/tests/game_play.test.cc index 669894f1..4af88b9d 100644 --- a/tests/game_play.test.cc +++ b/tests/game_play.test.cc @@ -13,12 +13,13 @@ namespace mahjong { TEST(GamePlay, Furiten) { auto state = GameState(); - state.hands[0].live = HandFromNotation("123m456p234678s44m"); - state.hands[0].open = false; + Hand& hand = state.hands[0]; + HandFromNotation("123m456p234678s44m", &hand); + hand.open = false; EXPECT_TRUE(isComplete(state, 0)); state.pendingPiece = Piece(kFourPin); // Place Four Pin in Discard Pile - state.hands[0].discards = {kFourPin}; + hand.discards = {kFourPin}; EXPECT_FALSE(CanRon(state, 0)); } diff --git a/tests/remove_pieces.test.cc b/tests/remove_pieces.test.cc index c9aeb5fb..5926c919 100644 --- a/tests/remove_pieces.test.cc +++ b/tests/remove_pieces.test.cc @@ -1,7 +1,6 @@ #include #include -#include #include "statefunctions/stateutilities.h" #include "types/gamestate.h" @@ -13,33 +12,37 @@ namespace mahjong { TEST(RemovePieces, RemoveCorrectAmount) { GameState state; state.hands[0].live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + state.hands[0].live_count = 4; EXPECT_EQ(RemovePieces(state, 0, kOneCharacter, 1), 1); - EXPECT_EQ(state.hands[0].live.size(), 3); + EXPECT_EQ(state.hands[0].live_count, 3); } TEST(RemovePieces, RemoveOnlyTheOnesAvailable) { GameState state; state.hands[0].live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + state.hands[0].live_count = 4; EXPECT_EQ(RemovePieces(state, 0, kFourPin, 2), 1); - EXPECT_EQ(state.hands[0].live.size(), 3); + EXPECT_EQ(state.hands[0].live_count, 3); } TEST(RemovePieces, OnlyRemovesOne) { GameState state; state.hands[0].live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + state.hands[0].live_count = 4; EXPECT_EQ(RemovePieces(state, 0, kWhiteDragon, 1), 1); - EXPECT_EQ(state.hands[0].live.back(), kWhiteDragon); + EXPECT_EQ(state.hands[0].live[2], kWhiteDragon); } TEST(RemovePieces, RemovesZeroWhenPieceDoesntExist) { GameState state; state.hands[0].live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + state.hands[0].live_count = 4; EXPECT_EQ(RemovePieces(state, 0, kGreenDragon, 8), 0); - EXPECT_EQ(state.hands[0].live.size(), 4); + EXPECT_EQ(state.hands[0].live_count, 4); } } // namespace mahjong diff --git a/tests/rules/basic_rules.test.cc b/tests/rules/basic_rules.test.cc index a882cd4b..770b92d5 100644 --- a/tests/rules/basic_rules.test.cc +++ b/tests/rules/basic_rules.test.cc @@ -40,7 +40,7 @@ TEST(RoundSetup, playerHands) { // Each player should have 13 tiles for (int i = 0; i < kNumPlayers; i++) { - EXPECT_EQ(state->hands[i].live.size(), 13) + EXPECT_EQ(state->hands[i].live_count, 13) << "Player " << i << " should have 13 tiles"; } } @@ -101,7 +101,7 @@ TEST(DrawMechanics, drawIncreasesTileCount) { // All players start with 13 tiles for (int i = 0; i < kNumPlayers; i++) { - EXPECT_EQ(state->hands[i].live.size(), 13); + EXPECT_EQ(state->hands[i].live_count, 13); } const int walls_before = Walls::GetRemainingPieces(*state); @@ -111,11 +111,11 @@ TEST(DrawMechanics, drawIncreasesTileCount) { EXPECT_EQ(state->currState, StateFunctionType::kDraw); // Player 0 should now have 14 tiles - EXPECT_EQ(state->hands[0].live.size(), 14); + EXPECT_EQ(state->hands[0].live_count, 14); // Other players still have 13 for (int i = 1; i < kNumPlayers; i++) { - EXPECT_EQ(state->hands[i].live.size(), 13); + EXPECT_EQ(state->hands[i].live_count, 13); } // Wall should have one less tile @@ -142,7 +142,7 @@ TEST(DiscardMechanics, discardDecreasesTileCount) { EXPECT_EQ(state->currState, StateFunctionType::kDraw); // Player 0 has 14 tiles after draw - EXPECT_EQ(state->hands[0].live.size(), 14); + EXPECT_EQ(state->hands[0].live_count, 14); // Move through player hand to discard state = AdvanceGameState(std::move(state)); @@ -154,7 +154,7 @@ TEST(DiscardMechanics, discardDecreasesTileCount) { EXPECT_EQ(state->currState, StateFunctionType::kDiscard); // Player should be back to 13 tiles - EXPECT_EQ(state->hands[0].live.size(), 13); + EXPECT_EQ(state->hands[0].live_count, 13); // Discard pile should have increased EXPECT_EQ(state->hands[0].discards_count, discards_before + 1); diff --git a/tests/rules/calls.test.cc b/tests/rules/calls.test.cc index 080f8c1d..42fd7e27 100644 --- a/tests/rules/calls.test.cc +++ b/tests/rules/calls.test.cc @@ -8,6 +8,7 @@ #include "controllers/playercontroller.h" #include "statefunctions/statecontroller.h" #include "types/event.h" +#include "types/gamestate.h" #include "types/piecetype.h" #include "types/sets.h" #include "types/statefunction.h" @@ -51,9 +52,12 @@ TEST(Calls, AcceptPon) { auto state = InitializeTestRound(12345, std::move(controllers)); // Override with hopeless hands - state->hands[0].live = HandFromNotation("1m2p3s4m5p6s7m8p9s1m2p3s4m"); - // Has the pair of nine bamboo - state->hands[1].live = HandFromNotation("1m3m5m7m9m99s2p4p6p1z3z5z7z"); + Hand& player0_hand = state->hands[0]; + // 14 Pieces because has drawn in InitializeTestRound. + HandFromNotation("11447m2258p33699s", &player0_hand); + // Has the pair of nine bamboo 13 Pieces, yet to draw. + Hand& player1_hand = state->hands[1]; + HandFromNotation("13579m99s246p135z", &player1_hand); // Advance to pon event // Should take 4 iterations: draw, player hand, discard, and then the pon @@ -69,12 +73,12 @@ TEST(Calls, AcceptPon) { // - State should be kDiscard (Player 1 needs to discard) EXPECT_EQ(state->currentPlayer, 1); EXPECT_EQ(state->currState, StateFunctionType::kDiscard); - EXPECT_EQ(state->hands[1].meld_count, 1); - EXPECT_EQ(state->hands[1].melds[0].type, SetType::kPon); - EXPECT_EQ(state->hands[1].melds[0].start, Piece(Piece::kNineBamboo)); + EXPECT_EQ(player1_hand.meld_count, 1); + EXPECT_EQ(player1_hand.melds[0].type, SetType::kPon); + EXPECT_EQ(player1_hand.melds[0].start, Piece(Piece::kNineBamboo)); - // Player 1's hand should be reduced by 2 tiles (used for pon) - EXPECT_EQ(state->hands[1].live.size(), 11); + // Player 1's live hand should be reduced by 3 tiles (pon + discard) + EXPECT_EQ(player1_hand.live_count, 10); } } // namespace mahjong diff --git a/tests/setup.test.cc b/tests/setup.test.cc index 87aba0ab..8be0a3d3 100644 --- a/tests/setup.test.cc +++ b/tests/setup.test.cc @@ -46,7 +46,7 @@ TEST(Setup, Dealing) { ASSERT_NO_THROW(state = Router::Instance().Route( StateFunctionType::kRoundStart)(std::move(state))); for (int i = 0; i < 4; i++) { - EXPECT_EQ(state->hands[i].live.size(), 13); + EXPECT_EQ(state->hands[i].live_count, 13); } state = Router::Instance().Route(StateFunctionType::kDraw)(std::move(state)); EXPECT_EQ(state->currentPlayer, 0); diff --git a/tests/utils/gamestate_utils.test.cc b/tests/utils/gamestate_utils.test.cc index 9aceb382..91480ec8 100644 --- a/tests/utils/gamestate_utils.test.cc +++ b/tests/utils/gamestate_utils.test.cc @@ -48,10 +48,10 @@ TEST(GameStateUtils, InitializeTestRoundDefault) { } // Draw occurred - EXPECT_EQ(state->hands[0].live.size(), 14); + EXPECT_EQ(state->hands[0].live_count, 14); for (int i = 1; i < kNumPlayers; i++) { - EXPECT_EQ(state->hands[i].live.size(), 13); + EXPECT_EQ(state->hands[i].live_count, 13); } } diff --git a/tests/utils/handformer.cc b/tests/utils/handformer.cc index ce26e932..7e7bc1ae 100644 --- a/tests/utils/handformer.cc +++ b/tests/utils/handformer.cc @@ -10,6 +10,7 @@ #include #include +#include "types/gamestate.h" #include "types/pieces.h" #include "types/piecetype.h" @@ -92,6 +93,12 @@ std::vector HandFromNotation(const std::string& notation) { return result; } +void HandFromNotation(const std::string& notation, Hand* hand) { + std::vector hand_vec = HandFromNotation(notation); + hand->live_count = hand_vec.size(); + std::ranges::move(hand_vec, hand->live.begin()); +} + bool IsValidNotation(const std::string& notation) { std::vector current_set; for (const auto& c : notation) { diff --git a/tests/utils/handformer.h b/tests/utils/handformer.h index e865e126..5f6a1e62 100644 --- a/tests/utils/handformer.h +++ b/tests/utils/handformer.h @@ -3,11 +3,13 @@ #include #include +#include "types/gamestate.h" #include "types/piecetype.h" namespace mahjong { std::vector HandFromNotation(const std::string& notation); +void HandFromNotation(const std::string& notation, Hand* hand); bool IsValidNotation(const std::string& notation); std::string HandToNotation(const std::vector& hand); diff --git a/tests/yakus/afterkan.test.cc b/tests/yakus/afterkan.test.cc index 43904d2e..7b4978db 100644 --- a/tests/yakus/afterkan.test.cc +++ b/tests/yakus/afterkan.test.cc @@ -16,12 +16,12 @@ namespace mahjong::yaku { TEST(isAfterAKan, 1Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m789m1111z999s55z"); + HandFromNotation("123m789m1111z999s55z", &hand); game_state.currentPlayer = 0; game_state.prevState = StateFunctionType::kReplacement; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAfterAKan(game_state, 0, branch)) { @@ -35,12 +35,12 @@ TEST(isAfterAKan, 1Han) { TEST(isAfterAKan, DoesntApply) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m789m1111z999s55z"); + HandFromNotation("123m789m1111z999s55z", &hand); game_state.currentPlayer = 0; game_state.prevState = StateFunctionType::kPon; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAfterAKan(game_state, 0, branch)) { @@ -54,12 +54,12 @@ TEST(isAfterAKan, DoesntApply) { TEST(isAfterAKan, WrongPlayer) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m789m1111z999s55z"); + HandFromNotation("123m789m1111z999s55z", &hand); game_state.currentPlayer = 2; game_state.prevState = StateFunctionType::kReplacement; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAfterAKan(game_state, 0, branch)) { diff --git a/tests/yakus/allpon.test.cc b/tests/yakus/allpon.test.cc index 719ee952..1f63f9c5 100644 --- a/tests/yakus/allpon.test.cc +++ b/tests/yakus/allpon.test.cc @@ -3,7 +3,6 @@ #include #include #include -#include #include "analysis/analysis.h" #include "analysis/handnode.h" @@ -20,9 +19,9 @@ namespace mahjong::yaku { TEST(isAllPons, 2Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m222p888s666z44m"); + HandFromNotation("111m222p888s666z44m", &hand); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllPons(game_state, 0, branch)) { @@ -36,14 +35,14 @@ TEST(isAllPons, 2Han) { TEST(isAllPons, WithKans) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m222p666z44m"); + HandFromNotation("111m222p666z44m", &hand); hand.melds[hand.meld_count++] = Meld{ .type = SetType::kKan, .start = Piece(kFivePin), }; hand.open = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllPons(game_state, 0, branch)) { @@ -57,14 +56,14 @@ TEST(isAllPons, WithKans) { TEST(isAllPons, ConcealedKan) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m222p666z44m"); + HandFromNotation("111m222p666z44m", &hand); hand.melds[hand.meld_count++] = Meld{ .type = SetType::kConcealedKan, .start = Piece(kFivePin), }; hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllPons(game_state, 0, branch)) { @@ -78,10 +77,10 @@ TEST(isAllPons, ConcealedKan) { TEST(isAllPons, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m222p666z789m44m"); + HandFromNotation("111m222p666z789m44m", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllPons(game_state, 0, branch)) { diff --git a/tests/yakus/allsimples.test.cc b/tests/yakus/allsimples.test.cc index 7d4e7279..57417d74 100644 --- a/tests/yakus/allsimples.test.cc +++ b/tests/yakus/allsimples.test.cc @@ -16,9 +16,9 @@ namespace mahjong::yaku { TEST(isAllSimples, 1Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("222m333p444s555p88m"); + HandFromNotation("222m333p444s555p88m", &hand); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllSimples(game_state, 0, branch)) { @@ -32,9 +32,9 @@ TEST(isAllSimples, 1Han) { TEST(isAllSimples, BadHandHonors) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("222m333p444s111z88m"); + HandFromNotation("222m333p444s111z88m", &hand); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllSimples(game_state, 0, branch)) { @@ -48,9 +48,9 @@ TEST(isAllSimples, BadHandHonors) { TEST(isAllSimples, BadHandTerminals) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("222m333p444s111m88m"); + HandFromNotation("222m333p444s111m88m", &hand); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllSimples(game_state, 0, branch)) { diff --git a/tests/yakus/allterminalsandhonors.test.cc b/tests/yakus/allterminalsandhonors.test.cc index 8da2b134..f27ece82 100644 --- a/tests/yakus/allterminalsandhonors.test.cc +++ b/tests/yakus/allterminalsandhonors.test.cc @@ -5,7 +5,6 @@ #include #include #include -#include #include "analysis/analysis.h" #include "analysis/handnode.h" @@ -21,10 +20,10 @@ namespace mahjong::yaku { TEST(isAllTerminalsAndHonors, 2Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("222z111p111m999s66z"); + HandFromNotation("222z111p111m999s66z", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllTerminalsAndHonors(game_state, 0, branch)) { @@ -38,10 +37,10 @@ TEST(isAllTerminalsAndHonors, 2Han) { TEST(isAllTerminalsAndHonors, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("222z111p111m888s66z"); + HandFromNotation("222z111p111m888s66z", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllTerminalsAndHonors(game_state, 0, branch)) { @@ -55,14 +54,14 @@ TEST(isAllTerminalsAndHonors, BadHand) { TEST(isAllTerminalsAndHonors, CanBeOpen) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("222z111m999s66z"); + HandFromNotation("222z111m999s66z", &hand); hand.open = true; hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kNinePin), }; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllTerminalsAndHonors(game_state, 0, branch)) { diff --git a/tests/yakus/blessingofman.test.cc b/tests/yakus/blessingofman.test.cc index 38dfb0bb..c45b252c 100644 --- a/tests/yakus/blessingofman.test.cc +++ b/tests/yakus/blessingofman.test.cc @@ -15,7 +15,7 @@ namespace mahjong::yaku { TEST(isBlessingOfMan, 5Han) { auto game_state = GameState(); Hand& hand = game_state.hands[3]; - hand.live = HandFromNotation("123m123p444m111z55m"); + HandFromNotation("123m123p444m111z55m", &hand); hand.open = false; game_state.turnNum = 1; @@ -25,7 +25,7 @@ TEST(isBlessingOfMan, 5Han) { game_state.hasRonned[3] = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBlessingOfMan(game_state, 3, branch)) { @@ -39,7 +39,7 @@ TEST(isBlessingOfMan, 5Han) { TEST(isBlessingOfMan, MustBeARon) { auto game_state = GameState(); Hand& hand = game_state.hands[3]; - hand.live = HandFromNotation("123m123p444m111z55m"); + HandFromNotation("123m123p444m111z55m", &hand); hand.open = false; game_state.turnNum = 3; @@ -49,7 +49,7 @@ TEST(isBlessingOfMan, MustBeARon) { game_state.hasRonned[3] = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBlessingOfMan(game_state, 3, branch)) { @@ -63,7 +63,7 @@ TEST(isBlessingOfMan, MustBeARon) { TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m123p444m111z55m"); + HandFromNotation("123m123p444m111z55m", &hand); hand.open = false; game_state.turnNum = 2; @@ -73,7 +73,7 @@ TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { game_state.hasRonned[0] = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBlessingOfMan(game_state, 0, branch)) { @@ -87,7 +87,7 @@ TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { TEST(isBlessingOfMan, NoCalledMustHaveOccured) { auto game_state = GameState(); Hand& hand = game_state.hands[3]; - hand.live = HandFromNotation("123m123p444m111z55m"); + HandFromNotation("123m123p444m111z55m", &hand); hand.open = false; game_state.turnNum = 1; @@ -96,7 +96,7 @@ TEST(isBlessingOfMan, NoCalledMustHaveOccured) { game_state.hasRonned[3] = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBlessingOfMan(game_state, 3, branch)) { diff --git a/tests/yakus/concealedhand.test.cc b/tests/yakus/concealedhand.test.cc index 31ce7fc3..9c11c56b 100644 --- a/tests/yakus/concealedhand.test.cc +++ b/tests/yakus/concealedhand.test.cc @@ -12,7 +12,7 @@ namespace mahjong::yaku { TEST(isFullyConcealedHand, 1Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("555m555p555s111z44m"); + HandFromNotation("555m555p555s111z44m", &hand); hand.open = false; game_state.currentPlayer = 0; @@ -22,7 +22,7 @@ TEST(isFullyConcealedHand, 1Han) { TEST(isFullyConcealedHand, MustTsumo) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("555m555p555s111z44m"); + HandFromNotation("555m555p555s111z44m", &hand); hand.open = false; game_state.currentPlayer = 1; @@ -32,7 +32,7 @@ TEST(isFullyConcealedHand, MustTsumo) { TEST(isFullyConcealedHand, MustBeClosedHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("555m555p555s111z44m"); + HandFromNotation("555m555p555s111z44m", &hand); hand.open = true; game_state.currentPlayer = 0; @@ -42,7 +42,7 @@ TEST(isFullyConcealedHand, MustBeClosedHand) { TEST(isFullyConcealedHand, MustHavePiecesRemainingInWall) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("555m555p555s111z44m"); + HandFromNotation("555m555p555s111z44m", &hand); hand.open = false; game_state.currentPlayer = 0; diff --git a/tests/yakus/concealedpon.test.cc b/tests/yakus/concealedpon.test.cc index 6104890a..4ee6b990 100644 --- a/tests/yakus/concealedpon.test.cc +++ b/tests/yakus/concealedpon.test.cc @@ -3,7 +3,6 @@ #include #include #include -#include #include "analysis/analysis.h" #include "analysis/handnode.h" @@ -18,10 +17,10 @@ namespace mahjong::yaku { TEST(isThreeConcealedPons, 2Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m111p111s666z44m"); + HandFromNotation("111m111p111s666z44m", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, 0, branch)) { @@ -35,14 +34,14 @@ TEST(isThreeConcealedPons, 2Han) { TEST(isThreeConcealedPons, PonsMustBeConcealed) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m111p111s44m"); + HandFromNotation("111m111p111s44m", &hand); hand.melds[hand.meld_count++] = Meld{ .type = SetType::kChi, .start = kTwoBamboo, }; hand.open = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, 0, branch)) { @@ -56,14 +55,14 @@ TEST(isThreeConcealedPons, PonsMustBeConcealed) { TEST(isThreeConcealedPons, CanHaveAdditionalOpenPon) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m111p111s44m"); + HandFromNotation("111m111p111s44m", &hand); hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = kTwoBamboo, }; hand.open = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, 0, branch)) { @@ -77,14 +76,14 @@ TEST(isThreeConcealedPons, CanHaveAdditionalOpenPon) { TEST(isThreeConcealedPons, PonsMustBeConcealedNegative) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m111p234s44m"); + HandFromNotation("111m111p234s44m", &hand); hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = kOneBamboo, }; hand.open = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, 0, branch)) { @@ -98,10 +97,10 @@ TEST(isThreeConcealedPons, PonsMustBeConcealedNegative) { TEST(isThreeConcealedPons, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m111p234567s44m"); + HandFromNotation("111m111p234567s44m", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, 0, branch)) { diff --git a/tests/yakus/dragonpon.test.cc b/tests/yakus/dragonpon.test.cc index 7a0aa2af..fb1fbe99 100644 --- a/tests/yakus/dragonpon.test.cc +++ b/tests/yakus/dragonpon.test.cc @@ -15,9 +15,9 @@ namespace mahjong::yaku { TEST(isWindOrDragonPon, WhiteDragon) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m555z11z"); + HandFromNotation("123m456m555z11z", &hand); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isWhiteDragon(game_state, 0, branch)) { @@ -31,9 +31,9 @@ TEST(isWindOrDragonPon, WhiteDragon) { TEST(isWindOrDragonPon, GreenDragon) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m666z11z"); + HandFromNotation("123m456m666z11z", &hand); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isGreenDragon(game_state, 0, branch)) { @@ -47,9 +47,9 @@ TEST(isWindOrDragonPon, GreenDragon) { TEST(isWindOrDragonPon, RedDragon) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m777z11z"); + HandFromNotation("123m456m777z11z", &hand); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRedDragon(game_state, 0, branch)) { @@ -63,9 +63,9 @@ TEST(isWindOrDragonPon, RedDragon) { TEST(isWindOrDragonPon, Kan) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m7777z11z"); + HandFromNotation("123m456m7777z11z", &hand); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRedDragon(game_state, 0, branch)) { @@ -79,10 +79,10 @@ TEST(isWindOrDragonPon, Kan) { TEST(isWindOrDragonPon, CanWhenOpen) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m777z11z"); + HandFromNotation("123m456m777z11z", &hand); hand.open = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRedDragon(game_state, 0, branch)) { @@ -96,9 +96,9 @@ TEST(isWindOrDragonPon, CanWhenOpen) { TEST(isWindOrDragonPon, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m222p11p"); + HandFromNotation("123m456m222p11p", &hand); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isGreenDragon(game_state, 0, branch)) { diff --git a/tests/yakus/fullflush.test.cc b/tests/yakus/fullflush.test.cc index ffb44e73..ac96f944 100644 --- a/tests/yakus/fullflush.test.cc +++ b/tests/yakus/fullflush.test.cc @@ -5,7 +5,6 @@ #include #include #include -#include #include "analysis/analysis.h" #include "analysis/handnode.h" @@ -21,15 +20,14 @@ namespace mahjong::yaku { TEST(isFullFlush, 5Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m222m345m99m"); + HandFromNotation("111m222m345m99m", &hand); hand.open = true; hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - ; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, 0, branch)) { @@ -43,10 +41,10 @@ TEST(isFullFlush, 5Han) { TEST(isFullFlush, 6Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m222m345m666m99m"); + HandFromNotation("111m222m345m666m99m", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, 0, branch)) { @@ -60,10 +58,10 @@ TEST(isFullFlush, 6Han) { TEST(isFullFlush, BadHandHonors) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m222m111z666m99m"); + HandFromNotation("111m222m111z666m99m", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, 0, branch)) { @@ -77,10 +75,10 @@ TEST(isFullFlush, BadHandHonors) { TEST(isFullFlush, BadHandSuit) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m222m111p666m99m"); + HandFromNotation("111m222m111p666m99m", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, 0, branch)) { @@ -94,10 +92,10 @@ TEST(isFullFlush, BadHandSuit) { TEST(isFullFlush, BadHandFullFlushHonors) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111z222z333z444z55z"); + HandFromNotation("111z222z333z444z55z", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, 0, branch)) { diff --git a/tests/yakus/halfflush.test.cc b/tests/yakus/halfflush.test.cc index c9c01c80..4d5b76f8 100644 --- a/tests/yakus/halfflush.test.cc +++ b/tests/yakus/halfflush.test.cc @@ -5,7 +5,6 @@ #include #include #include -#include #include "analysis/analysis.h" #include "analysis/handnode.h" @@ -21,14 +20,14 @@ namespace mahjong::yaku { TEST(isHalfFlush, 2Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("11m234m111z222z"); + HandFromNotation("11m234m111z222z", &hand); hand.open = true; hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isHalfFlush(game_state, 0, branch)) { @@ -42,10 +41,10 @@ TEST(isHalfFlush, 2Han) { TEST(isHalfFlush, 3Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("11m234m777m111z222z"); + HandFromNotation("11m234m777m111z222z", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isHalfFlush(game_state, 0, branch)) { @@ -59,14 +58,14 @@ TEST(isHalfFlush, 3Han) { TEST(isHalfFlush, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("11m234m111p222z"); + HandFromNotation("11m234m111p222z", &hand); hand.open = true; hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isHalfFlush(game_state, 0, branch)) { @@ -80,14 +79,14 @@ TEST(isHalfFlush, BadHand) { TEST(isHalfFlush, FullFlushIncompatible) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("11m234m888m777m"); + HandFromNotation("11m234m888m777m", &hand); hand.open = true; hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isHalfFlush(game_state, 0, branch)) { diff --git a/tests/yakus/littlethreedragons.test.cc b/tests/yakus/littlethreedragons.test.cc index df45f62a..0ca363d1 100644 --- a/tests/yakus/littlethreedragons.test.cc +++ b/tests/yakus/littlethreedragons.test.cc @@ -5,7 +5,6 @@ #include #include #include -#include #include "analysis/analysis.h" #include "analysis/handnode.h" @@ -21,10 +20,10 @@ namespace mahjong::yaku { TEST(isLittleThreeDragons, 2Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("555z666z111m222p77z"); + HandFromNotation("555z666z111m222p77z", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isLittleThreeDragons(game_state, 0, branch)) { @@ -38,14 +37,14 @@ TEST(isLittleThreeDragons, 2Han) { TEST(isLittleThreeDragons, WhenOpen) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("666z111m222p77z"); + HandFromNotation("666z111m222p77z", &hand); hand.open = true; hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kWhiteDragon), }; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isLittleThreeDragons(game_state, 0, branch)) { @@ -59,14 +58,14 @@ TEST(isLittleThreeDragons, WhenOpen) { TEST(isLittleThreeDragons, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("666z111m222p77s"); + HandFromNotation("666z111m222p77s", &hand); hand.open = true; hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kWhiteDragon), }; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isLittleThreeDragons(game_state, 0, branch)) { diff --git a/tests/yakus/mixedtriplechi.test.cc b/tests/yakus/mixedtriplechi.test.cc index 84f34e5e..aa68950b 100644 --- a/tests/yakus/mixedtriplechi.test.cc +++ b/tests/yakus/mixedtriplechi.test.cc @@ -16,10 +16,10 @@ namespace mahjong::yaku { TEST(isMixedTripleChi, Open) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123p123m123s555p11z"); + HandFromNotation("123p123m123s555p11z", &hand); hand.open = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isMixedTripleChi(game_state, 0, branch)) { @@ -33,10 +33,10 @@ TEST(isMixedTripleChi, Open) { TEST(isMixedTripleChi, Closed) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123p123m123s555p11z"); + HandFromNotation("123p123m123s555p11z", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isMixedTripleChi(game_state, 0, branch)) { @@ -50,10 +50,10 @@ TEST(isMixedTripleChi, Closed) { TEST(isMixedTripleChi, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123p123p123s555p11z"); + HandFromNotation("123p123p123s555p11z", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isMixedTripleChi(game_state, 0, branch)) { diff --git a/tests/yakus/outsidehand.test.cc b/tests/yakus/outsidehand.test.cc index 331aaaa2..d51108bb 100644 --- a/tests/yakus/outsidehand.test.cc +++ b/tests/yakus/outsidehand.test.cc @@ -16,10 +16,10 @@ namespace mahjong::yaku { TEST(isOutsideHand, Open) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m789m111z999s55z"); + HandFromNotation("123m789m111z999s55z", &hand); hand.open = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isOutsideHand(game_state, 0, branch)) { @@ -33,10 +33,10 @@ TEST(isOutsideHand, Open) { TEST(isOutsideHand, Closed) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m789m111z999s55z"); + HandFromNotation("123m789m111z999s55z", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isOutsideHand(game_state, 0, branch)) { @@ -50,9 +50,9 @@ TEST(isOutsideHand, Closed) { TEST(isOutsideHand, NoChi) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m111p111s999m66z"); + HandFromNotation("111m111p111s999m66z", &hand); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isOutsideHand(game_state, 0, branch)) { @@ -66,9 +66,9 @@ TEST(isOutsideHand, NoChi) { TEST(isOutsideHand, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m234p111s999m66z"); + HandFromNotation("111m234p111s999m66z", &hand); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isOutsideHand(game_state, 0, branch)) { diff --git a/tests/yakus/pinfu.test.cc b/tests/yakus/pinfu.test.cc index 54e62386..15c643fc 100644 --- a/tests/yakus/pinfu.test.cc +++ b/tests/yakus/pinfu.test.cc @@ -18,11 +18,11 @@ namespace mahjong::yaku { TEST(isPinfu, 1Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456p234678s44m"); + HandFromNotation("123m456p234678s44m", &hand); hand.open = false; game_state.pendingPiece = Piece(kFourPin); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPinfu(game_state, 0, branch)) { @@ -36,11 +36,11 @@ TEST(isPinfu, 1Han) { TEST(isPinfu, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m555p234678s44m"); + HandFromNotation("123m555p234678s44m", &hand); hand.open = false; game_state.pendingPiece = Piece(kTwoBamboo); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPinfu(game_state, 0, branch)) { @@ -54,11 +54,11 @@ TEST(isPinfu, BadHand) { TEST(isPinfu, CantBeOpen) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456p234678s44m"); + HandFromNotation("123m456p234678s44m", &hand); hand.open = true; game_state.pendingPiece = Piece(kFourPin); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPinfu(game_state, 0, branch)) { @@ -72,11 +72,11 @@ TEST(isPinfu, CantBeOpen) { TEST(isPinfu, NeedTwoWait) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456p234678s44m"); + HandFromNotation("123m456p234678s44m", &hand); hand.open = false; game_state.pendingPiece = Piece(kFivePin); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPinfu(game_state, 0, branch)) { diff --git a/tests/yakus/puredoublechi.test.cc b/tests/yakus/puredoublechi.test.cc index 3ca8f572..53bc3658 100644 --- a/tests/yakus/puredoublechi.test.cc +++ b/tests/yakus/puredoublechi.test.cc @@ -16,10 +16,10 @@ namespace mahjong::yaku { TEST(isPureDoubleChi, 1Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("234m234m555p888s88p"); + HandFromNotation("234m234m555p888s88p", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureDoubleChi(game_state, 0, branch)) { @@ -33,10 +33,10 @@ TEST(isPureDoubleChi, 1Han) { TEST(isPureDoubleChi, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("234m123m555p888s88p"); + HandFromNotation("234m123m555p888s88p", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureDoubleChi(game_state, 0, branch)) { @@ -50,10 +50,10 @@ TEST(isPureDoubleChi, BadHand) { TEST(isPureDoubleChi, MustBeConcealed) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("234m234m555p888s88p"); + HandFromNotation("234m234m555p888s88p", &hand); hand.open = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureDoubleChi(game_state, 0, branch)) { diff --git a/tests/yakus/purestraight.test.cc b/tests/yakus/purestraight.test.cc index 68190781..b2d624f4 100644 --- a/tests/yakus/purestraight.test.cc +++ b/tests/yakus/purestraight.test.cc @@ -16,10 +16,10 @@ namespace mahjong::yaku { TEST(isPureStraight, Open) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m789m555p11z"); + HandFromNotation("123m456m789m555p11z", &hand); hand.open = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureStraight(game_state, 0, branch)) { @@ -33,10 +33,10 @@ TEST(isPureStraight, Open) { TEST(isPureStraight, Closed) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m789m555p11z"); + HandFromNotation("123m456m789m555p11z", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureStraight(game_state, 0, branch)) { @@ -50,10 +50,10 @@ TEST(isPureStraight, Closed) { TEST(isPureStraight, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m999m555p11z"); + HandFromNotation("123m456m999m555p11z", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureStraight(game_state, 0, branch)) { diff --git a/tests/yakus/riichi.test.cc b/tests/yakus/riichi.test.cc index 1e12dff8..8d8f7ce1 100644 --- a/tests/yakus/riichi.test.cc +++ b/tests/yakus/riichi.test.cc @@ -15,7 +15,7 @@ namespace mahjong::yaku { TEST(isRiichi, Riichi) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("555m555p555s111z44m"); + HandFromNotation("555m555p555s111z44m", &hand); hand.riichi = true; hand.riichiRound = 7; @@ -28,7 +28,7 @@ TEST(isRiichi, Riichi) { TEST(isRiichi, Ippatsu) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("555m555p555s111z44m"); + HandFromNotation("555m555p555s111z44m", &hand); hand.riichi = true; hand.riichiRound = 14; @@ -41,7 +41,7 @@ TEST(isRiichi, Ippatsu) { TEST(isRiichi, DoubleRiichi) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("555m555p555s111z44m"); + HandFromNotation("555m555p555s111z44m", &hand); hand.riichi = true; hand.riichiRound = 1; @@ -54,7 +54,7 @@ TEST(isRiichi, DoubleRiichi) { TEST(isRiichi, NoRiichi) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("555m555p555s111z44m"); + HandFromNotation("555m555p555s111z44m", &hand); hand.riichi = false; game_state.turnNum = 2; diff --git a/tests/yakus/robbingkan.test.cc b/tests/yakus/robbingkan.test.cc index 6f9ee4d1..d34acad0 100644 --- a/tests/yakus/robbingkan.test.cc +++ b/tests/yakus/robbingkan.test.cc @@ -16,11 +16,11 @@ namespace mahjong::yaku { TEST(isRobbingAKan, 1Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m789m1111z999s55z"); + HandFromNotation("123m789m1111z999s55z", &hand); game_state.hasRonned[0] = true; game_state.nextState = StateFunctionType::kKanDiscard; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRobbingAKan(game_state, 0, branch)) { @@ -34,11 +34,11 @@ TEST(isRobbingAKan, 1Han) { TEST(isRobbingAKan, DoesntApply) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m789m1111z999s55z"); + HandFromNotation("123m789m1111z999s55z", &hand); game_state.hasRonned[0] = true; game_state.nextState = StateFunctionType::kPon; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRobbingAKan(game_state, 0, branch)) { diff --git a/tests/yakus/sevenpairs.test.cc b/tests/yakus/sevenpairs.test.cc index abef246e..b1b1278f 100644 --- a/tests/yakus/sevenpairs.test.cc +++ b/tests/yakus/sevenpairs.test.cc @@ -16,10 +16,10 @@ namespace mahjong::yaku { TEST(isSevenPairs, 2Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("11m22p33s44z55m11z66z"); + HandFromNotation("11m22p33s44z55m11z66z", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSevenPairs(game_state, 0, branch)) { @@ -33,10 +33,10 @@ TEST(isSevenPairs, 2Han) { TEST(isSevenPairs, MustBeConcealed) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("11m22p33s44z55m11z66z"); + HandFromNotation("11m22p33s44z55m11z66z", &hand); hand.open = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSevenPairs(game_state, 0, branch)) { @@ -50,10 +50,10 @@ TEST(isSevenPairs, MustBeConcealed) { TEST(isSevenPairs, UniquePairsOnly) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("1111m22p33s44z11z66z"); + HandFromNotation("1111m22p33s44z11z66z", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSevenPairs(game_state, 0, branch)) { diff --git a/tests/yakus/terminalinsets.test.cc b/tests/yakus/terminalinsets.test.cc index 2221d2d9..c8d6e214 100644 --- a/tests/yakus/terminalinsets.test.cc +++ b/tests/yakus/terminalinsets.test.cc @@ -3,7 +3,6 @@ #include #include #include -#include #include "analysis/analysis.h" #include "analysis/handnode.h" @@ -20,14 +19,14 @@ namespace mahjong::yaku { TEST(isTerminalsInAllSets, 2Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m789m111p11s"); + HandFromNotation("123m789m111p11s", &hand); hand.open = true; hand.melds[hand.meld_count++] = Meld{ .type = SetType::kChi, .start = Piece(kSevenPin), }; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTerminalsInAllSets(game_state, 0, branch)) { @@ -41,10 +40,10 @@ TEST(isTerminalsInAllSets, 2Han) { TEST(isTerminalsInAllSets, 3Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m789m111p789p11s"); + HandFromNotation("123m789m111p789p11s", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTerminalsInAllSets(game_state, 0, branch)) { @@ -58,7 +57,7 @@ TEST(isTerminalsInAllSets, 3Han) { TEST(isTerminalsInAllSets, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m789m222p11s"); + HandFromNotation("123m789m222p11s", &hand); hand.open = true; hand.open = true; hand.melds[hand.meld_count++] = Meld{ @@ -66,7 +65,7 @@ TEST(isTerminalsInAllSets, BadHand) { .start = Piece(kSevenPin), }; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTerminalsInAllSets(game_state, 0, branch)) { diff --git a/tests/yakus/triplekan.test.cc b/tests/yakus/triplekan.test.cc index 03eee6e4..506ce312 100644 --- a/tests/yakus/triplekan.test.cc +++ b/tests/yakus/triplekan.test.cc @@ -3,7 +3,6 @@ #include #include #include -#include #include "analysis/analysis.h" #include "analysis/handnode.h" @@ -33,12 +32,12 @@ TEST(isThreeKans, 2Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("666z22m"); + HandFromNotation("666z22m", &hand); hand.melds = {meld_a, meld_b, meld_c}; hand.meld_count = 3; hand.open = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeKans(game_state, 0, branch)) { @@ -69,12 +68,12 @@ TEST(isThreeKans, WithOtherMelds) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("22m"); + HandFromNotation("22m", &hand); hand.melds = {meld_a, meld_b, meld_c, meld_d}; hand.meld_count = 4; hand.open = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeKans(game_state, 0, branch)) { @@ -97,12 +96,12 @@ TEST(isThreeKans, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("777p666z22m"); + HandFromNotation("777p666z22m", &hand); hand.melds = {meld_a, meld_b}; hand.meld_count = 2; hand.open = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeKans(game_state, 0, branch)) { @@ -129,12 +128,12 @@ TEST(isThreeKans, AllConcealed) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("666z22m"); + HandFromNotation("666z22m", &hand); hand.melds = {meld_a, meld_b, meld_c}; hand.meld_count = 3; hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeKans(game_state, 0, branch)) { diff --git a/tests/yakus/triplepon.test.cc b/tests/yakus/triplepon.test.cc index 6d81cb06..12d3dfde 100644 --- a/tests/yakus/triplepon.test.cc +++ b/tests/yakus/triplepon.test.cc @@ -16,9 +16,9 @@ namespace mahjong::yaku { TEST(isTriplePon, 2Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m111p111s666z44m"); + HandFromNotation("111m111p111s666z44m", &hand); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTriplePon(game_state, 0, branch)) { @@ -32,9 +32,9 @@ TEST(isTriplePon, 2Han) { TEST(isTriplePon, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("111m111p222m666z44m"); + HandFromNotation("111m111p222m666z44m", &hand); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTriplePon(game_state, 0, branch)) { diff --git a/tests/yakus/twicepuredoublechi.test.cc b/tests/yakus/twicepuredoublechi.test.cc index 0b052fd0..b9ee9207 100644 --- a/tests/yakus/twicepuredoublechi.test.cc +++ b/tests/yakus/twicepuredoublechi.test.cc @@ -16,10 +16,10 @@ namespace mahjong::yaku { TEST(isTwicePureDoubleChi, 3Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("789p789p234m234m11z"); + HandFromNotation("789p789p234m234m11z", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTwicePureDoubleChi(game_state, 0, branch)) { @@ -33,10 +33,10 @@ TEST(isTwicePureDoubleChi, 3Han) { TEST(isTwicePureDoubleChi, MustBeConcealed) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("789p789p234m234m11z"); + HandFromNotation("789p789p234m234m11z", &hand); hand.open = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTwicePureDoubleChi(game_state, 0, branch)) { @@ -50,10 +50,10 @@ TEST(isTwicePureDoubleChi, MustBeConcealed) { TEST(isTwicePureDoubleChi, BadHand) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("789p789p234m567m11z"); + HandFromNotation("789p789p234m567m11z", &hand); hand.open = false; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTwicePureDoubleChi(game_state, 0, branch)) { diff --git a/tests/yakus/underthesea.test.cc b/tests/yakus/underthesea.test.cc index 2226e34a..bdad55a2 100644 --- a/tests/yakus/underthesea.test.cc +++ b/tests/yakus/underthesea.test.cc @@ -15,10 +15,10 @@ namespace mahjong::yaku { TEST(isBottomOfTheSea, 1Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m789m111z999s55z"); + HandFromNotation("123m789m111z999s55z", &hand); game_state.livingWallIndex = kLivingWallCount; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBottomOfTheSea(game_state, 0, branch)) { @@ -32,11 +32,11 @@ TEST(isBottomOfTheSea, 1Han) { TEST(isBottomOfTheSea, 1HanRonned) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m789m111z999s55z"); + HandFromNotation("123m789m111z999s55z", &hand); game_state.livingWallIndex = kLivingWallCount; game_state.hasRonned[0] = true; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBottomOfTheSea(game_state, 0, branch)) { @@ -50,9 +50,9 @@ TEST(isBottomOfTheSea, 1HanRonned) { TEST(isBottomOfTheSea, DoesntApply) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m789m111z999s55z"); + HandFromNotation("123m789m111z999s55z", &hand); - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBottomOfTheSea(game_state, 0, branch)) { diff --git a/tests/yakus/windpons.test.cc b/tests/yakus/windpons.test.cc index 960e6958..ba96e757 100644 --- a/tests/yakus/windpons.test.cc +++ b/tests/yakus/windpons.test.cc @@ -15,10 +15,10 @@ namespace mahjong::yaku { TEST(isWindOrDragonPon, SeatWind) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m444z55z"); + HandFromNotation("123m456m444z55z", &hand); game_state.roundNum = 1; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); auto branches = Node::AsBranchVectors(root.get()); @@ -35,10 +35,10 @@ TEST(isWindOrDragonPon, SeatWind) { TEST(isWindOrDragonPon, SeatWindKan) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m4444z55z"); + HandFromNotation("123m456m4444z55z", &hand); game_state.roundNum = 1; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, 0, branch)) { @@ -52,10 +52,10 @@ TEST(isWindOrDragonPon, SeatWindKan) { TEST(isWindOrDragonPon, PrevalentWind) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m111z55z"); + HandFromNotation("123m456m111z55z", &hand); game_state.roundNum = 1; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPrevalentWind(game_state, 0, branch)) { @@ -69,10 +69,10 @@ TEST(isWindOrDragonPon, PrevalentWind) { TEST(isWindOrDragonPon, PrevalentWindKan) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m1111z55z"); + HandFromNotation("123m456m1111z55z", &hand); game_state.roundNum = 1; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPrevalentWind(game_state, 0, branch)) { @@ -86,10 +86,10 @@ TEST(isWindOrDragonPon, PrevalentWindKan) { TEST(isWindOrDragonPon, Dealer2Han) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m111z55z"); + HandFromNotation("123m456m111z55z", &hand); game_state.roundNum = 0; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, 0, branch) && @@ -104,10 +104,10 @@ TEST(isWindOrDragonPon, Dealer2Han) { TEST(isWindOrDragonPon, Dealer2HanKan) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m1111z55z"); + HandFromNotation("123m456m1111z55z", &hand); game_state.roundNum = 0; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, 0, branch) && @@ -122,10 +122,10 @@ TEST(isWindOrDragonPon, Dealer2HanKan) { TEST(isWindOrDragonPon, NotSeatOrPrevalent) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m222z55z"); + HandFromNotation("123m456m222z55z", &hand); game_state.roundNum = 0; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, 0, branch) || @@ -140,10 +140,10 @@ TEST(isWindOrDragonPon, NotSeatOrPrevalent) { TEST(isWindOrDragonPon, NoWind) { auto game_state = GameState(); Hand& hand = game_state.hands[0]; - hand.live = HandFromNotation("123m456m666m55z"); + HandFromNotation("123m456m666m55z", &hand); game_state.roundNum = 0; - auto root = breakdownHand(hand.live); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, 0, branch) || From 015a03805df8ab526fa9e02f67f4442a3f739d60 Mon Sep 17 00:00:00 2001 From: alice Hartley Date: Thu, 4 Sep 2025 10:24:22 -0700 Subject: [PATCH 08/14] Use subranges with melds. --- src/analysis/analysis.cc | 2 +- src/scoring/scoring.cc | 20 ++++++------- src/scoring/yakus/allgreen.cc | 4 +-- src/scoring/yakus/allhonors.cc | 4 +-- src/scoring/yakus/allpons.cc | 7 ++--- src/scoring/yakus/allsimples.cc | 4 +-- src/scoring/yakus/allterminals.cc | 4 +-- src/scoring/yakus/allterminalsandhonors.cc | 4 +-- src/scoring/yakus/bigfourwinds.cc | 4 +-- src/scoring/yakus/bigthreedragons.cc | 4 +-- src/scoring/yakus/fourconcealedpon.cc | 4 +-- src/scoring/yakus/fourkans.cc | 4 +-- src/scoring/yakus/fullflush.cc | 4 +-- src/scoring/yakus/halfflush.cc | 6 ++-- src/scoring/yakus/honorpon.cc | 4 +-- src/scoring/yakus/littlefourwinds.cc | 4 +-- src/scoring/yakus/littlethreedragons.cc | 4 +-- src/scoring/yakus/maxbranches.cc | 28 +++++++++---------- src/scoring/yakus/mixedtriplechi.cc | 16 +++++------ src/scoring/yakus/outsidehand.cc | 9 +++--- src/scoring/yakus/purestraight.cc | 16 +++++------ src/scoring/yakus/terminalsinallsets.cc | 9 +++--- src/scoring/yakus/threeconcealedpons.cc | 4 +-- src/scoring/yakus/threekans.cc | 4 +-- src/scoring/yakus/triplepon.cc | 16 +++++------ src/statefunctions/gamestates/convertedkan.cc | 23 +++++++++------ src/types/gamestate.h | 5 +++- src/types/typeprinter.cc | 7 +++-- 28 files changed, 115 insertions(+), 109 deletions(-) diff --git a/src/analysis/analysis.cc b/src/analysis/analysis.cc index b0e936af..df9630c5 100644 --- a/src/analysis/analysis.cc +++ b/src/analysis/analysis.cc @@ -25,7 +25,7 @@ void countPieces(Breakdown* b) { std::vector AnalyzeHand(const Hand& hand, const bool only_complete) { Branch base_branch; base_branch.open = !hand.melds.empty(); - for (const Meld& meld : hand.melds) { + for (const auto& meld : hand.melds_range()) { switch (meld.type) { case SetType::kChi: base_branch.chis.emplace_back(meld.start); diff --git a/src/scoring/scoring.cc b/src/scoring/scoring.cc index 325a4a17..b6b0cb5e 100644 --- a/src/scoring/scoring.cc +++ b/src/scoring/scoring.cc @@ -103,15 +103,15 @@ Score scoreHand(const GameState& state, int player) { branchscore.han++; } } - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].start == dora) { + for (const auto& meld : hand.melds_range()) { + if (meld.start == dora) { branchscore.han++; } - if (hand.melds[i].type == SetType::kChi) { - if (hand.melds[i].start + 1 == dora) { + if (meld.type == SetType::kChi) { + if (meld.start + 1 == dora) { branchscore.han++; } - if (hand.melds[i].start + 2 == dora) { + if (meld.start + 2 == dora) { branchscore.han++; } } @@ -180,9 +180,9 @@ int getFu(const GameState& state, int player, fu += kSelfdraw; } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].type == SetType::kKan) { - if (!hand.melds[i].start.isHonor() && !hand.melds[i].start.isTerminal()) { + for (const auto& meld : hand.melds_range()) { + if (meld.type == SetType::kKan) { + if (!meld.start.isHonor() && !meld.start.isTerminal()) { fu += open ? kSimplekan : kCsimplekan; } else { fu += open ? kTermHonorkan : kCtermHonorkan; @@ -254,8 +254,8 @@ bool isOpenPinfu(const GameState& state, int player, } } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].type > SetType::kChi) { + for (const auto& meld : hand.melds_range()) { + if (meld.type > SetType::kChi) { return false; } } diff --git a/src/scoring/yakus/allgreen.cc b/src/scoring/yakus/allgreen.cc index caec6a4b..20e1e611 100644 --- a/src/scoring/yakus/allgreen.cc +++ b/src/scoring/yakus/allgreen.cc @@ -17,8 +17,8 @@ bool isAllGreen(const GameState& state, int player, } } - for (int i = 0; i < hand.meld_count; ++i) { - if (!hand.melds[i].start.isGreen()) { + for (const auto& meld : hand.melds_range()) { + if (!meld.start.isGreen()) { return false; } } diff --git a/src/scoring/yakus/allhonors.cc b/src/scoring/yakus/allhonors.cc index d7f73388..4d78b652 100644 --- a/src/scoring/yakus/allhonors.cc +++ b/src/scoring/yakus/allhonors.cc @@ -16,8 +16,8 @@ bool isAllHonors(const GameState& state, int player, return false; } } - for (int i = 0; i < hand.meld_count; ++i) { - if (!hand.melds[i].start.isHonor()) { + for (const auto& meld : hand.melds_range()) { + if (!meld.start.isHonor()) { return false; } } diff --git a/src/scoring/yakus/allpons.cc b/src/scoring/yakus/allpons.cc index b867307f..424280fc 100644 --- a/src/scoring/yakus/allpons.cc +++ b/src/scoring/yakus/allpons.cc @@ -18,10 +18,9 @@ bool isAllPons(const GameState& state, int player, } } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].type == SetType::kKan || - hand.melds[i].type == SetType::kPon || - hand.melds[i].type == SetType::kConcealedKan) { + for (const auto& meld : hand.melds_range()) { + if (meld.type == SetType::kKan || meld.type == SetType::kPon || + meld.type == SetType::kConcealedKan) { pons++; } } diff --git a/src/scoring/yakus/allsimples.cc b/src/scoring/yakus/allsimples.cc index 5cac7c88..71fb6f8b 100644 --- a/src/scoring/yakus/allsimples.cc +++ b/src/scoring/yakus/allsimples.cc @@ -16,8 +16,8 @@ bool isAllSimples(const GameState& state, int player, return false; } } - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].start.isHonor() || hand.melds[i].start.isTerminal()) { + for (const auto& meld : hand.melds_range()) { + if (meld.start.isHonor() || meld.start.isTerminal()) { return false; } } diff --git a/src/scoring/yakus/allterminals.cc b/src/scoring/yakus/allterminals.cc index ce48285e..f280ced3 100644 --- a/src/scoring/yakus/allterminals.cc +++ b/src/scoring/yakus/allterminals.cc @@ -16,8 +16,8 @@ bool isAllTerminals(const GameState& state, int player, return false; } } - for (int i = 0; i < hand.meld_count; ++i) { - if (!hand.melds[i].start.isTerminal()) { + for (const auto& meld : hand.melds_range()) { + if (!meld.start.isTerminal()) { return false; } } diff --git a/src/scoring/yakus/allterminalsandhonors.cc b/src/scoring/yakus/allterminalsandhonors.cc index 4cdb580a..39649462 100644 --- a/src/scoring/yakus/allterminalsandhonors.cc +++ b/src/scoring/yakus/allterminalsandhonors.cc @@ -17,8 +17,8 @@ bool isAllTerminalsAndHonors( return false; } } - for (int i = 0; i < hand.meld_count; ++i) { - if (!hand.melds[i].start.isHonor() && !hand.melds[i].start.isTerminal()) { + for (const auto& meld : hand.melds_range()) { + if (!meld.start.isHonor() && !meld.start.isTerminal()) { return false; } } diff --git a/src/scoring/yakus/bigfourwinds.cc b/src/scoring/yakus/bigfourwinds.cc index 736255cd..7a468a5b 100644 --- a/src/scoring/yakus/bigfourwinds.cc +++ b/src/scoring/yakus/bigfourwinds.cc @@ -28,8 +28,8 @@ bool isBigFourWinds(const GameState& state, int player, pons++; } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - switch (hand.melds[i].start.toUint8_t()) { + for (const auto& meld : hand.melds_range()) { + switch (meld.start.toUint8_t()) { case Piece::Type::kEastWind: case Piece::Type::kSouthWind: case Piece::Type::kWestWind: diff --git a/src/scoring/yakus/bigthreedragons.cc b/src/scoring/yakus/bigthreedragons.cc index 3701d935..b89dd694 100644 --- a/src/scoring/yakus/bigthreedragons.cc +++ b/src/scoring/yakus/bigthreedragons.cc @@ -27,8 +27,8 @@ bool isBigThreeDragons(const GameState& state, int player, pons++; } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - switch (hand.melds[i].start.toUint8_t()) { + for (const auto& meld : hand.melds_range()) { + switch (meld.start.toUint8_t()) { case Piece::Type::kRedDragon: case Piece::Type::kGreenDragon: case Piece::Type::kWhiteDragon: diff --git a/src/scoring/yakus/fourconcealedpon.cc b/src/scoring/yakus/fourconcealedpon.cc index 54fd7d2d..c117a5ac 100644 --- a/src/scoring/yakus/fourconcealedpon.cc +++ b/src/scoring/yakus/fourconcealedpon.cc @@ -21,8 +21,8 @@ bool isFourConcealedPon(const GameState& state, int player, } } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].type == SetType::kConcealedKan) { + for (const auto& meld : hand.melds_range()) { + if (meld.type == SetType::kConcealedKan) { concealed_pons++; } } diff --git a/src/scoring/yakus/fourkans.cc b/src/scoring/yakus/fourkans.cc index f50e7969..f4b99202 100644 --- a/src/scoring/yakus/fourkans.cc +++ b/src/scoring/yakus/fourkans.cc @@ -13,8 +13,8 @@ bool isFourKans(const GameState& state, int player, const std::vector& /*branch*/) { int kans = 0; const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].type >= SetType::kKan) { + for (const auto& meld : hand.melds_range()) { + if (meld.type >= SetType::kKan) { kans++; } } diff --git a/src/scoring/yakus/fullflush.cc b/src/scoring/yakus/fullflush.cc index d301da09..3c1e2a2d 100644 --- a/src/scoring/yakus/fullflush.cc +++ b/src/scoring/yakus/fullflush.cc @@ -20,8 +20,8 @@ bool isFullFlush(const GameState& state, int player, return false; } } - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].start.getSuit() != suit) { + for (const auto& meld : hand.melds_range()) { + if (meld.start.getSuit() != suit) { return false; } } diff --git a/src/scoring/yakus/halfflush.cc b/src/scoring/yakus/halfflush.cc index 0744c075..4684147d 100644 --- a/src/scoring/yakus/halfflush.cc +++ b/src/scoring/yakus/halfflush.cc @@ -23,12 +23,12 @@ bool isHalfFlush(const GameState& state, int player, return false; } } - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].start.isHonor()) { + for (const auto& meld : hand.melds_range()) { + if (meld.start.isHonor()) { honors = true; continue; } - if (suit != hand.melds[i].start.getSuit()) { + if (suit != meld.start.getSuit()) { return false; } } diff --git a/src/scoring/yakus/honorpon.cc b/src/scoring/yakus/honorpon.cc index c5b2eb13..0bc82d33 100644 --- a/src/scoring/yakus/honorpon.cc +++ b/src/scoring/yakus/honorpon.cc @@ -23,8 +23,8 @@ bool findPon(const GameState& state, int player, } } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].type >= SetType::kPon && hand.melds[i].start == piece) { + for (const auto& meld : hand.melds_range()) { + if (meld.type >= SetType::kPon && meld.start == piece) { return true; } } diff --git a/src/scoring/yakus/littlefourwinds.cc b/src/scoring/yakus/littlefourwinds.cc index fa299dea..12ceee4c 100644 --- a/src/scoring/yakus/littlefourwinds.cc +++ b/src/scoring/yakus/littlefourwinds.cc @@ -36,8 +36,8 @@ bool isLittleFourWinds(const GameState& state, int player, return false; } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - switch (hand.melds[i].start.toUint8_t()) { + for (const auto& meld : hand.melds_range()) { + switch (meld.start.toUint8_t()) { case Piece::Type::kEastWind: case Piece::Type::kSouthWind: case Piece::Type::kWestWind: diff --git a/src/scoring/yakus/littlethreedragons.cc b/src/scoring/yakus/littlethreedragons.cc index 09ee1999..13d5bc22 100644 --- a/src/scoring/yakus/littlethreedragons.cc +++ b/src/scoring/yakus/littlethreedragons.cc @@ -33,8 +33,8 @@ bool isLittleThreeDragons(const GameState& state, int player, return false; } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - switch (hand.melds[i].start.toUint8_t()) { + for (const auto& meld : hand.melds_range()) { + switch (meld.start.toUint8_t()) { case Piece::Type::kRedDragon: case Piece::Type::kGreenDragon: case Piece::Type::kWhiteDragon: diff --git a/src/scoring/yakus/maxbranches.cc b/src/scoring/yakus/maxbranches.cc index 5ed6b535..6f828d83 100644 --- a/src/scoring/yakus/maxbranches.cc +++ b/src/scoring/yakus/maxbranches.cc @@ -25,28 +25,28 @@ bool isMaxBranches(const GameState& state, int player, } sets.at(piece.getPieceNum() - start)++; } - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].start.getSuit() != suit) { + for (const auto& meld : hand.melds_range()) { + if (meld.start.getSuit() != suit) { return false; } - if (hand.melds[i].start.getPieceNum() < start || - hand.melds[i].start.getPieceNum() > start + 3) { + if (meld.start.getPieceNum() < start || + meld.start.getPieceNum() > start + 3) { return false; } - if (hand.melds[i].type >= SetType::kKan) { - if (hand.melds[i].start.getPieceNum() != start && - hand.melds[i].start.getPieceNum() != start + 1) { + if (meld.type >= SetType::kKan) { + if (meld.start.getPieceNum() != start && + meld.start.getPieceNum() != start + 1) { return false; } - sets.at(hand.melds[i].start.getPieceNum() - start) += 3; + sets.at(meld.start.getPieceNum() - start) += 3; } - if (hand.melds[i].type == SetType::kPon) { - sets.at(hand.melds[i].start.getPieceNum() - start) += 3; + if (meld.type == SetType::kPon) { + sets.at(meld.start.getPieceNum() - start) += 3; } - if (hand.melds[i].type == SetType::kChi) { - sets.at(hand.melds[i].start.getPieceNum() - start)++; - sets.at(hand.melds[i].start.getPieceNum() - start + 1)++; - sets.at(hand.melds[i].start.getPieceNum() - start + 2)++; + if (meld.type == SetType::kChi) { + sets.at(meld.start.getPieceNum() - start)++; + sets.at(meld.start.getPieceNum() - start + 1)++; + sets.at(meld.start.getPieceNum() - start + 2)++; } } for (int i = 0; i < 6; i++) { diff --git a/src/scoring/yakus/mixedtriplechi.cc b/src/scoring/yakus/mixedtriplechi.cc index 115254e5..6e1a5ed3 100644 --- a/src/scoring/yakus/mixedtriplechi.cc +++ b/src/scoring/yakus/mixedtriplechi.cc @@ -30,16 +30,16 @@ bool isMixedTripleChi(const GameState& state, int player, } } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].type == SetType::kChi) { - if (hand.melds[i].start.getSuit() == Piece::Type::kBambooSuit) { - bamboo_chi.at(hand.melds[i].start.getPieceNum()) = true; + for (const auto& meld : hand.melds_range()) { + if (meld.type == SetType::kChi) { + if (meld.start.getSuit() == Piece::Type::kBambooSuit) { + bamboo_chi.at(meld.start.getPieceNum()) = true; } - if (hand.melds[i].start.getSuit() == Piece::Type::kCharacterSuit) { - char_chi.at(hand.melds[i].start.getPieceNum()) = true; + if (meld.start.getSuit() == Piece::Type::kCharacterSuit) { + char_chi.at(meld.start.getPieceNum()) = true; } - if (hand.melds[i].start.getSuit() == Piece::Type::kPinSuit) { - pin_chi.at(hand.melds[i].start.getPieceNum()) = true; + if (meld.start.getSuit() == Piece::Type::kPinSuit) { + pin_chi.at(meld.start.getPieceNum()) = true; } } } diff --git a/src/scoring/yakus/outsidehand.cc b/src/scoring/yakus/outsidehand.cc index 5a839c68..a3f379d2 100644 --- a/src/scoring/yakus/outsidehand.cc +++ b/src/scoring/yakus/outsidehand.cc @@ -28,16 +28,15 @@ bool isOutsideHand(const GameState& state, int player, } } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].type == SetType::kChi) { - if (hand.melds[i].start.isTerminal() || - (hand.melds[i].start + 2).isTerminal()) { + for (const auto& meld : hand.melds_range()) { + if (meld.type == SetType::kChi) { + if (meld.start.isTerminal() || (meld.start + 2).isTerminal()) { chi = true; } else { return false; } } else { - if (!hand.melds[i].start.isTerminal() && !hand.melds[i].start.isHonor()) { + if (!meld.start.isTerminal() && !meld.start.isHonor()) { return false; } } diff --git a/src/scoring/yakus/purestraight.cc b/src/scoring/yakus/purestraight.cc index 488a979d..1421d633 100644 --- a/src/scoring/yakus/purestraight.cc +++ b/src/scoring/yakus/purestraight.cc @@ -42,25 +42,25 @@ bool isPureStraight(const GameState& state, int player, } } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].type == SetType::kChi) { + for (const auto& meld : hand.melds_range()) { + if (meld.type == SetType::kChi) { int ind = 0; - if (hand.melds[i].start.getPieceNum() == k_firstchistart) { + if (meld.start.getPieceNum() == k_firstchistart) { ind = 0; - } else if (hand.melds[i].start.getPieceNum() == k_secondchistart) { + } else if (meld.start.getPieceNum() == k_secondchistart) { ind = 1; - } else if (hand.melds[i].start.getPieceNum() == k_thirdchistart) { + } else if (meld.start.getPieceNum() == k_thirdchistart) { ind = 2; } else { continue; } - if (hand.melds[i].start.getSuit() == Piece::Type::kBambooSuit) { + if (meld.start.getSuit() == Piece::Type::kBambooSuit) { bamboo_chi.at(ind) = true; } - if (hand.melds[i].start.getSuit() == Piece::Type::kCharacterSuit) { + if (meld.start.getSuit() == Piece::Type::kCharacterSuit) { char_chi.at(ind) = true; } - if (hand.melds[i].start.getSuit() == Piece::Type::kPinSuit) { + if (meld.start.getSuit() == Piece::Type::kPinSuit) { pin_chi.at(ind) = true; } } diff --git a/src/scoring/yakus/terminalsinallsets.cc b/src/scoring/yakus/terminalsinallsets.cc index f9067655..e2c37e2a 100644 --- a/src/scoring/yakus/terminalsinallsets.cc +++ b/src/scoring/yakus/terminalsinallsets.cc @@ -31,13 +31,12 @@ bool isTerminalsInAllSets(const GameState& state, int player, } } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - switch (hand.melds[i].type) { + for (const auto& meld : hand.melds_range()) { + switch (meld.type) { case SetType::kSingle: return false; case SetType::kChi: - if (!hand.melds[i].start.isTerminal() && - !(hand.melds[i].start + 2).isTerminal()) { + if (!meld.start.isTerminal() && !(meld.start + 2).isTerminal()) { return false; } break; @@ -45,7 +44,7 @@ bool isTerminalsInAllSets(const GameState& state, int player, case SetType::kKan: case SetType::kConcealedKan: case SetType::kPon: - if (!hand.melds[i].start.isTerminal()) { + if (!meld.start.isTerminal()) { return false; } break; diff --git a/src/scoring/yakus/threeconcealedpons.cc b/src/scoring/yakus/threeconcealedpons.cc index 1565395a..6c154acf 100644 --- a/src/scoring/yakus/threeconcealedpons.cc +++ b/src/scoring/yakus/threeconcealedpons.cc @@ -18,8 +18,8 @@ bool isThreeConcealedPons(const GameState& state, int player, } } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].type == SetType::kConcealedKan) { + for (const auto& meld : hand.melds_range()) { + if (meld.type == SetType::kConcealedKan) { concealed_pons++; } } diff --git a/src/scoring/yakus/threekans.cc b/src/scoring/yakus/threekans.cc index 1bda22a9..dcb4c887 100644 --- a/src/scoring/yakus/threekans.cc +++ b/src/scoring/yakus/threekans.cc @@ -13,8 +13,8 @@ bool isThreeKans(const GameState& state, int player, const std::vector& /*branch*/) { int kans = 0; const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].type >= SetType::kKan) { + for (const auto& meld : hand.melds_range()) { + if (meld.type >= SetType::kKan) { kans++; } } diff --git a/src/scoring/yakus/triplepon.cc b/src/scoring/yakus/triplepon.cc index b0c33e85..8ed6b938 100644 --- a/src/scoring/yakus/triplepon.cc +++ b/src/scoring/yakus/triplepon.cc @@ -29,16 +29,16 @@ bool isTriplePon(const GameState& state, int player, } } const Hand& hand = state.hands[player]; - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].type >= SetType::kPon) { - if (hand.melds[i].start.getSuit() == Piece::Type::kBambooSuit) { - bamboo_pon.at(hand.melds[i].start.getPieceNum() - 1) = true; + for (const auto& meld : hand.melds_range()) { + if (meld.type >= SetType::kPon) { + if (meld.start.getSuit() == Piece::Type::kBambooSuit) { + bamboo_pon.at(meld.start.getPieceNum() - 1) = true; } - if (hand.melds[i].start.getSuit() == Piece::Type::kCharacterSuit) { - char_pon.at(hand.melds[i].start.getPieceNum() - 1) = true; + if (meld.start.getSuit() == Piece::Type::kCharacterSuit) { + char_pon.at(meld.start.getPieceNum() - 1) = true; } - if (hand.melds[i].start.getSuit() == Piece::Type::kPinSuit) { - pin_pon.at(hand.melds[i].start.getPieceNum() - 1) = true; + if (meld.start.getSuit() == Piece::Type::kPinSuit) { + pin_pon.at(meld.start.getPieceNum() - 1) = true; } } } diff --git a/src/statefunctions/gamestates/convertedkan.cc b/src/statefunctions/gamestates/convertedkan.cc index 4b480883..6f085c43 100644 --- a/src/statefunctions/gamestates/convertedkan.cc +++ b/src/statefunctions/gamestates/convertedkan.cc @@ -1,3 +1,4 @@ +#include #include #include #include @@ -7,6 +8,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/meld.h" #include "types/piecetype.h" #include "types/sets.h" #include "types/statefunction.h" @@ -27,16 +29,19 @@ std::unique_ptr ConvertedKan(std::unique_ptr state) { state->nextState = StateFunctionType::kError; return state; } - state->concealedKan = false; - Hand& hand = state->hands.at(state->currentPlayer); - for (int i = 0; i < hand.meld_count; ++i) { - if (hand.melds[i].type == SetType::kPon && - hand.melds[i].start == state->pendingPiece) { - hand.melds[i].type = SetType::kKan; - state->nextState = StateFunctionType::kKanDiscard; - return state; - } + + Hand& hand = state->hands[state->currentPlayer]; + if (auto* meld = std::ranges::find(hand.melds, + Meld{ + .type = SetType::kPon, + .start = state->pendingPiece, + }); + meld != hand.melds.end()) { + meld->type = SetType::kKan; + state->nextState = StateFunctionType::kKanDiscard; + return state; } + std::cerr << "Could Not find matching pon" << '\n'; state->nextState = StateFunctionType::kError; return state; diff --git a/src/types/gamestate.h b/src/types/gamestate.h index 99b75020..59801010 100644 --- a/src/types/gamestate.h +++ b/src/types/gamestate.h @@ -17,15 +17,18 @@ struct Hand { bool riichi = false; int riichiPieceDiscard = -1; int riichiRound = -1; - int meld_count = 0; std::array live; int live_count = 13; std::array melds; + int meld_count = 0; std::array discards; int discards_count = 0; [[nodiscard]] std::ranges::subrange live_range() const { return std::ranges::subrange(live.begin(), live.begin() + live_count); } + [[nodiscard]] std::ranges::subrange melds_range() const { + return std::ranges::subrange(melds.begin(), melds.begin() + meld_count); + } }; struct GameState { diff --git a/src/types/typeprinter.cc b/src/types/typeprinter.cc index 83c35638..5f2a6f51 100644 --- a/src/types/typeprinter.cc +++ b/src/types/typeprinter.cc @@ -11,6 +11,7 @@ #include "controllers/playercontroller.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/meld.h" #include "types/piecetype.h" std::ostream& operator<<(std::ostream& os, const mahjong::Event& e) { @@ -78,9 +79,9 @@ std::ostream& operator<<(std::ostream& os, const mahjong::Hand& hand) { } os << "]" << '\n'; os << "melds: [" << '\n'; - for (int i = 0; i < hand.meld_count; ++i) { - os << "{ type: " << hand.melds[i].typeToStr(); - os << ", start: " << hand.melds[i].start.toStr() << "}"; + for (const auto& meld : hand.melds_range()) { + os << "{ type: " << meld.typeToStr(); + os << ", start: " << meld.start.toStr() << "}"; os << ", "; } os << "]" << '\n'; From 2f9fd99f2da2dcec43586aee430729424c1846eb Mon Sep 17 00:00:00 2001 From: alice Hartley Date: Fri, 5 Sep 2025 00:05:23 -0700 Subject: [PATCH 09/14] Rearrange GameState into Player sub-struct. --- src/analysis/analysis.cc | 11 +-- src/analysis/analysis.h | 5 +- src/analysis/util.cc | 8 +-- src/analysis/util.h | 6 +- src/api/gamestate.cc | 22 +++--- src/api/types.h | 14 ++-- src/controllers/gentlemanbot.cc | 2 +- src/controllers/playercontroller.h | 1 - src/controllers/thricebot.cc | 8 +-- src/controllers/thricebot.h | 6 +- src/scoring/scoring.cc | 38 +++++----- src/scoring/scoring.h | 8 +-- src/scoring/yakus/afterakan.cc | 4 +- src/scoring/yakus/afterakan.h | 2 +- src/scoring/yakus/allgreen.cc | 7 +- src/scoring/yakus/allgreen.h | 2 +- src/scoring/yakus/allhonors.cc | 7 +- src/scoring/yakus/allhonors.h | 2 +- src/scoring/yakus/allpons.cc | 5 +- src/scoring/yakus/allpons.h | 2 +- src/scoring/yakus/allsimples.cc | 7 +- src/scoring/yakus/allsimples.h | 2 +- src/scoring/yakus/allterminals.cc | 7 +- src/scoring/yakus/allterminals.h | 2 +- src/scoring/yakus/allterminalsandhonors.cc | 7 +- src/scoring/yakus/allterminalsandhonors.h | 2 +- src/scoring/yakus/bigfourwinds.cc | 5 +- src/scoring/yakus/bigfourwinds.h | 2 +- src/scoring/yakus/bigthreedragons.cc | 5 +- src/scoring/yakus/bigthreedragons.h | 2 +- src/scoring/yakus/blessingofearth.cc | 6 +- src/scoring/yakus/blessingofearth.h | 2 +- src/scoring/yakus/blessingofheaven.cc | 8 +-- src/scoring/yakus/blessingofheaven.h | 2 +- src/scoring/yakus/blessingofman.cc | 8 +-- src/scoring/yakus/blessingofman.h | 2 +- src/scoring/yakus/bottomofthesea.cc | 2 +- src/scoring/yakus/bottomofthesea.h | 2 +- src/scoring/yakus/doubleriichi.cc | 4 +- src/scoring/yakus/doubleriichi.h | 2 +- src/scoring/yakus/fourconcealedpon.cc | 7 +- src/scoring/yakus/fourconcealedpon.h | 2 +- src/scoring/yakus/fourkans.cc | 5 +- src/scoring/yakus/fourkans.h | 2 +- src/scoring/yakus/fullflush.cc | 11 ++- src/scoring/yakus/fullflush.h | 2 +- src/scoring/yakus/fullyconcealedhand.cc | 9 +-- src/scoring/yakus/fullyconcealedhand.h | 2 +- src/scoring/yakus/halfflush.cc | 9 ++- src/scoring/yakus/halfflush.h | 2 +- src/scoring/yakus/honorpon.cc | 17 +++-- src/scoring/yakus/honorpon.h | 10 +-- src/scoring/yakus/ippatsu.cc | 6 +- src/scoring/yakus/ippatsu.h | 2 +- src/scoring/yakus/littlefourwinds.cc | 5 +- src/scoring/yakus/littlefourwinds.h | 2 +- src/scoring/yakus/littlethreedragons.cc | 5 +- src/scoring/yakus/littlethreedragons.h | 2 +- src/scoring/yakus/maxbranches.cc | 11 ++- src/scoring/yakus/maxbranches.h | 2 +- src/scoring/yakus/mixedtriplechi.cc | 5 +- src/scoring/yakus/mixedtriplechi.h | 2 +- src/scoring/yakus/ninegates.cc | 9 ++- src/scoring/yakus/ninegates.h | 2 +- src/scoring/yakus/outsidehand.cc | 11 ++- src/scoring/yakus/outsidehand.h | 4 +- src/scoring/yakus/pinfu.cc | 9 ++- src/scoring/yakus/pinfu.h | 2 +- src/scoring/yakus/puredoublechi.cc | 4 +- src/scoring/yakus/puredoublechi.h | 2 +- src/scoring/yakus/purestraight.cc | 5 +- src/scoring/yakus/purestraight.h | 2 +- src/scoring/yakus/riichi.cc | 4 +- src/scoring/yakus/riichi.h | 2 +- src/scoring/yakus/robbingakan.cc | 4 +- src/scoring/yakus/robbingakan.h | 2 +- src/scoring/yakus/sevenpairs.cc | 4 +- src/scoring/yakus/sevenpairs.h | 2 +- src/scoring/yakus/terminalsinallsets.cc | 5 +- src/scoring/yakus/terminalsinallsets.h | 2 +- src/scoring/yakus/thirteenorphans.cc | 7 +- src/scoring/yakus/thirteenorphans.h | 2 +- src/scoring/yakus/threeconcealedpons.cc | 5 +- src/scoring/yakus/threeconcealedpons.h | 2 +- src/scoring/yakus/threekans.cc | 5 +- src/scoring/yakus/threekans.h | 2 +- src/scoring/yakus/triplepon.cc | 5 +- src/scoring/yakus/triplepon.h | 2 +- src/scoring/yakus/twicepuredoublechi.cc | 4 +- src/scoring/yakus/twicepuredoublechi.h | 2 +- src/statefunctions/decisionfunction.cc | 71 +++++++++--------- src/statefunctions/decisionfunction.h | 18 ++--- src/statefunctions/gamestates/chi.cc | 45 ++++++------ src/statefunctions/gamestates/concealedkan.cc | 6 +- src/statefunctions/gamestates/convertedkan.cc | 8 +-- src/statefunctions/gamestates/discard.cc | 20 +++--- src/statefunctions/gamestates/draw.cc | 6 +- src/statefunctions/gamestates/exhaust.cc | 14 ++-- src/statefunctions/gamestates/gameend.cc | 6 +- src/statefunctions/gamestates/gamestart.cc | 5 +- src/statefunctions/gamestates/kan.cc | 16 ++--- src/statefunctions/gamestates/kandiscard.cc | 16 ++--- src/statefunctions/gamestates/playerhand.cc | 16 ++--- src/statefunctions/gamestates/pon.cc | 16 ++--- src/statefunctions/gamestates/replacement.cc | 6 +- src/statefunctions/gamestates/riichi.cc | 10 +-- src/statefunctions/gamestates/ron.cc | 49 +++++++------ src/statefunctions/gamestates/roundend.cc | 31 ++++---- src/statefunctions/gamestates/roundstart.cc | 6 +- src/statefunctions/gamestates/tsumo.cc | 20 +++--- src/statefunctions/statecontroller.cc | 2 +- src/statefunctions/stateutilities.cc | 58 ++++++++------- src/statefunctions/stateutilities.h | 14 ++-- src/types/event.h | 2 - src/types/gamestate.h | 40 ++++++----- src/types/statefunction.h | 2 +- src/types/typeprinter.cc | 37 +++++----- src/types/typeprinter.h | 6 +- src/types/yaku.h | 4 +- tests/api/game_control.test.cc | 64 ++++++++--------- tests/can_chi.test.cc | 24 +++---- tests/count_pieces.test.cc | 15 ++-- tests/discard_piece.test.cc | 21 +++--- tests/game_play.test.cc | 12 ++-- tests/remove_pieces.test.cc | 41 ++++++----- tests/rules/basic_rules.test.cc | 28 ++++---- tests/rules/calls.test.cc | 28 ++++---- tests/setup.test.cc | 6 +- tests/utils/gamestate_utils.cc | 30 +++----- tests/utils/gamestate_utils.h | 5 +- tests/utils/gamestate_utils.test.cc | 6 +- tests/utils/handformer.cc | 4 +- tests/utils/handformer.h | 4 +- tests/utils/handformer.test.cc | 34 ++++----- tests/yakus/afterkan.test.cc | 24 +++---- tests/yakus/allpon.test.cc | 44 ++++++------ tests/yakus/allsimples.test.cc | 28 ++++---- tests/yakus/allterminalsandhonors.test.cc | 34 ++++----- tests/yakus/blessingofman.test.cc | 49 ++++++------- tests/yakus/concealedhand.test.cc | 34 ++++----- tests/yakus/concealedpon.test.cc | 58 +++++++-------- tests/yakus/dragonpon.test.cc | 52 +++++++------- tests/yakus/fullflush.test.cc | 58 +++++++-------- tests/yakus/halfflush.test.cc | 48 ++++++------- tests/yakus/littlethreedragons.test.cc | 36 +++++----- tests/yakus/mixedtriplechi.test.cc | 32 ++++----- tests/yakus/outsidehand.test.cc | 38 +++++----- tests/yakus/pinfu.test.cc | 42 +++++------ tests/yakus/puredoublechi.test.cc | 32 ++++----- tests/yakus/purestraight.test.cc | 32 ++++----- tests/yakus/riichi.test.cc | 38 +++++----- tests/yakus/robbingkan.test.cc | 20 +++--- tests/yakus/sevenpairs.test.cc | 30 ++++---- tests/yakus/terminalinsets.test.cc | 38 +++++----- tests/yakus/triplekan.test.cc | 58 +++++++-------- tests/yakus/triplepon.test.cc | 18 ++--- tests/yakus/twicepuredoublechi.test.cc | 32 ++++----- tests/yakus/underthesea.test.cc | 26 +++---- tests/yakus/windpons.test.cc | 72 +++++++++---------- tools/driver/main.cc | 4 +- 160 files changed, 1138 insertions(+), 1181 deletions(-) diff --git a/src/analysis/analysis.cc b/src/analysis/analysis.cc index df9630c5..ce03aa56 100644 --- a/src/analysis/analysis.cc +++ b/src/analysis/analysis.cc @@ -22,10 +22,11 @@ void countPieces(Breakdown* b) { } } // namespace -std::vector AnalyzeHand(const Hand& hand, const bool only_complete) { +std::vector AnalyzeHand(const Player& player, + const bool only_complete) { Branch base_branch; - base_branch.open = !hand.melds.empty(); - for (const auto& meld : hand.melds_range()) { + base_branch.open = !player.melds.empty(); + for (const auto& meld : player.melds_range()) { switch (meld.type) { case SetType::kChi: base_branch.chis.emplace_back(meld.start); @@ -42,7 +43,7 @@ std::vector AnalyzeHand(const Hand& hand, const bool only_complete) { } } std::vector branches; - const std::unique_ptr root = breakdownHand(hand.live_range()); + const std::unique_ptr root = breakdownPlayer(player.live_range()); for (const auto& branch_vec : Node::AsBranchVectors(root.get())) { branches.push_back(base_branch); Branch& branch = branches.back(); @@ -74,7 +75,7 @@ std::vector AnalyzeHand(const Hand& hand, const bool only_complete) { return branches; } -std::unique_ptr breakdownHand(const std::span& pieces) { +std::unique_ptr breakdownPlayer(const std::span& pieces) { Breakdown b; b.rootNode = std::make_unique(/*id=*/b.id++); b.currentNode = b.rootNode.get(); diff --git a/src/analysis/analysis.h b/src/analysis/analysis.h index b0eea3e2..bddff06a 100644 --- a/src/analysis/analysis.h +++ b/src/analysis/analysis.h @@ -17,6 +17,7 @@ struct Branch { bool complete = true; }; -std::unique_ptr breakdownHand(const std::span& pieces); -std::vector AnalyzeHand(const Hand& hand, bool only_complete = false); +std::unique_ptr breakdownPlayer(const std::span& pieces); +std::vector AnalyzeHand(const Player& player, + bool only_complete = false); } // namespace mahjong diff --git a/src/analysis/util.cc b/src/analysis/util.cc index 0d38eca2..37c2da01 100644 --- a/src/analysis/util.cc +++ b/src/analysis/util.cc @@ -52,7 +52,7 @@ std::vector completeSet(const Piece a, const Piece b) { return waits; } -std::vector getWaits(const Hand& hand) { +std::vector getWaits(const Player& hand) { // 13, 10, 7, 4, 1 are possible piece counts for non-melded tiles if (hand.live_count == 0 || hand.live_count % 3 != 1) { return {}; @@ -73,8 +73,8 @@ std::vector getWaits(const Hand& hand) { return waits; } -std::vector getWaits(const Hand& hand, const Piece& piece) { - Hand new_hand = hand; +std::vector getWaits(const Player& hand, const Piece& piece) { + Player new_hand = hand; // This will move all pieces matching piece to the end of the array, but // we will only decrease the count by 1 so only a single piece will be // removed. @@ -83,7 +83,7 @@ std::vector getWaits(const Hand& hand, const Piece& piece) { return getWaits(new_hand); } -std::map> getPossibleWaits(const Hand& hand) { +std::map> getPossibleWaits(const Player& hand) { // 14, 11, 8, 5, 2 are the possible piece counts for non-melded tiles. if (hand.live_count == 0 || hand.live_count % 3 != 2) { return {}; diff --git a/src/analysis/util.h b/src/analysis/util.h index 257f2e6f..99fb613b 100644 --- a/src/analysis/util.h +++ b/src/analysis/util.h @@ -13,16 +13,16 @@ std::vector completeSet(Piece a, Piece b); // Returns list of waits that complete the hand. // Use with 13 piece hands. -std::vector getWaits(const Hand& hand); +std::vector getWaits(const Player& hand); // Returns list of waits that complete the hand with piece removed. // Use with 14 piece hands. -std::vector getWaits(const Hand& hand, const Piece& piece); +std::vector getWaits(const Player& hand, const Piece& piece); // Returns a map of waits for the discard of a given piece that complete the // hand. // Use with 14 piece hands. -std::map> getPossibleWaits(const Hand& hand); +std::map> getPossibleWaits(const Player& hand); using SetCheckFunc = std::function; // Calls func on each set in branch, returns true if and only if func returns diff --git a/src/api/gamestate.cc b/src/api/gamestate.cc index 6aaf539c..5f5bc5f3 100644 --- a/src/api/gamestate.cc +++ b/src/api/gamestate.cc @@ -25,8 +25,8 @@ CStateFunctionType ConvertStateFunctionType(mahjong::StateFunctionType func) { return kRoundStart; case mahjong::StateFunctionType::kDraw: return kDraw; - case mahjong::StateFunctionType::kPlayerHand: - return kPlayerHand; + case mahjong::StateFunctionType::kPlayerPlayer: + return kPlayerPlayer; case mahjong::StateFunctionType::kPon: return kPon; case mahjong::StateFunctionType::kChi: @@ -140,24 +140,24 @@ CObservedGameState ObserveGameState(mahjong::GameState* state) { // Player data for (int i = 0; i < 4; i++) { - observed.scores[i] = state->scores[i]; - observed.points[i] = state->points[i]; - observed.hasRonned[i] = state->hasRonned[i]; + observed.scores[i] = state->players[i].score; + observed.points[i] = state->players[i].points; + observed.hasRonned[i] = state->players[i].hasRonned; - // Convert Hand to CHand - const auto& cpp_hand = state->hands[i]; - CHand& c_hand = observed.hands[i]; + // Convert Player to CPlayer + const auto& cpp_hand = state->players[i]; + CPlayer& c_hand = observed.hands[i]; // Live pieces const int live_piece_count = static_cast(cpp_hand.live_count); - c_hand.livePieceCount = std::min(live_piece_count, kMaxLiveHandSize); + c_hand.livePieceCount = std::min(live_piece_count, kMaxLivePlayerSize); for (int j = 0; j < c_hand.livePieceCount; j++) { c_hand.livePieces[j] = static_cast(cpp_hand.live[j].toUint8_t()); } // Melds const int meld_count = cpp_hand.meld_count; - c_hand.meldCount = std::min(meld_count, kMaxMeldsPerHand); + c_hand.meldCount = std::min(meld_count, kMaxMeldsPerPlayer); for (int j = 0; j < c_hand.meldCount; j++) { c_hand.melds[j].type = static_cast(cpp_hand.melds[j].type); c_hand.melds[j].start = @@ -171,7 +171,7 @@ CObservedGameState ObserveGameState(mahjong::GameState* state) { c_hand.discards[j] = static_cast(discards[j].toUint8_t()); } - // Hand properties + // Player properties c_hand.open = cpp_hand.open; c_hand.riichi = cpp_hand.riichi; c_hand.riichiPieceDiscard = static_cast(cpp_hand.riichiPieceDiscard); diff --git a/src/api/types.h b/src/api/types.h index 2683306f..6d171454 100644 --- a/src/api/types.h +++ b/src/api/types.h @@ -6,8 +6,8 @@ namespace api { extern "C" { -static const int kMaxLiveHandSize = 14; // Maximum 14 pieces (13 + 1 drawn) -static const int kMaxMeldsPerHand = 4; // Maximum 4 melds possible +static const int kMaxLivePlayerSize = 14; // Maximum 14 pieces (13 + 1 drawn) +static const int kMaxMeldsPerPlayer = 4; // Maximum 4 melds possible static const int kMaxDiscardsPerPlayer = 27; // Flow interruption from calls can allow the max discards to go up // to 27. @@ -41,7 +41,7 @@ enum CStateFunctionType { kGameStart = 1, kRoundStart = 2, kDraw = 3, - kPlayerHand = 4, + kPlayerPlayer = 4, kPon = 5, kChi = 6, kKan = 7, @@ -63,10 +63,10 @@ struct CMeld { CPiece start; }; -struct CHand { - CPiece livePieces[kMaxLiveHandSize]; // Live pieces +struct CPlayer { + CPiece livePieces[kMaxLivePlayerSize]; // Live pieces int livePieceCount; // Number of live pieces - CMeld melds[kMaxMeldsPerHand]; // Melds + CMeld melds[kMaxMeldsPerPlayer]; // Melds int meldCount; // Number of melds CPiece discards[kMaxDiscardsPerPlayer]; // Discards int discardCount; // Number of discards @@ -91,7 +91,7 @@ struct CObservedGameState { int scores[4]; // Temporary round score changes int points[4]; // Player points bool hasRonned[4]; // Which players have declared ron this turn - CHand hands[4]; // Player hands with live pieces, melds, and discards + CPlayer hands[4]; // Player hands with live pieces, melds, and discards CStateFunctionType prevState; // Previous state function CStateFunctionType currState; // Current state function CStateFunctionType nextState; // Next state function diff --git a/src/controllers/gentlemanbot.cc b/src/controllers/gentlemanbot.cc index 1d2bb2d7..37aab896 100644 --- a/src/controllers/gentlemanbot.cc +++ b/src/controllers/gentlemanbot.cc @@ -71,7 +71,7 @@ Piece GentlemanBot::getDiscard() { std::vector third_tier_discards; std::array counts = {}; - const std::unique_ptr symbolic_hand = breakdownHand(hand_); + const std::unique_ptr symbolic_hand = breakdownPlayer(hand_); for (const auto& leaf : *symbolic_hand) { if (leaf.type() == SetType::kSingle) { diff --git a/src/controllers/playercontroller.h b/src/controllers/playercontroller.h index c287b7f9..8b9f9ed9 100644 --- a/src/controllers/playercontroller.h +++ b/src/controllers/playercontroller.h @@ -1,5 +1,4 @@ #pragma once -#include #include #include diff --git a/src/controllers/thricebot.cc b/src/controllers/thricebot.cc index c957a11a..50365127 100644 --- a/src/controllers/thricebot.cc +++ b/src/controllers/thricebot.cc @@ -20,7 +20,7 @@ REGISTER_PLAYER_CONTROLLER(ThriceBot); void ThriceBot::RoundStart(std::vector _hand, Wind s, Wind p) { for (const Piece m : _hand) { - HandTile h; + PlayerTile h; h.piece = m; if (m.isHonor()) { h.weight = kHonorWeight; @@ -54,8 +54,8 @@ void ThriceBot::assignweights() { } } -ThriceBot::HandTile ThriceBot::assignTileWeight(HandTile h1) { - HandTile h; +ThriceBot::PlayerTile ThriceBot::assignTileWeight(PlayerTile h1) { + PlayerTile h; h.piece = h1.piece; h.weight = h1.weight; for (auto& i : hand_) { @@ -89,7 +89,7 @@ void ThriceBot::ReceiveEvent(Event e) { } if (e.type == Event::kDiscard && e.player == pid_) { - HandTile h; + PlayerTile h; h.piece = Piece(e.piece); if (h.piece.isHonor()) { h.weight = kHonorWeight; diff --git a/src/controllers/thricebot.h b/src/controllers/thricebot.h index 274fa271..e309896b 100644 --- a/src/controllers/thricebot.h +++ b/src/controllers/thricebot.h @@ -14,7 +14,7 @@ namespace mahjong { class ThriceBot : public PlayerController { public: - struct HandTile { + struct PlayerTile { Piece piece; float weight{}; }; @@ -34,11 +34,11 @@ class ThriceBot : public PlayerController { private: void assignweights(); Piece popDiscard(); - HandTile assignTileWeight(HandTile h1); + PlayerTile assignTileWeight(PlayerTile h1); void checkDiscard(); bool checkTile(Piece p); - std::vector hand_; + std::vector hand_; std::array discarded_ = {}; Event lastEvent_; Wind swind_; diff --git a/src/scoring/scoring.cc b/src/scoring/scoring.cc index b6b0cb5e..3ec34664 100644 --- a/src/scoring/scoring.cc +++ b/src/scoring/scoring.cc @@ -58,9 +58,8 @@ const int kFuRounding = 10; } // namespace -Score scoreHand(const GameState& state, int player) { - const Hand& hand = state.hands[player]; - auto root = breakdownHand(hand.live_range()); +Score scorePlayer(const GameState& state, const Player& player) { + auto root = breakdownPlayer(player.live_range()); Score s; s.han = 0; s.yakuman = 0; @@ -77,7 +76,7 @@ Score scoreHand(const GameState& state, int player) { } for (const auto& yaku : Yakus::Instance().GetYakus()) { - if (yaku.type == Yaku::kClosed && hand.open) { + if (yaku.type == Yaku::kClosed && player.open) { continue; } if (!yaku.is_yaku_func(state, player, branch)) { @@ -89,7 +88,7 @@ Score scoreHand(const GameState& state, int player) { branchscore.han += yaku.value; break; case Yaku::kBonusWhenClosed: - branchscore.han += yaku.value + (hand.open ? 0 : 1); + branchscore.han += yaku.value + (player.open ? 0 : 1); break; case Yaku::kYakuman: branchscore.yakuman++; @@ -98,12 +97,12 @@ Score scoreHand(const GameState& state, int player) { } for (const auto& dora : Walls::GetDoras(state)) { - for (const auto& p : hand.live_range()) { + for (const auto& p : player.live_range()) { if (p == dora) { branchscore.han++; } } - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.start == dora) { branchscore.han++; } @@ -156,31 +155,30 @@ int getBasicPoints(Score s) { const int kSevenpairs = 25; -int getFu(const GameState& state, int player, +int getFu(const GameState& state, const Player& player, const std::vector& branch) { if (yaku::isSevenPairs(state, player, branch)) { return kSevenpairs; } if (yaku::isPinfu(state, player, branch)) { - if (state.hasRonned.at(player)) { + if (player.hasRonned) { return kPinfuDiscard; } return kPinfuSelfdraw; } int fu = 0; - if (!state.hands.at(player).open && state.hasRonned.at(player)) { + if (!player.open && player.hasRonned) { fu = kConcealedDiscard; } else { fu = kOpenOrSelfdraw; } - const bool open = state.hands.at(player).open; + const bool open = player.open; if (isOpenPinfu(state, player, branch)) { fu += kOpenpinfu; - } else if (!state.hasRonned.at(player)) { + } else if (!player.hasRonned) { fu += kSelfdraw; } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type == SetType::kKan) { if (!meld.start.isHonor() && !meld.start.isTerminal()) { fu += open ? kSimplekan : kCsimplekan; @@ -234,7 +232,7 @@ int getFu(const GameState& state, int player, (kFuRounding - (fu % kFuRounding)); // rounding up to multiple of ten } -bool isOpenPinfu(const GameState& state, int player, +bool isOpenPinfu(const GameState& state, const Player& player, const std::vector& branch) { for (const auto* node : branch) { if (node->type() == SetType::kPon) { @@ -253,18 +251,16 @@ bool isOpenPinfu(const GameState& state, int player, } } } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type > SetType::kChi) { return false; } } - return getWaits(state.hands[player], state.pendingPiece).size() >= 2; + return getWaits(player, state.pendingPiece).size() >= 2; } -bool isComplete(const GameState& state, int player) { - const Hand& hand = state.hands[player]; - auto root = breakdownHand(hand.live_range()); +bool isComplete(const GameState& state, const Player& player) { + auto root = breakdownPlayer(player.live_range()); if (!root->IsComplete() && !yaku::isThirteenOrphans(state, player)) { return false; } diff --git a/src/scoring/scoring.h b/src/scoring/scoring.h index 5cbb3b68..bc5293ce 100644 --- a/src/scoring/scoring.h +++ b/src/scoring/scoring.h @@ -6,15 +6,15 @@ #include "types/score.h" namespace mahjong { -Score scoreHand(const GameState& state, int player); +Score scorePlayer(const GameState& state, const Player& player); int getBasicPoints(Score s); -int getFu(const GameState& state, int player, +int getFu(const GameState& state, const Player& player, const std::vector& branch); -bool isOpenPinfu(const GameState& state, int player, +bool isOpenPinfu(const GameState& state, const Player& player, const std::vector& branch); -bool isComplete(const GameState& state, int player); +bool isComplete(const GameState& state, const Player& player); } // namespace mahjong diff --git a/src/scoring/yakus/afterakan.cc b/src/scoring/yakus/afterakan.cc index fdd0f218..2ac096c1 100644 --- a/src/scoring/yakus/afterakan.cc +++ b/src/scoring/yakus/afterakan.cc @@ -9,9 +9,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAfterAKan(const GameState& state, int player, +bool isAfterAKan(const GameState& state, const Player& player, const std::vector& /*branch*/) { - if (state.currentPlayer != player) { + if (state.currentPlayer != player.id) { return false; } if (state.prevState == StateFunctionType::kReplacement) { diff --git a/src/scoring/yakus/afterakan.h b/src/scoring/yakus/afterakan.h index 2df33c1a..53999a5a 100644 --- a/src/scoring/yakus/afterakan.h +++ b/src/scoring/yakus/afterakan.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isAfterAKan(const GameState& state, int player, +bool isAfterAKan(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allgreen.cc b/src/scoring/yakus/allgreen.cc index 20e1e611..49a293b1 100644 --- a/src/scoring/yakus/allgreen.cc +++ b/src/scoring/yakus/allgreen.cc @@ -8,16 +8,15 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllGreen(const GameState& state, int player, +bool isAllGreen(const GameState& /*state*/, const Player& player, const std::vector& /*branch*/) { - const Hand& hand = state.hands[player]; - for (const auto& piece : hand.live_range()) { + for (const auto& piece : player.live_range()) { if (!piece.isGreen()) { return false; } } - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (!meld.start.isGreen()) { return false; } diff --git a/src/scoring/yakus/allgreen.h b/src/scoring/yakus/allgreen.h index e1136307..b0ec6b44 100644 --- a/src/scoring/yakus/allgreen.h +++ b/src/scoring/yakus/allgreen.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isAllGreen(const GameState& state, int player, +bool isAllGreen(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allhonors.cc b/src/scoring/yakus/allhonors.cc index 4d78b652..96a7ba6f 100644 --- a/src/scoring/yakus/allhonors.cc +++ b/src/scoring/yakus/allhonors.cc @@ -8,15 +8,14 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllHonors(const GameState& state, int player, +bool isAllHonors(const GameState& /*state*/, const Player& player, const std::vector& /*branch*/) { - const Hand& hand = state.hands[player]; - for (const auto& piece : hand.live_range()) { + for (const auto& piece : player.live_range()) { if (!piece.isHonor()) { return false; } } - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (!meld.start.isHonor()) { return false; } diff --git a/src/scoring/yakus/allhonors.h b/src/scoring/yakus/allhonors.h index b894731c..842510bd 100644 --- a/src/scoring/yakus/allhonors.h +++ b/src/scoring/yakus/allhonors.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isAllHonors(const GameState& state, int player, +bool isAllHonors(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allpons.cc b/src/scoring/yakus/allpons.cc index 424280fc..21228029 100644 --- a/src/scoring/yakus/allpons.cc +++ b/src/scoring/yakus/allpons.cc @@ -9,7 +9,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllPons(const GameState& state, int player, +bool isAllPons(const GameState& /* state */, const Player& player, const std::vector& branch) { int pons = 0; for (const auto* node : branch) { @@ -17,8 +17,7 @@ bool isAllPons(const GameState& state, int player, pons++; } } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type == SetType::kKan || meld.type == SetType::kPon || meld.type == SetType::kConcealedKan) { pons++; diff --git a/src/scoring/yakus/allpons.h b/src/scoring/yakus/allpons.h index fb245568..2ddeb0d4 100644 --- a/src/scoring/yakus/allpons.h +++ b/src/scoring/yakus/allpons.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isAllPons(const GameState& state, int player, +bool isAllPons(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/allsimples.cc b/src/scoring/yakus/allsimples.cc index 71fb6f8b..bdc0dbd7 100644 --- a/src/scoring/yakus/allsimples.cc +++ b/src/scoring/yakus/allsimples.cc @@ -8,15 +8,14 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllSimples(const GameState& state, int player, +bool isAllSimples(const GameState& /* state */, const Player& player, const std::vector& /*branch*/) { - const Hand& hand = state.hands[player]; - for (const auto& piece : hand.live_range()) { + for (const auto& piece : player.live_range()) { if (piece.isHonor() || piece.isTerminal()) { return false; } } - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.start.isHonor() || meld.start.isTerminal()) { return false; } diff --git a/src/scoring/yakus/allsimples.h b/src/scoring/yakus/allsimples.h index ef1d27cc..41bac6c9 100644 --- a/src/scoring/yakus/allsimples.h +++ b/src/scoring/yakus/allsimples.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isAllSimples(const GameState& state, int player, +bool isAllSimples(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allterminals.cc b/src/scoring/yakus/allterminals.cc index f280ced3..27239aca 100644 --- a/src/scoring/yakus/allterminals.cc +++ b/src/scoring/yakus/allterminals.cc @@ -8,15 +8,14 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllTerminals(const GameState& state, int player, +bool isAllTerminals(const GameState& /*state*/, const Player& player, const std::vector& /*branch*/) { - const Hand& hand = state.hands[player]; - for (const auto& piece : hand.live_range()) { + for (const auto& piece : player.live_range()) { if (!piece.isTerminal()) { return false; } } - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (!meld.start.isTerminal()) { return false; } diff --git a/src/scoring/yakus/allterminals.h b/src/scoring/yakus/allterminals.h index b99e84a7..ffa10603 100644 --- a/src/scoring/yakus/allterminals.h +++ b/src/scoring/yakus/allterminals.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isAllTerminals(const GameState& state, int player, +bool isAllTerminals(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allterminalsandhonors.cc b/src/scoring/yakus/allterminalsandhonors.cc index 39649462..1bdf3fab 100644 --- a/src/scoring/yakus/allterminalsandhonors.cc +++ b/src/scoring/yakus/allterminalsandhonors.cc @@ -9,15 +9,14 @@ namespace mahjong::yaku { bool isAllTerminalsAndHonors( - const GameState& state, int player, + const GameState& /*state*/, const Player& player, const std::vector& /*branch*/) { - const Hand& hand = state.hands[player]; - for (const auto& piece : hand.live_range()) { + for (const auto& piece : player.live_range()) { if (!piece.isHonor() && !piece.isTerminal()) { return false; } } - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (!meld.start.isHonor() && !meld.start.isTerminal()) { return false; } diff --git a/src/scoring/yakus/allterminalsandhonors.h b/src/scoring/yakus/allterminalsandhonors.h index 230ee418..341d1d34 100644 --- a/src/scoring/yakus/allterminalsandhonors.h +++ b/src/scoring/yakus/allterminalsandhonors.h @@ -6,7 +6,7 @@ namespace mahjong::yaku { bool isAllTerminalsAndHonors( - const GameState& state, int player, + const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/bigfourwinds.cc b/src/scoring/yakus/bigfourwinds.cc index 7a468a5b..e04254c0 100644 --- a/src/scoring/yakus/bigfourwinds.cc +++ b/src/scoring/yakus/bigfourwinds.cc @@ -9,7 +9,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBigFourWinds(const GameState& state, int player, +bool isBigFourWinds(const GameState& /*state*/, const Player& player, const std::vector& branch) { int pons = 0; for (const auto* node : branch) { @@ -27,8 +27,7 @@ bool isBigFourWinds(const GameState& state, int player, } pons++; } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { switch (meld.start.toUint8_t()) { case Piece::Type::kEastWind: case Piece::Type::kSouthWind: diff --git a/src/scoring/yakus/bigfourwinds.h b/src/scoring/yakus/bigfourwinds.h index 67a01a20..8a91b9c4 100644 --- a/src/scoring/yakus/bigfourwinds.h +++ b/src/scoring/yakus/bigfourwinds.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isBigFourWinds(const GameState& state, int player, +bool isBigFourWinds(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/bigthreedragons.cc b/src/scoring/yakus/bigthreedragons.cc index b89dd694..e9a8c9a1 100644 --- a/src/scoring/yakus/bigthreedragons.cc +++ b/src/scoring/yakus/bigthreedragons.cc @@ -9,7 +9,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBigThreeDragons(const GameState& state, int player, +bool isBigThreeDragons(const GameState& /*state*/, const Player& player, const std::vector& branch) { int pons = 0; for (const auto* node : branch) { @@ -26,8 +26,7 @@ bool isBigThreeDragons(const GameState& state, int player, } pons++; } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { switch (meld.start.toUint8_t()) { case Piece::Type::kRedDragon: case Piece::Type::kGreenDragon: diff --git a/src/scoring/yakus/bigthreedragons.h b/src/scoring/yakus/bigthreedragons.h index 8198d106..96997f08 100644 --- a/src/scoring/yakus/bigthreedragons.h +++ b/src/scoring/yakus/bigthreedragons.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isBigThreeDragons(const GameState& state, int player, +bool isBigThreeDragons(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/blessingofearth.cc b/src/scoring/yakus/blessingofearth.cc index 11997813..9b418dfe 100644 --- a/src/scoring/yakus/blessingofearth.cc +++ b/src/scoring/yakus/blessingofearth.cc @@ -8,9 +8,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBlessingOfEarth(const GameState& state, int player, +bool isBlessingOfEarth(const GameState& state, const Player& player, const std::vector& /*branch*/) { - if (state.hands.at(player).open) { + if (player.open) { return false; } if (state.turnNum > 3) { @@ -19,7 +19,7 @@ bool isBlessingOfEarth(const GameState& state, int player, if (state.lastCall >= 0) { return false; } - if (state.hasRonned.at(player)) { + if (player.hasRonned) { return false; } return true; diff --git a/src/scoring/yakus/blessingofearth.h b/src/scoring/yakus/blessingofearth.h index a4956c3f..86d8e742 100644 --- a/src/scoring/yakus/blessingofearth.h +++ b/src/scoring/yakus/blessingofearth.h @@ -6,7 +6,7 @@ namespace mahjong::yaku { bool isBlessingOfEarth( - const GameState& state, int player, + const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/blessingofheaven.cc b/src/scoring/yakus/blessingofheaven.cc index 47fb97f5..5d63886c 100644 --- a/src/scoring/yakus/blessingofheaven.cc +++ b/src/scoring/yakus/blessingofheaven.cc @@ -8,15 +8,15 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBlessingOfHeaven(const GameState& state, int player, +bool isBlessingOfHeaven(const GameState& state, const Player& player, const std::vector& /*branch*/) { - if (state.hands.at(player).open) { + if (player.open) { return false; } - if (player != 0) { + if (player.id != 0) { return false; } - if (state.hasRonned[0]) { + if (state.players[0].hasRonned) { return false; } if (state.turnNum != 0) { diff --git a/src/scoring/yakus/blessingofheaven.h b/src/scoring/yakus/blessingofheaven.h index b9454c47..4bc91f2e 100644 --- a/src/scoring/yakus/blessingofheaven.h +++ b/src/scoring/yakus/blessingofheaven.h @@ -6,7 +6,7 @@ namespace mahjong::yaku { bool isBlessingOfHeaven( - const GameState& state, int player, + const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/blessingofman.cc b/src/scoring/yakus/blessingofman.cc index 2a532c99..091d4749 100644 --- a/src/scoring/yakus/blessingofman.cc +++ b/src/scoring/yakus/blessingofman.cc @@ -8,18 +8,18 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBlessingOfMan(const GameState& state, int player, +bool isBlessingOfMan(const GameState& state, const Player& player, const std::vector& /*branch*/) { - if (state.hands.at(player).open) { + if (player.open) { return false; } - if (state.turnNum > player) { + if (state.turnNum > player.id) { return false; } if (state.lastCall >= 0) { return false; } - if (state.hasRonned.at(player)) { + if (player.hasRonned) { return true; } return false; diff --git a/src/scoring/yakus/blessingofman.h b/src/scoring/yakus/blessingofman.h index 7f0912f0..1dcf576c 100644 --- a/src/scoring/yakus/blessingofman.h +++ b/src/scoring/yakus/blessingofman.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isBlessingOfMan(const GameState& state, int player, +bool isBlessingOfMan(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/bottomofthesea.cc b/src/scoring/yakus/bottomofthesea.cc index e24f164d..fbfeb962 100644 --- a/src/scoring/yakus/bottomofthesea.cc +++ b/src/scoring/yakus/bottomofthesea.cc @@ -9,7 +9,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBottomOfTheSea(const GameState& state, int /*player*/, +bool isBottomOfTheSea(const GameState& state, const Player& /*player*/, const std::vector& /*branch*/) { return Walls::GetRemainingPieces(state) == 0; } diff --git a/src/scoring/yakus/bottomofthesea.h b/src/scoring/yakus/bottomofthesea.h index 756c4637..aa669f02 100644 --- a/src/scoring/yakus/bottomofthesea.h +++ b/src/scoring/yakus/bottomofthesea.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isBottomOfTheSea(const GameState& state, int player, +bool isBottomOfTheSea(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/doubleriichi.cc b/src/scoring/yakus/doubleriichi.cc index a31dbf02..964e306c 100644 --- a/src/scoring/yakus/doubleriichi.cc +++ b/src/scoring/yakus/doubleriichi.cc @@ -8,9 +8,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isDoubleRiichi(const GameState& state, int player, +bool isDoubleRiichi(const GameState& state, const Player& player, const std::vector& /*branch*/) { - return state.hands.at(player).riichi && !state.hands.at(player).open && + return player.riichi && !player.open && (state.turnNum < 4 && state.lastCall < 0); } diff --git a/src/scoring/yakus/doubleriichi.h b/src/scoring/yakus/doubleriichi.h index 768c3ee3..5250cc64 100644 --- a/src/scoring/yakus/doubleriichi.h +++ b/src/scoring/yakus/doubleriichi.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isDoubleRiichi(const GameState& state, int player, +bool isDoubleRiichi(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/fourconcealedpon.cc b/src/scoring/yakus/fourconcealedpon.cc index c117a5ac..a2e786c6 100644 --- a/src/scoring/yakus/fourconcealedpon.cc +++ b/src/scoring/yakus/fourconcealedpon.cc @@ -9,9 +9,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isFourConcealedPon(const GameState& state, int player, +bool isFourConcealedPon(const GameState& /*state*/, const Player& player, const std::vector& branch) { - if (state.hands.at(player).open) { + if (player.open) { return false; } int concealed_pons = 0; @@ -20,8 +20,7 @@ bool isFourConcealedPon(const GameState& state, int player, concealed_pons++; } } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type == SetType::kConcealedKan) { concealed_pons++; } diff --git a/src/scoring/yakus/fourconcealedpon.h b/src/scoring/yakus/fourconcealedpon.h index d32f1456..70af5bb9 100644 --- a/src/scoring/yakus/fourconcealedpon.h +++ b/src/scoring/yakus/fourconcealedpon.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isFourConcealedPon(const GameState& state, int player, +bool isFourConcealedPon(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/fourkans.cc b/src/scoring/yakus/fourkans.cc index f4b99202..5f3fe30c 100644 --- a/src/scoring/yakus/fourkans.cc +++ b/src/scoring/yakus/fourkans.cc @@ -9,11 +9,10 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isFourKans(const GameState& state, int player, +bool isFourKans(const GameState& /*state*/, const Player& player, const std::vector& /*branch*/) { int kans = 0; - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type >= SetType::kKan) { kans++; } diff --git a/src/scoring/yakus/fourkans.h b/src/scoring/yakus/fourkans.h index 0af7ca72..41a231a3 100644 --- a/src/scoring/yakus/fourkans.h +++ b/src/scoring/yakus/fourkans.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isFourKans(const GameState& state, int player, +bool isFourKans(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/fullflush.cc b/src/scoring/yakus/fullflush.cc index 3c1e2a2d..3b3e8f99 100644 --- a/src/scoring/yakus/fullflush.cc +++ b/src/scoring/yakus/fullflush.cc @@ -8,19 +8,18 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isFullFlush(const GameState& state, int player, +bool isFullFlush(const GameState& /*state*/, const Player& player, const std::vector& /*branch*/) { - const Hand& hand = state.hands[player]; - if (hand.live[0].isHonor()) { + if (player.live[0].isHonor()) { return false; } - const int suit = hand.live[0].getSuit(); - for (const auto& piece : hand.live_range()) { + const int suit = player.live[0].getSuit(); + for (const auto& piece : player.live_range()) { if (piece.getSuit() != suit) { return false; } } - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.start.getSuit() != suit) { return false; } diff --git a/src/scoring/yakus/fullflush.h b/src/scoring/yakus/fullflush.h index e1d726f9..662fd357 100644 --- a/src/scoring/yakus/fullflush.h +++ b/src/scoring/yakus/fullflush.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isFullFlush(const GameState& state, int player, +bool isFullFlush(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/fullyconcealedhand.cc b/src/scoring/yakus/fullyconcealedhand.cc index dcc2c2d4..83f1965a 100644 --- a/src/scoring/yakus/fullyconcealedhand.cc +++ b/src/scoring/yakus/fullyconcealedhand.cc @@ -9,15 +9,16 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isFullyConcealedHand(const GameState& state, int player, - const std::vector& /*branch*/) { - return state.currentPlayer == player && !state.hands.at(player).open && +bool isFullyConcealedHand( + const GameState& state, const Player& player, + const std::vector& /*branch*/) { + return state.currentPlayer == player.id && !player.open && Walls::GetRemainingPieces(state) > 0; } REGISTER_YAKU({ .id = "fullyconcealedhand", - .name = "Fully Concealed Hand", + .name = "Fully Concealed Player", .type = Yaku::kClosed, .value = 1, .is_yaku_func = yaku::isFullyConcealedHand, diff --git a/src/scoring/yakus/fullyconcealedhand.h b/src/scoring/yakus/fullyconcealedhand.h index 73801979..8c747e36 100644 --- a/src/scoring/yakus/fullyconcealedhand.h +++ b/src/scoring/yakus/fullyconcealedhand.h @@ -6,7 +6,7 @@ namespace mahjong::yaku { bool isFullyConcealedHand( - const GameState& state, int player, + const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/halfflush.cc b/src/scoring/yakus/halfflush.cc index 4684147d..d87c972f 100644 --- a/src/scoring/yakus/halfflush.cc +++ b/src/scoring/yakus/halfflush.cc @@ -9,12 +9,11 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isHalfFlush(const GameState& state, int player, +bool isHalfFlush(const GameState& state, const Player& player, const std::vector& /*branch*/) { - const Hand& hand = state.hands[player]; - const int suit = hand.live[0].getSuit(); + const int suit = player.live[0].getSuit(); bool honors = false; - for (const auto& piece : hand.live_range()) { + for (const auto& piece : player.live_range()) { if (piece.isHonor()) { honors = true; continue; @@ -23,7 +22,7 @@ bool isHalfFlush(const GameState& state, int player, return false; } } - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.start.isHonor()) { honors = true; continue; diff --git a/src/scoring/yakus/halfflush.h b/src/scoring/yakus/halfflush.h index 3395c32d..23e2b23b 100644 --- a/src/scoring/yakus/halfflush.h +++ b/src/scoring/yakus/halfflush.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isHalfFlush(const GameState& state, int player, +bool isHalfFlush(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/honorpon.cc b/src/scoring/yakus/honorpon.cc index 0bc82d33..04124d53 100644 --- a/src/scoring/yakus/honorpon.cc +++ b/src/scoring/yakus/honorpon.cc @@ -14,7 +14,7 @@ namespace mahjong::yaku { namespace { -bool findPon(const GameState& state, int player, +bool findPon(const GameState& /* state */, const Player& player, const std::vector& branch, const Piece& piece) { for (const auto* node : branch) { @@ -22,8 +22,7 @@ bool findPon(const GameState& state, int player, return true; } } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type >= SetType::kPon && meld.start == piece) { return true; } @@ -33,29 +32,29 @@ bool findPon(const GameState& state, int player, } // namespace -bool isSeatWind(const GameState& state, int player, +bool isSeatWind(const GameState& state, const Player& player, const std::vector& branch) { return findPon(state, player, branch, - Piece::fromWind(GetSeat(state.roundNum, player))); + Piece::fromWind(GetSeat(state.roundNum, player.id))); } -bool isPrevalentWind(const GameState& state, int player, +bool isPrevalentWind(const GameState& state, const Player& player, const std::vector& branch) { return findPon(state, player, branch, Piece::fromWind(state.roundNum > 3 ? kSouth : kEast)); } -bool isGreenDragon(const GameState& state, int player, +bool isGreenDragon(const GameState& state, const Player& player, const std::vector& branch) { return findPon(state, player, branch, kGreenDragon); } -bool isRedDragon(const GameState& state, int player, +bool isRedDragon(const GameState& state, const Player& player, const std::vector& branch) { return findPon(state, player, branch, kRedDragon); } -bool isWhiteDragon(const GameState& state, int player, +bool isWhiteDragon(const GameState& state, const Player& player, const std::vector& branch) { return findPon(state, player, branch, kWhiteDragon); } diff --git a/src/scoring/yakus/honorpon.h b/src/scoring/yakus/honorpon.h index 49b0871b..9ad6509b 100644 --- a/src/scoring/yakus/honorpon.h +++ b/src/scoring/yakus/honorpon.h @@ -5,18 +5,18 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isSeatWind(const GameState& state, int player, +bool isSeatWind(const GameState& state, const Player& player, const std::vector& branch); -bool isPrevalentWind(const GameState& state, int player, +bool isPrevalentWind(const GameState& state, const Player& player, const std::vector& branch); -bool isGreenDragon(const GameState& state, int player, +bool isGreenDragon(const GameState& state, const Player& player, const std::vector& branch); -bool isRedDragon(const GameState& state, int player, +bool isRedDragon(const GameState& state, const Player& player, const std::vector& branch); -bool isWhiteDragon(const GameState& state, int player, +bool isWhiteDragon(const GameState& state, const Player& player, const std::vector& branch); } // namespace mahjong::yaku diff --git a/src/scoring/yakus/ippatsu.cc b/src/scoring/yakus/ippatsu.cc index 10eea80f..17fbba31 100644 --- a/src/scoring/yakus/ippatsu.cc +++ b/src/scoring/yakus/ippatsu.cc @@ -10,11 +10,11 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isIppatsu(const GameState& state, int player, +bool isIppatsu(const GameState& state, const Player& player, const std::vector& /*branch*/) { return (isRiichi(state, player) || isDoubleRiichi(state, player)) && - (state.turnNum - state.hands.at(player).riichiRound <= 4 && - state.lastCall < state.hands.at(player).riichiRound); + (state.turnNum - player.riichiRound <= 4 && + state.lastCall < player.riichiRound); } REGISTER_YAKU({ diff --git a/src/scoring/yakus/ippatsu.h b/src/scoring/yakus/ippatsu.h index 9d3bb36f..73c5d3ce 100644 --- a/src/scoring/yakus/ippatsu.h +++ b/src/scoring/yakus/ippatsu.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isIppatsu(const GameState& state, int player, +bool isIppatsu(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/littlefourwinds.cc b/src/scoring/yakus/littlefourwinds.cc index 12ceee4c..a5affb84 100644 --- a/src/scoring/yakus/littlefourwinds.cc +++ b/src/scoring/yakus/littlefourwinds.cc @@ -9,7 +9,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isLittleFourWinds(const GameState& state, int player, +bool isLittleFourWinds(const GameState& /*state*/, const Player& player, const std::vector& branch) { bool pair = false; int pons = 0; @@ -35,8 +35,7 @@ bool isLittleFourWinds(const GameState& state, int player, if (!pair) { return false; } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { switch (meld.start.toUint8_t()) { case Piece::Type::kEastWind: case Piece::Type::kSouthWind: diff --git a/src/scoring/yakus/littlefourwinds.h b/src/scoring/yakus/littlefourwinds.h index dcdb76be..8faa5587 100644 --- a/src/scoring/yakus/littlefourwinds.h +++ b/src/scoring/yakus/littlefourwinds.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isLittleFourWinds(const GameState& state, int player, +bool isLittleFourWinds(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/littlethreedragons.cc b/src/scoring/yakus/littlethreedragons.cc index 13d5bc22..f7fc5caf 100644 --- a/src/scoring/yakus/littlethreedragons.cc +++ b/src/scoring/yakus/littlethreedragons.cc @@ -9,7 +9,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isLittleThreeDragons(const GameState& state, int player, +bool isLittleThreeDragons(const GameState& /*state*/, const Player& player, const std::vector& branch) { bool pair = false; int pons = 0; @@ -32,8 +32,7 @@ bool isLittleThreeDragons(const GameState& state, int player, if (!pair) { return false; } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { switch (meld.start.toUint8_t()) { case Piece::Type::kRedDragon: case Piece::Type::kGreenDragon: diff --git a/src/scoring/yakus/littlethreedragons.h b/src/scoring/yakus/littlethreedragons.h index e81b2157..c7756ed4 100644 --- a/src/scoring/yakus/littlethreedragons.h +++ b/src/scoring/yakus/littlethreedragons.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isLittleThreeDragons(const GameState& state, int player, +bool isLittleThreeDragons(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/maxbranches.cc b/src/scoring/yakus/maxbranches.cc index 6f828d83..0f3a8d88 100644 --- a/src/scoring/yakus/maxbranches.cc +++ b/src/scoring/yakus/maxbranches.cc @@ -8,15 +8,14 @@ #include "types/sets.h" namespace mahjong::yaku { -bool isMaxBranches(const GameState& state, int player, +bool isMaxBranches(const GameState& /*state*/, const Player& player, const std::vector& /*branch*/) { - const Hand& hand = state.hands[player]; - const int start = hand.live[0].getPieceNum(); - const int suit = hand.live[0].getSuit(); + const int start = player.live[0].getPieceNum(); + const int suit = player.live[0].getSuit(); std::array sets = {}; const std::array final = {3, 3, 2, 2, 2, 2}; - for (const auto& piece : hand.live_range()) { + for (const auto& piece : player.live_range()) { if (piece.getSuit() != suit) { return false; } @@ -25,7 +24,7 @@ bool isMaxBranches(const GameState& state, int player, } sets.at(piece.getPieceNum() - start)++; } - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.start.getSuit() != suit) { return false; } diff --git a/src/scoring/yakus/maxbranches.h b/src/scoring/yakus/maxbranches.h index fa4ee698..4ce12c87 100644 --- a/src/scoring/yakus/maxbranches.h +++ b/src/scoring/yakus/maxbranches.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isMaxBranches(const GameState& state, int player, +bool isMaxBranches(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/mixedtriplechi.cc b/src/scoring/yakus/mixedtriplechi.cc index 6e1a5ed3..9446444d 100644 --- a/src/scoring/yakus/mixedtriplechi.cc +++ b/src/scoring/yakus/mixedtriplechi.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isMixedTripleChi(const GameState& state, int player, +bool isMixedTripleChi(const GameState& /* state */, const Player& player, const std::vector& branch) { const int k_piecesinasuit = 9; std::array bamboo_chi = {}; @@ -29,8 +29,7 @@ bool isMixedTripleChi(const GameState& state, int player, } } } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type == SetType::kChi) { if (meld.start.getSuit() == Piece::Type::kBambooSuit) { bamboo_chi.at(meld.start.getPieceNum()) = true; diff --git a/src/scoring/yakus/mixedtriplechi.h b/src/scoring/yakus/mixedtriplechi.h index 0957b7dc..08337597 100644 --- a/src/scoring/yakus/mixedtriplechi.h +++ b/src/scoring/yakus/mixedtriplechi.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isMixedTripleChi(const GameState& state, int player, +bool isMixedTripleChi(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/ninegates.cc b/src/scoring/yakus/ninegates.cc index f5eaf11a..15cf4847 100644 --- a/src/scoring/yakus/ninegates.cc +++ b/src/scoring/yakus/ninegates.cc @@ -10,16 +10,15 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isNineGates(const GameState& state, int player, +bool isNineGates(const GameState& state, const Player& player, const std::vector& branch) { - const Hand& hand = state.hands[player]; - if (hand.open) { + if (player.open) { return false; } if (!isFullFlush(state, player, branch)) { return false; } - if (hand.open) { + if (player.open) { return false; } std::map pieces; @@ -27,7 +26,7 @@ bool isNineGates(const GameState& state, int player, pieces.at(i) = 0; } bool duplicate = false; - for (const auto& piece : hand.live_range()) { + for (const auto& piece : player.live_range()) { if (pieces.contains(piece.getPieceNum())) { if ((pieces[piece.getPieceNum()] != 0) && !piece.isTerminal()) { if (duplicate) { diff --git a/src/scoring/yakus/ninegates.h b/src/scoring/yakus/ninegates.h index 385bc219..f9392395 100644 --- a/src/scoring/yakus/ninegates.h +++ b/src/scoring/yakus/ninegates.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isNineGates(const GameState& state, int player, +bool isNineGates(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/outsidehand.cc b/src/scoring/yakus/outsidehand.cc index a3f379d2..a34323c2 100644 --- a/src/scoring/yakus/outsidehand.cc +++ b/src/scoring/yakus/outsidehand.cc @@ -11,8 +11,8 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isOutsideHand(const GameState& state, int player, - const std::vector& branch) { +bool isOutsideHand(const GameState& state, const Player& player, + const std::vector& branch) { bool chi = false; for (const auto* node : branch) { if (node->type() == SetType::kChi) { @@ -27,8 +27,7 @@ bool isOutsideHand(const GameState& state, int player, } } } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type == SetType::kChi) { if (meld.start.isTerminal() || (meld.start + 2).isTerminal()) { chi = true; @@ -42,14 +41,14 @@ bool isOutsideHand(const GameState& state, int player, } } // Terminals in all Sets and All Terminals and Honors are more valuable and - // score instead of Outside Hand. + // score instead of Outside Player. return chi && !isTerminalsInAllSets(state, player, branch) && !isAllTerminalsAndHonors(state, player); } REGISTER_YAKU({ .id = "outsidehand", - .name = "Outside Hand", + .name = "Outside Player", .type = Yaku::kBonusWhenClosed, .value = 1, .is_yaku_func = yaku::isOutsideHand, diff --git a/src/scoring/yakus/outsidehand.h b/src/scoring/yakus/outsidehand.h index 07bc7531..c1bceda7 100644 --- a/src/scoring/yakus/outsidehand.h +++ b/src/scoring/yakus/outsidehand.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isOutsideHand(const GameState& state, int player, - const std::vector& branch); +bool isOutsideHand(const GameState& state, const Player& player, + const std::vector& branch); } diff --git a/src/scoring/yakus/pinfu.cc b/src/scoring/yakus/pinfu.cc index c9d05fc2..4d72ec1d 100644 --- a/src/scoring/yakus/pinfu.cc +++ b/src/scoring/yakus/pinfu.cc @@ -12,10 +12,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isPinfu(const GameState& state, int player, +bool isPinfu(const GameState& state, const Player& player, const std::vector& branch) { - const Hand& hand = state.hands.at(player); - if (hand.open) { + if (player.open) { return false; } for (const auto* node : branch) { @@ -38,13 +37,13 @@ bool isPinfu(const GameState& state, int player, if (node->start() == kEastWind && state.roundNum < 4) { return false; } - if (node->start() == Piece::fromWind(GetSeat(state.roundNum, player))) { + if (node->start() == Piece::fromWind(GetSeat(state.roundNum, player.id))) { return false; } } } } - return getWaits(state.hands[player], state.pendingPiece).size() >= 2; + return getWaits(player, state.pendingPiece).size() >= 2; } REGISTER_YAKU({ diff --git a/src/scoring/yakus/pinfu.h b/src/scoring/yakus/pinfu.h index 6d5f2cd6..8156c843 100644 --- a/src/scoring/yakus/pinfu.h +++ b/src/scoring/yakus/pinfu.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isPinfu(const GameState& state, int player, +bool isPinfu(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/puredoublechi.cc b/src/scoring/yakus/puredoublechi.cc index ed529af7..73cc75d5 100644 --- a/src/scoring/yakus/puredoublechi.cc +++ b/src/scoring/yakus/puredoublechi.cc @@ -11,9 +11,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isPureDoubleChi(const GameState& state, int player, +bool isPureDoubleChi(const GameState& state, const Player& player, const std::vector& branch) { - if (state.hands.at(player).open) { + if (player.open) { return false; } for (size_t i = 0; i < branch.size(); i++) { diff --git a/src/scoring/yakus/puredoublechi.h b/src/scoring/yakus/puredoublechi.h index 912af0af..7be76980 100644 --- a/src/scoring/yakus/puredoublechi.h +++ b/src/scoring/yakus/puredoublechi.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isPureDoubleChi(const GameState& state, int player, +bool isPureDoubleChi(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/purestraight.cc b/src/scoring/yakus/purestraight.cc index 1421d633..06f720c0 100644 --- a/src/scoring/yakus/purestraight.cc +++ b/src/scoring/yakus/purestraight.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isPureStraight(const GameState& state, int player, +bool isPureStraight(const GameState& /* state */, const Player& player, const std::vector& branch) { const int k_firstchistart = 1; const int k_secondchistart = 4; @@ -41,8 +41,7 @@ bool isPureStraight(const GameState& state, int player, } } } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type == SetType::kChi) { int ind = 0; if (meld.start.getPieceNum() == k_firstchistart) { diff --git a/src/scoring/yakus/purestraight.h b/src/scoring/yakus/purestraight.h index 64e879aa..649dce5b 100644 --- a/src/scoring/yakus/purestraight.h +++ b/src/scoring/yakus/purestraight.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isPureStraight(const GameState& state, int player, +bool isPureStraight(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/riichi.cc b/src/scoring/yakus/riichi.cc index 69847226..372e1795 100644 --- a/src/scoring/yakus/riichi.cc +++ b/src/scoring/yakus/riichi.cc @@ -8,9 +8,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isRiichi(const GameState& state, int player, +bool isRiichi(const GameState& state, const Player& player, const std::vector& /*branch*/) { - return state.hands.at(player).riichi && !state.hands.at(player).open && + return player.riichi && !player.open && (state.turnNum > 4 || state.lastCall < 0); } diff --git a/src/scoring/yakus/riichi.h b/src/scoring/yakus/riichi.h index 1b983db6..046d44b4 100644 --- a/src/scoring/yakus/riichi.h +++ b/src/scoring/yakus/riichi.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isRiichi(const GameState& state, int player, +bool isRiichi(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/robbingakan.cc b/src/scoring/yakus/robbingakan.cc index 042f4dc1..27b8b401 100644 --- a/src/scoring/yakus/robbingakan.cc +++ b/src/scoring/yakus/robbingakan.cc @@ -9,9 +9,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isRobbingAKan(const GameState& state, int player, +bool isRobbingAKan(const GameState& state, const Player& player, const std::vector& /*branch*/) { - if (!state.hasRonned.at(player)) { + if (!player.hasRonned) { return false; } if (state.nextState == StateFunctionType::kKanDiscard) { diff --git a/src/scoring/yakus/robbingakan.h b/src/scoring/yakus/robbingakan.h index 3d5f9949..bc2cbc39 100644 --- a/src/scoring/yakus/robbingakan.h +++ b/src/scoring/yakus/robbingakan.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isRobbingAKan(const GameState& state, int player, +bool isRobbingAKan(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/sevenpairs.cc b/src/scoring/yakus/sevenpairs.cc index 00c3968b..620c9909 100644 --- a/src/scoring/yakus/sevenpairs.cc +++ b/src/scoring/yakus/sevenpairs.cc @@ -11,9 +11,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isSevenPairs(const GameState& state, int player, +bool isSevenPairs(const GameState& /* state */, const Player& player, const std::vector& branch) { - if (state.hands[player].open) { + if (player.open) { return false; } std::set pairs; diff --git a/src/scoring/yakus/sevenpairs.h b/src/scoring/yakus/sevenpairs.h index 2f571e6f..25874463 100644 --- a/src/scoring/yakus/sevenpairs.h +++ b/src/scoring/yakus/sevenpairs.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isSevenPairs(const GameState& state, int player, +bool isSevenPairs(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/terminalsinallsets.cc b/src/scoring/yakus/terminalsinallsets.cc index e2c37e2a..62d441e3 100644 --- a/src/scoring/yakus/terminalsinallsets.cc +++ b/src/scoring/yakus/terminalsinallsets.cc @@ -9,7 +9,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isTerminalsInAllSets(const GameState& state, int player, +bool isTerminalsInAllSets(const GameState& /*state*/, const Player& player, const std::vector& branch) { for (const auto* node : branch) { switch (node->type()) { @@ -30,8 +30,7 @@ bool isTerminalsInAllSets(const GameState& state, int player, break; } } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { switch (meld.type) { case SetType::kSingle: return false; diff --git a/src/scoring/yakus/terminalsinallsets.h b/src/scoring/yakus/terminalsinallsets.h index 0368d2be..d5d41f19 100644 --- a/src/scoring/yakus/terminalsinallsets.h +++ b/src/scoring/yakus/terminalsinallsets.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isTerminalsInAllSets(const GameState& state, int player, +bool isTerminalsInAllSets(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/thirteenorphans.cc b/src/scoring/yakus/thirteenorphans.cc index 9509dd96..ddf97bce 100644 --- a/src/scoring/yakus/thirteenorphans.cc +++ b/src/scoring/yakus/thirteenorphans.cc @@ -11,10 +11,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isThirteenOrphans(const GameState& state, int player, +bool isThirteenOrphans(const GameState& /*state*/, const Player& player, const std::vector& /*branch*/) { - const Hand& hand = state.hands[player]; - if (hand.open) { + if (player.open) { return false; } std::map pieces = { @@ -25,7 +24,7 @@ bool isThirteenOrphans(const GameState& state, int player, {kGreenDragon, false}}; bool duplicate = false; - for (const auto& piece : hand.live_range()) { + for (const auto& piece : player.live_range()) { if (pieces.contains(piece)) { if (pieces[piece]) { duplicate = true; diff --git a/src/scoring/yakus/thirteenorphans.h b/src/scoring/yakus/thirteenorphans.h index cad273ce..ce6e6e59 100644 --- a/src/scoring/yakus/thirteenorphans.h +++ b/src/scoring/yakus/thirteenorphans.h @@ -6,7 +6,7 @@ namespace mahjong::yaku { bool isThirteenOrphans( - const GameState& state, int player, + const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/threeconcealedpons.cc b/src/scoring/yakus/threeconcealedpons.cc index 6c154acf..d53f58ba 100644 --- a/src/scoring/yakus/threeconcealedpons.cc +++ b/src/scoring/yakus/threeconcealedpons.cc @@ -9,7 +9,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isThreeConcealedPons(const GameState& state, int player, +bool isThreeConcealedPons(const GameState& /* state */, const Player& player, const std::vector& branch) { int concealed_pons = 0; for (const auto* node : branch) { @@ -17,8 +17,7 @@ bool isThreeConcealedPons(const GameState& state, int player, concealed_pons++; } } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type == SetType::kConcealedKan) { concealed_pons++; } diff --git a/src/scoring/yakus/threeconcealedpons.h b/src/scoring/yakus/threeconcealedpons.h index 0f65d725..e4cec878 100644 --- a/src/scoring/yakus/threeconcealedpons.h +++ b/src/scoring/yakus/threeconcealedpons.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isThreeConcealedPons(const GameState& state, int player, +bool isThreeConcealedPons(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/threekans.cc b/src/scoring/yakus/threekans.cc index dcb4c887..cd2bde02 100644 --- a/src/scoring/yakus/threekans.cc +++ b/src/scoring/yakus/threekans.cc @@ -9,11 +9,10 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isThreeKans(const GameState& state, int player, +bool isThreeKans(const GameState& /* state */, const Player& player, const std::vector& /*branch*/) { int kans = 0; - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type >= SetType::kKan) { kans++; } diff --git a/src/scoring/yakus/threekans.h b/src/scoring/yakus/threekans.h index 044f6ef6..7c63801e 100644 --- a/src/scoring/yakus/threekans.h +++ b/src/scoring/yakus/threekans.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isThreeKans(const GameState& state, int player, +bool isThreeKans(const GameState& state, const Player& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/triplepon.cc b/src/scoring/yakus/triplepon.cc index 8ed6b938..98226e7a 100644 --- a/src/scoring/yakus/triplepon.cc +++ b/src/scoring/yakus/triplepon.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isTriplePon(const GameState& state, int player, +bool isTriplePon(const GameState& /* state */, const Player& player, const std::vector& branch) { std::array bamboo_pon = {}; std::array char_pon = {}; @@ -28,8 +28,7 @@ bool isTriplePon(const GameState& state, int player, } } } - const Hand& hand = state.hands[player]; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type >= SetType::kPon) { if (meld.start.getSuit() == Piece::Type::kBambooSuit) { bamboo_pon.at(meld.start.getPieceNum() - 1) = true; diff --git a/src/scoring/yakus/triplepon.h b/src/scoring/yakus/triplepon.h index 1f664b37..0c25db28 100644 --- a/src/scoring/yakus/triplepon.h +++ b/src/scoring/yakus/triplepon.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isTriplePon(const GameState& state, int player, +bool isTriplePon(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/scoring/yakus/twicepuredoublechi.cc b/src/scoring/yakus/twicepuredoublechi.cc index 11a8c998..2aadbeb0 100644 --- a/src/scoring/yakus/twicepuredoublechi.cc +++ b/src/scoring/yakus/twicepuredoublechi.cc @@ -10,9 +10,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isTwicePureDoubleChi(const GameState& state, int player, +bool isTwicePureDoubleChi(const GameState& /*state*/, const Player& player, const std::vector& branch) { - if (state.hands.at(player).open) { + if (player.open) { return false; } int pairs = 0; diff --git a/src/scoring/yakus/twicepuredoublechi.h b/src/scoring/yakus/twicepuredoublechi.h index 96bc4869..5874f009 100644 --- a/src/scoring/yakus/twicepuredoublechi.h +++ b/src/scoring/yakus/twicepuredoublechi.h @@ -5,7 +5,7 @@ #include "types/gamestate.h" namespace mahjong::yaku { -bool isTwicePureDoubleChi(const GameState& state, int player, +bool isTwicePureDoubleChi(const GameState& state, const Player& player, const std::vector& branch); } diff --git a/src/statefunctions/decisionfunction.cc b/src/statefunctions/decisionfunction.cc index f4b2ebb6..73dd9c8d 100644 --- a/src/statefunctions/decisionfunction.cc +++ b/src/statefunctions/decisionfunction.cc @@ -16,116 +16,113 @@ namespace mahjong { // TODO(#18): "I really hate this" - alice -bool CanRon(const GameState& state, int player) { +bool CanRon(const GameState& state, const Player& player) { // If the pending piece is your discard, you can't Ron - for (const auto& piece : state.hands.at(player).discards) { + for (const auto& piece : player.discards) { if (state.pendingPiece == piece) { return false; } } // Build the theoretical hand - auto& tmp_state = const_cast(state); - auto& tmp_hand = tmp_state.hands[player]; - tmp_hand.live[tmp_hand.live_count++] = state.pendingPiece; + auto& tmp_player = const_cast(player); + tmp_player.live[tmp_player.live_count++] = state.pendingPiece; // If this Ron is occurring due to a concealed kan discard, if (state.concealedKan) { // If it happens to be a ron for a thirteen orphans, // it's allowed and you can ron if (yaku::isThirteenOrphans(state, player)) { - tmp_hand.live[--tmp_hand.live_count] = kError; + tmp_player.live[--tmp_player.live_count] = kError; return true; } // otherwise, you can't - tmp_hand.live[--tmp_hand.live_count] = kError; + tmp_player.live[--tmp_player.live_count] = kError; return false; } // if not a concealed kan, check if it's complete const bool can_ron = isComplete(state, player); - tmp_hand.live[--tmp_hand.live_count] = kError; + tmp_player.live[--tmp_player.live_count] = kError; return can_ron; } -bool CanKan(const GameState& state, int player) { +bool CanKan(const GameState& state, const Player& player) { if (Walls::GetRemainingPieces(state) == 0) { return false; } - if (state.hands.at(player).riichi) { + if (player.riichi) { return false; } - return CountPieces(state, player, state.pendingPiece) == 3; + return CountPieces(player, state.pendingPiece) == 3; } -bool CanPon(const GameState& state, int player) { - if (state.hands.at(player).riichi) { +bool CanPon(const GameState& state, const Player& player) { + if (player.riichi) { return false; } - return CountPieces(state, player, state.pendingPiece) == 2; + return CountPieces(player, state.pendingPiece) == 2; } -bool CanChi(const GameState& state, int player) { - if (state.hands.at(player).riichi) { +bool CanChi(const GameState& state, const Player& player) { + if (player.riichi) { return false; } if (state.pendingPiece.isHonor()) { return false; } - if (((state.currentPlayer + 1) % 4) != player) { + if (((state.currentPlayer + 1) % 4) != player.id) { return false; } - if (CountPieces(state, player, state.pendingPiece - 2) > 0 && - CountPieces(state, player, state.pendingPiece - 1) > 0) { + if (CountPieces(player, state.pendingPiece - 2) > 0 && + CountPieces(player, state.pendingPiece - 1) > 0) { return true; } - if (CountPieces(state, player, state.pendingPiece - 1) > 0 && - CountPieces(state, player, state.pendingPiece + 1) > 0) { + if (CountPieces(player, state.pendingPiece - 1) > 0 && + CountPieces(player, state.pendingPiece + 1) > 0) { return true; } - if (CountPieces(state, player, state.pendingPiece + 1) > 0 && - CountPieces(state, player, state.pendingPiece + 2) > 0) { + if (CountPieces(player, state.pendingPiece + 1) > 0 && + CountPieces(player, state.pendingPiece + 2) > 0) { return true; } return false; } -bool CanTsumo(const GameState& state, int player) { +bool CanTsumo(const GameState& state, const Player& player) { return isComplete(state, player); } -bool CanConvertedKan(const GameState& state, int player) { +bool CanConvertedKan(const GameState& state, const Player& player) { if (Walls::GetRemainingPieces(state) == 0) { return false; } - const Hand& hand = state.hands.at(player); - return std::any_of(hand.melds.begin(), hand.melds.begin() + hand.meld_count, - [&](auto meld) { + return std::any_of(player.melds.begin(), + player.melds.begin() + player.meld_count, [&](auto meld) { return meld.type == SetType::kPon && - CountPieces(state, player, meld.start) == 1; + CountPieces(player, meld.start) == 1; }); } -bool CanConcealedKan(const GameState& state, int player) { +bool CanConcealedKan(const GameState& state, const Player& player) { if (Walls::GetRemainingPieces(state) == 0) { return false; } // TODO(#19): Allow riichi concealed kan under the right conditions - if (state.hands.at(player).riichi) { + if (player.riichi) { return false; } - return CountPieces(state, player, state.pendingPiece) == 4; + return CountPieces(player, state.pendingPiece) == 4; } -bool CanRiichi(const GameState& state, int player) { - const Hand& hand = state.hands[player]; - if (hand.riichi) { +bool CanRiichi(const GameState& /*unused*/, const Player& player) { + if (player.riichi) { return false; } - if (hand.open) { + if (player.open) { return false; } - return !getPossibleWaits(state.hands[player]).empty(); + return !getPossibleWaits(player).empty(); } } // namespace mahjong diff --git a/src/statefunctions/decisionfunction.h b/src/statefunctions/decisionfunction.h index 4ebaa376..db46570b 100644 --- a/src/statefunctions/decisionfunction.h +++ b/src/statefunctions/decisionfunction.h @@ -7,20 +7,20 @@ namespace mahjong { using DecisionFunction = - std::function; + std::function; struct PossibleDecision { Event::Type type; DecisionFunction func; }; -bool CanKan(const GameState& state, int player); -bool CanPon(const GameState& state, int player); -bool CanChi(const GameState& state, int player); -bool CanRon(const GameState& state, int player); +bool CanKan(const GameState& state, const Player& player); +bool CanPon(const GameState& state, const Player& player); +bool CanChi(const GameState& state, const Player& player); +bool CanRon(const GameState& state, const Player& player); -bool CanTsumo(const GameState& state, int player); -bool CanConcealedKan(const GameState& state, int player); -bool CanConvertedKan(const GameState& state, int player); -bool CanRiichi(const GameState& state, int player); +bool CanTsumo(const GameState& state, const Player& player); +bool CanConcealedKan(const GameState& state, const Player& player); +bool CanConvertedKan(const GameState& state, const Player& player); +bool CanRiichi(const GameState& state, const Player& player); } // namespace mahjong diff --git a/src/statefunctions/gamestates/chi.cc b/src/statefunctions/gamestates/chi.cc index 597c4326..91aef104 100644 --- a/src/statefunctions/gamestates/chi.cc +++ b/src/statefunctions/gamestates/chi.cc @@ -15,18 +15,15 @@ namespace mahjong { namespace { -Piece GetChiStart(const GameState& state, int player) { - if (CountPieces(state, player, state.pendingPiece - 2) > 0 && - CountPieces(state, player, state.pendingPiece - 1) > 0) { - return state.pendingPiece - 2; +Piece GetChiStart(const Player& player, Piece p) { + if (CountPieces(player, p - 2) > 0 && CountPieces(player, p - 1) > 0) { + return p - 2; } - if (CountPieces(state, player, state.pendingPiece - 1) > 0 && - CountPieces(state, player, state.pendingPiece + 1) > 0) { - return state.pendingPiece - 1; + if (CountPieces(player, p - 1) > 0 && CountPieces(player, p + 1) > 0) { + return p - 1; } - if (CountPieces(state, player, state.pendingPiece + 1) > 0 && - CountPieces(state, player, state.pendingPiece + 2) > 0) { - return state.pendingPiece; + if (CountPieces(player, p + 1) > 0 && CountPieces(player, p + 2) > 0) { + return p; } return kError; } @@ -34,22 +31,23 @@ Piece GetChiStart(const GameState& state, int player) { std::unique_ptr Chi(std::unique_ptr state) { // only gives a single one of the chis // ui oof - const Piece chi_start = GetChiStart(*state, state->lastCaller); + const Piece chi_start = + GetChiStart(state->players[state->lastCaller], state->pendingPiece); if (chi_start == kError) { std::cerr << "Failed to get start of Chi" << '\n'; state->nextState = StateFunctionType::kError; return state; } - if (state->hands.at(state->currentPlayer).riichi && - state->hands.at(state->currentPlayer).discards_count == - state->hands.at(state->currentPlayer).riichiPieceDiscard) { - state->hands.at(state->currentPlayer).riichiPieceDiscard++; + if (state->players.at(state->currentPlayer).riichi && + state->players.at(state->currentPlayer).discards_count == + state->players.at(state->currentPlayer).riichiPieceDiscard) { + state->players.at(state->currentPlayer).riichiPieceDiscard++; } - Hand& hand = state->hands.at(state->lastCaller); + Player& player = state->players.at(state->lastCaller); - hand.open = true; + player.open = true; state->currentPlayer = state->lastCaller; AlertPlayers( @@ -61,21 +59,22 @@ std::unique_ptr Chi(std::unique_ptr state) { .decision = false, // decision }); - hand.live[hand.live_count++] = state->pendingPiece; + player.live[player.live_count++] = state->pendingPiece; state->lastCall = state->turnNum; state->concealedKan = false; state->turnNum++; - if (RemovePieces(*state, state->lastCaller, chi_start, /*count=*/1) != 1 || - RemovePieces(*state, state->lastCaller, chi_start + 1, /*count=*/1) != + if (RemovePieces(state->players[state->lastCaller], chi_start, /*count=*/1) != 1 || - RemovePieces(*state, state->lastCaller, chi_start + 2, /*count=*/1) != - 1) { + RemovePieces(state->players[state->lastCaller], chi_start + 1, + /*count=*/1) != 1 || + RemovePieces(state->players[state->lastCaller], chi_start + 2, + /*count=*/1) != 1) { std::cerr << "Not Enough Pieces to remove in Chi" << '\n'; state->nextState = StateFunctionType::kError; return state; } - hand.melds[hand.meld_count++] = Meld{ + player.melds[player.meld_count++] = Meld{ .type = SetType::kChi, .start = chi_start, }; diff --git a/src/statefunctions/gamestates/concealedkan.cc b/src/statefunctions/gamestates/concealedkan.cc index b7e8843c..67086c99 100644 --- a/src/statefunctions/gamestates/concealedkan.cc +++ b/src/statefunctions/gamestates/concealedkan.cc @@ -23,14 +23,14 @@ std::unique_ptr ConcealedKan(std::unique_ptr state) { state->pendingPiece.toUint8_t()), // piece .decision = false, // decision }); - if (RemovePieces(*state, state->currentPlayer, state->pendingPiece, + if (RemovePieces(state->players[state->currentPlayer], state->pendingPiece, /*count=*/4) != 4) { std::cerr << "Not Enough pieces to remove in ConcealedKan" << '\n'; state->nextState = StateFunctionType::kError; return state; } - Hand& hand = state->hands.at(state->currentPlayer); - hand.melds[hand.meld_count++] = Meld{ + Player& player = state->players.at(state->currentPlayer); + player.melds[player.meld_count++] = Meld{ .type = SetType::kConcealedKan, .start = state->pendingPiece, }; diff --git a/src/statefunctions/gamestates/convertedkan.cc b/src/statefunctions/gamestates/convertedkan.cc index 6f085c43..bb5f86e8 100644 --- a/src/statefunctions/gamestates/convertedkan.cc +++ b/src/statefunctions/gamestates/convertedkan.cc @@ -23,20 +23,20 @@ std::unique_ptr ConvertedKan(std::unique_ptr state) { state->pendingPiece.toUint8_t()), // piece .decision = false, // decision }); - if (RemovePieces(*state, state->currentPlayer, state->pendingPiece, + if (RemovePieces(state->players[state->currentPlayer], state->pendingPiece, /*count=*/1) != 1) { std::cerr << "Not Enough pieces to remove in ConvertedKan" << '\n'; state->nextState = StateFunctionType::kError; return state; } - Hand& hand = state->hands[state->currentPlayer]; - if (auto* meld = std::ranges::find(hand.melds, + Player& player =state->players[state->currentPlayer]; + if (auto* meld = std::ranges::find(player.melds, Meld{ .type = SetType::kPon, .start = state->pendingPiece, }); - meld != hand.melds.end()) { + meld != player.melds.end()) { meld->type = SetType::kKan; state->nextState = StateFunctionType::kKanDiscard; return state; diff --git a/src/statefunctions/gamestates/discard.cc b/src/statefunctions/gamestates/discard.cc index 3208c394..0f818dd7 100644 --- a/src/statefunctions/gamestates/discard.cc +++ b/src/statefunctions/gamestates/discard.cc @@ -24,7 +24,7 @@ std::unique_ptr Discard(std::unique_ptr state) { state->pendingPiece.toUint8_t()), // piece .decision = false, // decision }); - DiscardPiece(*state, state->currentPlayer, state->pendingPiece); + DiscardPiece(state->players[state->currentPlayer], state->pendingPiece); const std::vector decisions = { {.type = Event::kChi, .func = CanChi}, @@ -34,14 +34,14 @@ std::unique_ptr Discard(std::unique_ptr state) { }; std::array need_decision = {false, false, false, false}; - for (int player = 0; player < 4; player++) { - if (player == state->currentPlayer) { + for(const Player& player : state->players){ + if (player.id == state->currentPlayer) { continue; } for (const auto& [decision, decisionIsPossible] : decisions) { if (decisionIsPossible(*state, player)) { - need_decision.at(player) = true; - state->players.at(player)->ReceiveEvent(Event{ + need_decision.at(player.id) = true; + state->controllers.at(player.id)->ReceiveEvent(Event{ .type = decision, // type .player = state->currentPlayer, // player .piece = @@ -53,18 +53,18 @@ std::unique_ptr Discard(std::unique_ptr state) { } Event decision = kDeclineEvent; - for (int i = 0; i < 4; i++) { - if (need_decision.at(i)) { + for(Player& player : state->players){ + if (need_decision.at(player.id)) { Event temp_decision = - GetValidDecisionOrThrow(*state, i, /*inHand=*/false); + GetValidDecisionOrThrow(*state, player, /*inPlayer=*/false); if (temp_decision.type < decision.type) { // lower is higher priority - temp_decision.player = i; + temp_decision.player = player.id; temp_decision.piece = static_cast(state->pendingPiece.toUint8_t()); decision = temp_decision; } if (temp_decision.type == Event::kRon) { - state->hasRonned.at(i) = true; + player.hasRonned = true; } } } diff --git a/src/statefunctions/gamestates/draw.cc b/src/statefunctions/gamestates/draw.cc index dfafde03..7b434c04 100644 --- a/src/statefunctions/gamestates/draw.cc +++ b/src/statefunctions/gamestates/draw.cc @@ -12,9 +12,9 @@ std::unique_ptr Draw(std::unique_ptr state) { state->currentPlayer = (state->currentPlayer + 1) % 4; state->turnNum++; state->pendingPiece = Walls::TakePiece(*state); - Hand& hand = state->hands[state->currentPlayer]; - hand.live[hand.live_count++] = state->pendingPiece; - state->nextState = StateFunctionType::kPlayerHand; + Player& player =state->players[state->currentPlayer]; + player.live[player.live_count++] = state->pendingPiece; + state->nextState = StateFunctionType::kPlayerPlayer; return state; } } // namespace diff --git a/src/statefunctions/gamestates/exhaust.cc b/src/statefunctions/gamestates/exhaust.cc index 39d1b7b5..5ae4dfa1 100644 --- a/src/statefunctions/gamestates/exhaust.cc +++ b/src/statefunctions/gamestates/exhaust.cc @@ -14,7 +14,7 @@ std::unique_ptr Exhaust(std::unique_ptr state) { int total_winners = 0; for (int i = 0; i < 4; i++) { // TODO(#21): Implement no tenpai if you have all pieces of your wait - if (state->hands.at(i).riichi || !getWaits(state->hands[i]).empty()) { + if (state->players.at(i).riichi || !getWaits(state->players[i]).empty()) { winning_players.at(i) = 1; total_winners++; } @@ -26,24 +26,24 @@ std::unique_ptr Exhaust(std::unique_ptr state) { if (total_winners < 4 && total_winners > 0) { for (int i = 0; i < 4; i++) { if (winning_players.at(i) != 0) { - state->scores.at(i) = 3000 / total_winners; + state->players.at(i).score = 3000 / total_winners; } else { switch (total_winners) { case 1: - state->scores.at(i) = -1000; + state->players.at(i).score = -1000; break; case 2: - state->scores.at(i) = -1500; + state->players.at(i).score = -1500; break; case 3: - state->scores.at(i) = -3000; + state->players.at(i).score = -3000; break; default: break; } } - if (state->hands.at(i).riichi) { - state->scores.at(i) -= 1000; + if (state->players.at(i).riichi) { + state->players[i].score -= 1000; } } } diff --git a/src/statefunctions/gamestates/gameend.cc b/src/statefunctions/gamestates/gameend.cc index 509a1d2c..81f45d72 100644 --- a/src/statefunctions/gamestates/gameend.cc +++ b/src/statefunctions/gamestates/gameend.cc @@ -10,9 +10,9 @@ namespace mahjong { namespace { std::unique_ptr GameEnd(std::unique_ptr state) { - for (auto& player : state->players) { - player->ReceiveEvent(kEndEvent); - player.reset(); + for (auto& controller : state->controllers) { + controller->ReceiveEvent(kEndEvent); + controller.reset(); } return state; } diff --git a/src/statefunctions/gamestates/gamestart.cc b/src/statefunctions/gamestates/gamestart.cc index 5c446657..59b87dfa 100644 --- a/src/statefunctions/gamestates/gamestart.cc +++ b/src/statefunctions/gamestates/gamestart.cc @@ -11,8 +11,9 @@ namespace mahjong { namespace { std::unique_ptr GameStart(std::unique_ptr state) { for (int i = 0; i < 4; i++) { - state->points[i] = kStartingPoints; - state->players[i]->GameStart(i); + state->players[i].id = i; + state->players[i].points = kStartingPoints; + state->controllers[i]->GameStart(i); } state->g.seed(state->seed); state->nextState = StateFunctionType::kRoundStart; diff --git a/src/statefunctions/gamestates/kan.cc b/src/statefunctions/gamestates/kan.cc index 21878aa4..c663ddfc 100644 --- a/src/statefunctions/gamestates/kan.cc +++ b/src/statefunctions/gamestates/kan.cc @@ -24,26 +24,26 @@ std::unique_ptr Kan(std::unique_ptr state) { .decision = false, // decision }); - if (state->hands.at(state->currentPlayer).riichi && - state->hands.at(state->currentPlayer).discards_count == - state->hands.at(state->currentPlayer).riichiPieceDiscard) { - state->hands.at(state->currentPlayer).riichiPieceDiscard++; + if (state->players.at(state->currentPlayer).riichi && + state->players.at(state->currentPlayer).discards_count == + state->players.at(state->currentPlayer).riichiPieceDiscard) { + state->players.at(state->currentPlayer).riichiPieceDiscard++; } - Hand& hand = state->hands.at(state->lastCaller); - hand.open = true; + Player& player =state->players.at(state->lastCaller); + player.open = true; state->currentPlayer = state->lastCaller; state->lastCall = state->turnNum; state->concealedKan = false; state->turnNum++; - if (RemovePieces(*state, state->lastCaller, state->pendingPiece, + if (RemovePieces(player, state->pendingPiece, /*count=*/3) != 3) { std::cerr << "Not Enough Pieces to remove in kan" << '\n'; state->nextState = StateFunctionType::kError; return state; } - hand.melds[hand.meld_count++] = Meld{ + player.melds[player.meld_count++] = Meld{ .type = SetType::kKan, .start = state->pendingPiece, }; diff --git a/src/statefunctions/gamestates/kandiscard.cc b/src/statefunctions/gamestates/kandiscard.cc index e287d034..c3f217b2 100644 --- a/src/statefunctions/gamestates/kandiscard.cc +++ b/src/statefunctions/gamestates/kandiscard.cc @@ -15,13 +15,13 @@ namespace mahjong { namespace { std::unique_ptr KanDiscard(std::unique_ptr state) { std::array need_decision = {false, false, false, false}; - for (int player = 0; player < 4; player++) { - if (player == state->currentPlayer) { + for(const Player& player : state->players){ + if (player.id == state->currentPlayer) { continue; } if (CanRon(*state, player)) { - need_decision.at(player) = true; - state->players.at(state->currentPlayer) + need_decision.at(player.id) = true; + state->controllers.at(state->currentPlayer) ->ReceiveEvent(Event{ .type = Event::kRon, // type .player = state->currentPlayer, // player @@ -33,12 +33,12 @@ std::unique_ptr KanDiscard(std::unique_ptr state) { } bool have_ronned = false; - for (int i = 0; i < 4; i++) { - if (need_decision.at(i)) { + for(Player& player : state->players){ + if (need_decision.at(player.id)) { const Event temp_decision = - GetValidDecisionOrThrow(*state, i, /*inHand=*/false); + GetValidDecisionOrThrow(*state, player, /*inPlayer=*/false); if (temp_decision.type == Event::kRon) { - state->hasRonned.at(i) = true; + player.hasRonned = true; have_ronned = true; } } diff --git a/src/statefunctions/gamestates/playerhand.cc b/src/statefunctions/gamestates/playerhand.cc index 923d4cf7..00631c94 100644 --- a/src/statefunctions/gamestates/playerhand.cc +++ b/src/statefunctions/gamestates/playerhand.cc @@ -15,22 +15,22 @@ namespace mahjong { namespace { -std::unique_ptr PlayerHand(std::unique_ptr state) { +std::unique_ptr PlayerPlayer(std::unique_ptr state) { const std::vector decisions = { PossibleDecision{.type = Event::kTsumo, .func = CanTsumo}, PossibleDecision{.type = Event::kConcealedKan, .func = CanConcealedKan}, PossibleDecision{.type = Event::kConvertedKan, .func = CanConvertedKan}, PossibleDecision{.type = Event::kRiichi, .func = CanRiichi}, PossibleDecision{.type = Event::kDiscard, - .func = [](const GameState& state, int) { - return !state.hands.at(state.currentPlayer).riichi; + .func = [](const GameState&, const Player& player) { + return !player.riichi; }}}; bool decision_asked = false; for (const auto& [decision, decisionIsPossible] : decisions) { - if (decisionIsPossible(*state, state->currentPlayer)) { + if (decisionIsPossible(*state, state->players[state->currentPlayer])) { decision_asked = true; - state->players.at(state->currentPlayer) + state->controllers.at(state->currentPlayer) ->ReceiveEvent(Event{ .type = decision, // type .player = state->currentPlayer, // player @@ -49,8 +49,8 @@ std::unique_ptr PlayerHand(std::unique_ptr state) { decision.decision = true; state->nextState = StateFunctionType::kDiscard; } else { - decision = - GetValidDecisionOrThrow(*state, state->currentPlayer, /*inHand=*/true); + decision = GetValidDecisionOrThrow(*state, state->players[state->currentPlayer], + /*inPlayer=*/true); } // note riichi handling is a lil borked on the player agency side @@ -86,5 +86,5 @@ std::unique_ptr PlayerHand(std::unique_ptr state) { } } // namespace -REGISTER_ROUTE(PlayerHand, StateFunctionType::kPlayerHand); +REGISTER_ROUTE(PlayerPlayer, StateFunctionType::kPlayerPlayer); } // namespace mahjong diff --git a/src/statefunctions/gamestates/pon.cc b/src/statefunctions/gamestates/pon.cc index 8c844e22..efd0db12 100644 --- a/src/statefunctions/gamestates/pon.cc +++ b/src/statefunctions/gamestates/pon.cc @@ -16,7 +16,7 @@ namespace mahjong { namespace { std::unique_ptr Pon(std::unique_ptr state) { - state->hands.at(state->lastCaller).open = true; + state->players.at(state->lastCaller).open = true; AlertPlayers(*state, Event{ .type = Event::kPon, // type @@ -26,25 +26,25 @@ std::unique_ptr Pon(std::unique_ptr state) { .decision = false, // decision }); - if (state->hands.at(state->currentPlayer).riichi && - state->hands.at(state->currentPlayer).discards_count == - state->hands.at(state->currentPlayer).riichiPieceDiscard) { - state->hands.at(state->currentPlayer).riichiPieceDiscard++; + if (state->players.at(state->currentPlayer).riichi && + state->players.at(state->currentPlayer).discards_count == + state->players.at(state->currentPlayer).riichiPieceDiscard) { + state->players.at(state->currentPlayer).riichiPieceDiscard++; } - Hand& hand = state->hands.at(state->lastCaller); + Player& player = state->players.at(state->lastCaller); state->currentPlayer = state->lastCaller; state->lastCall = state->turnNum; state->concealedKan = false; state->turnNum++; - if (RemovePieces(*state, state->lastCaller, state->pendingPiece, + if (RemovePieces(state->players[state->lastCaller], state->pendingPiece, /*count=*/2) != 2) { std::cerr << "Not enough pieces to remove in Pon" << '\n'; state->nextState = StateFunctionType::kError; return state; } - hand.melds[hand.meld_count++] = Meld{ + player.melds[player.meld_count++] = Meld{ .type = SetType::kPon, .start = state->pendingPiece, }; diff --git a/src/statefunctions/gamestates/replacement.cc b/src/statefunctions/gamestates/replacement.cc index 58cd906d..8f243e37 100644 --- a/src/statefunctions/gamestates/replacement.cc +++ b/src/statefunctions/gamestates/replacement.cc @@ -15,8 +15,8 @@ namespace mahjong { namespace { std::unique_ptr Replacement(std::unique_ptr state) { const Piece draw = Walls::TakeReplacementTile(*state); - Hand& hand = state->hands.at(state->currentPlayer); - hand.live[hand.live_count++] = draw; + Player& player =state->players.at(state->currentPlayer); + player.live[player.live_count++] = draw; state->pendingPiece = draw; AlertPlayers(*state, @@ -28,7 +28,7 @@ std::unique_ptr Replacement(std::unique_ptr state) { .decision = false, // decision }); - state->nextState = StateFunctionType::kPlayerHand; + state->nextState = StateFunctionType::kPlayerPlayer; return state; } } // namespace diff --git a/src/statefunctions/gamestates/riichi.cc b/src/statefunctions/gamestates/riichi.cc index 88492d25..e7d9bd02 100644 --- a/src/statefunctions/gamestates/riichi.cc +++ b/src/statefunctions/gamestates/riichi.cc @@ -16,7 +16,7 @@ namespace mahjong { namespace { std::unique_ptr Riichi(std::unique_ptr state) { // TODO(#22): Ask the players if they want to riichi - state->pendingPiece = getPossibleWaits(state->hands[state->currentPlayer]) + state->pendingPiece = getPossibleWaits(state->players[state->currentPlayer]) .begin() ->second.front(); @@ -29,10 +29,10 @@ std::unique_ptr Riichi(std::unique_ptr state) { .decision = false, // decision }); - Hand& hand = state->hands[state->currentPlayer]; - hand.riichiRound = state->turnNum; - hand.riichiPieceDiscard = hand.discards_count; - hand.riichi = true; + Player& player =state->players[state->currentPlayer]; + player.riichiRound = state->turnNum; + player.riichiPieceDiscard = player.discards_count; + player.riichi = true; state->riichiSticks++; state->nextState = StateFunctionType::kDiscard; diff --git a/src/statefunctions/gamestates/ron.cc b/src/statefunctions/gamestates/ron.cc index 6d38ab6b..d1261d62 100644 --- a/src/statefunctions/gamestates/ron.cc +++ b/src/statefunctions/gamestates/ron.cc @@ -14,60 +14,59 @@ namespace mahjong { namespace { std::unique_ptr Ron(std::unique_ptr state) { - Hand& caller_hand = state->hands[state->lastCaller]; - caller_hand.live[caller_hand.live_count++] = state->pendingPiece; + Player& caller_player = state->players[state->lastCaller]; + caller_player.live[caller_player.live_count++] = state->pendingPiece; std::array basic_points = {}; - Hand& curr_hand = state->hands[state->currentPlayer]; - if (curr_hand.riichi && - curr_hand.discards_count == curr_hand.riichiPieceDiscard) { + Player& curr_player = state->players[state->currentPlayer]; + if (curr_player.riichi && + curr_player.discards_count == curr_player.riichiPieceDiscard) { state->riichiSticks--; - curr_hand.riichi = false; + curr_player.riichi = false; } - for (int player = 0; player < 4; player++) { - if (state->hasRonned.at(player)) { + for (Player& player : state->players) { + if (player.hasRonned) { AlertPlayers(*state, Event{ .type = Event::kRon, // type - .player = player, // player + .player = player.id, // player .piece = static_cast( state->pendingPiece.toUint8_t()), // piece .decision = false, // decision }); - basic_points.at(player) = getBasicPoints(scoreHand(*state, player)); + basic_points.at(player.id) = getBasicPoints(scorePlayer(*state, player)); } - if (state->hands.at(player).riichi) { - state->scores.at(player) -= 1000; + if (player.riichi) { + player.score -= 1000; } } int payment = 0; - for (int i = 0; i < 4; i++) { - const int player = (state->roundNum + i) % 4; - if (state->hasRonned.at(player)) { - state->scores.at(player) += 1000 * state->riichiSticks; + for (Player& player : state->players) { + if (player.hasRonned) { + player.score += 1000 * state->riichiSticks; state->riichiSticks = 0; - state->scores.at(player) += 300 * state->counters; + player.score += 300 * state->counters; payment += 300 * state->counters; - if (i == state->roundNum % 4) { - int amount = 6 * basic_points.at(player); + if (player.id == state->roundNum % 4) { + int amount = 6 * basic_points.at(player.id); if ((amount % 100) != 0) { amount = amount + (100 - (amount % 100)); } - state->scores.at(player) += amount; + player.score += amount; payment += amount; } else { - int amount = 4 * basic_points.at(player); + int amount = 4 * basic_points.at(player.id); if ((amount % 100) != 0) { amount = amount + (100 - (amount % 100)); } - state->scores.at(player) += amount; + player.score += amount; payment += amount; } } } - state->scores.at(state->currentPlayer) -= payment; + state->players[state->currentPlayer].score -= payment; - if (state->hasRonned.at(state->roundNum % 4)) { + if (state->players.at(state->roundNum % 4).hasRonned) { state->counters++; } else { state->roundNum++; @@ -76,7 +75,7 @@ std::unique_ptr Ron(std::unique_ptr state) { bool allzeros = true; for (int i = 0; i < 4; i++) { - if (state->scores.at(i) != 0) { + if (state->players.at(i).score != 0) { allzeros = false; } } diff --git a/src/statefunctions/gamestates/roundend.cc b/src/statefunctions/gamestates/roundend.cc index 50718b50..fd9056d3 100644 --- a/src/statefunctions/gamestates/roundend.cc +++ b/src/statefunctions/gamestates/roundend.cc @@ -20,38 +20,43 @@ std::unique_ptr RoundEnd(std::unique_ptr state) { state->concealedKan = false; state->lastCaller = -1; state->pendingPiece = Piece(Piece::kError); - state->hasRonned = {}; + for (auto& player : state->players) { + player.hasRonned = false; + } - state->hands = {}; + state->controllers = {}; const int last_round = 3; if (state->roundNum > last_round && state->riichiSticks > 0) { std::vector winners; int highscore = -100000; for (int i = 0; i < 4; i++) { - if (state->points[i] + state->scores.at(i) > highscore) { - highscore = state->points[i] + state->scores.at(i); + if (state->players[i].points + state->players.at(i).score > highscore) { + highscore = state->players[i].points + state->players.at(i).score; winners.clear(); winners.push_back(i); - } else if (state->points[i] + state->scores.at(i) == highscore) { + } else if (state->players[i].points + state->players.at(i).score == + highscore) { winners.push_back(i); } } for (const auto& winner : winners) { - state->scores.at(winner) += (state->riichiSticks * 1000) / winners.size(); + state->players.at(winner).score += + (state->riichiSticks * 1000) / winners.size(); } } // TODO(#17): Scoring for (int i = 0; i < 4; i++) { - AlertPlayers(*state, - Event{.type = Event::kPointDiff, - .player = i, - .piece = static_cast(state->scores.at(i) / 100), - .decision = false}); - state->points[i] += state->scores.at(i); + AlertPlayers( + *state, + Event{.type = Event::kPointDiff, + .player = i, + .piece = static_cast(state->players.at(i).score / 100), + .decision = false}); + state->players[i].points += state->players.at(i).score; + state->players[i].score = 0; } - state->scores = {}; // TODO (#14): for now naively increment the round number state->roundNum++; diff --git a/src/statefunctions/gamestates/roundstart.cc b/src/statefunctions/gamestates/roundstart.cc index cd13f181..ffbdd7a8 100644 --- a/src/statefunctions/gamestates/roundstart.cc +++ b/src/statefunctions/gamestates/roundstart.cc @@ -20,11 +20,11 @@ std::unique_ptr RoundStart(std::unique_ptr state) { Walls::New(*state); for (size_t i = 0; i < 4; i++) { auto hand = Walls::TakeHand(*state); - state->players.at(i)->RoundStart( + state->controllers.at(i)->RoundStart( hand, static_cast((i + 3 * (state->roundNum % 4)) % 4), (state->roundNum > 3) ? kSouth : kEast); - state->hands[i].live_count = hand.size(); - std::ranges::move(hand, state->hands[i].live.begin()); + state->players[i].live_count = hand.size(); + std::ranges::move(hand, state->players[i].live.begin()); } AlertPlayers(*state, diff --git a/src/statefunctions/gamestates/tsumo.cc b/src/statefunctions/gamestates/tsumo.cc index 88994182..30e6d4c9 100644 --- a/src/statefunctions/gamestates/tsumo.cc +++ b/src/statefunctions/gamestates/tsumo.cc @@ -22,15 +22,15 @@ std::unique_ptr Tsumo(std::unique_ptr state) { .decision = false, // decision }); const int basic_points = - getBasicPoints(scoreHand(*state, state->currentPlayer)); - state->scores.at(state->currentPlayer) += state->riichiSticks * 1000; + getBasicPoints(scorePlayer(*state, state->players[state->currentPlayer])); + state->players[state->currentPlayer].score += state->riichiSticks * 1000; state->riichiSticks = 0; - state->scores.at(state->currentPlayer) += state->counters * 300; + state->players[state->currentPlayer].score += state->counters * 300; for (int i = 0; i < 4; i++) { if (i == state->currentPlayer) { - if (state->hands.at(state->currentPlayer).riichi) { - state->scores.at(i) -= 1000; + if (state->players.at(state->currentPlayer).riichi) { + state->players.at(i).score -= 1000; } continue; } @@ -44,12 +44,12 @@ std::unique_ptr Tsumo(std::unique_ptr state) { if ((amount % 100) != 0) { amount = amount + (100 - (amount % 100)); } - state->scores.at(i) -= amount; - state->scores.at(i) -= state->counters * 100; - if (state->hands.at(i).riichi) { - state->scores.at(i) -= 1000; + state->players.at(i).score -= amount; + state->players.at(i).score -= state->counters * 100; + if (state->players.at(i).riichi) { + state->players.at(i).score -= 1000; } - state->scores.at(state->currentPlayer) += amount; + state->players[state->currentPlayer].score += amount; } if (state->currentPlayer == state->roundNum % 4) { diff --git a/src/statefunctions/statecontroller.cc b/src/statefunctions/statecontroller.cc index 2ee0a069..8acd112b 100644 --- a/src/statefunctions/statecontroller.cc +++ b/src/statefunctions/statecontroller.cc @@ -42,7 +42,7 @@ void ExitGame(int game) { std::unique_ptr InitGameState(const GameSettings& settings) { auto state = std::make_unique(); for (int i = 0; i < 4; i++) { - state->players.at(i) = ControllerManager::Instance().NewController( + state->controllers.at(i) = ControllerManager::Instance().NewController( settings.seatControllers.at(i)); } if (settings.seed != 0U) { diff --git a/src/statefunctions/stateutilities.cc b/src/statefunctions/stateutilities.cc index eb647a6b..d3af4594 100644 --- a/src/statefunctions/stateutilities.cc +++ b/src/statefunctions/stateutilities.cc @@ -23,22 +23,20 @@ Wind GetSeat(int round, int player) { // Push Event to Player Queue void AlertPlayers(const GameState& state, Event e) { e.decision = false; - for (const auto& player : state.players) { - player->ReceiveEvent(e); + for (const auto& controller : state.controllers) { + controller->ReceiveEvent(e); } } // Count number of piece p that are in given players hands -uint8_t CountPieces(const GameState& state, int player, Piece p) { - const Hand& hand = state.hands.at(player); - return std::ranges::count(hand.live_range(), p); +uint8_t CountPieces(const Player& player, Piece p) { + return std::ranges::count(player.live_range(), p); } // Remove an instance of piece p from given players hand -uint8_t RemovePieces(GameState& state, int player, Piece p, uint8_t count) { - Hand& hand = state.hands.at(player); +uint8_t RemovePieces(Player& player, Piece p, uint8_t count) { uint8_t removed = 0; - count = std::min(CountPieces(state, player, p), count); + count = std::min(CountPieces(player, p), count); const auto match_piece = [&](Piece _p) { if (count > removed && p == _p) { removed++; @@ -46,19 +44,19 @@ uint8_t RemovePieces(GameState& state, int player, Piece p, uint8_t count) { } return false; }; - std::ranges::remove_if(hand.live, match_piece); - hand.live_count -= removed; + std::ranges::remove_if(player.live, match_piece); + player.live_count -= removed; return removed; } // Discard an instance of piece p from given players hand -void DiscardPiece(GameState& state, int player, Piece p) { - RemovePieces(state, player, p, /*count=*/1); - state.hands[player].discards[state.hands[player].discards_count++] = p; +void DiscardPiece(Player& player, Piece p) { + RemovePieces(player, p, /*count=*/1); + player.discards[player.discards_count++] = p; } Piece AskForDiscard(const GameState& state) { - state.players.at(state.currentPlayer) + state.controllers.at(state.currentPlayer) ->ReceiveEvent(Event{ .type = Event::kDiscard, // type .player = state.currentPlayer, // player @@ -67,50 +65,50 @@ Piece AskForDiscard(const GameState& state) { }); return Piece( - GetValidDecisionOrThrow(state, state.currentPlayer, /*inHand=*/true) + GetValidDecisionOrThrow(state, state.players[state.currentPlayer], /*inPlayer=*/true) .piece); } -Event GetValidDecisionOrThrow(const GameState& state, int player, bool inHand) { +Event GetValidDecisionOrThrow(const GameState& state, const Player& player, + bool inPlayer) { Event decision; bool valid = false; int i = 0; while (!valid) { if (i > 100) { Event replacement_decision = decision; - replacement_decision.type = inHand ? Event::kDiscard : Event::kDecline; - if (inHand) { - replacement_decision.piece = - state.hands[player].live_range().back().toUint8_t(); + replacement_decision.type = inPlayer ? Event::kDiscard : Event::kDecline; + if (inPlayer) { + replacement_decision.piece = player.live_range().back().toUint8_t(); } - if (ValidateDecision(state, player, replacement_decision, inHand)) { + if (ValidateDecision(state, player, replacement_decision, inPlayer)) { return replacement_decision; } std::cerr << "WARNING: Player Controller sent invalid event too many times." << '\n'; std::cerr << "Decision.type: " << decision.type << " Decision.piece " - << decision.piece << " player: " << player - << " inHand: " << (inHand ? "true" : "false") << '\n'; + << decision.piece << " player: " << player.id + << " inPlayer: " << (inPlayer ? "true" : "false") << '\n'; std::cerr << "ERROR: was not able to recover from invalid event." << '\n'; throw 0xBAD22222; } i++; - decision = state.players.at(player)->RetrieveDecision(); - valid = ValidateDecision(state, player, decision, inHand); + decision = state.controllers.at(player.id)->RetrieveDecision(); + valid = ValidateDecision(state, player, decision, inPlayer); } return decision; } -bool ValidateDecision(const GameState& state, int player, Event decision, - bool inHand) { +bool ValidateDecision(const GameState& state, const Player& player, + Event decision, bool inPlayer) { if (decision.type > Event::kDiscard) { return false; } - if (decision.type > Event::kDecline && !inHand) { + if (decision.type > Event::kDecline && !inPlayer) { return false; } - if (decision.type < Event::kTsumo && inHand) { + if (decision.type < Event::kTsumo && inPlayer) { return false; } switch (decision.type) { @@ -131,7 +129,7 @@ bool ValidateDecision(const GameState& state, int player, Event decision, case Event::kRiichi: return CanRiichi(state, player); case Event::kDiscard: - return CountPieces(state, player, Piece(decision.piece)) > 0; + return CountPieces(player, Piece(decision.piece)) > 0; case Event::kDecline: return true; default: diff --git a/src/statefunctions/stateutilities.h b/src/statefunctions/stateutilities.h index 13fcd2f7..f42ba79f 100644 --- a/src/statefunctions/stateutilities.h +++ b/src/statefunctions/stateutilities.h @@ -2,6 +2,7 @@ #include #include "types/event.h" +#include "types/gamestate.h" #include "types/piecetype.h" #include "types/winds.h" @@ -10,14 +11,15 @@ struct GameState; Wind GetSeat(int round, int player); -uint8_t RemovePieces(GameState& state, int player, Piece p, uint8_t count); -void DiscardPiece(GameState& state, int player, Piece p); +uint8_t RemovePieces(Player& player, Piece p, uint8_t count); +void DiscardPiece(Player& player, Piece p); void AlertPlayers(const GameState& state, Event e); Piece AskForDiscard(const GameState& state); -uint8_t CountPieces(const GameState& state, int player, Piece p); -bool ValidateDecision(const GameState& state, int player, Event decision, - bool inHand); -Event GetValidDecisionOrThrow(const GameState& state, int player, bool inHand); +uint8_t CountPieces(const Player& player, Piece p); +bool ValidateDecision(const GameState& state, const Player& player, + Event decision, bool inPlayer); +Event GetValidDecisionOrThrow(const GameState& state, const Player& player, + bool inPlayer); } // namespace mahjong diff --git a/src/types/event.h b/src/types/event.h index c1896766..d6d52c5d 100644 --- a/src/types/event.h +++ b/src/types/event.h @@ -1,9 +1,7 @@ #pragma once #include -#include #include -#include "types/piecetype.h" namespace mahjong { diff --git a/src/types/gamestate.h b/src/types/gamestate.h index 59801010..b512d3b9 100644 --- a/src/types/gamestate.h +++ b/src/types/gamestate.h @@ -12,17 +12,23 @@ namespace mahjong { -struct Hand { - bool open = false; +struct Hand {}; + +struct Player { + int id; + std::array discards; + int discards_count = 0; bool riichi = false; - int riichiPieceDiscard = -1; - int riichiRound = -1; + int riichiPieceDiscard; + int riichiRound; + int score; + bool hasRonned; + int points; + bool open; std::array live; int live_count = 13; std::array melds; int meld_count = 0; - std::array discards; - int discards_count = 0; [[nodiscard]] std::ranges::subrange live_range() const { return std::ranges::subrange(live.begin(), live.begin() + live_count); } @@ -39,23 +45,23 @@ struct GameState { int counters = 0; int lastCall = -1; int lastCaller = -1; + int livingWallIndex = 0; + int deadWallIndex = 0; + int doraCount = 1; bool concealedKan = false; + Piece pendingPiece = Piece(Piece::Type::kError); + + std::array players; + std::array livingWall; + std::array deadWall; + uint64_t seed = 0; std::mt19937_64 g; - int doraCount = 1; - Piece pendingPiece = Piece(Piece::Type::kError); + std::array, kNumPlayers> controllers = {}; + StateFunctionType prevState; StateFunctionType currState; StateFunctionType nextState; - std::array livingWall; - int livingWallIndex = 0; - std::array deadWall; - int deadWallIndex = 0; - std::array scores = {}; - std::array hasRonned = {}; - std::array hands = {}; - std::array, kNumPlayers> players = {}; - std::array points = {}; }; } // namespace mahjong diff --git a/src/types/statefunction.h b/src/types/statefunction.h index 2adefdf4..bc16490c 100644 --- a/src/types/statefunction.h +++ b/src/types/statefunction.h @@ -13,7 +13,7 @@ enum class StateFunctionType { kGameStart, kRoundStart, kDraw, - kPlayerHand, + kPlayerPlayer, kPon, kChi, kKan, diff --git a/src/types/typeprinter.cc b/src/types/typeprinter.cc index 5f2a6f51..183a078a 100644 --- a/src/types/typeprinter.cc +++ b/src/types/typeprinter.cc @@ -33,21 +33,16 @@ std::ostream& operator<<(std::ostream& os, const mahjong::GameState& state) { os << "lastCaller: " << state.lastCaller << '\n'; os << "seed: " << state.seed << '\n'; os << "pendingPiece: " << state.pendingPiece.toStr() << '\n'; - os << "hasRonned: " << '\n'; - for (size_t i = 0; i < state.hasRonned.size(); i++) { - os << "hasRonned[" << i << "]: {" << state.hasRonned.at(i) << "}" << '\n'; - } os << "hands: " << '\n'; - for (size_t i = 0; i < state.hands.size(); i++) { - os << "hand[" << i << "]: {" << state.hands.at(i) << "}" << '\n'; - } - os << "players: " << '\n'; for (size_t i = 0; i < state.players.size(); i++) { + os << "hand[" << i << "]: {" << state.players.at(i) << "}" << '\n'; + } + os << "controllers: " << '\n'; + for (size_t i = 0; i < state.controllers.size(); i++) { os << "player[" << i << "]: "; os << "{ controller: " - << ((state.players[i] != nullptr) ? state.players[i]->Name() - : "NULLPTR"); - os << " points: " << state.points[i]; + << ((state.controllers[i] != nullptr) ? state.controllers[i]->Name() + : "NULLPTR"); os << '\n'; } os << "{ doraCount: " << state.doraCount; @@ -67,26 +62,28 @@ std::ostream& operator<<(std::ostream& os, const mahjong::GameState& state) { return os; } -std::ostream& operator<<(std::ostream& os, const mahjong::Hand& hand) { - os << "{ open: " << hand.open; - os << " riichi: " << hand.riichi; - os << " riichiPieceDiscard: " << hand.riichiPieceDiscard; - os << " riichiRound: " << hand.riichiRound; +std::ostream& operator<<(std::ostream& os, const mahjong::Player& player) { + os << "{ open: " << player.open; + os << " riichi: " << player.riichi; + os << " riichiPieceDiscard: " << player.riichiPieceDiscard; + os << " riichiRound: " << player.riichiRound; os << " live: [" << '\n'; - ; - for (const auto& piece : hand.live_range()) { + os << "hasRonned: " << '\n'; + os << "hasRonned: {" << player.hasRonned << "}" << '\n'; + os << " points: " << player.points; + for (const auto& piece : player.live_range()) { os << piece.toStr() << ", "; } os << "]" << '\n'; os << "melds: [" << '\n'; - for (const auto& meld : hand.melds_range()) { + for (const auto& meld : player.melds_range()) { os << "{ type: " << meld.typeToStr(); os << ", start: " << meld.start.toStr() << "}"; os << ", "; } os << "]" << '\n'; os << "discards: [" << '\n'; - for (const auto& piece : hand.discards) { + for (const auto& piece : player.discards) { os << piece.toStr() << ", "; } os << "]" << '\n'; diff --git a/src/types/typeprinter.h b/src/types/typeprinter.h index ef36eff5..f1414e2e 100644 --- a/src/types/typeprinter.h +++ b/src/types/typeprinter.h @@ -5,7 +5,7 @@ namespace mahjong { struct Event; struct GameState; -struct Hand; +struct Player; class Node; struct Meld; class Walls; @@ -16,12 +16,10 @@ std::ostream& operator<<(std::ostream& os, const mahjong::Event& e); std::ostream& operator<<(std::ostream& os, const mahjong::GameState& state); -std::ostream& operator<<(std::ostream& os, const mahjong::Hand& hand); +std::ostream& operator<<(std::ostream& os, const mahjong::Player& player); std::ostream& operator<<(std::ostream& os, const mahjong::Node& node); std::ostream& operator<<(std::ostream& os, const mahjong::Meld& meld); std::ostream& operator<<(std::ostream& os, const mahjong::Walls& walls); - -std::ostream& operator<<(std::ostream& os, const mahjong::Player& player); diff --git a/src/types/yaku.h b/src/types/yaku.h index b4f4e6ac..75357ceb 100644 --- a/src/types/yaku.h +++ b/src/types/yaku.h @@ -7,8 +7,8 @@ namespace mahjong { -using yakuFunc = std::function&)>; +using yakuFunc = std::function&)>; using Han = int; diff --git a/tests/api/game_control.test.cc b/tests/api/game_control.test.cc index 43353620..19604819 100644 --- a/tests/api/game_control.test.cc +++ b/tests/api/game_control.test.cc @@ -32,9 +32,9 @@ TEST(Api, SettingsConversion) { mahjong::GameState* state = api::InitGameState(&settings); EXPECT_NE(state, nullptr); EXPECT_EQ(state->seed, settings.seed); - EXPECT_EQ(state->players.size(), settings.num_controllers); - for (uint64_t i = 0; i < state->players.size(); ++i) { - EXPECT_EQ(state->players[i]->Name(), settings.seat_controllers[i]); + EXPECT_EQ(state->controllers.size(), settings.num_controllers); + for (uint64_t i = 0; i < state->controllers.size(); ++i) { + EXPECT_EQ(state->controllers[i]->Name(), settings.seat_controllers[i]); } api::FreeGameState(state); } @@ -81,9 +81,9 @@ TEST(Api, ObserveGameState) { // Check arrays are properly sized and initialized for (int i = 0; i < 4; i++) { - EXPECT_EQ(observed.scores[i], state->scores[i]); - EXPECT_EQ(observed.points[i], state->points[i]); - EXPECT_EQ(observed.hasRonned[i], state->hasRonned[i]); + EXPECT_EQ(observed.scores[i], state->players[i].score); + EXPECT_EQ(observed.points[i], state->players[i].points); + EXPECT_EQ(observed.hasRonned[i], state->players[i].hasRonned); } api::FreeGameState(state); @@ -123,13 +123,13 @@ TEST(Api, ObserveGameStateAfterAdvancement) { // Check points are copied for (int i = 0; i < 4; i++) { - EXPECT_EQ(observed.points[i], state->points[i]); + EXPECT_EQ(observed.points[i], state->players[i].points); } api::FreeGameState(state); } -TEST(Api, ObserveGameStateHandsAndDiscards) { +TEST(Api, ObserveGameStatePlayersAndDiscards) { const api::CGameSettings settings = kDefaultSettings; mahjong::GameState* state = api::InitGameState(&settings); @@ -143,46 +143,46 @@ TEST(Api, ObserveGameStateHandsAndDiscards) { // Check that hands are copied (after round start, players should have hands) for (int player = 0; player < 4; player++) { - const api::CHand& c_hand = observed.hands[player]; - const mahjong::Hand& cpp_hand = state->hands[player]; + const api::CPlayer& c_player = observed.hands[player]; + const mahjong::Player& cpp_player = state->players[player]; // Check live pieces - EXPECT_EQ(c_hand.livePieceCount, static_cast(cpp_hand.live_count)); - for (int piece = 0; piece < api::kMaxLiveHandSize; piece++) { - if (piece < c_hand.livePieceCount) { - EXPECT_EQ(c_hand.livePieces[piece], - static_cast(cpp_hand.live[piece].toUint8_t())); + EXPECT_EQ(c_player.livePieceCount, static_cast(cpp_player.live_count)); + for (int piece = 0; piece < api::kMaxLivePlayerSize; piece++) { + if (piece < c_player.livePieceCount) { + EXPECT_EQ(c_player.livePieces[piece], + static_cast(cpp_player.live[piece].toUint8_t())); } else { // Should be filled with error pieces - EXPECT_EQ(c_hand.livePieces[piece], + EXPECT_EQ(c_player.livePieces[piece], static_cast(mahjong::Piece::Type::kError)); } } // Check melds - EXPECT_EQ(c_hand.meldCount, cpp_hand.meld_count); - for (int meld = 0; meld < c_hand.meldCount; meld++) { - EXPECT_EQ(static_cast(c_hand.melds[meld].type), - static_cast(cpp_hand.melds[meld].type)); + EXPECT_EQ(c_player.meldCount, cpp_player.meld_count); + for (int meld = 0; meld < c_player.meldCount; meld++) { + EXPECT_EQ(static_cast(c_player.melds[meld].type), + static_cast(cpp_player.melds[meld].type)); EXPECT_EQ( - c_hand.melds[meld].start, - static_cast(cpp_hand.melds[meld].start.toUint8_t())); + c_player.melds[meld].start, + static_cast(cpp_player.melds[meld].start.toUint8_t())); } - // Check discards using CHand structure - EXPECT_EQ(c_hand.discardCount, static_cast(cpp_hand.discards_count)); - for (int discard = 0; discard < c_hand.discardCount; discard++) { + // Check discards using CPlayer structure + EXPECT_EQ(c_player.discardCount, static_cast(cpp_player.discards_count)); + for (int discard = 0; discard < c_player.discardCount; discard++) { EXPECT_EQ( - c_hand.discards[discard], - static_cast(cpp_hand.discards[discard].toUint8_t())); + c_player.discards[discard], + static_cast(cpp_player.discards[discard].toUint8_t())); } // Check hand properties - EXPECT_EQ(c_hand.open, cpp_hand.open); - EXPECT_EQ(c_hand.riichi, cpp_hand.riichi); - EXPECT_EQ(c_hand.riichiPieceDiscard, - static_cast(cpp_hand.riichiPieceDiscard)); - EXPECT_EQ(c_hand.riichiRound, cpp_hand.riichiRound); + EXPECT_EQ(c_player.open, cpp_player.open); + EXPECT_EQ(c_player.riichi, cpp_player.riichi); + EXPECT_EQ(c_player.riichiPieceDiscard, + static_cast(cpp_player.riichiPieceDiscard)); + EXPECT_EQ(c_player.riichiRound, cpp_player.riichiRound); } api::FreeGameState(state); diff --git a/tests/can_chi.test.cc b/tests/can_chi.test.cc index 18258d9f..d02fbbb7 100644 --- a/tests/can_chi.test.cc +++ b/tests/can_chi.test.cc @@ -13,34 +13,34 @@ TEST(CanChi, EastShouldChiOnNorth) { GameState state; state.pendingPiece = kOneCharacter; state.currentPlayer = 3; - state.hands[0].live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; - state.hands[0].live_count = 3; - EXPECT_TRUE(CanChi(state, 0)); + state.players[0].live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; + state.players[0].live_count = 3; + EXPECT_TRUE(CanChi(state, state.players[0])); state.pendingPiece = kTwoCharacter; - EXPECT_TRUE(CanChi(state, 0)); + EXPECT_TRUE(CanChi(state, state.players[0])); state.pendingPiece = kThreeCharacter; - EXPECT_TRUE(CanChi(state, 0)); + EXPECT_TRUE(CanChi(state, state.players[0])); state.pendingPiece = kFourCharacter; - EXPECT_TRUE(CanChi(state, 0)); + EXPECT_TRUE(CanChi(state, state.players[0])); } TEST(CanChi, EastShouldNotChiOnSouth) { GameState state; state.pendingPiece = kOneCharacter; state.currentPlayer = 1; - state.hands[0].live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; - state.hands[0].live_count = 3; - EXPECT_FALSE(CanChi(state, 0)); + state.players[0].live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; + state.players[0].live_count = 3; + EXPECT_FALSE(CanChi(state, state.players[0])); } TEST(CanChi, NoChiOnHonor) { GameState state; state.pendingPiece = kOneCharacter; state.currentPlayer = 3; - state.hands[0].live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; - state.hands[0].live_count = 3; + state.players[0].live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; + state.players[0].live_count = 3; state.pendingPiece = kWhiteDragon; - EXPECT_FALSE(CanChi(state, 0)); + EXPECT_FALSE(CanChi(state, state.players[0])); } } // namespace mahjong diff --git a/tests/count_pieces.test.cc b/tests/count_pieces.test.cc index 7752fdb4..8c88ee27 100644 --- a/tests/count_pieces.test.cc +++ b/tests/count_pieces.test.cc @@ -5,19 +5,18 @@ #include "statefunctions/stateutilities.h" #include "types/gamestate.h" #include "types/pieces.h" -#include "types/piecetype.h" namespace mahjong { TEST(CountPieces, CountPieces) { - GameState state; - state.hands[0].live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; - state.hands[0].live_count = 4; + Player player; + player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + player.live_count = 4; - EXPECT_EQ(CountPieces(state, 0, kOneCharacter), 1); - EXPECT_EQ(CountPieces(state, 0, kFourPin), 1); - EXPECT_EQ(CountPieces(state, 0, kWhiteDragon), 2); - EXPECT_EQ(CountPieces(state, 0, kGreenDragon), 0); + EXPECT_EQ(CountPieces(player, kOneCharacter), 1); + EXPECT_EQ(CountPieces(player, kFourPin), 1); + EXPECT_EQ(CountPieces(player, kWhiteDragon), 2); + EXPECT_EQ(CountPieces(player, kGreenDragon), 0); } } // namespace mahjong diff --git a/tests/discard_piece.test.cc b/tests/discard_piece.test.cc index 86d1afa0..1f515de0 100644 --- a/tests/discard_piece.test.cc +++ b/tests/discard_piece.test.cc @@ -5,26 +5,25 @@ #include "statefunctions/stateutilities.h" #include "types/gamestate.h" #include "types/pieces.h" -#include "types/piecetype.h" namespace mahjong { TEST(DiscardPiece, DiscardsCorrectPiece) { - GameState state; - state.hands[0].live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; - state.hands[0].live_count = 4; + Player player; + player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + player.live_count = 4; - DiscardPiece(state, 0, kOneCharacter); - EXPECT_EQ(state.hands[0].discards[0], kOneCharacter); + DiscardPiece(player, kOneCharacter); + EXPECT_EQ(player.discards[0], kOneCharacter); } TEST(DiscardPiece, DoesntDiscardInCorrectPiece) { - GameState state; - state.hands[0].live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; - state.hands[0].live_count = 4; + Player player; + player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + player.live_count = 4; - DiscardPiece(state, 0, kGreenDragon); - EXPECT_EQ(state.hands[0].live_count, 4); + DiscardPiece(player, kGreenDragon); + EXPECT_EQ(player.live_count, 4); } } // namespace mahjong diff --git a/tests/game_play.test.cc b/tests/game_play.test.cc index 4af88b9d..93025b7c 100644 --- a/tests/game_play.test.cc +++ b/tests/game_play.test.cc @@ -13,14 +13,14 @@ namespace mahjong { TEST(GamePlay, Furiten) { auto state = GameState(); - Hand& hand = state.hands[0]; - HandFromNotation("123m456p234678s44m", &hand); - hand.open = false; - EXPECT_TRUE(isComplete(state, 0)); + Player& player = state.players[0]; + HandFromNotation("123m456p234678s44m", &player); + player.open = false; + EXPECT_TRUE(isComplete(state, player)); state.pendingPiece = Piece(kFourPin); // Place Four Pin in Discard Pile - hand.discards = {kFourPin}; - EXPECT_FALSE(CanRon(state, 0)); + player.discards = {kFourPin}; + EXPECT_FALSE(CanRon(state, player)); } } // namespace mahjong diff --git a/tests/remove_pieces.test.cc b/tests/remove_pieces.test.cc index 5926c919..18a9cadf 100644 --- a/tests/remove_pieces.test.cc +++ b/tests/remove_pieces.test.cc @@ -5,44 +5,43 @@ #include "statefunctions/stateutilities.h" #include "types/gamestate.h" #include "types/pieces.h" -#include "types/piecetype.h" namespace mahjong { TEST(RemovePieces, RemoveCorrectAmount) { - GameState state; - state.hands[0].live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; - state.hands[0].live_count = 4; + Player player; + player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + player.live_count = 4; - EXPECT_EQ(RemovePieces(state, 0, kOneCharacter, 1), 1); - EXPECT_EQ(state.hands[0].live_count, 3); + EXPECT_EQ(RemovePieces(player, kOneCharacter, 1), 1); + EXPECT_EQ(player.live_count, 3); } TEST(RemovePieces, RemoveOnlyTheOnesAvailable) { - GameState state; - state.hands[0].live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; - state.hands[0].live_count = 4; + Player player; + player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + player.live_count = 4; - EXPECT_EQ(RemovePieces(state, 0, kFourPin, 2), 1); - EXPECT_EQ(state.hands[0].live_count, 3); + EXPECT_EQ(RemovePieces(player, kFourPin, 2), 1); + EXPECT_EQ(player.live_count, 3); } TEST(RemovePieces, OnlyRemovesOne) { - GameState state; - state.hands[0].live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; - state.hands[0].live_count = 4; + Player player; + player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + player.live_count = 4; - EXPECT_EQ(RemovePieces(state, 0, kWhiteDragon, 1), 1); - EXPECT_EQ(state.hands[0].live[2], kWhiteDragon); + EXPECT_EQ(RemovePieces(player, kWhiteDragon, 1), 1); + EXPECT_EQ(player.live[2], kWhiteDragon); } TEST(RemovePieces, RemovesZeroWhenPieceDoesntExist) { - GameState state; - state.hands[0].live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; - state.hands[0].live_count = 4; + Player player; + player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + player.live_count = 4; - EXPECT_EQ(RemovePieces(state, 0, kGreenDragon, 8), 0); - EXPECT_EQ(state.hands[0].live_count, 4); + EXPECT_EQ(RemovePieces(player, kGreenDragon, 8), 0); + EXPECT_EQ(player.live_count, 4); } } // namespace mahjong diff --git a/tests/rules/basic_rules.test.cc b/tests/rules/basic_rules.test.cc index 770b92d5..aa06d154 100644 --- a/tests/rules/basic_rules.test.cc +++ b/tests/rules/basic_rules.test.cc @@ -29,18 +29,18 @@ TEST(GameSetup, playerScore) { EXPECT_EQ(state->currState, StateFunctionType::kGameStart); // All players have the expected starting points for (int i = 0; i < kNumPlayers; i++) { - EXPECT_EQ(state->points[i], kStartingPoints); + EXPECT_EQ(state->players[i].points, kStartingPoints); } } -TEST(RoundSetup, playerHands) { +TEST(RoundSetup, playerPlayers) { auto state = CreateTestGameState(); // Advance through Round Start state = AdvanceThroughState(std::move(state), StateFunctionType::kRoundStart); // Each player should have 13 tiles for (int i = 0; i < kNumPlayers; i++) { - EXPECT_EQ(state->hands[i].live_count, 13) + EXPECT_EQ(state->players[i].live_count, 13) << "Player " << i << " should have 13 tiles"; } } @@ -86,7 +86,7 @@ TEST(TurnOrder, playerRotation) { EXPECT_EQ(state->turnNum, turn); state = AdvanceGameState(std::move(state)); - EXPECT_EQ(state->currState, StateFunctionType::kPlayerHand); + EXPECT_EQ(state->currState, StateFunctionType::kPlayerPlayer); state = AdvanceGameState(std::move(state)); EXPECT_EQ(state->currState, StateFunctionType::kDiscard); state = AdvanceGameState(std::move(state)); @@ -101,7 +101,7 @@ TEST(DrawMechanics, drawIncreasesTileCount) { // All players start with 13 tiles for (int i = 0; i < kNumPlayers; i++) { - EXPECT_EQ(state->hands[i].live_count, 13); + EXPECT_EQ(state->players[i].live_count, 13); } const int walls_before = Walls::GetRemainingPieces(*state); @@ -111,11 +111,11 @@ TEST(DrawMechanics, drawIncreasesTileCount) { EXPECT_EQ(state->currState, StateFunctionType::kDraw); // Player 0 should now have 14 tiles - EXPECT_EQ(state->hands[0].live_count, 14); + EXPECT_EQ(state->players[0].live_count, 14); // Other players still have 13 for (int i = 1; i < kNumPlayers; i++) { - EXPECT_EQ(state->hands[i].live_count, 13); + EXPECT_EQ(state->players[i].live_count, 13); } // Wall should have one less tile @@ -127,14 +127,14 @@ TEST(StateMachine, earlyGameTransitions) { // Advance through Round Start state = AdvanceThroughState(std::move(state), StateFunctionType::kRoundStart); - // Verify early game transitions (RoundStart -> Draw -> PlayerHand) + // Verify early game transitions (RoundStart -> Draw -> PlayerPlayer) // After round start, next state should be draw EXPECT_EQ(state->nextState, StateFunctionType::kDraw); state = AdvanceGameState(std::move(state)); EXPECT_EQ(state->currState, StateFunctionType::kDraw); // After draw, next state should be player hand - EXPECT_EQ(state->nextState, StateFunctionType::kPlayerHand); + EXPECT_EQ(state->nextState, StateFunctionType::kPlayerPlayer); } TEST(DiscardMechanics, discardDecreasesTileCount) { @@ -142,22 +142,22 @@ TEST(DiscardMechanics, discardDecreasesTileCount) { EXPECT_EQ(state->currState, StateFunctionType::kDraw); // Player 0 has 14 tiles after draw - EXPECT_EQ(state->hands[0].live_count, 14); + EXPECT_EQ(state->players[0].live_count, 14); // Move through player hand to discard state = AdvanceGameState(std::move(state)); - EXPECT_EQ(state->currState, StateFunctionType::kPlayerHand); + EXPECT_EQ(state->currState, StateFunctionType::kPlayerPlayer); EXPECT_EQ(state->nextState, StateFunctionType::kDiscard); - const int discards_before = state->hands[0].discards_count; + const int discards_before = state->players[0].discards_count; state = AdvanceGameState(std::move(state)); EXPECT_EQ(state->currState, StateFunctionType::kDiscard); // Player should be back to 13 tiles - EXPECT_EQ(state->hands[0].live_count, 13); + EXPECT_EQ(state->players[0].live_count, 13); // Discard pile should have increased - EXPECT_EQ(state->hands[0].discards_count, discards_before + 1); + EXPECT_EQ(state->players[0].discards_count, discards_before + 1); } } // namespace mahjong diff --git a/tests/rules/calls.test.cc b/tests/rules/calls.test.cc index 42fd7e27..c551ac16 100644 --- a/tests/rules/calls.test.cc +++ b/tests/rules/calls.test.cc @@ -1,9 +1,9 @@ #include +#include #include #include #include -#include #include "controllers/playercontroller.h" #include "statefunctions/statecontroller.h" @@ -22,10 +22,10 @@ TEST(Calls, AcceptPon) { // Player 0: Has a 9 bamboo, and discards it // Player 1: Has a pair of 9 bamboo, will pon when player 0 discards - std::vector> controllers; + std::array, 4> controllers; // Player 0 - controllers.push_back( + controllers[0] = std::make_unique([](const Event& e) -> Event { // Discard 9 Bamboo if (e.type == Event::kDiscard) { @@ -35,10 +35,10 @@ TEST(Calls, AcceptPon) { } return PlayerControllerFake::DefaultDecisionCallback(e); - })); + }); // Player 1 - controllers.push_back( + controllers[1] = std::make_unique([](const Event& e) -> Event { // Accept all Pons if (e.type == Event::kPon) { @@ -46,18 +46,18 @@ TEST(Calls, AcceptPon) { } return PlayerControllerFake::DefaultDecisionCallback(e); - })); + }); // Player 2 and 3 are set to default decline all auto state = InitializeTestRound(12345, std::move(controllers)); // Override with hopeless hands - Hand& player0_hand = state->hands[0]; + Player& player0 = state->players[0]; // 14 Pieces because has drawn in InitializeTestRound. - HandFromNotation("11447m2258p33699s", &player0_hand); + HandFromNotation("11447m2258p33699s", &player0); // Has the pair of nine bamboo 13 Pieces, yet to draw. - Hand& player1_hand = state->hands[1]; - HandFromNotation("13579m99s246p135z", &player1_hand); + Player& player1 = state->players[1]; + HandFromNotation("13579m99s246p135z", &player1); // Advance to pon event // Should take 4 iterations: draw, player hand, discard, and then the pon @@ -73,12 +73,12 @@ TEST(Calls, AcceptPon) { // - State should be kDiscard (Player 1 needs to discard) EXPECT_EQ(state->currentPlayer, 1); EXPECT_EQ(state->currState, StateFunctionType::kDiscard); - EXPECT_EQ(player1_hand.meld_count, 1); - EXPECT_EQ(player1_hand.melds[0].type, SetType::kPon); - EXPECT_EQ(player1_hand.melds[0].start, Piece(Piece::kNineBamboo)); + EXPECT_EQ(player1.meld_count, 1); + EXPECT_EQ(player1.melds[0].type, SetType::kPon); + EXPECT_EQ(player1.melds[0].start, Piece(Piece::kNineBamboo)); // Player 1's live hand should be reduced by 3 tiles (pon + discard) - EXPECT_EQ(player1_hand.live_count, 10); + EXPECT_EQ(player1.live_count, 10); } } // namespace mahjong diff --git a/tests/setup.test.cc b/tests/setup.test.cc index 8be0a3d3..125ff6fa 100644 --- a/tests/setup.test.cc +++ b/tests/setup.test.cc @@ -31,7 +31,7 @@ TEST(Setup, PrevalentWind) { TEST(Setup, DoraIndicator) { std::unique_ptr state = std::make_unique(); for (int i = 0; i < 4; i++) { - state->players[i] = std::make_unique(); + state->controllers[i] = std::make_unique(); } ASSERT_NO_THROW(state = Router::Instance().Route( StateFunctionType::kRoundStart)(std::move(state))); @@ -41,12 +41,12 @@ TEST(Setup, DoraIndicator) { TEST(Setup, Dealing) { std::unique_ptr state = std::make_unique(); for (int i = 0; i < 4; i++) { - state->players[i] = std::make_unique(); + state->controllers[i] = std::make_unique(); } ASSERT_NO_THROW(state = Router::Instance().Route( StateFunctionType::kRoundStart)(std::move(state))); for (int i = 0; i < 4; i++) { - EXPECT_EQ(state->hands[i].live_count, 13); + EXPECT_EQ(state->players[i].live_count, 13); } state = Router::Instance().Route(StateFunctionType::kDraw)(std::move(state)); EXPECT_EQ(state->currentPlayer, 0); diff --git a/tests/utils/gamestate_utils.cc b/tests/utils/gamestate_utils.cc index 96066945..2c648b84 100644 --- a/tests/utils/gamestate_utils.cc +++ b/tests/utils/gamestate_utils.cc @@ -1,13 +1,12 @@ #include "gamestate_utils.h" -#include +#include #include #include #include #include #include #include -#include #include "controllers/playercontroller.h" #include "statefunctions/router.h" @@ -53,7 +52,7 @@ std::unique_ptr CreateTestGameState(uint64_t seed) { auto state = std::make_unique(); state->seed = seed; for (int i = 0; i < kNumPlayers; i++) { - state->players[i] = std::make_unique(); + state->controllers[i] = std::make_unique(); } state->nextState = StateFunctionType::kGameStart; return state; @@ -61,29 +60,16 @@ std::unique_ptr CreateTestGameState(uint64_t seed) { std::unique_ptr InitializeTestRound( uint64_t seed, - std::vector> playerControllers) { + std::array, kNumPlayers> playerControllers) { auto state = std::make_unique(); state->seed = seed; // Use provided controllers or default to PlayerControllerFake - if (!playerControllers.empty()) { - const size_t num_players = - std::min(playerControllers.size(), static_cast(kNumPlayers)); - for (size_t i = 0; i < num_players; i++) { - if (playerControllers[i]) { - state->players[i] = std::move(playerControllers[i]); - } else { - state->players[i] = std::make_unique(); - } - } - // Fill remaining players with default controllers - for (size_t i = num_players; i < kNumPlayers; i++) { - state->players[i] = std::make_unique(); - } - } else { - // All players get default fake controllers - for (int i = 0; i < kNumPlayers; i++) { - state->players[i] = std::make_unique(); + for (size_t i = 0; i < kNumPlayers; i++) { + if (playerControllers[i]) { + state->controllers[i] = std::move(playerControllers[i]); + } else { + state->controllers[i] = std::make_unique(); } } diff --git a/tests/utils/gamestate_utils.h b/tests/utils/gamestate_utils.h index e4a212d3..7875aade 100644 --- a/tests/utils/gamestate_utils.h +++ b/tests/utils/gamestate_utils.h @@ -1,9 +1,9 @@ #pragma once #include -#include #include "controllers/playercontroller.h" #include "types/gamestate.h" +#include "types/settings.h" #include "types/statefunction.h" namespace mahjong { @@ -25,6 +25,7 @@ std::unique_ptr CreateTestGameState(uint64_t seed = 12345); // Advances through standard round initialization std::unique_ptr InitializeTestRound( uint64_t seed = 12345, - std::vector> playerControllers = {}); + std::array, kNumPlayers> + playerControllers = {}); } // namespace mahjong diff --git a/tests/utils/gamestate_utils.test.cc b/tests/utils/gamestate_utils.test.cc index 91480ec8..66acc629 100644 --- a/tests/utils/gamestate_utils.test.cc +++ b/tests/utils/gamestate_utils.test.cc @@ -44,14 +44,14 @@ TEST(GameStateUtils, InitializeTestRoundDefault) { // All players are filled with a controller for (int i = 0; i < kNumPlayers; i++) { - EXPECT_NE(state->players[i], nullptr); + EXPECT_NE(state->controllers[i], nullptr); } // Draw occurred - EXPECT_EQ(state->hands[0].live_count, 14); + EXPECT_EQ(state->players[0].live_count, 14); for (int i = 1; i < kNumPlayers; i++) { - EXPECT_EQ(state->hands[i].live_count, 13); + EXPECT_EQ(state->players[i].live_count, 13); } } diff --git a/tests/utils/handformer.cc b/tests/utils/handformer.cc index 7e7bc1ae..9ff56f07 100644 --- a/tests/utils/handformer.cc +++ b/tests/utils/handformer.cc @@ -93,7 +93,7 @@ std::vector HandFromNotation(const std::string& notation) { return result; } -void HandFromNotation(const std::string& notation, Hand* hand) { +void HandFromNotation(const std::string& notation, Player* hand) { std::vector hand_vec = HandFromNotation(notation); hand->live_count = hand_vec.size(); std::ranges::move(hand_vec, hand->live.begin()); @@ -134,7 +134,7 @@ bool IsValidNotation(const std::string& notation) { return current_set.empty(); } -std::string HandToNotation(const std::vector& hand) { +std::string PlayerToNotation(const std::vector& hand) { std::map> suit_and_tiles; for (const auto& t : hand) { diff --git a/tests/utils/handformer.h b/tests/utils/handformer.h index 5f6a1e62..8d85cabf 100644 --- a/tests/utils/handformer.h +++ b/tests/utils/handformer.h @@ -9,8 +9,8 @@ namespace mahjong { std::vector HandFromNotation(const std::string& notation); -void HandFromNotation(const std::string& notation, Hand* hand); +void HandFromNotation(const std::string& notation, Player* hand); bool IsValidNotation(const std::string& notation); -std::string HandToNotation(const std::vector& hand); +std::string PlayerToNotation(const std::vector& hand); } // namespace mahjong diff --git a/tests/utils/handformer.test.cc b/tests/utils/handformer.test.cc index f1a88bf0..87b0afac 100644 --- a/tests/utils/handformer.test.cc +++ b/tests/utils/handformer.test.cc @@ -10,28 +10,28 @@ namespace mahjong { -TEST(HandFormer, HandFromNotationFormSet) { +TEST(PlayerFormer, HandFromNotationFormSet) { const std::vector hand = {Piece(kOneBamboo), Piece(kTwoBamboo), Piece(kThreeBamboo)}; auto result = HandFromNotation("123s"); EXPECT_EQ(result, hand); } -TEST(HandFormer, HandFromNotationFormWithManySuits) { +TEST(PlayerFormer, HandFromNotationFormWithManySuits) { const std::vector hand = {Piece(kOneBamboo), Piece(kTwoBamboo), Piece(kThreeBamboo), Piece(kFourCharacter)}; auto result = HandFromNotation("123s4m"); EXPECT_EQ(result, hand); } -TEST(HandFormer, HandFromNotationFormRedFives) { +TEST(PlayerFormer, HandFromNotationFormRedFives) { const std::vector hand = {Piece(kRedFiveCharacter), Piece(kRedFiveBamboo), Piece(kRedFivePin)}; auto result = HandFromNotation("0m0s0p"); EXPECT_EQ(result, hand); } -TEST(HandFormer, HandFromNotationFormHonors) { +TEST(PlayerFormer, HandFromNotationFormHonors) { const std::vector hand = {Piece(kEastWind), Piece(kSouthWind), Piece(kWestWind), Piece(kNorthWind), Piece(kWhiteDragon), Piece(kGreenDragon), @@ -40,7 +40,7 @@ TEST(HandFormer, HandFromNotationFormHonors) { EXPECT_EQ(result, hand); } -TEST(HandFormer, HandFromNotationFormTerminals) { +TEST(PlayerFormer, HandFromNotationFormTerminals) { const std::vector hand = {Piece(kOneCharacter), Piece(kNineCharacter), Piece(kOneBamboo), Piece(kNineBamboo), Piece(kOnePin), Piece(kNinePin)}; @@ -48,20 +48,20 @@ TEST(HandFormer, HandFromNotationFormTerminals) { EXPECT_EQ(result, hand); } -TEST(HandFormer, HandFromNotationInvalidPiece) { +TEST(PlayerFormer, HandFromNotationInvalidPiece) { const std::vector hand = {Piece(Piece::kError)}; auto result = HandFromNotation("7g"); EXPECT_EQ(result, hand); } -TEST(HandFormer, HandFromNotationInvalidPieceSet) { +TEST(PlayerFormer, HandFromNotationInvalidPieceSet) { const std::vector hand = {Piece(Piece::kError), Piece(Piece::kError), Piece(Piece::kError)}; auto result = HandFromNotation("799g"); EXPECT_EQ(result, hand); } -TEST(HandFormer, IsValidNotationWithValidNotations) { +TEST(PlayerFormer, IsValidNotationWithValidNotations) { EXPECT_TRUE(IsValidNotation("123s")); EXPECT_TRUE(IsValidNotation("123s456m")); EXPECT_TRUE(IsValidNotation("11z22z33z")); @@ -72,7 +72,7 @@ TEST(HandFormer, IsValidNotationWithValidNotations) { EXPECT_TRUE(IsValidNotation("")); } -TEST(HandFormer, IsValidNotationWithInvaildNotations) { +TEST(PlayerFormer, IsValidNotationWithInvaildNotations) { EXPECT_FALSE(IsValidNotation("123")); EXPECT_FALSE(IsValidNotation("123g456m")); EXPECT_FALSE(IsValidNotation("11z22z33")); @@ -80,35 +80,35 @@ TEST(HandFormer, IsValidNotationWithInvaildNotations) { EXPECT_FALSE(IsValidNotation("8z")); } -TEST(HandFormer, HandToNotationSingleSet) { +TEST(PlayerFormer, PlayerToNotationSingleSet) { const std::vector hand = {Piece(kOneBamboo), Piece(kTwoBamboo), Piece(kThreeBamboo)}; - EXPECT_EQ(HandToNotation(hand), "123s"); + EXPECT_EQ(PlayerToNotation(hand), "123s"); } -TEST(HandFormer, HandToNotationMultipleSets) { +TEST(PlayerFormer, PlayerToNotationMultipleSets) { const std::vector hand = { Piece(kOneBamboo), Piece(kTwoBamboo), Piece(kThreeBamboo), Piece(kFourPin), Piece(kFivePin), Piece(kSixPin), Piece(kNineCharacter), Piece(kEastWind), Piece(kWestWind), }; - EXPECT_EQ(HandToNotation(hand), "13z123s456p9m"); + EXPECT_EQ(PlayerToNotation(hand), "13z123s456p9m"); } -TEST(HandFormer, HandToNotationSkipsErrorPieces) { +TEST(PlayerFormer, PlayerToNotationSkipsErrorPieces) { const std::vector hand = { Piece(kOneBamboo), Piece(Piece::kError), Piece(kThreeBamboo), }; - EXPECT_EQ(HandToNotation(hand), "13s"); + EXPECT_EQ(PlayerToNotation(hand), "13s"); } -TEST(HandFormer, HandToNotationRedFives) { +TEST(PlayerFormer, PlayerToNotationRedFives) { const std::vector hand = { Piece(kFiveBamboo), Piece(kRedFiveBamboo), }; - EXPECT_EQ(HandToNotation(hand), "50s"); + EXPECT_EQ(PlayerToNotation(hand), "50s"); } } // namespace mahjong diff --git a/tests/yakus/afterkan.test.cc b/tests/yakus/afterkan.test.cc index 7b4978db..a8563a5b 100644 --- a/tests/yakus/afterkan.test.cc +++ b/tests/yakus/afterkan.test.cc @@ -15,16 +15,16 @@ namespace mahjong::yaku { TEST(isAfterAKan, 1Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m789m1111z999s55z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m789m1111z999s55z", &player); game_state.currentPlayer = 0; game_state.prevState = StateFunctionType::kReplacement; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAfterAKan(game_state, 0, branch)) { + if (isAfterAKan(game_state, player, branch)) { SUCCEED(); return; } @@ -34,16 +34,16 @@ TEST(isAfterAKan, 1Han) { TEST(isAfterAKan, DoesntApply) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m789m1111z999s55z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m789m1111z999s55z", &player); game_state.currentPlayer = 0; game_state.prevState = StateFunctionType::kPon; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAfterAKan(game_state, 0, branch)) { + if (isAfterAKan(game_state, player, branch)) { FAIL(); return; } @@ -53,16 +53,16 @@ TEST(isAfterAKan, DoesntApply) { TEST(isAfterAKan, WrongPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m789m1111z999s55z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m789m1111z999s55z", &player); game_state.currentPlayer = 2; game_state.prevState = StateFunctionType::kReplacement; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAfterAKan(game_state, 0, branch)) { + if (isAfterAKan(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/allpon.test.cc b/tests/yakus/allpon.test.cc index 1f63f9c5..b21c6ec8 100644 --- a/tests/yakus/allpon.test.cc +++ b/tests/yakus/allpon.test.cc @@ -18,13 +18,13 @@ namespace mahjong::yaku { TEST(isAllPons, 2Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m222p888s666z44m", &hand); + Player& player =game_state.players[0]; + HandFromNotation("111m222p888s666z44m", &player); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllPons(game_state, 0, branch)) { + if (isAllPons(game_state, player, branch)) { SUCCEED(); return; } @@ -34,18 +34,18 @@ TEST(isAllPons, 2Han) { TEST(isAllPons, WithKans) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m222p666z44m", &hand); - hand.melds[hand.meld_count++] = Meld{ + Player& player =game_state.players[0]; + HandFromNotation("111m222p666z44m", &player); + player.melds[player.meld_count++] = Meld{ .type = SetType::kKan, .start = Piece(kFivePin), }; - hand.open = true; + player.open = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllPons(game_state, 0, branch)) { + if (isAllPons(game_state, player, branch)) { SUCCEED(); return; } @@ -55,18 +55,18 @@ TEST(isAllPons, WithKans) { TEST(isAllPons, ConcealedKan) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m222p666z44m", &hand); - hand.melds[hand.meld_count++] = Meld{ + Player& player =game_state.players[0]; + HandFromNotation("111m222p666z44m", &player); + player.melds[player.meld_count++] = Meld{ .type = SetType::kConcealedKan, .start = Piece(kFivePin), }; - hand.open = false; + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllPons(game_state, 0, branch)) { + if (isAllPons(game_state, player, branch)) { SUCCEED(); return; } @@ -74,16 +74,16 @@ TEST(isAllPons, ConcealedKan) { FAIL(); } -TEST(isAllPons, BadHand) { +TEST(isAllPons, BadPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m222p666z789m44m", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("111m222p666z789m44m", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllPons(game_state, 0, branch)) { + if (isAllPons(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/allsimples.test.cc b/tests/yakus/allsimples.test.cc index 57417d74..75f7f611 100644 --- a/tests/yakus/allsimples.test.cc +++ b/tests/yakus/allsimples.test.cc @@ -15,13 +15,13 @@ namespace mahjong::yaku { TEST(isAllSimples, 1Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("222m333p444s555p88m", &hand); + Player& player =game_state.players[0]; + HandFromNotation("222m333p444s555p88m", &player); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllSimples(game_state, 0, branch)) { + if (isAllSimples(game_state, player, branch)) { SUCCEED(); return; } @@ -29,15 +29,15 @@ TEST(isAllSimples, 1Han) { FAIL(); } -TEST(isAllSimples, BadHandHonors) { +TEST(isAllSimples, BadPlayerHonors) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("222m333p444s111z88m", &hand); + Player& player =game_state.players[0]; + HandFromNotation("222m333p444s111z88m", &player); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllSimples(game_state, 0, branch)) { + if (isAllSimples(game_state, player, branch)) { FAIL(); return; } @@ -45,15 +45,15 @@ TEST(isAllSimples, BadHandHonors) { SUCCEED(); } -TEST(isAllSimples, BadHandTerminals) { +TEST(isAllSimples, BadPlayerTerminals) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("222m333p444s111m88m", &hand); + Player& player =game_state.players[0]; + HandFromNotation("222m333p444s111m88m", &player); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllSimples(game_state, 0, branch)) { + if (isAllSimples(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/allterminalsandhonors.test.cc b/tests/yakus/allterminalsandhonors.test.cc index f27ece82..0caf5d6a 100644 --- a/tests/yakus/allterminalsandhonors.test.cc +++ b/tests/yakus/allterminalsandhonors.test.cc @@ -19,14 +19,14 @@ namespace mahjong::yaku { TEST(isAllTerminalsAndHonors, 2Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("222z111p111m999s66z", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("222z111p111m999s66z", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllTerminalsAndHonors(game_state, 0, branch)) { + if (isAllTerminalsAndHonors(game_state, player, branch)) { SUCCEED(); return; } @@ -34,16 +34,16 @@ TEST(isAllTerminalsAndHonors, 2Han) { FAIL(); } -TEST(isAllTerminalsAndHonors, BadHand) { +TEST(isAllTerminalsAndHonors, BadPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("222z111p111m888s66z", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("222z111p111m888s66z", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllTerminalsAndHonors(game_state, 0, branch)) { + if (isAllTerminalsAndHonors(game_state, player, branch)) { FAIL(); return; } @@ -53,18 +53,18 @@ TEST(isAllTerminalsAndHonors, BadHand) { TEST(isAllTerminalsAndHonors, CanBeOpen) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("222z111m999s66z", &hand); - hand.open = true; - hand.melds[hand.meld_count++] = Meld{ + Player& player =game_state.players[0]; + HandFromNotation("222z111m999s66z", &player); + player.open = true; + player.melds[player.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kNinePin), }; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllTerminalsAndHonors(game_state, 0, branch)) { + if (isAllTerminalsAndHonors(game_state, player, branch)) { SUCCEED(); return; } diff --git a/tests/yakus/blessingofman.test.cc b/tests/yakus/blessingofman.test.cc index c45b252c..31e1b317 100644 --- a/tests/yakus/blessingofman.test.cc +++ b/tests/yakus/blessingofman.test.cc @@ -14,21 +14,22 @@ namespace mahjong::yaku { TEST(isBlessingOfMan, 5Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[3]; - HandFromNotation("123m123p444m111z55m", &hand); - hand.open = false; + Player& player =game_state.players[3]; + HandFromNotation("123m123p444m111z55m", &player); + player.open = false; + player.id = 3; game_state.turnNum = 1; // No calls have occured game_state.lastCall = -1; - game_state.hasRonned[3] = true; + player.hasRonned = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isBlessingOfMan(game_state, 3, branch)) { + if (isBlessingOfMan(game_state, player, branch)) { SUCCEED(); return; } @@ -38,21 +39,21 @@ TEST(isBlessingOfMan, 5Han) { TEST(isBlessingOfMan, MustBeARon) { auto game_state = GameState(); - Hand& hand = game_state.hands[3]; - HandFromNotation("123m123p444m111z55m", &hand); - hand.open = false; + Player& player =game_state.players[3]; + HandFromNotation("123m123p444m111z55m", &player); + player.open = false; game_state.turnNum = 3; // No calls have occured game_state.lastCall = -1; - game_state.hasRonned[3] = false; + player.hasRonned = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isBlessingOfMan(game_state, 3, branch)) { + if (isBlessingOfMan(game_state, player, branch)) { FAIL(); return; } @@ -62,21 +63,21 @@ TEST(isBlessingOfMan, MustBeARon) { TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m123p444m111z55m", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("123m123p444m111z55m", &player); + player.open = false; game_state.turnNum = 2; // No calls have occured game_state.lastCall = -1; - game_state.hasRonned[0] = true; + player.hasRonned = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isBlessingOfMan(game_state, 0, branch)) { + if (isBlessingOfMan(game_state, player, branch)) { FAIL(); return; } @@ -86,20 +87,20 @@ TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { TEST(isBlessingOfMan, NoCalledMustHaveOccured) { auto game_state = GameState(); - Hand& hand = game_state.hands[3]; - HandFromNotation("123m123p444m111z55m", &hand); - hand.open = false; + Player& player =game_state.players[3]; + HandFromNotation("123m123p444m111z55m", &player); + player.open = false; game_state.turnNum = 1; game_state.lastCall = 0; - game_state.hasRonned[3] = true; + player.hasRonned = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isBlessingOfMan(game_state, 3, branch)) { + if (isBlessingOfMan(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/concealedhand.test.cc b/tests/yakus/concealedhand.test.cc index 9c11c56b..607f001a 100644 --- a/tests/yakus/concealedhand.test.cc +++ b/tests/yakus/concealedhand.test.cc @@ -11,44 +11,44 @@ namespace mahjong::yaku { TEST(isFullyConcealedHand, 1Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("555m555p555s111z44m", &hand); - hand.open = false; + Player& player = game_state.players[0]; + HandFromNotation("555m555p555s111z44m", &player); + player.open = false; game_state.currentPlayer = 0; - EXPECT_TRUE(isFullyConcealedHand(game_state, 0)); + EXPECT_TRUE(isFullyConcealedHand(game_state, player)); } TEST(isFullyConcealedHand, MustTsumo) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("555m555p555s111z44m", &hand); - hand.open = false; + Player& player = game_state.players[0]; + HandFromNotation("555m555p555s111z44m", &player); + player.open = false; game_state.currentPlayer = 1; - EXPECT_FALSE(isFullyConcealedHand(game_state, 0)); + EXPECT_FALSE(isFullyConcealedHand(game_state, player)); } -TEST(isFullyConcealedHand, MustBeClosedHand) { +TEST(isFullyConcealedHand, MustBeClosedPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("555m555p555s111z44m", &hand); - hand.open = true; + Player& player = game_state.players[0]; + HandFromNotation("555m555p555s111z44m", &player); + player.open = true; game_state.currentPlayer = 0; - EXPECT_FALSE(isFullyConcealedHand(game_state, 0)); + EXPECT_FALSE(isFullyConcealedHand(game_state, player)); } TEST(isFullyConcealedHand, MustHavePiecesRemainingInWall) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("555m555p555s111z44m", &hand); - hand.open = false; + Player& player = game_state.players[0]; + HandFromNotation("555m555p555s111z44m", &player); + player.open = false; game_state.currentPlayer = 0; // Empty the Wall game_state.livingWallIndex = kLivingWallCount; - EXPECT_FALSE(isFullyConcealedHand(game_state, 0)); + EXPECT_FALSE(isFullyConcealedHand(game_state, player)); } } // namespace mahjong::yaku diff --git a/tests/yakus/concealedpon.test.cc b/tests/yakus/concealedpon.test.cc index 4ee6b990..e275f2f1 100644 --- a/tests/yakus/concealedpon.test.cc +++ b/tests/yakus/concealedpon.test.cc @@ -16,14 +16,14 @@ namespace mahjong::yaku { TEST(isThreeConcealedPons, 2Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m111p111s666z44m", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("111m111p111s666z44m", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeConcealedPons(game_state, 0, branch)) { + if (isThreeConcealedPons(game_state, player, branch)) { SUCCEED(); return; } @@ -33,18 +33,18 @@ TEST(isThreeConcealedPons, 2Han) { TEST(isThreeConcealedPons, PonsMustBeConcealed) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m111p111s44m", &hand); - hand.melds[hand.meld_count++] = Meld{ + Player& player =game_state.players[0]; + HandFromNotation("111m111p111s44m", &player); + player.melds[player.meld_count++] = Meld{ .type = SetType::kChi, .start = kTwoBamboo, }; - hand.open = true; + player.open = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeConcealedPons(game_state, 0, branch)) { + if (isThreeConcealedPons(game_state, player, branch)) { SUCCEED(); return; } @@ -54,18 +54,18 @@ TEST(isThreeConcealedPons, PonsMustBeConcealed) { TEST(isThreeConcealedPons, CanHaveAdditionalOpenPon) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m111p111s44m", &hand); - hand.melds[hand.meld_count++] = Meld{ + Player& player =game_state.players[0]; + HandFromNotation("111m111p111s44m", &player); + player.melds[player.meld_count++] = Meld{ .type = SetType::kPon, .start = kTwoBamboo, }; - hand.open = true; + player.open = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeConcealedPons(game_state, 0, branch)) { + if (isThreeConcealedPons(game_state, player, branch)) { SUCCEED(); return; } @@ -75,18 +75,18 @@ TEST(isThreeConcealedPons, CanHaveAdditionalOpenPon) { TEST(isThreeConcealedPons, PonsMustBeConcealedNegative) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m111p234s44m", &hand); - hand.melds[hand.meld_count++] = Meld{ + Player& player =game_state.players[0]; + HandFromNotation("111m111p234s44m", &player); + player.melds[player.meld_count++] = Meld{ .type = SetType::kPon, .start = kOneBamboo, }; - hand.open = true; + player.open = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeConcealedPons(game_state, 0, branch)) { + if (isThreeConcealedPons(game_state, player, branch)) { FAIL(); return; } @@ -94,16 +94,16 @@ TEST(isThreeConcealedPons, PonsMustBeConcealedNegative) { SUCCEED(); } -TEST(isThreeConcealedPons, BadHand) { +TEST(isThreeConcealedPons, BadPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m111p234567s44m", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("111m111p234567s44m", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeConcealedPons(game_state, 0, branch)) { + if (isThreeConcealedPons(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/dragonpon.test.cc b/tests/yakus/dragonpon.test.cc index fb1fbe99..2526cb0a 100644 --- a/tests/yakus/dragonpon.test.cc +++ b/tests/yakus/dragonpon.test.cc @@ -14,13 +14,13 @@ namespace mahjong::yaku { TEST(isWindOrDragonPon, WhiteDragon) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m555z11z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m456m555z11z", &player); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isWhiteDragon(game_state, 0, branch)) { + if (isWhiteDragon(game_state, player, branch)) { SUCCEED(); return; } @@ -30,13 +30,13 @@ TEST(isWindOrDragonPon, WhiteDragon) { TEST(isWindOrDragonPon, GreenDragon) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m666z11z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m456m666z11z", &player); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isGreenDragon(game_state, 0, branch)) { + if (isGreenDragon(game_state, player, branch)) { SUCCEED(); return; } @@ -46,13 +46,13 @@ TEST(isWindOrDragonPon, GreenDragon) { TEST(isWindOrDragonPon, RedDragon) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m777z11z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m456m777z11z", &player); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isRedDragon(game_state, 0, branch)) { + if (isRedDragon(game_state, player, branch)) { SUCCEED(); return; } @@ -62,13 +62,13 @@ TEST(isWindOrDragonPon, RedDragon) { TEST(isWindOrDragonPon, Kan) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m7777z11z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m456m7777z11z", &player); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isRedDragon(game_state, 0, branch)) { + if (isRedDragon(game_state, player, branch)) { SUCCEED(); return; } @@ -78,14 +78,14 @@ TEST(isWindOrDragonPon, Kan) { TEST(isWindOrDragonPon, CanWhenOpen) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m777z11z", &hand); - hand.open = true; + Player& player =game_state.players[0]; + HandFromNotation("123m456m777z11z", &player); + player.open = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isRedDragon(game_state, 0, branch)) { + if (isRedDragon(game_state, player, branch)) { SUCCEED(); return; } @@ -93,15 +93,15 @@ TEST(isWindOrDragonPon, CanWhenOpen) { FAIL(); } -TEST(isWindOrDragonPon, BadHand) { +TEST(isWindOrDragonPon, BadPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m222p11p", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m456m222p11p", &player); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isGreenDragon(game_state, 0, branch)) { + if (isGreenDragon(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/fullflush.test.cc b/tests/yakus/fullflush.test.cc index ac96f944..306385ae 100644 --- a/tests/yakus/fullflush.test.cc +++ b/tests/yakus/fullflush.test.cc @@ -19,18 +19,18 @@ namespace mahjong::yaku { TEST(isFullFlush, 5Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m222m345m99m", &hand); - hand.open = true; - hand.melds[hand.meld_count++] = Meld{ + Player& player =game_state.players[0]; + HandFromNotation("111m222m345m99m", &player); + player.open = true; + player.melds[player.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isFullFlush(game_state, 0, branch)) { + if (isFullFlush(game_state, player, branch)) { SUCCEED(); return; } @@ -40,14 +40,14 @@ TEST(isFullFlush, 5Han) { TEST(isFullFlush, 6Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m222m345m666m99m", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("111m222m345m666m99m", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isFullFlush(game_state, 0, branch)) { + if (isFullFlush(game_state, player, branch)) { SUCCEED(); return; } @@ -55,16 +55,16 @@ TEST(isFullFlush, 6Han) { FAIL(); } -TEST(isFullFlush, BadHandHonors) { +TEST(isFullFlush, BadPlayerHonors) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m222m111z666m99m", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("111m222m111z666m99m", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isFullFlush(game_state, 0, branch)) { + if (isFullFlush(game_state, player, branch)) { FAIL(); return; } @@ -72,16 +72,16 @@ TEST(isFullFlush, BadHandHonors) { SUCCEED(); } -TEST(isFullFlush, BadHandSuit) { +TEST(isFullFlush, BadPlayerSuit) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m222m111p666m99m", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("111m222m111p666m99m", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isFullFlush(game_state, 0, branch)) { + if (isFullFlush(game_state, player, branch)) { FAIL(); return; } @@ -89,16 +89,16 @@ TEST(isFullFlush, BadHandSuit) { SUCCEED(); } -TEST(isFullFlush, BadHandFullFlushHonors) { +TEST(isFullFlush, BadPlayerFullFlushHonors) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111z222z333z444z55z", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("111z222z333z444z55z", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isFullFlush(game_state, 0, branch)) { + if (isFullFlush(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/halfflush.test.cc b/tests/yakus/halfflush.test.cc index 4d5b76f8..c47c68c7 100644 --- a/tests/yakus/halfflush.test.cc +++ b/tests/yakus/halfflush.test.cc @@ -19,18 +19,18 @@ namespace mahjong::yaku { TEST(isHalfFlush, 2Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("11m234m111z222z", &hand); - hand.open = true; - hand.melds[hand.meld_count++] = Meld{ + Player& player =game_state.players[0]; + HandFromNotation("11m234m111z222z", &player); + player.open = true; + player.melds[player.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isHalfFlush(game_state, 0, branch)) { + if (isHalfFlush(game_state, player, branch)) { SUCCEED(); return; } @@ -40,14 +40,14 @@ TEST(isHalfFlush, 2Han) { TEST(isHalfFlush, 3Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("11m234m777m111z222z", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("11m234m777m111z222z", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isHalfFlush(game_state, 0, branch)) { + if (isHalfFlush(game_state, player, branch)) { SUCCEED(); return; } @@ -55,20 +55,20 @@ TEST(isHalfFlush, 3Han) { FAIL(); } -TEST(isHalfFlush, BadHand) { +TEST(isHalfFlush, BadPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("11m234m111p222z", &hand); - hand.open = true; - hand.melds[hand.meld_count++] = Meld{ + Player& player =game_state.players[0]; + HandFromNotation("11m234m111p222z", &player); + player.open = true; + player.melds[player.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isHalfFlush(game_state, 0, branch)) { + if (isHalfFlush(game_state, player, branch)) { FAIL(); return; } @@ -78,18 +78,18 @@ TEST(isHalfFlush, BadHand) { TEST(isHalfFlush, FullFlushIncompatible) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("11m234m888m777m", &hand); - hand.open = true; - hand.melds[hand.meld_count++] = Meld{ + Player& player =game_state.players[0]; + HandFromNotation("11m234m888m777m", &player); + player.open = true; + player.melds[player.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isHalfFlush(game_state, 0, branch)) { + if (isHalfFlush(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/littlethreedragons.test.cc b/tests/yakus/littlethreedragons.test.cc index 0ca363d1..664af521 100644 --- a/tests/yakus/littlethreedragons.test.cc +++ b/tests/yakus/littlethreedragons.test.cc @@ -19,14 +19,14 @@ namespace mahjong::yaku { TEST(isLittleThreeDragons, 2Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("555z666z111m222p77z", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("555z666z111m222p77z", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isLittleThreeDragons(game_state, 0, branch)) { + if (isLittleThreeDragons(game_state, player, branch)) { SUCCEED(); return; } @@ -36,18 +36,18 @@ TEST(isLittleThreeDragons, 2Han) { TEST(isLittleThreeDragons, WhenOpen) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("666z111m222p77z", &hand); - hand.open = true; - hand.melds[hand.meld_count++] = Meld{ + Player& player =game_state.players[0]; + HandFromNotation("666z111m222p77z", &player); + player.open = true; + player.melds[player.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kWhiteDragon), }; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isLittleThreeDragons(game_state, 0, branch)) { + if (isLittleThreeDragons(game_state, player, branch)) { SUCCEED(); return; } @@ -55,20 +55,20 @@ TEST(isLittleThreeDragons, WhenOpen) { FAIL(); } -TEST(isLittleThreeDragons, BadHand) { +TEST(isLittleThreeDragons, BadPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("666z111m222p77s", &hand); - hand.open = true; - hand.melds[hand.meld_count++] = Meld{ + Player& player =game_state.players[0]; + HandFromNotation("666z111m222p77s", &player); + player.open = true; + player.melds[player.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kWhiteDragon), }; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isLittleThreeDragons(game_state, 0, branch)) { + if (isLittleThreeDragons(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/mixedtriplechi.test.cc b/tests/yakus/mixedtriplechi.test.cc index aa68950b..1ea8e940 100644 --- a/tests/yakus/mixedtriplechi.test.cc +++ b/tests/yakus/mixedtriplechi.test.cc @@ -15,14 +15,14 @@ namespace mahjong::yaku { TEST(isMixedTripleChi, Open) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123p123m123s555p11z", &hand); - hand.open = true; + Player& player =game_state.players[0]; + HandFromNotation("123p123m123s555p11z", &player); + player.open = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isMixedTripleChi(game_state, 0, branch)) { + if (isMixedTripleChi(game_state, player, branch)) { SUCCEED(); return; } @@ -32,14 +32,14 @@ TEST(isMixedTripleChi, Open) { TEST(isMixedTripleChi, Closed) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123p123m123s555p11z", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("123p123m123s555p11z", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isMixedTripleChi(game_state, 0, branch)) { + if (isMixedTripleChi(game_state, player, branch)) { SUCCEED(); return; } @@ -47,16 +47,16 @@ TEST(isMixedTripleChi, Closed) { FAIL(); } -TEST(isMixedTripleChi, BadHand) { +TEST(isMixedTripleChi, BadPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123p123p123s555p11z", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("123p123p123s555p11z", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isMixedTripleChi(game_state, 0, branch)) { + if (isMixedTripleChi(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/outsidehand.test.cc b/tests/yakus/outsidehand.test.cc index d51108bb..d781cca6 100644 --- a/tests/yakus/outsidehand.test.cc +++ b/tests/yakus/outsidehand.test.cc @@ -15,14 +15,14 @@ namespace mahjong::yaku { TEST(isOutsideHand, Open) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m789m111z999s55z", &hand); - hand.open = true; + Player& player =game_state.players[0]; + HandFromNotation("123m789m111z999s55z", &player); + player.open = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isOutsideHand(game_state, 0, branch)) { + if (isOutsideHand(game_state, player, branch)) { SUCCEED(); return; } @@ -32,14 +32,14 @@ TEST(isOutsideHand, Open) { TEST(isOutsideHand, Closed) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m789m111z999s55z", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("123m789m111z999s55z", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isOutsideHand(game_state, 0, branch)) { + if (isOutsideHand(game_state, player, branch)) { SUCCEED(); return; } @@ -49,13 +49,13 @@ TEST(isOutsideHand, Closed) { TEST(isOutsideHand, NoChi) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m111p111s999m66z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("111m111p111s999m66z", &player); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isOutsideHand(game_state, 0, branch)) { + if (isOutsideHand(game_state, player, branch)) { FAIL(); return; } @@ -63,15 +63,15 @@ TEST(isOutsideHand, NoChi) { SUCCEED(); } -TEST(isOutsideHand, BadHand) { +TEST(isOutsideHand, BadPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m234p111s999m66z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("111m234p111s999m66z", &player); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isOutsideHand(game_state, 0, branch)) { + if (isOutsideHand(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/pinfu.test.cc b/tests/yakus/pinfu.test.cc index 15c643fc..5fe8b0eb 100644 --- a/tests/yakus/pinfu.test.cc +++ b/tests/yakus/pinfu.test.cc @@ -17,15 +17,15 @@ namespace mahjong::yaku { TEST(isPinfu, 1Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456p234678s44m", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("123m456p234678s44m", &player); + player.open = false; game_state.pendingPiece = Piece(kFourPin); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPinfu(game_state, 0, branch)) { + if (isPinfu(game_state, player, branch)) { SUCCEED(); return; } @@ -33,17 +33,17 @@ TEST(isPinfu, 1Han) { FAIL(); } -TEST(isPinfu, BadHand) { +TEST(isPinfu, BadPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m555p234678s44m", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("123m555p234678s44m", &player); + player.open = false; game_state.pendingPiece = Piece(kTwoBamboo); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPinfu(game_state, 0, branch)) { + if (isPinfu(game_state, player, branch)) { FAIL(); return; } @@ -53,15 +53,15 @@ TEST(isPinfu, BadHand) { TEST(isPinfu, CantBeOpen) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456p234678s44m", &hand); - hand.open = true; + Player& player =game_state.players[0]; + HandFromNotation("123m456p234678s44m", &player); + player.open = true; game_state.pendingPiece = Piece(kFourPin); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPinfu(game_state, 0, branch)) { + if (isPinfu(game_state, player, branch)) { FAIL(); return; } @@ -71,15 +71,15 @@ TEST(isPinfu, CantBeOpen) { TEST(isPinfu, NeedTwoWait) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456p234678s44m", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("123m456p234678s44m", &player); + player.open = false; game_state.pendingPiece = Piece(kFivePin); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPinfu(game_state, 0, branch)) { + if (isPinfu(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/puredoublechi.test.cc b/tests/yakus/puredoublechi.test.cc index 53bc3658..26704360 100644 --- a/tests/yakus/puredoublechi.test.cc +++ b/tests/yakus/puredoublechi.test.cc @@ -15,14 +15,14 @@ namespace mahjong::yaku { TEST(isPureDoubleChi, 1Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("234m234m555p888s88p", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("234m234m555p888s88p", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPureDoubleChi(game_state, 0, branch)) { + if (isPureDoubleChi(game_state, player, branch)) { SUCCEED(); return; } @@ -30,16 +30,16 @@ TEST(isPureDoubleChi, 1Han) { FAIL(); } -TEST(isPureDoubleChi, BadHand) { +TEST(isPureDoubleChi, BadPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("234m123m555p888s88p", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("234m123m555p888s88p", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPureDoubleChi(game_state, 0, branch)) { + if (isPureDoubleChi(game_state, player, branch)) { FAIL(); return; } @@ -49,14 +49,14 @@ TEST(isPureDoubleChi, BadHand) { TEST(isPureDoubleChi, MustBeConcealed) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("234m234m555p888s88p", &hand); - hand.open = true; + Player& player =game_state.players[0]; + HandFromNotation("234m234m555p888s88p", &player); + player.open = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPureDoubleChi(game_state, 0, branch)) { + if (isPureDoubleChi(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/purestraight.test.cc b/tests/yakus/purestraight.test.cc index b2d624f4..f3864eb7 100644 --- a/tests/yakus/purestraight.test.cc +++ b/tests/yakus/purestraight.test.cc @@ -15,14 +15,14 @@ namespace mahjong::yaku { TEST(isPureStraight, Open) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m789m555p11z", &hand); - hand.open = true; + Player& player =game_state.players[0]; + HandFromNotation("123m456m789m555p11z", &player); + player.open = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPureStraight(game_state, 0, branch)) { + if (isPureStraight(game_state, player, branch)) { SUCCEED(); return; } @@ -32,14 +32,14 @@ TEST(isPureStraight, Open) { TEST(isPureStraight, Closed) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m789m555p11z", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("123m456m789m555p11z", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPureStraight(game_state, 0, branch)) { + if (isPureStraight(game_state, player, branch)) { SUCCEED(); return; } @@ -47,16 +47,16 @@ TEST(isPureStraight, Closed) { FAIL(); } -TEST(isPureStraight, BadHand) { +TEST(isPureStraight, BadPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m999m555p11z", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("123m456m999m555p11z", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPureStraight(game_state, 0, branch)) { + if (isPureStraight(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/riichi.test.cc b/tests/yakus/riichi.test.cc index 8d8f7ce1..306f2fc4 100644 --- a/tests/yakus/riichi.test.cc +++ b/tests/yakus/riichi.test.cc @@ -14,52 +14,52 @@ namespace mahjong::yaku { TEST(isRiichi, Riichi) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("555m555p555s111z44m", &hand); - hand.riichi = true; + Player& player = game_state.players[0]; + HandFromNotation("555m555p555s111z44m", &player); + player.riichi = true; - hand.riichiRound = 7; + player.riichiRound = 7; game_state.turnNum = 15; game_state.lastCall = 2; - EXPECT_TRUE(isRiichi(game_state, 0)); + EXPECT_TRUE(isRiichi(game_state, player)); } TEST(isRiichi, Ippatsu) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("555m555p555s111z44m", &hand); - hand.riichi = true; + Player& player = game_state.players[0]; + HandFromNotation("555m555p555s111z44m", &player); + player.riichi = true; - hand.riichiRound = 14; + player.riichiRound = 14; game_state.turnNum = 15; game_state.lastCall = 2; - EXPECT_TRUE(isIppatsu(game_state, 0)); + EXPECT_TRUE(isIppatsu(game_state, player)); } TEST(isRiichi, DoubleRiichi) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("555m555p555s111z44m", &hand); - hand.riichi = true; + Player& player = game_state.players[0]; + HandFromNotation("555m555p555s111z44m", &player); + player.riichi = true; - hand.riichiRound = 1; + player.riichiRound = 1; game_state.turnNum = 2; game_state.lastCall = -1; - EXPECT_TRUE(isDoubleRiichi(game_state, 0)); + EXPECT_TRUE(isDoubleRiichi(game_state, player)); } TEST(isRiichi, NoRiichi) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("555m555p555s111z44m", &hand); - hand.riichi = false; + Player& player = game_state.players[0]; + HandFromNotation("555m555p555s111z44m", &player); + player.riichi = false; game_state.turnNum = 2; game_state.lastCall = -1; - EXPECT_FALSE(isRiichi(game_state, 0)); + EXPECT_FALSE(isRiichi(game_state, player)); } } // namespace mahjong::yaku diff --git a/tests/yakus/robbingkan.test.cc b/tests/yakus/robbingkan.test.cc index d34acad0..e0b148d0 100644 --- a/tests/yakus/robbingkan.test.cc +++ b/tests/yakus/robbingkan.test.cc @@ -15,15 +15,15 @@ namespace mahjong::yaku { TEST(isRobbingAKan, 1Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m789m1111z999s55z", &hand); - game_state.hasRonned[0] = true; + Player& player =game_state.players[0]; + HandFromNotation("123m789m1111z999s55z", &player); + game_state.players[0].hasRonned = true; game_state.nextState = StateFunctionType::kKanDiscard; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isRobbingAKan(game_state, 0, branch)) { + if (isRobbingAKan(game_state, player, branch)) { SUCCEED(); return; } @@ -33,15 +33,15 @@ TEST(isRobbingAKan, 1Han) { TEST(isRobbingAKan, DoesntApply) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m789m1111z999s55z", &hand); - game_state.hasRonned[0] = true; + Player& player =game_state.players[0]; + HandFromNotation("123m789m1111z999s55z", &player); + game_state.players[0].hasRonned = true; game_state.nextState = StateFunctionType::kPon; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isRobbingAKan(game_state, 0, branch)) { + if (isRobbingAKan(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/sevenpairs.test.cc b/tests/yakus/sevenpairs.test.cc index b1b1278f..d8c2655e 100644 --- a/tests/yakus/sevenpairs.test.cc +++ b/tests/yakus/sevenpairs.test.cc @@ -15,14 +15,14 @@ namespace mahjong::yaku { TEST(isSevenPairs, 2Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("11m22p33s44z55m11z66z", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("11m22p33s44z55m11z66z", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSevenPairs(game_state, 0, branch)) { + if (isSevenPairs(game_state, player, branch)) { SUCCEED(); return; } @@ -32,14 +32,14 @@ TEST(isSevenPairs, 2Han) { TEST(isSevenPairs, MustBeConcealed) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("11m22p33s44z55m11z66z", &hand); - hand.open = true; + Player& player =game_state.players[0]; + HandFromNotation("11m22p33s44z55m11z66z", &player); + player.open = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSevenPairs(game_state, 0, branch)) { + if (isSevenPairs(game_state, player, branch)) { FAIL(); return; } @@ -49,14 +49,14 @@ TEST(isSevenPairs, MustBeConcealed) { TEST(isSevenPairs, UniquePairsOnly) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("1111m22p33s44z11z66z", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("1111m22p33s44z11z66z", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSevenPairs(game_state, 0, branch)) { + if (isSevenPairs(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/terminalinsets.test.cc b/tests/yakus/terminalinsets.test.cc index c8d6e214..4fdcbff8 100644 --- a/tests/yakus/terminalinsets.test.cc +++ b/tests/yakus/terminalinsets.test.cc @@ -18,18 +18,18 @@ namespace mahjong::yaku { TEST(isTerminalsInAllSets, 2Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m789m111p11s", &hand); - hand.open = true; - hand.melds[hand.meld_count++] = Meld{ + Player& player =game_state.players[0]; + HandFromNotation("123m789m111p11s", &player); + player.open = true; + player.melds[player.meld_count++] = Meld{ .type = SetType::kChi, .start = Piece(kSevenPin), }; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTerminalsInAllSets(game_state, 0, branch)) { + if (isTerminalsInAllSets(game_state, player, branch)) { SUCCEED(); return; } @@ -39,14 +39,14 @@ TEST(isTerminalsInAllSets, 2Han) { TEST(isTerminalsInAllSets, 3Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m789m111p789p11s", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("123m789m111p789p11s", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTerminalsInAllSets(game_state, 0, branch)) { + if (isTerminalsInAllSets(game_state, player, branch)) { SUCCEED(); return; } @@ -54,21 +54,21 @@ TEST(isTerminalsInAllSets, 3Han) { FAIL(); } -TEST(isTerminalsInAllSets, BadHand) { +TEST(isTerminalsInAllSets, BadPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m789m222p11s", &hand); - hand.open = true; - hand.open = true; - hand.melds[hand.meld_count++] = Meld{ + Player& player =game_state.players[0]; + HandFromNotation("123m789m222p11s", &player); + player.open = true; + player.open = true; + player.melds[player.meld_count++] = Meld{ .type = SetType::kChi, .start = Piece(kSevenPin), }; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTerminalsInAllSets(game_state, 0, branch)) { + if (isTerminalsInAllSets(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/triplekan.test.cc b/tests/yakus/triplekan.test.cc index 506ce312..e1185c71 100644 --- a/tests/yakus/triplekan.test.cc +++ b/tests/yakus/triplekan.test.cc @@ -31,16 +31,16 @@ TEST(isThreeKans, 2Han) { }; auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("666z22m", &hand); - hand.melds = {meld_a, meld_b, meld_c}; - hand.meld_count = 3; - hand.open = true; + Player& player =game_state.players[0]; + HandFromNotation("666z22m", &player); + player.melds = {meld_a, meld_b, meld_c}; + player.meld_count = 3; + player.open = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeKans(game_state, 0, branch)) { + if (isThreeKans(game_state, player, branch)) { SUCCEED(); return; } @@ -67,16 +67,16 @@ TEST(isThreeKans, WithOtherMelds) { }; auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("22m", &hand); - hand.melds = {meld_a, meld_b, meld_c, meld_d}; - hand.meld_count = 4; - hand.open = true; + Player& player =game_state.players[0]; + HandFromNotation("22m", &player); + player.melds = {meld_a, meld_b, meld_c, meld_d}; + player.meld_count = 4; + player.open = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeKans(game_state, 0, branch)) { + if (isThreeKans(game_state, player, branch)) { SUCCEED(); return; } @@ -84,7 +84,7 @@ TEST(isThreeKans, WithOtherMelds) { FAIL(); } -TEST(isThreeKans, BadHand) { +TEST(isThreeKans, BadPlayer) { const Meld meld_a = { .type = SetType::kConcealedKan, .start = Piece(kOneBamboo), @@ -95,16 +95,16 @@ TEST(isThreeKans, BadHand) { }; auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("777p666z22m", &hand); - hand.melds = {meld_a, meld_b}; - hand.meld_count = 2; - hand.open = true; + Player& player =game_state.players[0]; + HandFromNotation("777p666z22m", &player); + player.melds = {meld_a, meld_b}; + player.meld_count = 2; + player.open = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeKans(game_state, 0, branch)) { + if (isThreeKans(game_state, player, branch)) { FAIL(); return; } @@ -127,16 +127,16 @@ TEST(isThreeKans, AllConcealed) { }; auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("666z22m", &hand); - hand.melds = {meld_a, meld_b, meld_c}; - hand.meld_count = 3; - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("666z22m", &player); + player.melds = {meld_a, meld_b, meld_c}; + player.meld_count = 3; + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeKans(game_state, 0, branch)) { + if (isThreeKans(game_state, player, branch)) { SUCCEED(); return; } diff --git a/tests/yakus/triplepon.test.cc b/tests/yakus/triplepon.test.cc index 12d3dfde..3b222668 100644 --- a/tests/yakus/triplepon.test.cc +++ b/tests/yakus/triplepon.test.cc @@ -15,13 +15,13 @@ namespace mahjong::yaku { TEST(isTriplePon, 2Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m111p111s666z44m", &hand); + Player& player =game_state.players[0]; + HandFromNotation("111m111p111s666z44m", &player); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTriplePon(game_state, 0, branch)) { + if (isTriplePon(game_state, player, branch)) { SUCCEED(); return; } @@ -29,15 +29,15 @@ TEST(isTriplePon, 2Han) { FAIL(); } -TEST(isTriplePon, BadHand) { +TEST(isTriplePon, BadPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("111m111p222m666z44m", &hand); + Player& player =game_state.players[0]; + HandFromNotation("111m111p222m666z44m", &player); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTriplePon(game_state, 0, branch)) { + if (isTriplePon(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/twicepuredoublechi.test.cc b/tests/yakus/twicepuredoublechi.test.cc index b9ee9207..b26e2498 100644 --- a/tests/yakus/twicepuredoublechi.test.cc +++ b/tests/yakus/twicepuredoublechi.test.cc @@ -15,14 +15,14 @@ namespace mahjong::yaku { TEST(isTwicePureDoubleChi, 3Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("789p789p234m234m11z", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("789p789p234m234m11z", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTwicePureDoubleChi(game_state, 0, branch)) { + if (isTwicePureDoubleChi(game_state, player, branch)) { SUCCEED(); return; } @@ -32,14 +32,14 @@ TEST(isTwicePureDoubleChi, 3Han) { TEST(isTwicePureDoubleChi, MustBeConcealed) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("789p789p234m234m11z", &hand); - hand.open = true; + Player& player =game_state.players[0]; + HandFromNotation("789p789p234m234m11z", &player); + player.open = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTwicePureDoubleChi(game_state, 0, branch)) { + if (isTwicePureDoubleChi(game_state, player, branch)) { FAIL(); return; } @@ -47,16 +47,16 @@ TEST(isTwicePureDoubleChi, MustBeConcealed) { SUCCEED(); } -TEST(isTwicePureDoubleChi, BadHand) { +TEST(isTwicePureDoubleChi, BadPlayer) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("789p789p234m567m11z", &hand); - hand.open = false; + Player& player =game_state.players[0]; + HandFromNotation("789p789p234m567m11z", &player); + player.open = false; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTwicePureDoubleChi(game_state, 0, branch)) { + if (isTwicePureDoubleChi(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/underthesea.test.cc b/tests/yakus/underthesea.test.cc index bdad55a2..ff2e91f1 100644 --- a/tests/yakus/underthesea.test.cc +++ b/tests/yakus/underthesea.test.cc @@ -14,14 +14,14 @@ namespace mahjong::yaku { TEST(isBottomOfTheSea, 1Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m789m111z999s55z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m789m111z999s55z", &player); game_state.livingWallIndex = kLivingWallCount; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isBottomOfTheSea(game_state, 0, branch)) { + if (isBottomOfTheSea(game_state, player, branch)) { SUCCEED(); return; } @@ -31,15 +31,15 @@ TEST(isBottomOfTheSea, 1Han) { TEST(isBottomOfTheSea, 1HanRonned) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m789m111z999s55z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m789m111z999s55z", &player); game_state.livingWallIndex = kLivingWallCount; - game_state.hasRonned[0] = true; + game_state.players[0].hasRonned = true; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isBottomOfTheSea(game_state, 0, branch)) { + if (isBottomOfTheSea(game_state, player, branch)) { SUCCEED(); return; } @@ -49,13 +49,13 @@ TEST(isBottomOfTheSea, 1HanRonned) { TEST(isBottomOfTheSea, DoesntApply) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m789m111z999s55z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m789m111z999s55z", &player); - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isBottomOfTheSea(game_state, 0, branch)) { + if (isBottomOfTheSea(game_state, player, branch)) { FAIL(); return; } diff --git a/tests/yakus/windpons.test.cc b/tests/yakus/windpons.test.cc index ba96e757..ae5886e0 100644 --- a/tests/yakus/windpons.test.cc +++ b/tests/yakus/windpons.test.cc @@ -14,16 +14,16 @@ namespace mahjong::yaku { TEST(isWindOrDragonPon, SeatWind) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m444z55z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m456m444z55z", &player); game_state.roundNum = 1; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); auto branches = Node::AsBranchVectors(root.get()); for (const auto& branch : branches) { - if (isSeatWind(game_state, 0, branch)) { + if (isSeatWind(game_state, player, branch)) { SUCCEED(); return; } @@ -34,14 +34,14 @@ TEST(isWindOrDragonPon, SeatWind) { TEST(isWindOrDragonPon, SeatWindKan) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m4444z55z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m456m4444z55z", &player); game_state.roundNum = 1; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSeatWind(game_state, 0, branch)) { + if (isSeatWind(game_state, player, branch)) { SUCCEED(); return; } @@ -51,14 +51,14 @@ TEST(isWindOrDragonPon, SeatWindKan) { TEST(isWindOrDragonPon, PrevalentWind) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m111z55z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m456m111z55z", &player); game_state.roundNum = 1; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPrevalentWind(game_state, 0, branch)) { + if (isPrevalentWind(game_state, player, branch)) { SUCCEED(); return; } @@ -68,14 +68,14 @@ TEST(isWindOrDragonPon, PrevalentWind) { TEST(isWindOrDragonPon, PrevalentWindKan) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m1111z55z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m456m1111z55z", &player); game_state.roundNum = 1; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPrevalentWind(game_state, 0, branch)) { + if (isPrevalentWind(game_state, player, branch)) { SUCCEED(); return; } @@ -85,15 +85,15 @@ TEST(isWindOrDragonPon, PrevalentWindKan) { TEST(isWindOrDragonPon, Dealer2Han) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m111z55z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m456m111z55z", &player); game_state.roundNum = 0; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSeatWind(game_state, 0, branch) && - isPrevalentWind(game_state, 0, branch)) { + if (isSeatWind(game_state, player, branch) && + isPrevalentWind(game_state, player, branch)) { SUCCEED(); return; } @@ -103,15 +103,15 @@ TEST(isWindOrDragonPon, Dealer2Han) { TEST(isWindOrDragonPon, Dealer2HanKan) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m1111z55z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m456m1111z55z", &player); game_state.roundNum = 0; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSeatWind(game_state, 0, branch) && - isPrevalentWind(game_state, 0, branch)) { + if (isSeatWind(game_state, player, branch) && + isPrevalentWind(game_state, player, branch)) { SUCCEED(); return; } @@ -121,15 +121,15 @@ TEST(isWindOrDragonPon, Dealer2HanKan) { TEST(isWindOrDragonPon, NotSeatOrPrevalent) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m222z55z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m456m222z55z", &player); game_state.roundNum = 0; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSeatWind(game_state, 0, branch) || - isPrevalentWind(game_state, 0, branch)) { + if (isSeatWind(game_state, player, branch) || + isPrevalentWind(game_state, player, branch)) { FAIL(); return; } @@ -139,15 +139,15 @@ TEST(isWindOrDragonPon, NotSeatOrPrevalent) { TEST(isWindOrDragonPon, NoWind) { auto game_state = GameState(); - Hand& hand = game_state.hands[0]; - HandFromNotation("123m456m666m55z", &hand); + Player& player =game_state.players[0]; + HandFromNotation("123m456m666m55z", &player); game_state.roundNum = 0; - auto root = breakdownHand(hand.live_range()); + auto root = breakdownPlayer(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSeatWind(game_state, 0, branch) || - isPrevalentWind(game_state, 0, branch)) { + if (isSeatWind(game_state, player, branch) || + isPrevalentWind(game_state, player, branch)) { FAIL(); return; } diff --git a/tools/driver/main.cc b/tools/driver/main.cc index 46d7d1e0..9721b8ff 100644 --- a/tools/driver/main.cc +++ b/tools/driver/main.cc @@ -79,8 +79,8 @@ int main() { // state->lastCall = 36; // state->pendingPiece = kNineCharacter; // state->roundNum = 2; - // state->hands[0].live = {kNineCharacter,kNineCharacter,kNineCharacter,kOnePin,kTwoPin,kThreePin,kEastWind,kEastWind}; - // state->hands[0].melds = { + // state->players[0].live = {kNineCharacter,kNineCharacter,kNineCharacter,kOnePin,kTwoPin,kThreePin,kEastWind,kEastWind}; + // state->players[0].melds = { // { // Meld::kChi, // kThreeBamboo From 3ed58e02fce3cf274009d94e80e2477923519652 Mon Sep 17 00:00:00 2001 From: alice Hartley Date: Fri, 5 Sep 2025 10:50:42 -0700 Subject: [PATCH 10/14] BreakdownPlayer -> BreakdownHand --- src/analysis/analysis.cc | 4 ++-- src/analysis/analysis.h | 2 +- src/controllers/gentlemanbot.cc | 2 +- src/scoring/scoring.cc | 4 ++-- tests/yakus/afterkan.test.cc | 6 +++--- tests/yakus/allpon.test.cc | 8 ++++---- tests/yakus/allsimples.test.cc | 6 +++--- tests/yakus/allterminalsandhonors.test.cc | 6 +++--- tests/yakus/blessingofman.test.cc | 8 ++++---- tests/yakus/concealedpon.test.cc | 10 +++++----- tests/yakus/dragonpon.test.cc | 12 ++++++------ tests/yakus/fullflush.test.cc | 10 +++++----- tests/yakus/halfflush.test.cc | 8 ++++---- tests/yakus/littlethreedragons.test.cc | 6 +++--- tests/yakus/mixedtriplechi.test.cc | 6 +++--- tests/yakus/outsidehand.test.cc | 8 ++++---- tests/yakus/pinfu.test.cc | 8 ++++---- tests/yakus/puredoublechi.test.cc | 6 +++--- tests/yakus/purestraight.test.cc | 6 +++--- tests/yakus/robbingkan.test.cc | 4 ++-- tests/yakus/sevenpairs.test.cc | 6 +++--- tests/yakus/terminalinsets.test.cc | 6 +++--- tests/yakus/triplekan.test.cc | 8 ++++---- tests/yakus/triplepon.test.cc | 4 ++-- tests/yakus/twicepuredoublechi.test.cc | 6 +++--- tests/yakus/underthesea.test.cc | 6 +++--- tests/yakus/windpons.test.cc | 16 ++++++++-------- 27 files changed, 91 insertions(+), 91 deletions(-) diff --git a/src/analysis/analysis.cc b/src/analysis/analysis.cc index ce03aa56..763bd907 100644 --- a/src/analysis/analysis.cc +++ b/src/analysis/analysis.cc @@ -43,7 +43,7 @@ std::vector AnalyzeHand(const Player& player, } } std::vector branches; - const std::unique_ptr root = breakdownPlayer(player.live_range()); + const std::unique_ptr root = breakdownHand(player.live_range()); for (const auto& branch_vec : Node::AsBranchVectors(root.get())) { branches.push_back(base_branch); Branch& branch = branches.back(); @@ -75,7 +75,7 @@ std::vector AnalyzeHand(const Player& player, return branches; } -std::unique_ptr breakdownPlayer(const std::span& pieces) { +std::unique_ptr breakdownHand(const std::span& pieces) { Breakdown b; b.rootNode = std::make_unique(/*id=*/b.id++); b.currentNode = b.rootNode.get(); diff --git a/src/analysis/analysis.h b/src/analysis/analysis.h index bddff06a..67c53659 100644 --- a/src/analysis/analysis.h +++ b/src/analysis/analysis.h @@ -17,7 +17,7 @@ struct Branch { bool complete = true; }; -std::unique_ptr breakdownPlayer(const std::span& pieces); +std::unique_ptr breakdownHand(const std::span& pieces); std::vector AnalyzeHand(const Player& player, bool only_complete = false); } // namespace mahjong diff --git a/src/controllers/gentlemanbot.cc b/src/controllers/gentlemanbot.cc index 37aab896..1d2bb2d7 100644 --- a/src/controllers/gentlemanbot.cc +++ b/src/controllers/gentlemanbot.cc @@ -71,7 +71,7 @@ Piece GentlemanBot::getDiscard() { std::vector third_tier_discards; std::array counts = {}; - const std::unique_ptr symbolic_hand = breakdownPlayer(hand_); + const std::unique_ptr symbolic_hand = breakdownHand(hand_); for (const auto& leaf : *symbolic_hand) { if (leaf.type() == SetType::kSingle) { diff --git a/src/scoring/scoring.cc b/src/scoring/scoring.cc index 3ec34664..8c785c4f 100644 --- a/src/scoring/scoring.cc +++ b/src/scoring/scoring.cc @@ -59,7 +59,7 @@ const int kFuRounding = 10; } // namespace Score scorePlayer(const GameState& state, const Player& player) { - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); Score s; s.han = 0; s.yakuman = 0; @@ -260,7 +260,7 @@ bool isOpenPinfu(const GameState& state, const Player& player, } bool isComplete(const GameState& state, const Player& player) { - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); if (!root->IsComplete() && !yaku::isThirteenOrphans(state, player)) { return false; } diff --git a/tests/yakus/afterkan.test.cc b/tests/yakus/afterkan.test.cc index a8563a5b..55049873 100644 --- a/tests/yakus/afterkan.test.cc +++ b/tests/yakus/afterkan.test.cc @@ -21,7 +21,7 @@ TEST(isAfterAKan, 1Han) { game_state.prevState = StateFunctionType::kReplacement; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAfterAKan(game_state, player, branch)) { @@ -40,7 +40,7 @@ TEST(isAfterAKan, DoesntApply) { game_state.prevState = StateFunctionType::kPon; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAfterAKan(game_state, player, branch)) { @@ -59,7 +59,7 @@ TEST(isAfterAKan, WrongPlayer) { game_state.prevState = StateFunctionType::kReplacement; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAfterAKan(game_state, player, branch)) { diff --git a/tests/yakus/allpon.test.cc b/tests/yakus/allpon.test.cc index b21c6ec8..a88fd051 100644 --- a/tests/yakus/allpon.test.cc +++ b/tests/yakus/allpon.test.cc @@ -21,7 +21,7 @@ TEST(isAllPons, 2Han) { Player& player =game_state.players[0]; HandFromNotation("111m222p888s666z44m", &player); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllPons(game_state, player, branch)) { @@ -42,7 +42,7 @@ TEST(isAllPons, WithKans) { }; player.open = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllPons(game_state, player, branch)) { @@ -63,7 +63,7 @@ TEST(isAllPons, ConcealedKan) { }; player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllPons(game_state, player, branch)) { @@ -80,7 +80,7 @@ TEST(isAllPons, BadPlayer) { HandFromNotation("111m222p666z789m44m", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllPons(game_state, player, branch)) { diff --git a/tests/yakus/allsimples.test.cc b/tests/yakus/allsimples.test.cc index 75f7f611..b083b761 100644 --- a/tests/yakus/allsimples.test.cc +++ b/tests/yakus/allsimples.test.cc @@ -18,7 +18,7 @@ TEST(isAllSimples, 1Han) { Player& player =game_state.players[0]; HandFromNotation("222m333p444s555p88m", &player); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllSimples(game_state, player, branch)) { @@ -34,7 +34,7 @@ TEST(isAllSimples, BadPlayerHonors) { Player& player =game_state.players[0]; HandFromNotation("222m333p444s111z88m", &player); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllSimples(game_state, player, branch)) { @@ -50,7 +50,7 @@ TEST(isAllSimples, BadPlayerTerminals) { Player& player =game_state.players[0]; HandFromNotation("222m333p444s111m88m", &player); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllSimples(game_state, player, branch)) { diff --git a/tests/yakus/allterminalsandhonors.test.cc b/tests/yakus/allterminalsandhonors.test.cc index 0caf5d6a..b0843147 100644 --- a/tests/yakus/allterminalsandhonors.test.cc +++ b/tests/yakus/allterminalsandhonors.test.cc @@ -23,7 +23,7 @@ TEST(isAllTerminalsAndHonors, 2Han) { HandFromNotation("222z111p111m999s66z", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllTerminalsAndHonors(game_state, player, branch)) { @@ -40,7 +40,7 @@ TEST(isAllTerminalsAndHonors, BadPlayer) { HandFromNotation("222z111p111m888s66z", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllTerminalsAndHonors(game_state, player, branch)) { @@ -61,7 +61,7 @@ TEST(isAllTerminalsAndHonors, CanBeOpen) { .start = Piece(kNinePin), }; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isAllTerminalsAndHonors(game_state, player, branch)) { diff --git a/tests/yakus/blessingofman.test.cc b/tests/yakus/blessingofman.test.cc index 31e1b317..0154a3c7 100644 --- a/tests/yakus/blessingofman.test.cc +++ b/tests/yakus/blessingofman.test.cc @@ -26,7 +26,7 @@ TEST(isBlessingOfMan, 5Han) { player.hasRonned = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBlessingOfMan(game_state, player, branch)) { @@ -50,7 +50,7 @@ TEST(isBlessingOfMan, MustBeARon) { player.hasRonned = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBlessingOfMan(game_state, player, branch)) { @@ -74,7 +74,7 @@ TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { player.hasRonned = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBlessingOfMan(game_state, player, branch)) { @@ -97,7 +97,7 @@ TEST(isBlessingOfMan, NoCalledMustHaveOccured) { player.hasRonned = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBlessingOfMan(game_state, player, branch)) { diff --git a/tests/yakus/concealedpon.test.cc b/tests/yakus/concealedpon.test.cc index e275f2f1..a68fb7d8 100644 --- a/tests/yakus/concealedpon.test.cc +++ b/tests/yakus/concealedpon.test.cc @@ -20,7 +20,7 @@ TEST(isThreeConcealedPons, 2Han) { HandFromNotation("111m111p111s666z44m", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, player, branch)) { @@ -41,7 +41,7 @@ TEST(isThreeConcealedPons, PonsMustBeConcealed) { }; player.open = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, player, branch)) { @@ -62,7 +62,7 @@ TEST(isThreeConcealedPons, CanHaveAdditionalOpenPon) { }; player.open = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, player, branch)) { @@ -83,7 +83,7 @@ TEST(isThreeConcealedPons, PonsMustBeConcealedNegative) { }; player.open = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, player, branch)) { @@ -100,7 +100,7 @@ TEST(isThreeConcealedPons, BadPlayer) { HandFromNotation("111m111p234567s44m", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeConcealedPons(game_state, player, branch)) { diff --git a/tests/yakus/dragonpon.test.cc b/tests/yakus/dragonpon.test.cc index 2526cb0a..17e1290f 100644 --- a/tests/yakus/dragonpon.test.cc +++ b/tests/yakus/dragonpon.test.cc @@ -17,7 +17,7 @@ TEST(isWindOrDragonPon, WhiteDragon) { Player& player =game_state.players[0]; HandFromNotation("123m456m555z11z", &player); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isWhiteDragon(game_state, player, branch)) { @@ -33,7 +33,7 @@ TEST(isWindOrDragonPon, GreenDragon) { Player& player =game_state.players[0]; HandFromNotation("123m456m666z11z", &player); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isGreenDragon(game_state, player, branch)) { @@ -49,7 +49,7 @@ TEST(isWindOrDragonPon, RedDragon) { Player& player =game_state.players[0]; HandFromNotation("123m456m777z11z", &player); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRedDragon(game_state, player, branch)) { @@ -65,7 +65,7 @@ TEST(isWindOrDragonPon, Kan) { Player& player =game_state.players[0]; HandFromNotation("123m456m7777z11z", &player); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRedDragon(game_state, player, branch)) { @@ -82,7 +82,7 @@ TEST(isWindOrDragonPon, CanWhenOpen) { HandFromNotation("123m456m777z11z", &player); player.open = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRedDragon(game_state, player, branch)) { @@ -98,7 +98,7 @@ TEST(isWindOrDragonPon, BadPlayer) { Player& player =game_state.players[0]; HandFromNotation("123m456m222p11p", &player); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isGreenDragon(game_state, player, branch)) { diff --git a/tests/yakus/fullflush.test.cc b/tests/yakus/fullflush.test.cc index 306385ae..6199afc0 100644 --- a/tests/yakus/fullflush.test.cc +++ b/tests/yakus/fullflush.test.cc @@ -27,7 +27,7 @@ TEST(isFullFlush, 5Han) { .start = Piece(kSixCharacter), }; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, player, branch)) { @@ -44,7 +44,7 @@ TEST(isFullFlush, 6Han) { HandFromNotation("111m222m345m666m99m", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, player, branch)) { @@ -61,7 +61,7 @@ TEST(isFullFlush, BadPlayerHonors) { HandFromNotation("111m222m111z666m99m", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, player, branch)) { @@ -78,7 +78,7 @@ TEST(isFullFlush, BadPlayerSuit) { HandFromNotation("111m222m111p666m99m", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, player, branch)) { @@ -95,7 +95,7 @@ TEST(isFullFlush, BadPlayerFullFlushHonors) { HandFromNotation("111z222z333z444z55z", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isFullFlush(game_state, player, branch)) { diff --git a/tests/yakus/halfflush.test.cc b/tests/yakus/halfflush.test.cc index c47c68c7..6debdf67 100644 --- a/tests/yakus/halfflush.test.cc +++ b/tests/yakus/halfflush.test.cc @@ -27,7 +27,7 @@ TEST(isHalfFlush, 2Han) { .start = Piece(kSixCharacter), }; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isHalfFlush(game_state, player, branch)) { @@ -44,7 +44,7 @@ TEST(isHalfFlush, 3Han) { HandFromNotation("11m234m777m111z222z", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isHalfFlush(game_state, player, branch)) { @@ -65,7 +65,7 @@ TEST(isHalfFlush, BadPlayer) { .start = Piece(kSixCharacter), }; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isHalfFlush(game_state, player, branch)) { @@ -86,7 +86,7 @@ TEST(isHalfFlush, FullFlushIncompatible) { .start = Piece(kSixCharacter), }; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isHalfFlush(game_state, player, branch)) { diff --git a/tests/yakus/littlethreedragons.test.cc b/tests/yakus/littlethreedragons.test.cc index 664af521..5166956e 100644 --- a/tests/yakus/littlethreedragons.test.cc +++ b/tests/yakus/littlethreedragons.test.cc @@ -23,7 +23,7 @@ TEST(isLittleThreeDragons, 2Han) { HandFromNotation("555z666z111m222p77z", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isLittleThreeDragons(game_state, player, branch)) { @@ -44,7 +44,7 @@ TEST(isLittleThreeDragons, WhenOpen) { .start = Piece(kWhiteDragon), }; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isLittleThreeDragons(game_state, player, branch)) { @@ -65,7 +65,7 @@ TEST(isLittleThreeDragons, BadPlayer) { .start = Piece(kWhiteDragon), }; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isLittleThreeDragons(game_state, player, branch)) { diff --git a/tests/yakus/mixedtriplechi.test.cc b/tests/yakus/mixedtriplechi.test.cc index 1ea8e940..8084e65b 100644 --- a/tests/yakus/mixedtriplechi.test.cc +++ b/tests/yakus/mixedtriplechi.test.cc @@ -19,7 +19,7 @@ TEST(isMixedTripleChi, Open) { HandFromNotation("123p123m123s555p11z", &player); player.open = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isMixedTripleChi(game_state, player, branch)) { @@ -36,7 +36,7 @@ TEST(isMixedTripleChi, Closed) { HandFromNotation("123p123m123s555p11z", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isMixedTripleChi(game_state, player, branch)) { @@ -53,7 +53,7 @@ TEST(isMixedTripleChi, BadPlayer) { HandFromNotation("123p123p123s555p11z", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isMixedTripleChi(game_state, player, branch)) { diff --git a/tests/yakus/outsidehand.test.cc b/tests/yakus/outsidehand.test.cc index d781cca6..c0f91a0f 100644 --- a/tests/yakus/outsidehand.test.cc +++ b/tests/yakus/outsidehand.test.cc @@ -19,7 +19,7 @@ TEST(isOutsideHand, Open) { HandFromNotation("123m789m111z999s55z", &player); player.open = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isOutsideHand(game_state, player, branch)) { @@ -36,7 +36,7 @@ TEST(isOutsideHand, Closed) { HandFromNotation("123m789m111z999s55z", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isOutsideHand(game_state, player, branch)) { @@ -52,7 +52,7 @@ TEST(isOutsideHand, NoChi) { Player& player =game_state.players[0]; HandFromNotation("111m111p111s999m66z", &player); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isOutsideHand(game_state, player, branch)) { @@ -68,7 +68,7 @@ TEST(isOutsideHand, BadPlayer) { Player& player =game_state.players[0]; HandFromNotation("111m234p111s999m66z", &player); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isOutsideHand(game_state, player, branch)) { diff --git a/tests/yakus/pinfu.test.cc b/tests/yakus/pinfu.test.cc index 5fe8b0eb..8b69bc56 100644 --- a/tests/yakus/pinfu.test.cc +++ b/tests/yakus/pinfu.test.cc @@ -22,7 +22,7 @@ TEST(isPinfu, 1Han) { player.open = false; game_state.pendingPiece = Piece(kFourPin); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPinfu(game_state, player, branch)) { @@ -40,7 +40,7 @@ TEST(isPinfu, BadPlayer) { player.open = false; game_state.pendingPiece = Piece(kTwoBamboo); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPinfu(game_state, player, branch)) { @@ -58,7 +58,7 @@ TEST(isPinfu, CantBeOpen) { player.open = true; game_state.pendingPiece = Piece(kFourPin); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPinfu(game_state, player, branch)) { @@ -76,7 +76,7 @@ TEST(isPinfu, NeedTwoWait) { player.open = false; game_state.pendingPiece = Piece(kFivePin); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPinfu(game_state, player, branch)) { diff --git a/tests/yakus/puredoublechi.test.cc b/tests/yakus/puredoublechi.test.cc index 26704360..0cdf1da0 100644 --- a/tests/yakus/puredoublechi.test.cc +++ b/tests/yakus/puredoublechi.test.cc @@ -19,7 +19,7 @@ TEST(isPureDoubleChi, 1Han) { HandFromNotation("234m234m555p888s88p", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureDoubleChi(game_state, player, branch)) { @@ -36,7 +36,7 @@ TEST(isPureDoubleChi, BadPlayer) { HandFromNotation("234m123m555p888s88p", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureDoubleChi(game_state, player, branch)) { @@ -53,7 +53,7 @@ TEST(isPureDoubleChi, MustBeConcealed) { HandFromNotation("234m234m555p888s88p", &player); player.open = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureDoubleChi(game_state, player, branch)) { diff --git a/tests/yakus/purestraight.test.cc b/tests/yakus/purestraight.test.cc index f3864eb7..5931f4fc 100644 --- a/tests/yakus/purestraight.test.cc +++ b/tests/yakus/purestraight.test.cc @@ -19,7 +19,7 @@ TEST(isPureStraight, Open) { HandFromNotation("123m456m789m555p11z", &player); player.open = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureStraight(game_state, player, branch)) { @@ -36,7 +36,7 @@ TEST(isPureStraight, Closed) { HandFromNotation("123m456m789m555p11z", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureStraight(game_state, player, branch)) { @@ -53,7 +53,7 @@ TEST(isPureStraight, BadPlayer) { HandFromNotation("123m456m999m555p11z", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPureStraight(game_state, player, branch)) { diff --git a/tests/yakus/robbingkan.test.cc b/tests/yakus/robbingkan.test.cc index e0b148d0..dc25a5f3 100644 --- a/tests/yakus/robbingkan.test.cc +++ b/tests/yakus/robbingkan.test.cc @@ -20,7 +20,7 @@ TEST(isRobbingAKan, 1Han) { game_state.players[0].hasRonned = true; game_state.nextState = StateFunctionType::kKanDiscard; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRobbingAKan(game_state, player, branch)) { @@ -38,7 +38,7 @@ TEST(isRobbingAKan, DoesntApply) { game_state.players[0].hasRonned = true; game_state.nextState = StateFunctionType::kPon; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isRobbingAKan(game_state, player, branch)) { diff --git a/tests/yakus/sevenpairs.test.cc b/tests/yakus/sevenpairs.test.cc index d8c2655e..f56413f8 100644 --- a/tests/yakus/sevenpairs.test.cc +++ b/tests/yakus/sevenpairs.test.cc @@ -19,7 +19,7 @@ TEST(isSevenPairs, 2Han) { HandFromNotation("11m22p33s44z55m11z66z", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSevenPairs(game_state, player, branch)) { @@ -36,7 +36,7 @@ TEST(isSevenPairs, MustBeConcealed) { HandFromNotation("11m22p33s44z55m11z66z", &player); player.open = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSevenPairs(game_state, player, branch)) { @@ -53,7 +53,7 @@ TEST(isSevenPairs, UniquePairsOnly) { HandFromNotation("1111m22p33s44z11z66z", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSevenPairs(game_state, player, branch)) { diff --git a/tests/yakus/terminalinsets.test.cc b/tests/yakus/terminalinsets.test.cc index 4fdcbff8..fc0ab53c 100644 --- a/tests/yakus/terminalinsets.test.cc +++ b/tests/yakus/terminalinsets.test.cc @@ -26,7 +26,7 @@ TEST(isTerminalsInAllSets, 2Han) { .start = Piece(kSevenPin), }; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTerminalsInAllSets(game_state, player, branch)) { @@ -43,7 +43,7 @@ TEST(isTerminalsInAllSets, 3Han) { HandFromNotation("123m789m111p789p11s", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTerminalsInAllSets(game_state, player, branch)) { @@ -65,7 +65,7 @@ TEST(isTerminalsInAllSets, BadPlayer) { .start = Piece(kSevenPin), }; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTerminalsInAllSets(game_state, player, branch)) { diff --git a/tests/yakus/triplekan.test.cc b/tests/yakus/triplekan.test.cc index e1185c71..c8bc5118 100644 --- a/tests/yakus/triplekan.test.cc +++ b/tests/yakus/triplekan.test.cc @@ -37,7 +37,7 @@ TEST(isThreeKans, 2Han) { player.meld_count = 3; player.open = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeKans(game_state, player, branch)) { @@ -73,7 +73,7 @@ TEST(isThreeKans, WithOtherMelds) { player.meld_count = 4; player.open = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeKans(game_state, player, branch)) { @@ -101,7 +101,7 @@ TEST(isThreeKans, BadPlayer) { player.meld_count = 2; player.open = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeKans(game_state, player, branch)) { @@ -133,7 +133,7 @@ TEST(isThreeKans, AllConcealed) { player.meld_count = 3; player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isThreeKans(game_state, player, branch)) { diff --git a/tests/yakus/triplepon.test.cc b/tests/yakus/triplepon.test.cc index 3b222668..129bdcfa 100644 --- a/tests/yakus/triplepon.test.cc +++ b/tests/yakus/triplepon.test.cc @@ -18,7 +18,7 @@ TEST(isTriplePon, 2Han) { Player& player =game_state.players[0]; HandFromNotation("111m111p111s666z44m", &player); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTriplePon(game_state, player, branch)) { @@ -34,7 +34,7 @@ TEST(isTriplePon, BadPlayer) { Player& player =game_state.players[0]; HandFromNotation("111m111p222m666z44m", &player); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTriplePon(game_state, player, branch)) { diff --git a/tests/yakus/twicepuredoublechi.test.cc b/tests/yakus/twicepuredoublechi.test.cc index b26e2498..54758597 100644 --- a/tests/yakus/twicepuredoublechi.test.cc +++ b/tests/yakus/twicepuredoublechi.test.cc @@ -19,7 +19,7 @@ TEST(isTwicePureDoubleChi, 3Han) { HandFromNotation("789p789p234m234m11z", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTwicePureDoubleChi(game_state, player, branch)) { @@ -36,7 +36,7 @@ TEST(isTwicePureDoubleChi, MustBeConcealed) { HandFromNotation("789p789p234m234m11z", &player); player.open = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTwicePureDoubleChi(game_state, player, branch)) { @@ -53,7 +53,7 @@ TEST(isTwicePureDoubleChi, BadPlayer) { HandFromNotation("789p789p234m567m11z", &player); player.open = false; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isTwicePureDoubleChi(game_state, player, branch)) { diff --git a/tests/yakus/underthesea.test.cc b/tests/yakus/underthesea.test.cc index ff2e91f1..8639d0a2 100644 --- a/tests/yakus/underthesea.test.cc +++ b/tests/yakus/underthesea.test.cc @@ -18,7 +18,7 @@ TEST(isBottomOfTheSea, 1Han) { HandFromNotation("123m789m111z999s55z", &player); game_state.livingWallIndex = kLivingWallCount; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBottomOfTheSea(game_state, player, branch)) { @@ -36,7 +36,7 @@ TEST(isBottomOfTheSea, 1HanRonned) { game_state.livingWallIndex = kLivingWallCount; game_state.players[0].hasRonned = true; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBottomOfTheSea(game_state, player, branch)) { @@ -52,7 +52,7 @@ TEST(isBottomOfTheSea, DoesntApply) { Player& player =game_state.players[0]; HandFromNotation("123m789m111z999s55z", &player); - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isBottomOfTheSea(game_state, player, branch)) { diff --git a/tests/yakus/windpons.test.cc b/tests/yakus/windpons.test.cc index ae5886e0..efb169f7 100644 --- a/tests/yakus/windpons.test.cc +++ b/tests/yakus/windpons.test.cc @@ -18,7 +18,7 @@ TEST(isWindOrDragonPon, SeatWind) { HandFromNotation("123m456m444z55z", &player); game_state.roundNum = 1; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); auto branches = Node::AsBranchVectors(root.get()); @@ -38,7 +38,7 @@ TEST(isWindOrDragonPon, SeatWindKan) { HandFromNotation("123m456m4444z55z", &player); game_state.roundNum = 1; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, player, branch)) { @@ -55,7 +55,7 @@ TEST(isWindOrDragonPon, PrevalentWind) { HandFromNotation("123m456m111z55z", &player); game_state.roundNum = 1; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPrevalentWind(game_state, player, branch)) { @@ -72,7 +72,7 @@ TEST(isWindOrDragonPon, PrevalentWindKan) { HandFromNotation("123m456m1111z55z", &player); game_state.roundNum = 1; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isPrevalentWind(game_state, player, branch)) { @@ -89,7 +89,7 @@ TEST(isWindOrDragonPon, Dealer2Han) { HandFromNotation("123m456m111z55z", &player); game_state.roundNum = 0; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, player, branch) && @@ -107,7 +107,7 @@ TEST(isWindOrDragonPon, Dealer2HanKan) { HandFromNotation("123m456m1111z55z", &player); game_state.roundNum = 0; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, player, branch) && @@ -125,7 +125,7 @@ TEST(isWindOrDragonPon, NotSeatOrPrevalent) { HandFromNotation("123m456m222z55z", &player); game_state.roundNum = 0; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, player, branch) || @@ -143,7 +143,7 @@ TEST(isWindOrDragonPon, NoWind) { HandFromNotation("123m456m666m55z", &player); game_state.roundNum = 0; - auto root = breakdownPlayer(player.live_range()); + auto root = breakdownHand(player.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { if (isSeatWind(game_state, player, branch) || From 387d82bb85c001d116d608eaf0ca7dd7eea94f0d Mon Sep 17 00:00:00 2001 From: alice Hartley Date: Fri, 5 Sep 2025 12:21:30 -0700 Subject: [PATCH 11/14] Move Player to hand.h --- src/analysis/analysis.cc | 2 +- src/analysis/analysis.h | 1 + src/analysis/util.cc | 2 +- src/analysis/util.h | 1 + src/api/gamestate.cc | 1 + src/scoring/scoring.cc | 1 + src/scoring/scoring.h | 1 + src/scoring/yakus/afterakan.cc | 1 + src/scoring/yakus/afterakan.h | 1 + src/scoring/yakus/allgreen.cc | 1 + src/scoring/yakus/allgreen.h | 1 + src/scoring/yakus/allhonors.cc | 1 + src/scoring/yakus/allhonors.h | 1 + src/scoring/yakus/allpons.cc | 1 + src/scoring/yakus/allpons.h | 1 + src/scoring/yakus/allsimples.cc | 1 + src/scoring/yakus/allsimples.h | 1 + src/scoring/yakus/allterminals.cc | 1 + src/scoring/yakus/allterminals.h | 1 + src/scoring/yakus/allterminalsandhonors.cc | 1 + src/scoring/yakus/allterminalsandhonors.h | 1 + src/scoring/yakus/bigfourwinds.cc | 1 + src/scoring/yakus/bigfourwinds.h | 1 + src/scoring/yakus/bigthreedragons.cc | 1 + src/scoring/yakus/bigthreedragons.h | 1 + src/scoring/yakus/blessingofearth.cc | 1 + src/scoring/yakus/blessingofearth.h | 1 + src/scoring/yakus/blessingofheaven.cc | 1 + src/scoring/yakus/blessingofheaven.h | 1 + src/scoring/yakus/blessingofman.cc | 1 + src/scoring/yakus/blessingofman.h | 1 + src/scoring/yakus/bottomofthesea.cc | 1 + src/scoring/yakus/bottomofthesea.h | 1 + src/scoring/yakus/doubleriichi.cc | 1 + src/scoring/yakus/doubleriichi.h | 1 + src/scoring/yakus/fourconcealedpon.cc | 1 + src/scoring/yakus/fourconcealedpon.h | 1 + src/scoring/yakus/fourkans.cc | 1 + src/scoring/yakus/fourkans.h | 1 + src/scoring/yakus/fullflush.cc | 1 + src/scoring/yakus/fullflush.h | 1 + src/scoring/yakus/fullyconcealedhand.cc | 1 + src/scoring/yakus/fullyconcealedhand.h | 1 + src/scoring/yakus/halfflush.cc | 1 + src/scoring/yakus/halfflush.h | 1 + src/scoring/yakus/honorpon.cc | 1 + src/scoring/yakus/honorpon.h | 1 + src/scoring/yakus/ippatsu.cc | 1 + src/scoring/yakus/ippatsu.h | 1 + src/scoring/yakus/littlefourwinds.cc | 1 + src/scoring/yakus/littlefourwinds.h | 1 + src/scoring/yakus/littlethreedragons.cc | 1 + src/scoring/yakus/littlethreedragons.h | 1 + src/scoring/yakus/maxbranches.cc | 1 + src/scoring/yakus/maxbranches.h | 1 + src/scoring/yakus/mixedtriplechi.cc | 1 + src/scoring/yakus/mixedtriplechi.h | 1 + src/scoring/yakus/ninegates.cc | 1 + src/scoring/yakus/ninegates.h | 1 + src/scoring/yakus/outsidehand.cc | 1 + src/scoring/yakus/outsidehand.h | 1 + src/scoring/yakus/pinfu.cc | 1 + src/scoring/yakus/pinfu.h | 1 + src/scoring/yakus/puredoublechi.cc | 1 + src/scoring/yakus/puredoublechi.h | 1 + src/scoring/yakus/purestraight.cc | 1 + src/scoring/yakus/purestraight.h | 1 + src/scoring/yakus/riichi.cc | 1 + src/scoring/yakus/riichi.h | 1 + src/scoring/yakus/robbingakan.cc | 1 + src/scoring/yakus/robbingakan.h | 1 + src/scoring/yakus/sevenpairs.cc | 1 + src/scoring/yakus/sevenpairs.h | 1 + src/scoring/yakus/terminalsinallsets.cc | 1 + src/scoring/yakus/terminalsinallsets.h | 1 + src/scoring/yakus/thirteenorphans.cc | 1 + src/scoring/yakus/thirteenorphans.h | 1 + src/scoring/yakus/threeconcealedpons.cc | 1 + src/scoring/yakus/threeconcealedpons.h | 1 + src/scoring/yakus/threekans.cc | 1 + src/scoring/yakus/threekans.h | 1 + src/scoring/yakus/triplepon.cc | 1 + src/scoring/yakus/triplepon.h | 1 + src/scoring/yakus/twicepuredoublechi.cc | 1 + src/scoring/yakus/twicepuredoublechi.h | 1 + src/statefunctions/decisionfunction.cc | 1 + src/statefunctions/decisionfunction.h | 1 + src/statefunctions/gamestates/chi.cc | 1 + src/statefunctions/gamestates/concealedkan.cc | 1 + src/statefunctions/gamestates/convertedkan.cc | 1 + src/statefunctions/gamestates/discard.cc | 1 + src/statefunctions/gamestates/draw.cc | 1 + src/statefunctions/gamestates/error.cc | 1 + src/statefunctions/gamestates/exhaust.cc | 1 + src/statefunctions/gamestates/gameend.cc | 1 + src/statefunctions/gamestates/gamestart.cc | 1 + src/statefunctions/gamestates/kan.cc | 1 + src/statefunctions/gamestates/kandiscard.cc | 1 + src/statefunctions/gamestates/playerhand.cc | 1 + src/statefunctions/gamestates/pon.cc | 1 + src/statefunctions/gamestates/replacement.cc | 1 + src/statefunctions/gamestates/riichi.cc | 1 + src/statefunctions/gamestates/ron.cc | 1 + src/statefunctions/gamestates/roundend.cc | 1 + src/statefunctions/gamestates/roundstart.cc | 1 + src/statefunctions/statecontroller.cc | 1 + src/statefunctions/stateutilities.cc | 1 + src/statefunctions/stateutilities.h | 1 + src/types/CMakeLists.txt | 1 + src/types/gamestate.h | 26 +-------------- src/types/hand.h | 32 +++++++++++++++++++ src/types/typeprinter.cc | 1 + src/types/walls.cc | 1 + src/types/walls.h | 1 + src/types/yaku.h | 1 + tests/api/game_control.test.cc | 1 + tests/count_pieces.test.cc | 2 +- tests/discard_piece.test.cc | 2 +- tests/game_play.test.cc | 1 + tests/remove_pieces.test.cc | 2 +- tests/rules/calls.test.cc | 1 + tests/utils/gamestate_utils.cc | 1 + tests/utils/gamestate_utils.h | 1 + tests/utils/handformer.cc | 2 +- tests/utils/handformer.h | 1 + tests/yakus/afterkan.test.cc | 1 + tests/yakus/allpon.test.cc | 1 + tests/yakus/allsimples.test.cc | 1 + tests/yakus/allterminalsandhonors.test.cc | 1 + tests/yakus/blessingofman.test.cc | 1 + tests/yakus/concealedhand.test.cc | 1 + tests/yakus/concealedpon.test.cc | 1 + tests/yakus/dragonpon.test.cc | 1 + tests/yakus/fullflush.test.cc | 1 + tests/yakus/halfflush.test.cc | 1 + tests/yakus/littlethreedragons.test.cc | 1 + tests/yakus/mixedtriplechi.test.cc | 1 + tests/yakus/outsidehand.test.cc | 1 + tests/yakus/pinfu.test.cc | 1 + tests/yakus/puredoublechi.test.cc | 1 + tests/yakus/purestraight.test.cc | 1 + tests/yakus/riichi.test.cc | 1 + tests/yakus/robbingkan.test.cc | 1 + tests/yakus/sevenpairs.test.cc | 1 + tests/yakus/terminalinsets.test.cc | 1 + tests/yakus/triplekan.test.cc | 1 + tests/yakus/triplepon.test.cc | 1 + tests/yakus/twicepuredoublechi.test.cc | 1 + tests/yakus/underthesea.test.cc | 1 + tests/yakus/windpons.test.cc | 1 + 150 files changed, 181 insertions(+), 31 deletions(-) create mode 100644 src/types/hand.h diff --git a/src/analysis/analysis.cc b/src/analysis/analysis.cc index 763bd907..bca70409 100644 --- a/src/analysis/analysis.cc +++ b/src/analysis/analysis.cc @@ -8,7 +8,7 @@ #include "analysis/handnode.h" #include "analysis/handtree.h" -#include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/piecetype.h" #include "types/sets.h" diff --git a/src/analysis/analysis.h b/src/analysis/analysis.h index 67c53659..d0caf5a7 100644 --- a/src/analysis/analysis.h +++ b/src/analysis/analysis.h @@ -4,6 +4,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" namespace mahjong { diff --git a/src/analysis/util.cc b/src/analysis/util.cc index 37c2da01..27332fed 100644 --- a/src/analysis/util.cc +++ b/src/analysis/util.cc @@ -6,7 +6,7 @@ #include #include "analysis/analysis.h" -#include "types/gamestate.h" +#include "types/hand.h" #include "types/pieces.h" #include "types/piecetype.h" #include "types/sets.h" diff --git a/src/analysis/util.h b/src/analysis/util.h index 99fb613b..cfcd4d77 100644 --- a/src/analysis/util.h +++ b/src/analysis/util.h @@ -4,6 +4,7 @@ #include "analysis/analysis.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" #include "types/sets.h" diff --git a/src/api/gamestate.cc b/src/api/gamestate.cc index 5f5bc5f3..f89dc3c3 100644 --- a/src/api/gamestate.cc +++ b/src/api/gamestate.cc @@ -8,6 +8,7 @@ #include "controllers/controllermanager.h" #include "statefunctions/statecontroller.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/settings.h" #include "types/statefunction.h" diff --git a/src/scoring/scoring.cc b/src/scoring/scoring.cc index 8c785c4f..f3dc381a 100644 --- a/src/scoring/scoring.cc +++ b/src/scoring/scoring.cc @@ -10,6 +10,7 @@ #include "scoring/yakus/sevenpairs.h" #include "scoring/yakus/thirteenorphans.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/pieces.h" #include "types/piecetype.h" #include "types/score.h" diff --git a/src/scoring/scoring.h b/src/scoring/scoring.h index bc5293ce..1bd2a547 100644 --- a/src/scoring/scoring.h +++ b/src/scoring/scoring.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/score.h" namespace mahjong { diff --git a/src/scoring/yakus/afterakan.cc b/src/scoring/yakus/afterakan.cc index 2ac096c1..265cfe5c 100644 --- a/src/scoring/yakus/afterakan.cc +++ b/src/scoring/yakus/afterakan.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/statefunction.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/afterakan.h b/src/scoring/yakus/afterakan.h index 53999a5a..2923f4f6 100644 --- a/src/scoring/yakus/afterakan.h +++ b/src/scoring/yakus/afterakan.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isAfterAKan(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/allgreen.cc b/src/scoring/yakus/allgreen.cc index 49a293b1..4001474b 100644 --- a/src/scoring/yakus/allgreen.cc +++ b/src/scoring/yakus/allgreen.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/yaku.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/allgreen.h b/src/scoring/yakus/allgreen.h index b0ec6b44..7839ac6a 100644 --- a/src/scoring/yakus/allgreen.h +++ b/src/scoring/yakus/allgreen.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isAllGreen(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/allhonors.cc b/src/scoring/yakus/allhonors.cc index 96a7ba6f..6b8b58e6 100644 --- a/src/scoring/yakus/allhonors.cc +++ b/src/scoring/yakus/allhonors.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/yaku.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/allhonors.h b/src/scoring/yakus/allhonors.h index 842510bd..fe697345 100644 --- a/src/scoring/yakus/allhonors.h +++ b/src/scoring/yakus/allhonors.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isAllHonors(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/allpons.cc b/src/scoring/yakus/allpons.cc index 21228029..4e4004ea 100644 --- a/src/scoring/yakus/allpons.cc +++ b/src/scoring/yakus/allpons.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/allpons.h b/src/scoring/yakus/allpons.h index 2ddeb0d4..f8ffbd9e 100644 --- a/src/scoring/yakus/allpons.h +++ b/src/scoring/yakus/allpons.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isAllPons(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/allsimples.cc b/src/scoring/yakus/allsimples.cc index bdc0dbd7..a10d5639 100644 --- a/src/scoring/yakus/allsimples.cc +++ b/src/scoring/yakus/allsimples.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/yaku.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/allsimples.h b/src/scoring/yakus/allsimples.h index 41bac6c9..503b4060 100644 --- a/src/scoring/yakus/allsimples.h +++ b/src/scoring/yakus/allsimples.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isAllSimples(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/allterminals.cc b/src/scoring/yakus/allterminals.cc index 27239aca..bb3803c5 100644 --- a/src/scoring/yakus/allterminals.cc +++ b/src/scoring/yakus/allterminals.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/yaku.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/allterminals.h b/src/scoring/yakus/allterminals.h index ffa10603..973d9a0d 100644 --- a/src/scoring/yakus/allterminals.h +++ b/src/scoring/yakus/allterminals.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isAllTerminals(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/allterminalsandhonors.cc b/src/scoring/yakus/allterminalsandhonors.cc index 1bdf3fab..f1e91e3c 100644 --- a/src/scoring/yakus/allterminalsandhonors.cc +++ b/src/scoring/yakus/allterminalsandhonors.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/yaku.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/allterminalsandhonors.h b/src/scoring/yakus/allterminalsandhonors.h index 341d1d34..44826809 100644 --- a/src/scoring/yakus/allterminalsandhonors.h +++ b/src/scoring/yakus/allterminalsandhonors.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isAllTerminalsAndHonors( diff --git a/src/scoring/yakus/bigfourwinds.cc b/src/scoring/yakus/bigfourwinds.cc index e04254c0..c713df11 100644 --- a/src/scoring/yakus/bigfourwinds.cc +++ b/src/scoring/yakus/bigfourwinds.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/bigfourwinds.h b/src/scoring/yakus/bigfourwinds.h index 8a91b9c4..bed1b26d 100644 --- a/src/scoring/yakus/bigfourwinds.h +++ b/src/scoring/yakus/bigfourwinds.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isBigFourWinds(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/bigthreedragons.cc b/src/scoring/yakus/bigthreedragons.cc index e9a8c9a1..853dea5c 100644 --- a/src/scoring/yakus/bigthreedragons.cc +++ b/src/scoring/yakus/bigthreedragons.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/bigthreedragons.h b/src/scoring/yakus/bigthreedragons.h index 96997f08..7f499001 100644 --- a/src/scoring/yakus/bigthreedragons.h +++ b/src/scoring/yakus/bigthreedragons.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isBigThreeDragons(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/blessingofearth.cc b/src/scoring/yakus/blessingofearth.cc index 9b418dfe..6372c46b 100644 --- a/src/scoring/yakus/blessingofearth.cc +++ b/src/scoring/yakus/blessingofearth.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/yaku.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/blessingofearth.h b/src/scoring/yakus/blessingofearth.h index 86d8e742..60c166da 100644 --- a/src/scoring/yakus/blessingofearth.h +++ b/src/scoring/yakus/blessingofearth.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isBlessingOfEarth( diff --git a/src/scoring/yakus/blessingofheaven.cc b/src/scoring/yakus/blessingofheaven.cc index 5d63886c..d4a09158 100644 --- a/src/scoring/yakus/blessingofheaven.cc +++ b/src/scoring/yakus/blessingofheaven.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/yaku.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/blessingofheaven.h b/src/scoring/yakus/blessingofheaven.h index 4bc91f2e..8d9c2a54 100644 --- a/src/scoring/yakus/blessingofheaven.h +++ b/src/scoring/yakus/blessingofheaven.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isBlessingOfHeaven( diff --git a/src/scoring/yakus/blessingofman.cc b/src/scoring/yakus/blessingofman.cc index 091d4749..e2e5d2b8 100644 --- a/src/scoring/yakus/blessingofman.cc +++ b/src/scoring/yakus/blessingofman.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/yaku.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/blessingofman.h b/src/scoring/yakus/blessingofman.h index 1dcf576c..818bf2a4 100644 --- a/src/scoring/yakus/blessingofman.h +++ b/src/scoring/yakus/blessingofman.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isBlessingOfMan(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/bottomofthesea.cc b/src/scoring/yakus/bottomofthesea.cc index fbfeb962..3df09009 100644 --- a/src/scoring/yakus/bottomofthesea.cc +++ b/src/scoring/yakus/bottomofthesea.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/walls.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/bottomofthesea.h b/src/scoring/yakus/bottomofthesea.h index aa669f02..da40848a 100644 --- a/src/scoring/yakus/bottomofthesea.h +++ b/src/scoring/yakus/bottomofthesea.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isBottomOfTheSea(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/doubleriichi.cc b/src/scoring/yakus/doubleriichi.cc index 964e306c..ac00eabd 100644 --- a/src/scoring/yakus/doubleriichi.cc +++ b/src/scoring/yakus/doubleriichi.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/yaku.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/doubleriichi.h b/src/scoring/yakus/doubleriichi.h index 5250cc64..477287ac 100644 --- a/src/scoring/yakus/doubleriichi.h +++ b/src/scoring/yakus/doubleriichi.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isDoubleRiichi(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/fourconcealedpon.cc b/src/scoring/yakus/fourconcealedpon.cc index a2e786c6..55aea284 100644 --- a/src/scoring/yakus/fourconcealedpon.cc +++ b/src/scoring/yakus/fourconcealedpon.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/fourconcealedpon.h b/src/scoring/yakus/fourconcealedpon.h index 70af5bb9..c05088a9 100644 --- a/src/scoring/yakus/fourconcealedpon.h +++ b/src/scoring/yakus/fourconcealedpon.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isFourConcealedPon(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/fourkans.cc b/src/scoring/yakus/fourkans.cc index 5f3fe30c..a79e12e1 100644 --- a/src/scoring/yakus/fourkans.cc +++ b/src/scoring/yakus/fourkans.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/fourkans.h b/src/scoring/yakus/fourkans.h index 41a231a3..37f9fb24 100644 --- a/src/scoring/yakus/fourkans.h +++ b/src/scoring/yakus/fourkans.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isFourKans(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/fullflush.cc b/src/scoring/yakus/fullflush.cc index 3b3e8f99..0bdd69e2 100644 --- a/src/scoring/yakus/fullflush.cc +++ b/src/scoring/yakus/fullflush.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/yaku.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/fullflush.h b/src/scoring/yakus/fullflush.h index 662fd357..47a2f38f 100644 --- a/src/scoring/yakus/fullflush.h +++ b/src/scoring/yakus/fullflush.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isFullFlush(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/fullyconcealedhand.cc b/src/scoring/yakus/fullyconcealedhand.cc index 83f1965a..711615da 100644 --- a/src/scoring/yakus/fullyconcealedhand.cc +++ b/src/scoring/yakus/fullyconcealedhand.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/walls.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/fullyconcealedhand.h b/src/scoring/yakus/fullyconcealedhand.h index 8c747e36..5c9ebad0 100644 --- a/src/scoring/yakus/fullyconcealedhand.h +++ b/src/scoring/yakus/fullyconcealedhand.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isFullyConcealedHand( diff --git a/src/scoring/yakus/halfflush.cc b/src/scoring/yakus/halfflush.cc index d87c972f..8dba5fe0 100644 --- a/src/scoring/yakus/halfflush.cc +++ b/src/scoring/yakus/halfflush.cc @@ -6,6 +6,7 @@ #include "scoring/yakus.h" #include "scoring/yakus/fullflush.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/yaku.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/halfflush.h b/src/scoring/yakus/halfflush.h index 23e2b23b..83907515 100644 --- a/src/scoring/yakus/halfflush.h +++ b/src/scoring/yakus/halfflush.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isHalfFlush(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/honorpon.cc b/src/scoring/yakus/honorpon.cc index 04124d53..8132a2bb 100644 --- a/src/scoring/yakus/honorpon.cc +++ b/src/scoring/yakus/honorpon.cc @@ -6,6 +6,7 @@ #include "scoring/yakus.h" #include "statefunctions/stateutilities.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/pieces.h" #include "types/piecetype.h" #include "types/sets.h" diff --git a/src/scoring/yakus/honorpon.h b/src/scoring/yakus/honorpon.h index 9ad6509b..16e878bf 100644 --- a/src/scoring/yakus/honorpon.h +++ b/src/scoring/yakus/honorpon.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isSeatWind(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/ippatsu.cc b/src/scoring/yakus/ippatsu.cc index 17fbba31..149846c3 100644 --- a/src/scoring/yakus/ippatsu.cc +++ b/src/scoring/yakus/ippatsu.cc @@ -7,6 +7,7 @@ #include "scoring/yakus/doubleriichi.h" #include "scoring/yakus/riichi.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/yaku.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/ippatsu.h b/src/scoring/yakus/ippatsu.h index 73c5d3ce..a80bcdbb 100644 --- a/src/scoring/yakus/ippatsu.h +++ b/src/scoring/yakus/ippatsu.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isIppatsu(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/littlefourwinds.cc b/src/scoring/yakus/littlefourwinds.cc index a5affb84..959b9f1c 100644 --- a/src/scoring/yakus/littlefourwinds.cc +++ b/src/scoring/yakus/littlefourwinds.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/littlefourwinds.h b/src/scoring/yakus/littlefourwinds.h index 8faa5587..08e4cd40 100644 --- a/src/scoring/yakus/littlefourwinds.h +++ b/src/scoring/yakus/littlefourwinds.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isLittleFourWinds(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/littlethreedragons.cc b/src/scoring/yakus/littlethreedragons.cc index f7fc5caf..6e8b2ffc 100644 --- a/src/scoring/yakus/littlethreedragons.cc +++ b/src/scoring/yakus/littlethreedragons.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/littlethreedragons.h b/src/scoring/yakus/littlethreedragons.h index c7756ed4..685bae83 100644 --- a/src/scoring/yakus/littlethreedragons.h +++ b/src/scoring/yakus/littlethreedragons.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isLittleThreeDragons(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/maxbranches.cc b/src/scoring/yakus/maxbranches.cc index 0f3a8d88..ac26df8b 100644 --- a/src/scoring/yakus/maxbranches.cc +++ b/src/scoring/yakus/maxbranches.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/maxbranches.h b/src/scoring/yakus/maxbranches.h index 4ce12c87..c80072ad 100644 --- a/src/scoring/yakus/maxbranches.h +++ b/src/scoring/yakus/maxbranches.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isMaxBranches(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/mixedtriplechi.cc b/src/scoring/yakus/mixedtriplechi.cc index 9446444d..660756ee 100644 --- a/src/scoring/yakus/mixedtriplechi.cc +++ b/src/scoring/yakus/mixedtriplechi.cc @@ -6,6 +6,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/mixedtriplechi.h b/src/scoring/yakus/mixedtriplechi.h index 08337597..02d8e2b6 100644 --- a/src/scoring/yakus/mixedtriplechi.h +++ b/src/scoring/yakus/mixedtriplechi.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isMixedTripleChi(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/ninegates.cc b/src/scoring/yakus/ninegates.cc index 15cf4847..53bc5324 100644 --- a/src/scoring/yakus/ninegates.cc +++ b/src/scoring/yakus/ninegates.cc @@ -7,6 +7,7 @@ #include "scoring/yakus.h" #include "scoring/yakus/fullflush.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/yaku.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/ninegates.h b/src/scoring/yakus/ninegates.h index f9392395..d7abb318 100644 --- a/src/scoring/yakus/ninegates.h +++ b/src/scoring/yakus/ninegates.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isNineGates(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/outsidehand.cc b/src/scoring/yakus/outsidehand.cc index a34323c2..511cafbc 100644 --- a/src/scoring/yakus/outsidehand.cc +++ b/src/scoring/yakus/outsidehand.cc @@ -7,6 +7,7 @@ #include "scoring/yakus/allterminalsandhonors.h" #include "scoring/yakus/terminalsinallsets.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/outsidehand.h b/src/scoring/yakus/outsidehand.h index c1bceda7..bde39f15 100644 --- a/src/scoring/yakus/outsidehand.h +++ b/src/scoring/yakus/outsidehand.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isOutsideHand(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/pinfu.cc b/src/scoring/yakus/pinfu.cc index 4d72ec1d..ce380791 100644 --- a/src/scoring/yakus/pinfu.cc +++ b/src/scoring/yakus/pinfu.cc @@ -7,6 +7,7 @@ #include "scoring/yakus.h" #include "statefunctions/stateutilities.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/pieces.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/pinfu.h b/src/scoring/yakus/pinfu.h index 8156c843..f811a5ed 100644 --- a/src/scoring/yakus/pinfu.h +++ b/src/scoring/yakus/pinfu.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isPinfu(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/puredoublechi.cc b/src/scoring/yakus/puredoublechi.cc index 73cc75d5..f3887e14 100644 --- a/src/scoring/yakus/puredoublechi.cc +++ b/src/scoring/yakus/puredoublechi.cc @@ -7,6 +7,7 @@ #include "scoring/yakus.h" #include "scoring/yakus/twicepuredoublechi.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/puredoublechi.h b/src/scoring/yakus/puredoublechi.h index 7be76980..d502f931 100644 --- a/src/scoring/yakus/puredoublechi.h +++ b/src/scoring/yakus/puredoublechi.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isPureDoubleChi(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/purestraight.cc b/src/scoring/yakus/purestraight.cc index 06f720c0..78bb7b0a 100644 --- a/src/scoring/yakus/purestraight.cc +++ b/src/scoring/yakus/purestraight.cc @@ -6,6 +6,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/purestraight.h b/src/scoring/yakus/purestraight.h index 649dce5b..1458d36b 100644 --- a/src/scoring/yakus/purestraight.h +++ b/src/scoring/yakus/purestraight.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isPureStraight(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/riichi.cc b/src/scoring/yakus/riichi.cc index 372e1795..0bd78579 100644 --- a/src/scoring/yakus/riichi.cc +++ b/src/scoring/yakus/riichi.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/yaku.h" namespace mahjong::yaku { diff --git a/src/scoring/yakus/riichi.h b/src/scoring/yakus/riichi.h index 046d44b4..0f8288d1 100644 --- a/src/scoring/yakus/riichi.h +++ b/src/scoring/yakus/riichi.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isRiichi(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/robbingakan.cc b/src/scoring/yakus/robbingakan.cc index 27b8b401..5c6f429a 100644 --- a/src/scoring/yakus/robbingakan.cc +++ b/src/scoring/yakus/robbingakan.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/statefunction.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/robbingakan.h b/src/scoring/yakus/robbingakan.h index bc2cbc39..30048599 100644 --- a/src/scoring/yakus/robbingakan.h +++ b/src/scoring/yakus/robbingakan.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isRobbingAKan(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/sevenpairs.cc b/src/scoring/yakus/sevenpairs.cc index 620c9909..69b010fd 100644 --- a/src/scoring/yakus/sevenpairs.cc +++ b/src/scoring/yakus/sevenpairs.cc @@ -6,6 +6,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/sevenpairs.h b/src/scoring/yakus/sevenpairs.h index 25874463..0622b458 100644 --- a/src/scoring/yakus/sevenpairs.h +++ b/src/scoring/yakus/sevenpairs.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isSevenPairs(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/terminalsinallsets.cc b/src/scoring/yakus/terminalsinallsets.cc index 62d441e3..1a881bc4 100644 --- a/src/scoring/yakus/terminalsinallsets.cc +++ b/src/scoring/yakus/terminalsinallsets.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/terminalsinallsets.h b/src/scoring/yakus/terminalsinallsets.h index d5d41f19..3964f9d0 100644 --- a/src/scoring/yakus/terminalsinallsets.h +++ b/src/scoring/yakus/terminalsinallsets.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isTerminalsInAllSets(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/thirteenorphans.cc b/src/scoring/yakus/thirteenorphans.cc index ddf97bce..6cee4403 100644 --- a/src/scoring/yakus/thirteenorphans.cc +++ b/src/scoring/yakus/thirteenorphans.cc @@ -6,6 +6,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/pieces.h" #include "types/piecetype.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/thirteenorphans.h b/src/scoring/yakus/thirteenorphans.h index ce6e6e59..867bae30 100644 --- a/src/scoring/yakus/thirteenorphans.h +++ b/src/scoring/yakus/thirteenorphans.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isThirteenOrphans( diff --git a/src/scoring/yakus/threeconcealedpons.cc b/src/scoring/yakus/threeconcealedpons.cc index d53f58ba..4906d478 100644 --- a/src/scoring/yakus/threeconcealedpons.cc +++ b/src/scoring/yakus/threeconcealedpons.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/threeconcealedpons.h b/src/scoring/yakus/threeconcealedpons.h index e4cec878..b3c211c3 100644 --- a/src/scoring/yakus/threeconcealedpons.h +++ b/src/scoring/yakus/threeconcealedpons.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isThreeConcealedPons(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/threekans.cc b/src/scoring/yakus/threekans.cc index cd2bde02..c499c457 100644 --- a/src/scoring/yakus/threekans.cc +++ b/src/scoring/yakus/threekans.cc @@ -5,6 +5,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/threekans.h b/src/scoring/yakus/threekans.h index 7c63801e..d090c8f3 100644 --- a/src/scoring/yakus/threekans.h +++ b/src/scoring/yakus/threekans.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isThreeKans(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/triplepon.cc b/src/scoring/yakus/triplepon.cc index 98226e7a..21c71133 100644 --- a/src/scoring/yakus/triplepon.cc +++ b/src/scoring/yakus/triplepon.cc @@ -6,6 +6,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/triplepon.h b/src/scoring/yakus/triplepon.h index 0c25db28..ef5458b6 100644 --- a/src/scoring/yakus/triplepon.h +++ b/src/scoring/yakus/triplepon.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isTriplePon(const GameState& state, const Player& player, diff --git a/src/scoring/yakus/twicepuredoublechi.cc b/src/scoring/yakus/twicepuredoublechi.cc index 2aadbeb0..20630818 100644 --- a/src/scoring/yakus/twicepuredoublechi.cc +++ b/src/scoring/yakus/twicepuredoublechi.cc @@ -6,6 +6,7 @@ #include "analysis/handnode.h" #include "scoring/yakus.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/sets.h" #include "types/yaku.h" diff --git a/src/scoring/yakus/twicepuredoublechi.h b/src/scoring/yakus/twicepuredoublechi.h index 5874f009..b569e334 100644 --- a/src/scoring/yakus/twicepuredoublechi.h +++ b/src/scoring/yakus/twicepuredoublechi.h @@ -3,6 +3,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong::yaku { bool isTwicePureDoubleChi(const GameState& state, const Player& player, diff --git a/src/statefunctions/decisionfunction.cc b/src/statefunctions/decisionfunction.cc index 73dd9c8d..1dbaf01b 100644 --- a/src/statefunctions/decisionfunction.cc +++ b/src/statefunctions/decisionfunction.cc @@ -8,6 +8,7 @@ #include "scoring/yakus/thirteenorphans.h" #include "statefunctions/stateutilities.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/pieces.h" #include "types/piecetype.h" #include "types/sets.h" diff --git a/src/statefunctions/decisionfunction.h b/src/statefunctions/decisionfunction.h index db46570b..de1e9a93 100644 --- a/src/statefunctions/decisionfunction.h +++ b/src/statefunctions/decisionfunction.h @@ -4,6 +4,7 @@ #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong { using DecisionFunction = diff --git a/src/statefunctions/gamestates/chi.cc b/src/statefunctions/gamestates/chi.cc index 91aef104..64a7cbe7 100644 --- a/src/statefunctions/gamestates/chi.cc +++ b/src/statefunctions/gamestates/chi.cc @@ -7,6 +7,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" diff --git a/src/statefunctions/gamestates/concealedkan.cc b/src/statefunctions/gamestates/concealedkan.cc index 67086c99..2a306fed 100644 --- a/src/statefunctions/gamestates/concealedkan.cc +++ b/src/statefunctions/gamestates/concealedkan.cc @@ -7,6 +7,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/piecetype.h" #include "types/sets.h" diff --git a/src/statefunctions/gamestates/convertedkan.cc b/src/statefunctions/gamestates/convertedkan.cc index bb5f86e8..5c9da342 100644 --- a/src/statefunctions/gamestates/convertedkan.cc +++ b/src/statefunctions/gamestates/convertedkan.cc @@ -8,6 +8,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/piecetype.h" #include "types/sets.h" diff --git a/src/statefunctions/gamestates/discard.cc b/src/statefunctions/gamestates/discard.cc index 0f818dd7..8832c965 100644 --- a/src/statefunctions/gamestates/discard.cc +++ b/src/statefunctions/gamestates/discard.cc @@ -9,6 +9,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" #include "types/statefunction.h" #include "types/walls.h" diff --git a/src/statefunctions/gamestates/draw.cc b/src/statefunctions/gamestates/draw.cc index 7b434c04..b087283c 100644 --- a/src/statefunctions/gamestates/draw.cc +++ b/src/statefunctions/gamestates/draw.cc @@ -3,6 +3,7 @@ #include "statefunctions/router.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/statefunction.h" #include "types/walls.h" diff --git a/src/statefunctions/gamestates/error.cc b/src/statefunctions/gamestates/error.cc index 46c5a16d..9636945e 100644 --- a/src/statefunctions/gamestates/error.cc +++ b/src/statefunctions/gamestates/error.cc @@ -3,6 +3,7 @@ #include "statefunctions/router.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/statefunction.h" namespace mahjong { diff --git a/src/statefunctions/gamestates/exhaust.cc b/src/statefunctions/gamestates/exhaust.cc index 5ae4dfa1..29409310 100644 --- a/src/statefunctions/gamestates/exhaust.cc +++ b/src/statefunctions/gamestates/exhaust.cc @@ -4,6 +4,7 @@ #include "analysis/util.h" #include "statefunctions/router.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/statefunction.h" namespace mahjong { diff --git a/src/statefunctions/gamestates/gameend.cc b/src/statefunctions/gamestates/gameend.cc index 81f45d72..4956d569 100644 --- a/src/statefunctions/gamestates/gameend.cc +++ b/src/statefunctions/gamestates/gameend.cc @@ -4,6 +4,7 @@ #include "statefunctions/router.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/statefunction.h" namespace mahjong { diff --git a/src/statefunctions/gamestates/gamestart.cc b/src/statefunctions/gamestates/gamestart.cc index 59b87dfa..ec70fcd2 100644 --- a/src/statefunctions/gamestates/gamestart.cc +++ b/src/statefunctions/gamestates/gamestart.cc @@ -3,6 +3,7 @@ #include "statefunctions/router.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/settings.h" #include "types/statefunction.h" diff --git a/src/statefunctions/gamestates/kan.cc b/src/statefunctions/gamestates/kan.cc index c663ddfc..3e123264 100644 --- a/src/statefunctions/gamestates/kan.cc +++ b/src/statefunctions/gamestates/kan.cc @@ -7,6 +7,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/piecetype.h" #include "types/sets.h" diff --git a/src/statefunctions/gamestates/kandiscard.cc b/src/statefunctions/gamestates/kandiscard.cc index c3f217b2..17a614c3 100644 --- a/src/statefunctions/gamestates/kandiscard.cc +++ b/src/statefunctions/gamestates/kandiscard.cc @@ -7,6 +7,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" #include "types/statefunction.h" diff --git a/src/statefunctions/gamestates/playerhand.cc b/src/statefunctions/gamestates/playerhand.cc index 00631c94..81e3ba70 100644 --- a/src/statefunctions/gamestates/playerhand.cc +++ b/src/statefunctions/gamestates/playerhand.cc @@ -9,6 +9,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" #include "types/statefunction.h" diff --git a/src/statefunctions/gamestates/pon.cc b/src/statefunctions/gamestates/pon.cc index efd0db12..1881bf63 100644 --- a/src/statefunctions/gamestates/pon.cc +++ b/src/statefunctions/gamestates/pon.cc @@ -7,6 +7,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/piecetype.h" #include "types/sets.h" diff --git a/src/statefunctions/gamestates/replacement.cc b/src/statefunctions/gamestates/replacement.cc index 8f243e37..41b9265d 100644 --- a/src/statefunctions/gamestates/replacement.cc +++ b/src/statefunctions/gamestates/replacement.cc @@ -7,6 +7,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" #include "types/statefunction.h" #include "types/walls.h" diff --git a/src/statefunctions/gamestates/riichi.cc b/src/statefunctions/gamestates/riichi.cc index e7d9bd02..75cde37e 100644 --- a/src/statefunctions/gamestates/riichi.cc +++ b/src/statefunctions/gamestates/riichi.cc @@ -8,6 +8,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" #include "types/statefunction.h" diff --git a/src/statefunctions/gamestates/ron.cc b/src/statefunctions/gamestates/ron.cc index d1261d62..ac505b01 100644 --- a/src/statefunctions/gamestates/ron.cc +++ b/src/statefunctions/gamestates/ron.cc @@ -7,6 +7,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" #include "types/statefunction.h" diff --git a/src/statefunctions/gamestates/roundend.cc b/src/statefunctions/gamestates/roundend.cc index fd9056d3..03e42b28 100644 --- a/src/statefunctions/gamestates/roundend.cc +++ b/src/statefunctions/gamestates/roundend.cc @@ -7,6 +7,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" #include "types/statefunction.h" diff --git a/src/statefunctions/gamestates/roundstart.cc b/src/statefunctions/gamestates/roundstart.cc index ffbdd7a8..f1ffd231 100644 --- a/src/statefunctions/gamestates/roundstart.cc +++ b/src/statefunctions/gamestates/roundstart.cc @@ -9,6 +9,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/statefunction.h" #include "types/walls.h" #include "types/winds.h" diff --git a/src/statefunctions/statecontroller.cc b/src/statefunctions/statecontroller.cc index 8acd112b..1be82f9e 100644 --- a/src/statefunctions/statecontroller.cc +++ b/src/statefunctions/statecontroller.cc @@ -12,6 +12,7 @@ #include "controllers/controllermanager.h" #include "statefunctions/router.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/settings.h" #include "types/statefunction.h" diff --git a/src/statefunctions/stateutilities.cc b/src/statefunctions/stateutilities.cc index d3af4594..17e7d8d4 100644 --- a/src/statefunctions/stateutilities.cc +++ b/src/statefunctions/stateutilities.cc @@ -11,6 +11,7 @@ #include "statefunctions/decisionfunction.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" #include "types/winds.h" diff --git a/src/statefunctions/stateutilities.h b/src/statefunctions/stateutilities.h index f42ba79f..32964ca6 100644 --- a/src/statefunctions/stateutilities.h +++ b/src/statefunctions/stateutilities.h @@ -3,6 +3,7 @@ #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" #include "types/winds.h" diff --git a/src/types/CMakeLists.txt b/src/types/CMakeLists.txt index 93bd26bb..8f337895 100644 --- a/src/types/CMakeLists.txt +++ b/src/types/CMakeLists.txt @@ -8,6 +8,7 @@ target_sources( FILES "event.h" "gamestate.h" + "hand.h" "meld.h" "pieces.h" "piecetype.h" diff --git a/src/types/gamestate.h b/src/types/gamestate.h index b512d3b9..1b66a72e 100644 --- a/src/types/gamestate.h +++ b/src/types/gamestate.h @@ -5,6 +5,7 @@ #include #include "controllers/playercontroller.h" +#include "types/hand.h" #include "types/meld.h" #include "types/piecetype.h" #include "types/settings.h" @@ -12,31 +13,6 @@ namespace mahjong { -struct Hand {}; - -struct Player { - int id; - std::array discards; - int discards_count = 0; - bool riichi = false; - int riichiPieceDiscard; - int riichiRound; - int score; - bool hasRonned; - int points; - bool open; - std::array live; - int live_count = 13; - std::array melds; - int meld_count = 0; - [[nodiscard]] std::ranges::subrange live_range() const { - return std::ranges::subrange(live.begin(), live.begin() + live_count); - } - [[nodiscard]] std::ranges::subrange melds_range() const { - return std::ranges::subrange(melds.begin(), melds.begin() + meld_count); - } -}; - struct GameState { int currentPlayer = -1; int turnNum = -1; diff --git a/src/types/hand.h b/src/types/hand.h new file mode 100644 index 00000000..10170f55 --- /dev/null +++ b/src/types/hand.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include "types/meld.h" +#include "types/piecetype.h" +#include "types/settings.h" +namespace mahjong { + +struct Player { + int id; + std::array discards; + int discards_count = 0; + bool riichi = false; + int riichiPieceDiscard; + int riichiRound; + int score; + bool hasRonned; + int points; + bool open; + std::array live; + int live_count = 13; + std::array melds; + int meld_count = 0; + [[nodiscard]] std::ranges::subrange live_range() const { + return std::ranges::subrange(live.begin(), live.begin() + live_count); + } + [[nodiscard]] std::ranges::subrange melds_range() const { + return std::ranges::subrange(melds.begin(), melds.begin() + meld_count); + } +}; +} // namespace mahjong diff --git a/src/types/typeprinter.cc b/src/types/typeprinter.cc index 183a078a..bec31537 100644 --- a/src/types/typeprinter.cc +++ b/src/types/typeprinter.cc @@ -11,6 +11,7 @@ #include "controllers/playercontroller.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/piecetype.h" diff --git a/src/types/walls.cc b/src/types/walls.cc index 90bb4718..fa417e8f 100644 --- a/src/types/walls.cc +++ b/src/types/walls.cc @@ -6,6 +6,7 @@ #include #include "types/gamestate.h" +#include "types/hand.h" #include "types/pieces.h" #include "types/piecetype.h" #include "types/settings.h" diff --git a/src/types/walls.h b/src/types/walls.h index 6a72ae13..64666305 100644 --- a/src/types/walls.h +++ b/src/types/walls.h @@ -3,6 +3,7 @@ #include "piecetype.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" namespace mahjong { diff --git a/src/types/yaku.h b/src/types/yaku.h index 75357ceb..5db13bc3 100644 --- a/src/types/yaku.h +++ b/src/types/yaku.h @@ -4,6 +4,7 @@ #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" namespace mahjong { diff --git a/tests/api/game_control.test.cc b/tests/api/game_control.test.cc index 19604819..d43075e9 100644 --- a/tests/api/game_control.test.cc +++ b/tests/api/game_control.test.cc @@ -7,6 +7,7 @@ #include "api/gamestate.h" #include "api/types.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" namespace { diff --git a/tests/count_pieces.test.cc b/tests/count_pieces.test.cc index 8c88ee27..de851643 100644 --- a/tests/count_pieces.test.cc +++ b/tests/count_pieces.test.cc @@ -3,7 +3,7 @@ #include #include "statefunctions/stateutilities.h" -#include "types/gamestate.h" +#include "types/hand.h" #include "types/pieces.h" namespace mahjong { diff --git a/tests/discard_piece.test.cc b/tests/discard_piece.test.cc index 1f515de0..6afca8f0 100644 --- a/tests/discard_piece.test.cc +++ b/tests/discard_piece.test.cc @@ -3,7 +3,7 @@ #include #include "statefunctions/stateutilities.h" -#include "types/gamestate.h" +#include "types/hand.h" #include "types/pieces.h" namespace mahjong { diff --git a/tests/game_play.test.cc b/tests/game_play.test.cc index 93025b7c..93950f1f 100644 --- a/tests/game_play.test.cc +++ b/tests/game_play.test.cc @@ -5,6 +5,7 @@ #include "scoring/scoring.h" #include "statefunctions/decisionfunction.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/pieces.h" #include "types/piecetype.h" #include "utils/handformer.h" diff --git a/tests/remove_pieces.test.cc b/tests/remove_pieces.test.cc index 18a9cadf..b355cddb 100644 --- a/tests/remove_pieces.test.cc +++ b/tests/remove_pieces.test.cc @@ -3,7 +3,7 @@ #include #include "statefunctions/stateutilities.h" -#include "types/gamestate.h" +#include "types/hand.h" #include "types/pieces.h" namespace mahjong { diff --git a/tests/rules/calls.test.cc b/tests/rules/calls.test.cc index c551ac16..ffd955d9 100644 --- a/tests/rules/calls.test.cc +++ b/tests/rules/calls.test.cc @@ -9,6 +9,7 @@ #include "statefunctions/statecontroller.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" #include "types/sets.h" #include "types/statefunction.h" diff --git a/tests/utils/gamestate_utils.cc b/tests/utils/gamestate_utils.cc index 2c648b84..3e7b7d9c 100644 --- a/tests/utils/gamestate_utils.cc +++ b/tests/utils/gamestate_utils.cc @@ -12,6 +12,7 @@ #include "statefunctions/router.h" #include "statefunctions/statecontroller.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/settings.h" #include "types/statefunction.h" #include "utils/playercontrollerfake.h" diff --git a/tests/utils/gamestate_utils.h b/tests/utils/gamestate_utils.h index 7875aade..c84611f2 100644 --- a/tests/utils/gamestate_utils.h +++ b/tests/utils/gamestate_utils.h @@ -3,6 +3,7 @@ #include "controllers/playercontroller.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/settings.h" #include "types/statefunction.h" diff --git a/tests/utils/handformer.cc b/tests/utils/handformer.cc index 9ff56f07..705c8c17 100644 --- a/tests/utils/handformer.cc +++ b/tests/utils/handformer.cc @@ -10,7 +10,7 @@ #include #include -#include "types/gamestate.h" +#include "types/hand.h" #include "types/pieces.h" #include "types/piecetype.h" diff --git a/tests/utils/handformer.h b/tests/utils/handformer.h index 8d85cabf..01676219 100644 --- a/tests/utils/handformer.h +++ b/tests/utils/handformer.h @@ -4,6 +4,7 @@ #include #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" namespace mahjong { diff --git a/tests/yakus/afterkan.test.cc b/tests/yakus/afterkan.test.cc index 55049873..d33256dd 100644 --- a/tests/yakus/afterkan.test.cc +++ b/tests/yakus/afterkan.test.cc @@ -8,6 +8,7 @@ #include "analysis/handnode.h" #include "scoring/yakus/afterakan.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/statefunction.h" #include "utils/handformer.h" diff --git a/tests/yakus/allpon.test.cc b/tests/yakus/allpon.test.cc index a88fd051..d5cf9f86 100644 --- a/tests/yakus/allpon.test.cc +++ b/tests/yakus/allpon.test.cc @@ -8,6 +8,7 @@ #include "analysis/handnode.h" #include "scoring/yakus/allpons.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" diff --git a/tests/yakus/allsimples.test.cc b/tests/yakus/allsimples.test.cc index b083b761..e25ada28 100644 --- a/tests/yakus/allsimples.test.cc +++ b/tests/yakus/allsimples.test.cc @@ -9,6 +9,7 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { diff --git a/tests/yakus/allterminalsandhonors.test.cc b/tests/yakus/allterminalsandhonors.test.cc index b0843147..f255206d 100644 --- a/tests/yakus/allterminalsandhonors.test.cc +++ b/tests/yakus/allterminalsandhonors.test.cc @@ -9,6 +9,7 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" diff --git a/tests/yakus/blessingofman.test.cc b/tests/yakus/blessingofman.test.cc index 0154a3c7..0c3c888a 100644 --- a/tests/yakus/blessingofman.test.cc +++ b/tests/yakus/blessingofman.test.cc @@ -9,6 +9,7 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { diff --git a/tests/yakus/concealedhand.test.cc b/tests/yakus/concealedhand.test.cc index 607f001a..db418279 100644 --- a/tests/yakus/concealedhand.test.cc +++ b/tests/yakus/concealedhand.test.cc @@ -5,6 +5,7 @@ #include "scoring/yakus/fullyconcealedhand.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/settings.h" #include "utils/handformer.h" diff --git a/tests/yakus/concealedpon.test.cc b/tests/yakus/concealedpon.test.cc index a68fb7d8..850b23ea 100644 --- a/tests/yakus/concealedpon.test.cc +++ b/tests/yakus/concealedpon.test.cc @@ -8,6 +8,7 @@ #include "analysis/handnode.h" #include "scoring/yakus/threeconcealedpons.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/sets.h" diff --git a/tests/yakus/dragonpon.test.cc b/tests/yakus/dragonpon.test.cc index 17e1290f..c4c99f13 100644 --- a/tests/yakus/dragonpon.test.cc +++ b/tests/yakus/dragonpon.test.cc @@ -8,6 +8,7 @@ #include "analysis/handnode.h" #include "scoring/yakus/honorpon.h" #include "types/gamestate.h" +#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { diff --git a/tests/yakus/fullflush.test.cc b/tests/yakus/fullflush.test.cc index 6199afc0..67b7045f 100644 --- a/tests/yakus/fullflush.test.cc +++ b/tests/yakus/fullflush.test.cc @@ -9,6 +9,7 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" diff --git a/tests/yakus/halfflush.test.cc b/tests/yakus/halfflush.test.cc index 6debdf67..941bc3c8 100644 --- a/tests/yakus/halfflush.test.cc +++ b/tests/yakus/halfflush.test.cc @@ -9,6 +9,7 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" diff --git a/tests/yakus/littlethreedragons.test.cc b/tests/yakus/littlethreedragons.test.cc index 5166956e..202d7eb7 100644 --- a/tests/yakus/littlethreedragons.test.cc +++ b/tests/yakus/littlethreedragons.test.cc @@ -9,6 +9,7 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" diff --git a/tests/yakus/mixedtriplechi.test.cc b/tests/yakus/mixedtriplechi.test.cc index 8084e65b..ec2bd051 100644 --- a/tests/yakus/mixedtriplechi.test.cc +++ b/tests/yakus/mixedtriplechi.test.cc @@ -9,6 +9,7 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { diff --git a/tests/yakus/outsidehand.test.cc b/tests/yakus/outsidehand.test.cc index c0f91a0f..1d443ff4 100644 --- a/tests/yakus/outsidehand.test.cc +++ b/tests/yakus/outsidehand.test.cc @@ -9,6 +9,7 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { diff --git a/tests/yakus/pinfu.test.cc b/tests/yakus/pinfu.test.cc index 8b69bc56..96ee8a0c 100644 --- a/tests/yakus/pinfu.test.cc +++ b/tests/yakus/pinfu.test.cc @@ -9,6 +9,7 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/pieces.h" #include "types/piecetype.h" #include "utils/handformer.h" diff --git a/tests/yakus/puredoublechi.test.cc b/tests/yakus/puredoublechi.test.cc index 0cdf1da0..3e71a737 100644 --- a/tests/yakus/puredoublechi.test.cc +++ b/tests/yakus/puredoublechi.test.cc @@ -9,6 +9,7 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { diff --git a/tests/yakus/purestraight.test.cc b/tests/yakus/purestraight.test.cc index 5931f4fc..be9f3701 100644 --- a/tests/yakus/purestraight.test.cc +++ b/tests/yakus/purestraight.test.cc @@ -9,6 +9,7 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { diff --git a/tests/yakus/riichi.test.cc b/tests/yakus/riichi.test.cc index 306f2fc4..a2c33214 100644 --- a/tests/yakus/riichi.test.cc +++ b/tests/yakus/riichi.test.cc @@ -8,6 +8,7 @@ #include "scoring/yakus/doubleriichi.h" #include "scoring/yakus/ippatsu.h" #include "types/gamestate.h" +#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { diff --git a/tests/yakus/robbingkan.test.cc b/tests/yakus/robbingkan.test.cc index dc25a5f3..ef65ea8d 100644 --- a/tests/yakus/robbingkan.test.cc +++ b/tests/yakus/robbingkan.test.cc @@ -8,6 +8,7 @@ #include "analysis/handnode.h" #include "scoring/yakus/robbingakan.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/statefunction.h" #include "utils/handformer.h" diff --git a/tests/yakus/sevenpairs.test.cc b/tests/yakus/sevenpairs.test.cc index f56413f8..b55191fb 100644 --- a/tests/yakus/sevenpairs.test.cc +++ b/tests/yakus/sevenpairs.test.cc @@ -9,6 +9,7 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { diff --git a/tests/yakus/terminalinsets.test.cc b/tests/yakus/terminalinsets.test.cc index fc0ab53c..e0ad4331 100644 --- a/tests/yakus/terminalinsets.test.cc +++ b/tests/yakus/terminalinsets.test.cc @@ -8,6 +8,7 @@ #include "analysis/handnode.h" #include "scoring/yakus/terminalsinallsets.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" diff --git a/tests/yakus/triplekan.test.cc b/tests/yakus/triplekan.test.cc index c8bc5118..07c021bf 100644 --- a/tests/yakus/triplekan.test.cc +++ b/tests/yakus/triplekan.test.cc @@ -8,6 +8,7 @@ #include "analysis/handnode.h" #include "scoring/yakus/threekans.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/meld.h" #include "types/pieces.h" #include "types/piecetype.h" diff --git a/tests/yakus/triplepon.test.cc b/tests/yakus/triplepon.test.cc index 129bdcfa..6ec4acfe 100644 --- a/tests/yakus/triplepon.test.cc +++ b/tests/yakus/triplepon.test.cc @@ -9,6 +9,7 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { diff --git a/tests/yakus/twicepuredoublechi.test.cc b/tests/yakus/twicepuredoublechi.test.cc index 54758597..cd8471c4 100644 --- a/tests/yakus/twicepuredoublechi.test.cc +++ b/tests/yakus/twicepuredoublechi.test.cc @@ -9,6 +9,7 @@ #include "analysis/analysis.h" #include "analysis/handnode.h" #include "types/gamestate.h" +#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { diff --git a/tests/yakus/underthesea.test.cc b/tests/yakus/underthesea.test.cc index 8639d0a2..3f14c0c4 100644 --- a/tests/yakus/underthesea.test.cc +++ b/tests/yakus/underthesea.test.cc @@ -7,6 +7,7 @@ #include "analysis/handnode.h" #include "scoring/yakus/bottomofthesea.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/settings.h" #include "utils/handformer.h" diff --git a/tests/yakus/windpons.test.cc b/tests/yakus/windpons.test.cc index efb169f7..61a9abe2 100644 --- a/tests/yakus/windpons.test.cc +++ b/tests/yakus/windpons.test.cc @@ -8,6 +8,7 @@ #include "analysis/handnode.h" #include "scoring/yakus/honorpon.h" #include "types/gamestate.h" +#include "types/hand.h" #include "utils/handformer.h" namespace mahjong::yaku { From bfe6158683f44778eedf3a8f8c5687aa6664518b Mon Sep 17 00:00:00 2001 From: alice Hartley Date: Fri, 5 Sep 2025 12:51:04 -0700 Subject: [PATCH 12/14] Rename Player back to Hand. --- src/analysis/analysis.cc | 3 +-- src/analysis/analysis.h | 3 +-- src/analysis/util.cc | 8 ++++---- src/analysis/util.h | 6 +++--- src/scoring/scoring.cc | 16 ++++++++-------- src/scoring/scoring.h | 8 ++++---- src/scoring/yakus/afterakan.cc | 2 +- src/scoring/yakus/afterakan.h | 2 +- src/scoring/yakus/allgreen.cc | 4 ++-- src/scoring/yakus/allgreen.h | 2 +- src/scoring/yakus/allhonors.cc | 4 ++-- src/scoring/yakus/allhonors.h | 2 +- src/scoring/yakus/allpons.cc | 4 ++-- src/scoring/yakus/allpons.h | 2 +- src/scoring/yakus/allsimples.cc | 4 ++-- src/scoring/yakus/allsimples.h | 2 +- src/scoring/yakus/allterminals.cc | 4 ++-- src/scoring/yakus/allterminals.h | 2 +- src/scoring/yakus/allterminalsandhonors.cc | 4 ++-- src/scoring/yakus/allterminalsandhonors.h | 2 +- src/scoring/yakus/bigfourwinds.cc | 4 ++-- src/scoring/yakus/bigfourwinds.h | 2 +- src/scoring/yakus/bigthreedragons.cc | 4 ++-- src/scoring/yakus/bigthreedragons.h | 2 +- src/scoring/yakus/blessingofearth.cc | 2 +- src/scoring/yakus/blessingofearth.h | 2 +- src/scoring/yakus/blessingofheaven.cc | 2 +- src/scoring/yakus/blessingofheaven.h | 2 +- src/scoring/yakus/blessingofman.cc | 2 +- src/scoring/yakus/blessingofman.h | 2 +- src/scoring/yakus/bottomofthesea.cc | 2 +- src/scoring/yakus/bottomofthesea.h | 2 +- src/scoring/yakus/doubleriichi.cc | 2 +- src/scoring/yakus/doubleriichi.h | 2 +- src/scoring/yakus/fourconcealedpon.cc | 4 ++-- src/scoring/yakus/fourconcealedpon.h | 2 +- src/scoring/yakus/fourkans.cc | 4 ++-- src/scoring/yakus/fourkans.h | 2 +- src/scoring/yakus/fullflush.cc | 4 ++-- src/scoring/yakus/fullflush.h | 2 +- src/scoring/yakus/fullyconcealedhand.cc | 5 ++--- src/scoring/yakus/fullyconcealedhand.h | 2 +- src/scoring/yakus/halfflush.cc | 4 ++-- src/scoring/yakus/halfflush.h | 2 +- src/scoring/yakus/honorpon.cc | 14 +++++++------- src/scoring/yakus/honorpon.h | 10 +++++----- src/scoring/yakus/ippatsu.cc | 2 +- src/scoring/yakus/ippatsu.h | 2 +- src/scoring/yakus/littlefourwinds.cc | 4 ++-- src/scoring/yakus/littlefourwinds.h | 2 +- src/scoring/yakus/littlethreedragons.cc | 4 ++-- src/scoring/yakus/littlethreedragons.h | 2 +- src/scoring/yakus/maxbranches.cc | 4 ++-- src/scoring/yakus/maxbranches.h | 2 +- src/scoring/yakus/mixedtriplechi.cc | 4 ++-- src/scoring/yakus/mixedtriplechi.h | 2 +- src/scoring/yakus/ninegates.cc | 4 ++-- src/scoring/yakus/ninegates.h | 2 +- src/scoring/yakus/outsidehand.cc | 6 +++--- src/scoring/yakus/outsidehand.h | 4 ++-- src/scoring/yakus/pinfu.cc | 5 +++-- src/scoring/yakus/pinfu.h | 2 +- src/scoring/yakus/puredoublechi.cc | 2 +- src/scoring/yakus/puredoublechi.h | 2 +- src/scoring/yakus/purestraight.cc | 4 ++-- src/scoring/yakus/purestraight.h | 2 +- src/scoring/yakus/riichi.cc | 2 +- src/scoring/yakus/riichi.h | 2 +- src/scoring/yakus/robbingakan.cc | 2 +- src/scoring/yakus/robbingakan.h | 2 +- src/scoring/yakus/sevenpairs.cc | 2 +- src/scoring/yakus/sevenpairs.h | 2 +- src/scoring/yakus/terminalsinallsets.cc | 4 ++-- src/scoring/yakus/terminalsinallsets.h | 2 +- src/scoring/yakus/thirteenorphans.cc | 4 ++-- src/scoring/yakus/thirteenorphans.h | 2 +- src/scoring/yakus/threeconcealedpons.cc | 4 ++-- src/scoring/yakus/threeconcealedpons.h | 2 +- src/scoring/yakus/threekans.cc | 4 ++-- src/scoring/yakus/threekans.h | 2 +- src/scoring/yakus/triplepon.cc | 4 ++-- src/scoring/yakus/triplepon.h | 2 +- src/scoring/yakus/twicepuredoublechi.cc | 2 +- src/scoring/yakus/twicepuredoublechi.h | 2 +- src/statefunctions/decisionfunction.cc | 18 +++++++++--------- src/statefunctions/decisionfunction.h | 18 +++++++++--------- src/statefunctions/gamestates/chi.cc | 4 ++-- src/statefunctions/gamestates/concealedkan.cc | 2 +- src/statefunctions/gamestates/convertedkan.cc | 2 +- src/statefunctions/gamestates/discard.cc | 4 ++-- src/statefunctions/gamestates/draw.cc | 2 +- src/statefunctions/gamestates/error.cc | 1 - src/statefunctions/gamestates/exhaust.cc | 1 - src/statefunctions/gamestates/gameend.cc | 1 - src/statefunctions/gamestates/gamestart.cc | 1 - src/statefunctions/gamestates/kan.cc | 2 +- src/statefunctions/gamestates/kandiscard.cc | 4 ++-- src/statefunctions/gamestates/playerhand.cc | 7 ++++--- src/statefunctions/gamestates/pon.cc | 2 +- src/statefunctions/gamestates/replacement.cc | 2 +- src/statefunctions/gamestates/riichi.cc | 2 +- src/statefunctions/gamestates/ron.cc | 10 +++++----- src/statefunctions/gamestates/roundstart.cc | 1 - src/statefunctions/statecontroller.cc | 1 - src/statefunctions/stateutilities.cc | 16 ++++++++-------- src/statefunctions/stateutilities.h | 10 +++++----- src/types/event.h | 1 - src/types/gamestate.h | 2 +- src/types/hand.h | 2 +- src/types/typeprinter.cc | 2 +- src/types/typeprinter.h | 4 ++-- src/types/walls.cc | 1 - src/types/yaku.h | 2 +- tests/api/game_control.test.cc | 5 +++-- tests/count_pieces.test.cc | 2 +- tests/discard_piece.test.cc | 7 +++---- tests/game_play.test.cc | 2 +- tests/remove_pieces.test.cc | 8 ++++---- tests/rules/calls.test.cc | 4 ++-- tests/utils/gamestate_utils.cc | 5 ++--- tests/utils/handformer.cc | 2 +- tests/utils/handformer.h | 2 +- tests/yakus/afterkan.test.cc | 6 +++--- tests/yakus/allpon.test.cc | 8 ++++---- tests/yakus/allsimples.test.cc | 6 +++--- tests/yakus/allterminalsandhonors.test.cc | 6 +++--- tests/yakus/blessingofman.test.cc | 8 ++++---- tests/yakus/concealedhand.test.cc | 8 ++++---- tests/yakus/concealedpon.test.cc | 10 +++++----- tests/yakus/dragonpon.test.cc | 12 ++++++------ tests/yakus/fullflush.test.cc | 10 +++++----- tests/yakus/halfflush.test.cc | 8 ++++---- tests/yakus/littlethreedragons.test.cc | 6 +++--- tests/yakus/mixedtriplechi.test.cc | 6 +++--- tests/yakus/outsidehand.test.cc | 8 ++++---- tests/yakus/pinfu.test.cc | 8 ++++---- tests/yakus/puredoublechi.test.cc | 6 +++--- tests/yakus/purestraight.test.cc | 6 +++--- tests/yakus/riichi.test.cc | 8 ++++---- tests/yakus/robbingkan.test.cc | 4 ++-- tests/yakus/sevenpairs.test.cc | 6 +++--- tests/yakus/terminalinsets.test.cc | 6 +++--- tests/yakus/triplekan.test.cc | 8 ++++---- tests/yakus/triplepon.test.cc | 4 ++-- tests/yakus/twicepuredoublechi.test.cc | 6 +++--- tests/yakus/underthesea.test.cc | 6 +++--- tests/yakus/windpons.test.cc | 16 ++++++++-------- 147 files changed, 308 insertions(+), 318 deletions(-) diff --git a/src/analysis/analysis.cc b/src/analysis/analysis.cc index bca70409..43d0768e 100644 --- a/src/analysis/analysis.cc +++ b/src/analysis/analysis.cc @@ -22,8 +22,7 @@ void countPieces(Breakdown* b) { } } // namespace -std::vector AnalyzeHand(const Player& player, - const bool only_complete) { +std::vector AnalyzeHand(const Hand& player, const bool only_complete) { Branch base_branch; base_branch.open = !player.melds.empty(); for (const auto& meld : player.melds_range()) { diff --git a/src/analysis/analysis.h b/src/analysis/analysis.h index d0caf5a7..923e5594 100644 --- a/src/analysis/analysis.h +++ b/src/analysis/analysis.h @@ -19,6 +19,5 @@ struct Branch { }; std::unique_ptr breakdownHand(const std::span& pieces); -std::vector AnalyzeHand(const Player& player, - bool only_complete = false); +std::vector AnalyzeHand(const Hand& player, bool only_complete = false); } // namespace mahjong diff --git a/src/analysis/util.cc b/src/analysis/util.cc index 27332fed..683ef5d3 100644 --- a/src/analysis/util.cc +++ b/src/analysis/util.cc @@ -52,7 +52,7 @@ std::vector completeSet(const Piece a, const Piece b) { return waits; } -std::vector getWaits(const Player& hand) { +std::vector getWaits(const Hand& hand) { // 13, 10, 7, 4, 1 are possible piece counts for non-melded tiles if (hand.live_count == 0 || hand.live_count % 3 != 1) { return {}; @@ -73,8 +73,8 @@ std::vector getWaits(const Player& hand) { return waits; } -std::vector getWaits(const Player& hand, const Piece& piece) { - Player new_hand = hand; +std::vector getWaits(const Hand& hand, const Piece& piece) { + Hand new_hand = hand; // This will move all pieces matching piece to the end of the array, but // we will only decrease the count by 1 so only a single piece will be // removed. @@ -83,7 +83,7 @@ std::vector getWaits(const Player& hand, const Piece& piece) { return getWaits(new_hand); } -std::map> getPossibleWaits(const Player& hand) { +std::map> getPossibleWaits(const Hand& hand) { // 14, 11, 8, 5, 2 are the possible piece counts for non-melded tiles. if (hand.live_count == 0 || hand.live_count % 3 != 2) { return {}; diff --git a/src/analysis/util.h b/src/analysis/util.h index cfcd4d77..e0123add 100644 --- a/src/analysis/util.h +++ b/src/analysis/util.h @@ -14,16 +14,16 @@ std::vector completeSet(Piece a, Piece b); // Returns list of waits that complete the hand. // Use with 13 piece hands. -std::vector getWaits(const Player& hand); +std::vector getWaits(const Hand& hand); // Returns list of waits that complete the hand with piece removed. // Use with 14 piece hands. -std::vector getWaits(const Player& hand, const Piece& piece); +std::vector getWaits(const Hand& hand, const Piece& piece); // Returns a map of waits for the discard of a given piece that complete the // hand. // Use with 14 piece hands. -std::map> getPossibleWaits(const Player& hand); +std::map> getPossibleWaits(const Hand& hand); using SetCheckFunc = std::function; // Calls func on each set in branch, returns true if and only if func returns diff --git a/src/scoring/scoring.cc b/src/scoring/scoring.cc index f3dc381a..efb48e96 100644 --- a/src/scoring/scoring.cc +++ b/src/scoring/scoring.cc @@ -59,8 +59,8 @@ const int kFuRounding = 10; } // namespace -Score scorePlayer(const GameState& state, const Player& player) { - auto root = breakdownHand(player.live_range()); +Score scorePlayer(const GameState& state, const Hand& player) { + auto root = breakdownHand(player.live_range()); Score s; s.han = 0; s.yakuman = 0; @@ -156,7 +156,7 @@ int getBasicPoints(Score s) { const int kSevenpairs = 25; -int getFu(const GameState& state, const Player& player, +int getFu(const GameState& state, const Hand& player, const std::vector& branch) { if (yaku::isSevenPairs(state, player, branch)) { return kSevenpairs; @@ -179,7 +179,7 @@ int getFu(const GameState& state, const Player& player, } else if (!player.hasRonned) { fu += kSelfdraw; } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type == SetType::kKan) { if (!meld.start.isHonor() && !meld.start.isTerminal()) { fu += open ? kSimplekan : kCsimplekan; @@ -233,7 +233,7 @@ int getFu(const GameState& state, const Player& player, (kFuRounding - (fu % kFuRounding)); // rounding up to multiple of ten } -bool isOpenPinfu(const GameState& state, const Player& player, +bool isOpenPinfu(const GameState& state, const Hand& player, const std::vector& branch) { for (const auto* node : branch) { if (node->type() == SetType::kPon) { @@ -252,7 +252,7 @@ bool isOpenPinfu(const GameState& state, const Player& player, } } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type > SetType::kChi) { return false; } @@ -260,8 +260,8 @@ bool isOpenPinfu(const GameState& state, const Player& player, return getWaits(player, state.pendingPiece).size() >= 2; } -bool isComplete(const GameState& state, const Player& player) { - auto root = breakdownHand(player.live_range()); +bool isComplete(const GameState& state, const Hand& player) { + auto root = breakdownHand(player.live_range()); if (!root->IsComplete() && !yaku::isThirteenOrphans(state, player)) { return false; } diff --git a/src/scoring/scoring.h b/src/scoring/scoring.h index 1bd2a547..2865efee 100644 --- a/src/scoring/scoring.h +++ b/src/scoring/scoring.h @@ -7,15 +7,15 @@ #include "types/score.h" namespace mahjong { -Score scorePlayer(const GameState& state, const Player& player); +Score scorePlayer(const GameState& state, const Hand& player); int getBasicPoints(Score s); -int getFu(const GameState& state, const Player& player, +int getFu(const GameState& state, const Hand& player, const std::vector& branch); -bool isOpenPinfu(const GameState& state, const Player& player, +bool isOpenPinfu(const GameState& state, const Hand& player, const std::vector& branch); -bool isComplete(const GameState& state, const Player& player); +bool isComplete(const GameState& state, const Hand& player); } // namespace mahjong diff --git a/src/scoring/yakus/afterakan.cc b/src/scoring/yakus/afterakan.cc index 265cfe5c..69615fd1 100644 --- a/src/scoring/yakus/afterakan.cc +++ b/src/scoring/yakus/afterakan.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAfterAKan(const GameState& state, const Player& player, +bool isAfterAKan(const GameState& state, const Hand& player, const std::vector& /*branch*/) { if (state.currentPlayer != player.id) { return false; diff --git a/src/scoring/yakus/afterakan.h b/src/scoring/yakus/afterakan.h index 2923f4f6..dafc6380 100644 --- a/src/scoring/yakus/afterakan.h +++ b/src/scoring/yakus/afterakan.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isAfterAKan(const GameState& state, const Player& player, +bool isAfterAKan(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allgreen.cc b/src/scoring/yakus/allgreen.cc index 4001474b..62efdcb7 100644 --- a/src/scoring/yakus/allgreen.cc +++ b/src/scoring/yakus/allgreen.cc @@ -9,9 +9,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllGreen(const GameState& /*state*/, const Player& player, +bool isAllGreen(const GameState& /*state*/, const Hand& player, const std::vector& /*branch*/) { - for (const auto& piece : player.live_range()) { + for (const auto& piece : player.live_range()) { if (!piece.isGreen()) { return false; } diff --git a/src/scoring/yakus/allgreen.h b/src/scoring/yakus/allgreen.h index 7839ac6a..3c940df2 100644 --- a/src/scoring/yakus/allgreen.h +++ b/src/scoring/yakus/allgreen.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isAllGreen(const GameState& state, const Player& player, +bool isAllGreen(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allhonors.cc b/src/scoring/yakus/allhonors.cc index 6b8b58e6..c6219427 100644 --- a/src/scoring/yakus/allhonors.cc +++ b/src/scoring/yakus/allhonors.cc @@ -9,9 +9,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllHonors(const GameState& /*state*/, const Player& player, +bool isAllHonors(const GameState& /*state*/, const Hand& player, const std::vector& /*branch*/) { - for (const auto& piece : player.live_range()) { + for (const auto& piece : player.live_range()) { if (!piece.isHonor()) { return false; } diff --git a/src/scoring/yakus/allhonors.h b/src/scoring/yakus/allhonors.h index fe697345..ffbd0780 100644 --- a/src/scoring/yakus/allhonors.h +++ b/src/scoring/yakus/allhonors.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isAllHonors(const GameState& state, const Player& player, +bool isAllHonors(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allpons.cc b/src/scoring/yakus/allpons.cc index 4e4004ea..10393288 100644 --- a/src/scoring/yakus/allpons.cc +++ b/src/scoring/yakus/allpons.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllPons(const GameState& /* state */, const Player& player, +bool isAllPons(const GameState& /* state */, const Hand& player, const std::vector& branch) { int pons = 0; for (const auto* node : branch) { @@ -18,7 +18,7 @@ bool isAllPons(const GameState& /* state */, const Player& player, pons++; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type == SetType::kKan || meld.type == SetType::kPon || meld.type == SetType::kConcealedKan) { pons++; diff --git a/src/scoring/yakus/allpons.h b/src/scoring/yakus/allpons.h index f8ffbd9e..5a7981d7 100644 --- a/src/scoring/yakus/allpons.h +++ b/src/scoring/yakus/allpons.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isAllPons(const GameState& state, const Player& player, +bool isAllPons(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/allsimples.cc b/src/scoring/yakus/allsimples.cc index a10d5639..ed1df6b8 100644 --- a/src/scoring/yakus/allsimples.cc +++ b/src/scoring/yakus/allsimples.cc @@ -9,9 +9,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllSimples(const GameState& /* state */, const Player& player, +bool isAllSimples(const GameState& /* state */, const Hand& player, const std::vector& /*branch*/) { - for (const auto& piece : player.live_range()) { + for (const auto& piece : player.live_range()) { if (piece.isHonor() || piece.isTerminal()) { return false; } diff --git a/src/scoring/yakus/allsimples.h b/src/scoring/yakus/allsimples.h index 503b4060..0e4d61d5 100644 --- a/src/scoring/yakus/allsimples.h +++ b/src/scoring/yakus/allsimples.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isAllSimples(const GameState& state, const Player& player, +bool isAllSimples(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allterminals.cc b/src/scoring/yakus/allterminals.cc index bb3803c5..3ea5e4c5 100644 --- a/src/scoring/yakus/allterminals.cc +++ b/src/scoring/yakus/allterminals.cc @@ -9,9 +9,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllTerminals(const GameState& /*state*/, const Player& player, +bool isAllTerminals(const GameState& /*state*/, const Hand& player, const std::vector& /*branch*/) { - for (const auto& piece : player.live_range()) { + for (const auto& piece : player.live_range()) { if (!piece.isTerminal()) { return false; } diff --git a/src/scoring/yakus/allterminals.h b/src/scoring/yakus/allterminals.h index 973d9a0d..92edd20c 100644 --- a/src/scoring/yakus/allterminals.h +++ b/src/scoring/yakus/allterminals.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isAllTerminals(const GameState& state, const Player& player, +bool isAllTerminals(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allterminalsandhonors.cc b/src/scoring/yakus/allterminalsandhonors.cc index f1e91e3c..fe0ac67f 100644 --- a/src/scoring/yakus/allterminalsandhonors.cc +++ b/src/scoring/yakus/allterminalsandhonors.cc @@ -10,9 +10,9 @@ namespace mahjong::yaku { bool isAllTerminalsAndHonors( - const GameState& /*state*/, const Player& player, + const GameState& /*state*/, const Hand& player, const std::vector& /*branch*/) { - for (const auto& piece : player.live_range()) { + for (const auto& piece : player.live_range()) { if (!piece.isHonor() && !piece.isTerminal()) { return false; } diff --git a/src/scoring/yakus/allterminalsandhonors.h b/src/scoring/yakus/allterminalsandhonors.h index 44826809..326fbc79 100644 --- a/src/scoring/yakus/allterminalsandhonors.h +++ b/src/scoring/yakus/allterminalsandhonors.h @@ -7,7 +7,7 @@ namespace mahjong::yaku { bool isAllTerminalsAndHonors( - const GameState& state, const Player& player, + const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/bigfourwinds.cc b/src/scoring/yakus/bigfourwinds.cc index c713df11..0eed780c 100644 --- a/src/scoring/yakus/bigfourwinds.cc +++ b/src/scoring/yakus/bigfourwinds.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBigFourWinds(const GameState& /*state*/, const Player& player, +bool isBigFourWinds(const GameState& /*state*/, const Hand& player, const std::vector& branch) { int pons = 0; for (const auto* node : branch) { @@ -28,7 +28,7 @@ bool isBigFourWinds(const GameState& /*state*/, const Player& player, } pons++; } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { switch (meld.start.toUint8_t()) { case Piece::Type::kEastWind: case Piece::Type::kSouthWind: diff --git a/src/scoring/yakus/bigfourwinds.h b/src/scoring/yakus/bigfourwinds.h index bed1b26d..bd5f813c 100644 --- a/src/scoring/yakus/bigfourwinds.h +++ b/src/scoring/yakus/bigfourwinds.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isBigFourWinds(const GameState& state, const Player& player, +bool isBigFourWinds(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/bigthreedragons.cc b/src/scoring/yakus/bigthreedragons.cc index 853dea5c..0ddd2bb3 100644 --- a/src/scoring/yakus/bigthreedragons.cc +++ b/src/scoring/yakus/bigthreedragons.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBigThreeDragons(const GameState& /*state*/, const Player& player, +bool isBigThreeDragons(const GameState& /*state*/, const Hand& player, const std::vector& branch) { int pons = 0; for (const auto* node : branch) { @@ -27,7 +27,7 @@ bool isBigThreeDragons(const GameState& /*state*/, const Player& player, } pons++; } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { switch (meld.start.toUint8_t()) { case Piece::Type::kRedDragon: case Piece::Type::kGreenDragon: diff --git a/src/scoring/yakus/bigthreedragons.h b/src/scoring/yakus/bigthreedragons.h index 7f499001..22fc2fba 100644 --- a/src/scoring/yakus/bigthreedragons.h +++ b/src/scoring/yakus/bigthreedragons.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isBigThreeDragons(const GameState& state, const Player& player, +bool isBigThreeDragons(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/blessingofearth.cc b/src/scoring/yakus/blessingofearth.cc index 6372c46b..f73eb81f 100644 --- a/src/scoring/yakus/blessingofearth.cc +++ b/src/scoring/yakus/blessingofearth.cc @@ -9,7 +9,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBlessingOfEarth(const GameState& state, const Player& player, +bool isBlessingOfEarth(const GameState& state, const Hand& player, const std::vector& /*branch*/) { if (player.open) { return false; diff --git a/src/scoring/yakus/blessingofearth.h b/src/scoring/yakus/blessingofearth.h index 60c166da..12bae67c 100644 --- a/src/scoring/yakus/blessingofearth.h +++ b/src/scoring/yakus/blessingofearth.h @@ -7,7 +7,7 @@ namespace mahjong::yaku { bool isBlessingOfEarth( - const GameState& state, const Player& player, + const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/blessingofheaven.cc b/src/scoring/yakus/blessingofheaven.cc index d4a09158..ef06d82d 100644 --- a/src/scoring/yakus/blessingofheaven.cc +++ b/src/scoring/yakus/blessingofheaven.cc @@ -9,7 +9,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBlessingOfHeaven(const GameState& state, const Player& player, +bool isBlessingOfHeaven(const GameState& state, const Hand& player, const std::vector& /*branch*/) { if (player.open) { return false; diff --git a/src/scoring/yakus/blessingofheaven.h b/src/scoring/yakus/blessingofheaven.h index 8d9c2a54..a77f89de 100644 --- a/src/scoring/yakus/blessingofheaven.h +++ b/src/scoring/yakus/blessingofheaven.h @@ -7,7 +7,7 @@ namespace mahjong::yaku { bool isBlessingOfHeaven( - const GameState& state, const Player& player, + const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/blessingofman.cc b/src/scoring/yakus/blessingofman.cc index e2e5d2b8..2a701979 100644 --- a/src/scoring/yakus/blessingofman.cc +++ b/src/scoring/yakus/blessingofman.cc @@ -9,7 +9,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBlessingOfMan(const GameState& state, const Player& player, +bool isBlessingOfMan(const GameState& state, const Hand& player, const std::vector& /*branch*/) { if (player.open) { return false; diff --git a/src/scoring/yakus/blessingofman.h b/src/scoring/yakus/blessingofman.h index 818bf2a4..bb6a73be 100644 --- a/src/scoring/yakus/blessingofman.h +++ b/src/scoring/yakus/blessingofman.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isBlessingOfMan(const GameState& state, const Player& player, +bool isBlessingOfMan(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/bottomofthesea.cc b/src/scoring/yakus/bottomofthesea.cc index 3df09009..c1904460 100644 --- a/src/scoring/yakus/bottomofthesea.cc +++ b/src/scoring/yakus/bottomofthesea.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBottomOfTheSea(const GameState& state, const Player& /*player*/, +bool isBottomOfTheSea(const GameState& state, const Hand& /*player*/, const std::vector& /*branch*/) { return Walls::GetRemainingPieces(state) == 0; } diff --git a/src/scoring/yakus/bottomofthesea.h b/src/scoring/yakus/bottomofthesea.h index da40848a..c9cb0347 100644 --- a/src/scoring/yakus/bottomofthesea.h +++ b/src/scoring/yakus/bottomofthesea.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isBottomOfTheSea(const GameState& state, const Player& player, +bool isBottomOfTheSea(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/doubleriichi.cc b/src/scoring/yakus/doubleriichi.cc index ac00eabd..eecc44d1 100644 --- a/src/scoring/yakus/doubleriichi.cc +++ b/src/scoring/yakus/doubleriichi.cc @@ -9,7 +9,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isDoubleRiichi(const GameState& state, const Player& player, +bool isDoubleRiichi(const GameState& state, const Hand& player, const std::vector& /*branch*/) { return player.riichi && !player.open && (state.turnNum < 4 && state.lastCall < 0); diff --git a/src/scoring/yakus/doubleriichi.h b/src/scoring/yakus/doubleriichi.h index 477287ac..64776db7 100644 --- a/src/scoring/yakus/doubleriichi.h +++ b/src/scoring/yakus/doubleriichi.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isDoubleRiichi(const GameState& state, const Player& player, +bool isDoubleRiichi(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/fourconcealedpon.cc b/src/scoring/yakus/fourconcealedpon.cc index 55aea284..1a9d5469 100644 --- a/src/scoring/yakus/fourconcealedpon.cc +++ b/src/scoring/yakus/fourconcealedpon.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isFourConcealedPon(const GameState& /*state*/, const Player& player, +bool isFourConcealedPon(const GameState& /*state*/, const Hand& player, const std::vector& branch) { if (player.open) { return false; @@ -21,7 +21,7 @@ bool isFourConcealedPon(const GameState& /*state*/, const Player& player, concealed_pons++; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type == SetType::kConcealedKan) { concealed_pons++; } diff --git a/src/scoring/yakus/fourconcealedpon.h b/src/scoring/yakus/fourconcealedpon.h index c05088a9..5cac68a9 100644 --- a/src/scoring/yakus/fourconcealedpon.h +++ b/src/scoring/yakus/fourconcealedpon.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isFourConcealedPon(const GameState& state, const Player& player, +bool isFourConcealedPon(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/fourkans.cc b/src/scoring/yakus/fourkans.cc index a79e12e1..de173b93 100644 --- a/src/scoring/yakus/fourkans.cc +++ b/src/scoring/yakus/fourkans.cc @@ -10,10 +10,10 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isFourKans(const GameState& /*state*/, const Player& player, +bool isFourKans(const GameState& /*state*/, const Hand& player, const std::vector& /*branch*/) { int kans = 0; - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type >= SetType::kKan) { kans++; } diff --git a/src/scoring/yakus/fourkans.h b/src/scoring/yakus/fourkans.h index 37f9fb24..9b2daf67 100644 --- a/src/scoring/yakus/fourkans.h +++ b/src/scoring/yakus/fourkans.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isFourKans(const GameState& state, const Player& player, +bool isFourKans(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/fullflush.cc b/src/scoring/yakus/fullflush.cc index 0bdd69e2..3e4b2322 100644 --- a/src/scoring/yakus/fullflush.cc +++ b/src/scoring/yakus/fullflush.cc @@ -9,9 +9,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isFullFlush(const GameState& /*state*/, const Player& player, +bool isFullFlush(const GameState& /*state*/, const Hand& player, const std::vector& /*branch*/) { - if (player.live[0].isHonor()) { + if (player.live[0].isHonor()) { return false; } const int suit = player.live[0].getSuit(); diff --git a/src/scoring/yakus/fullflush.h b/src/scoring/yakus/fullflush.h index 47a2f38f..bcab996d 100644 --- a/src/scoring/yakus/fullflush.h +++ b/src/scoring/yakus/fullflush.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isFullFlush(const GameState& state, const Player& player, +bool isFullFlush(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/fullyconcealedhand.cc b/src/scoring/yakus/fullyconcealedhand.cc index 711615da..d694f43c 100644 --- a/src/scoring/yakus/fullyconcealedhand.cc +++ b/src/scoring/yakus/fullyconcealedhand.cc @@ -10,9 +10,8 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isFullyConcealedHand( - const GameState& state, const Player& player, - const std::vector& /*branch*/) { +bool isFullyConcealedHand(const GameState& state, const Hand& player, + const std::vector& /*branch*/) { return state.currentPlayer == player.id && !player.open && Walls::GetRemainingPieces(state) > 0; } diff --git a/src/scoring/yakus/fullyconcealedhand.h b/src/scoring/yakus/fullyconcealedhand.h index 5c9ebad0..92278350 100644 --- a/src/scoring/yakus/fullyconcealedhand.h +++ b/src/scoring/yakus/fullyconcealedhand.h @@ -7,7 +7,7 @@ namespace mahjong::yaku { bool isFullyConcealedHand( - const GameState& state, const Player& player, + const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/halfflush.cc b/src/scoring/yakus/halfflush.cc index 8dba5fe0..f0e4e978 100644 --- a/src/scoring/yakus/halfflush.cc +++ b/src/scoring/yakus/halfflush.cc @@ -10,9 +10,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isHalfFlush(const GameState& state, const Player& player, +bool isHalfFlush(const GameState& state, const Hand& player, const std::vector& /*branch*/) { - const int suit = player.live[0].getSuit(); + const int suit = player.live[0].getSuit(); bool honors = false; for (const auto& piece : player.live_range()) { if (piece.isHonor()) { diff --git a/src/scoring/yakus/halfflush.h b/src/scoring/yakus/halfflush.h index 83907515..f5bf23fc 100644 --- a/src/scoring/yakus/halfflush.h +++ b/src/scoring/yakus/halfflush.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isHalfFlush(const GameState& state, const Player& player, +bool isHalfFlush(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/honorpon.cc b/src/scoring/yakus/honorpon.cc index 8132a2bb..4800574b 100644 --- a/src/scoring/yakus/honorpon.cc +++ b/src/scoring/yakus/honorpon.cc @@ -15,7 +15,7 @@ namespace mahjong::yaku { namespace { -bool findPon(const GameState& /* state */, const Player& player, +bool findPon(const GameState& /* state */, const Hand& player, const std::vector& branch, const Piece& piece) { for (const auto* node : branch) { @@ -23,7 +23,7 @@ bool findPon(const GameState& /* state */, const Player& player, return true; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type >= SetType::kPon && meld.start == piece) { return true; } @@ -33,29 +33,29 @@ bool findPon(const GameState& /* state */, const Player& player, } // namespace -bool isSeatWind(const GameState& state, const Player& player, +bool isSeatWind(const GameState& state, const Hand& player, const std::vector& branch) { return findPon(state, player, branch, Piece::fromWind(GetSeat(state.roundNum, player.id))); } -bool isPrevalentWind(const GameState& state, const Player& player, +bool isPrevalentWind(const GameState& state, const Hand& player, const std::vector& branch) { return findPon(state, player, branch, Piece::fromWind(state.roundNum > 3 ? kSouth : kEast)); } -bool isGreenDragon(const GameState& state, const Player& player, +bool isGreenDragon(const GameState& state, const Hand& player, const std::vector& branch) { return findPon(state, player, branch, kGreenDragon); } -bool isRedDragon(const GameState& state, const Player& player, +bool isRedDragon(const GameState& state, const Hand& player, const std::vector& branch) { return findPon(state, player, branch, kRedDragon); } -bool isWhiteDragon(const GameState& state, const Player& player, +bool isWhiteDragon(const GameState& state, const Hand& player, const std::vector& branch) { return findPon(state, player, branch, kWhiteDragon); } diff --git a/src/scoring/yakus/honorpon.h b/src/scoring/yakus/honorpon.h index 16e878bf..5108626f 100644 --- a/src/scoring/yakus/honorpon.h +++ b/src/scoring/yakus/honorpon.h @@ -6,18 +6,18 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isSeatWind(const GameState& state, const Player& player, +bool isSeatWind(const GameState& state, const Hand& player, const std::vector& branch); -bool isPrevalentWind(const GameState& state, const Player& player, +bool isPrevalentWind(const GameState& state, const Hand& player, const std::vector& branch); -bool isGreenDragon(const GameState& state, const Player& player, +bool isGreenDragon(const GameState& state, const Hand& player, const std::vector& branch); -bool isRedDragon(const GameState& state, const Player& player, +bool isRedDragon(const GameState& state, const Hand& player, const std::vector& branch); -bool isWhiteDragon(const GameState& state, const Player& player, +bool isWhiteDragon(const GameState& state, const Hand& player, const std::vector& branch); } // namespace mahjong::yaku diff --git a/src/scoring/yakus/ippatsu.cc b/src/scoring/yakus/ippatsu.cc index 149846c3..c606771f 100644 --- a/src/scoring/yakus/ippatsu.cc +++ b/src/scoring/yakus/ippatsu.cc @@ -11,7 +11,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isIppatsu(const GameState& state, const Player& player, +bool isIppatsu(const GameState& state, const Hand& player, const std::vector& /*branch*/) { return (isRiichi(state, player) || isDoubleRiichi(state, player)) && (state.turnNum - player.riichiRound <= 4 && diff --git a/src/scoring/yakus/ippatsu.h b/src/scoring/yakus/ippatsu.h index a80bcdbb..eab15d26 100644 --- a/src/scoring/yakus/ippatsu.h +++ b/src/scoring/yakus/ippatsu.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isIppatsu(const GameState& state, const Player& player, +bool isIppatsu(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/littlefourwinds.cc b/src/scoring/yakus/littlefourwinds.cc index 959b9f1c..0757d847 100644 --- a/src/scoring/yakus/littlefourwinds.cc +++ b/src/scoring/yakus/littlefourwinds.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isLittleFourWinds(const GameState& /*state*/, const Player& player, +bool isLittleFourWinds(const GameState& /*state*/, const Hand& player, const std::vector& branch) { bool pair = false; int pons = 0; @@ -36,7 +36,7 @@ bool isLittleFourWinds(const GameState& /*state*/, const Player& player, if (!pair) { return false; } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { switch (meld.start.toUint8_t()) { case Piece::Type::kEastWind: case Piece::Type::kSouthWind: diff --git a/src/scoring/yakus/littlefourwinds.h b/src/scoring/yakus/littlefourwinds.h index 08e4cd40..449d7cba 100644 --- a/src/scoring/yakus/littlefourwinds.h +++ b/src/scoring/yakus/littlefourwinds.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isLittleFourWinds(const GameState& state, const Player& player, +bool isLittleFourWinds(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/littlethreedragons.cc b/src/scoring/yakus/littlethreedragons.cc index 6e8b2ffc..a892601c 100644 --- a/src/scoring/yakus/littlethreedragons.cc +++ b/src/scoring/yakus/littlethreedragons.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isLittleThreeDragons(const GameState& /*state*/, const Player& player, +bool isLittleThreeDragons(const GameState& /*state*/, const Hand& player, const std::vector& branch) { bool pair = false; int pons = 0; @@ -33,7 +33,7 @@ bool isLittleThreeDragons(const GameState& /*state*/, const Player& player, if (!pair) { return false; } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { switch (meld.start.toUint8_t()) { case Piece::Type::kRedDragon: case Piece::Type::kGreenDragon: diff --git a/src/scoring/yakus/littlethreedragons.h b/src/scoring/yakus/littlethreedragons.h index 685bae83..c3cca0a6 100644 --- a/src/scoring/yakus/littlethreedragons.h +++ b/src/scoring/yakus/littlethreedragons.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isLittleThreeDragons(const GameState& state, const Player& player, +bool isLittleThreeDragons(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/maxbranches.cc b/src/scoring/yakus/maxbranches.cc index ac26df8b..e2fe8e2b 100644 --- a/src/scoring/yakus/maxbranches.cc +++ b/src/scoring/yakus/maxbranches.cc @@ -9,9 +9,9 @@ #include "types/sets.h" namespace mahjong::yaku { -bool isMaxBranches(const GameState& /*state*/, const Player& player, +bool isMaxBranches(const GameState& /*state*/, const Hand& player, const std::vector& /*branch*/) { - const int start = player.live[0].getPieceNum(); + const int start = player.live[0].getPieceNum(); const int suit = player.live[0].getSuit(); std::array sets = {}; const std::array final = {3, 3, 2, 2, 2, 2}; diff --git a/src/scoring/yakus/maxbranches.h b/src/scoring/yakus/maxbranches.h index c80072ad..4b56f0ca 100644 --- a/src/scoring/yakus/maxbranches.h +++ b/src/scoring/yakus/maxbranches.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isMaxBranches(const GameState& state, const Player& player, +bool isMaxBranches(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/mixedtriplechi.cc b/src/scoring/yakus/mixedtriplechi.cc index 660756ee..45e423da 100644 --- a/src/scoring/yakus/mixedtriplechi.cc +++ b/src/scoring/yakus/mixedtriplechi.cc @@ -11,7 +11,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isMixedTripleChi(const GameState& /* state */, const Player& player, +bool isMixedTripleChi(const GameState& /* state */, const Hand& player, const std::vector& branch) { const int k_piecesinasuit = 9; std::array bamboo_chi = {}; @@ -30,7 +30,7 @@ bool isMixedTripleChi(const GameState& /* state */, const Player& player, } } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type == SetType::kChi) { if (meld.start.getSuit() == Piece::Type::kBambooSuit) { bamboo_chi.at(meld.start.getPieceNum()) = true; diff --git a/src/scoring/yakus/mixedtriplechi.h b/src/scoring/yakus/mixedtriplechi.h index 02d8e2b6..4dedfc54 100644 --- a/src/scoring/yakus/mixedtriplechi.h +++ b/src/scoring/yakus/mixedtriplechi.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isMixedTripleChi(const GameState& state, const Player& player, +bool isMixedTripleChi(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/ninegates.cc b/src/scoring/yakus/ninegates.cc index 53bc5324..e1c32f65 100644 --- a/src/scoring/yakus/ninegates.cc +++ b/src/scoring/yakus/ninegates.cc @@ -11,9 +11,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isNineGates(const GameState& state, const Player& player, +bool isNineGates(const GameState& state, const Hand& player, const std::vector& branch) { - if (player.open) { + if (player.open) { return false; } if (!isFullFlush(state, player, branch)) { diff --git a/src/scoring/yakus/ninegates.h b/src/scoring/yakus/ninegates.h index d7abb318..af2385a8 100644 --- a/src/scoring/yakus/ninegates.h +++ b/src/scoring/yakus/ninegates.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isNineGates(const GameState& state, const Player& player, +bool isNineGates(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/outsidehand.cc b/src/scoring/yakus/outsidehand.cc index 511cafbc..2f2582aa 100644 --- a/src/scoring/yakus/outsidehand.cc +++ b/src/scoring/yakus/outsidehand.cc @@ -12,8 +12,8 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isOutsideHand(const GameState& state, const Player& player, - const std::vector& branch) { +bool isOutsideHand(const GameState& state, const Hand& player, + const std::vector& branch) { bool chi = false; for (const auto* node : branch) { if (node->type() == SetType::kChi) { @@ -28,7 +28,7 @@ bool isOutsideHand(const GameState& state, const Player& player, } } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type == SetType::kChi) { if (meld.start.isTerminal() || (meld.start + 2).isTerminal()) { chi = true; diff --git a/src/scoring/yakus/outsidehand.h b/src/scoring/yakus/outsidehand.h index bde39f15..db41d7b0 100644 --- a/src/scoring/yakus/outsidehand.h +++ b/src/scoring/yakus/outsidehand.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isOutsideHand(const GameState& state, const Player& player, - const std::vector& branch); +bool isOutsideHand(const GameState& state, const Hand& player, + const std::vector& branch); } diff --git a/src/scoring/yakus/pinfu.cc b/src/scoring/yakus/pinfu.cc index ce380791..fc8ac41a 100644 --- a/src/scoring/yakus/pinfu.cc +++ b/src/scoring/yakus/pinfu.cc @@ -13,7 +13,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isPinfu(const GameState& state, const Player& player, +bool isPinfu(const GameState& state, const Hand& player, const std::vector& branch) { if (player.open) { return false; @@ -38,7 +38,8 @@ bool isPinfu(const GameState& state, const Player& player, if (node->start() == kEastWind && state.roundNum < 4) { return false; } - if (node->start() == Piece::fromWind(GetSeat(state.roundNum, player.id))) { + if (node->start() == + Piece::fromWind(GetSeat(state.roundNum, player.id))) { return false; } } diff --git a/src/scoring/yakus/pinfu.h b/src/scoring/yakus/pinfu.h index f811a5ed..7a57fb56 100644 --- a/src/scoring/yakus/pinfu.h +++ b/src/scoring/yakus/pinfu.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isPinfu(const GameState& state, const Player& player, +bool isPinfu(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/puredoublechi.cc b/src/scoring/yakus/puredoublechi.cc index f3887e14..0780fad2 100644 --- a/src/scoring/yakus/puredoublechi.cc +++ b/src/scoring/yakus/puredoublechi.cc @@ -12,7 +12,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isPureDoubleChi(const GameState& state, const Player& player, +bool isPureDoubleChi(const GameState& state, const Hand& player, const std::vector& branch) { if (player.open) { return false; diff --git a/src/scoring/yakus/puredoublechi.h b/src/scoring/yakus/puredoublechi.h index d502f931..a7bc57ca 100644 --- a/src/scoring/yakus/puredoublechi.h +++ b/src/scoring/yakus/puredoublechi.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isPureDoubleChi(const GameState& state, const Player& player, +bool isPureDoubleChi(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/purestraight.cc b/src/scoring/yakus/purestraight.cc index 78bb7b0a..867bbd9f 100644 --- a/src/scoring/yakus/purestraight.cc +++ b/src/scoring/yakus/purestraight.cc @@ -11,7 +11,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isPureStraight(const GameState& /* state */, const Player& player, +bool isPureStraight(const GameState& /* state */, const Hand& player, const std::vector& branch) { const int k_firstchistart = 1; const int k_secondchistart = 4; @@ -42,7 +42,7 @@ bool isPureStraight(const GameState& /* state */, const Player& player, } } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type == SetType::kChi) { int ind = 0; if (meld.start.getPieceNum() == k_firstchistart) { diff --git a/src/scoring/yakus/purestraight.h b/src/scoring/yakus/purestraight.h index 1458d36b..62985ebe 100644 --- a/src/scoring/yakus/purestraight.h +++ b/src/scoring/yakus/purestraight.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isPureStraight(const GameState& state, const Player& player, +bool isPureStraight(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/riichi.cc b/src/scoring/yakus/riichi.cc index 0bd78579..c847820c 100644 --- a/src/scoring/yakus/riichi.cc +++ b/src/scoring/yakus/riichi.cc @@ -9,7 +9,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isRiichi(const GameState& state, const Player& player, +bool isRiichi(const GameState& state, const Hand& player, const std::vector& /*branch*/) { return player.riichi && !player.open && (state.turnNum > 4 || state.lastCall < 0); diff --git a/src/scoring/yakus/riichi.h b/src/scoring/yakus/riichi.h index 0f8288d1..924d8dce 100644 --- a/src/scoring/yakus/riichi.h +++ b/src/scoring/yakus/riichi.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isRiichi(const GameState& state, const Player& player, +bool isRiichi(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/robbingakan.cc b/src/scoring/yakus/robbingakan.cc index 5c6f429a..d3d694df 100644 --- a/src/scoring/yakus/robbingakan.cc +++ b/src/scoring/yakus/robbingakan.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isRobbingAKan(const GameState& state, const Player& player, +bool isRobbingAKan(const GameState& state, const Hand& player, const std::vector& /*branch*/) { if (!player.hasRonned) { return false; diff --git a/src/scoring/yakus/robbingakan.h b/src/scoring/yakus/robbingakan.h index 30048599..cf1ab3ac 100644 --- a/src/scoring/yakus/robbingakan.h +++ b/src/scoring/yakus/robbingakan.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isRobbingAKan(const GameState& state, const Player& player, +bool isRobbingAKan(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/sevenpairs.cc b/src/scoring/yakus/sevenpairs.cc index 69b010fd..57f06a2b 100644 --- a/src/scoring/yakus/sevenpairs.cc +++ b/src/scoring/yakus/sevenpairs.cc @@ -12,7 +12,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isSevenPairs(const GameState& /* state */, const Player& player, +bool isSevenPairs(const GameState& /* state */, const Hand& player, const std::vector& branch) { if (player.open) { return false; diff --git a/src/scoring/yakus/sevenpairs.h b/src/scoring/yakus/sevenpairs.h index 0622b458..4ece168c 100644 --- a/src/scoring/yakus/sevenpairs.h +++ b/src/scoring/yakus/sevenpairs.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isSevenPairs(const GameState& state, const Player& player, +bool isSevenPairs(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/terminalsinallsets.cc b/src/scoring/yakus/terminalsinallsets.cc index 1a881bc4..2dee44ef 100644 --- a/src/scoring/yakus/terminalsinallsets.cc +++ b/src/scoring/yakus/terminalsinallsets.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isTerminalsInAllSets(const GameState& /*state*/, const Player& player, +bool isTerminalsInAllSets(const GameState& /*state*/, const Hand& player, const std::vector& branch) { for (const auto* node : branch) { switch (node->type()) { @@ -31,7 +31,7 @@ bool isTerminalsInAllSets(const GameState& /*state*/, const Player& player, break; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { switch (meld.type) { case SetType::kSingle: return false; diff --git a/src/scoring/yakus/terminalsinallsets.h b/src/scoring/yakus/terminalsinallsets.h index 3964f9d0..e5bb2fb1 100644 --- a/src/scoring/yakus/terminalsinallsets.h +++ b/src/scoring/yakus/terminalsinallsets.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isTerminalsInAllSets(const GameState& state, const Player& player, +bool isTerminalsInAllSets(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/thirteenorphans.cc b/src/scoring/yakus/thirteenorphans.cc index 6cee4403..9d1ee124 100644 --- a/src/scoring/yakus/thirteenorphans.cc +++ b/src/scoring/yakus/thirteenorphans.cc @@ -12,9 +12,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isThirteenOrphans(const GameState& /*state*/, const Player& player, +bool isThirteenOrphans(const GameState& /*state*/, const Hand& player, const std::vector& /*branch*/) { - if (player.open) { + if (player.open) { return false; } std::map pieces = { diff --git a/src/scoring/yakus/thirteenorphans.h b/src/scoring/yakus/thirteenorphans.h index 867bae30..7d66849f 100644 --- a/src/scoring/yakus/thirteenorphans.h +++ b/src/scoring/yakus/thirteenorphans.h @@ -7,7 +7,7 @@ namespace mahjong::yaku { bool isThirteenOrphans( - const GameState& state, const Player& player, + const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/threeconcealedpons.cc b/src/scoring/yakus/threeconcealedpons.cc index 4906d478..f82d907e 100644 --- a/src/scoring/yakus/threeconcealedpons.cc +++ b/src/scoring/yakus/threeconcealedpons.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isThreeConcealedPons(const GameState& /* state */, const Player& player, +bool isThreeConcealedPons(const GameState& /* state */, const Hand& player, const std::vector& branch) { int concealed_pons = 0; for (const auto* node : branch) { @@ -18,7 +18,7 @@ bool isThreeConcealedPons(const GameState& /* state */, const Player& player, concealed_pons++; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type == SetType::kConcealedKan) { concealed_pons++; } diff --git a/src/scoring/yakus/threeconcealedpons.h b/src/scoring/yakus/threeconcealedpons.h index b3c211c3..4c49c685 100644 --- a/src/scoring/yakus/threeconcealedpons.h +++ b/src/scoring/yakus/threeconcealedpons.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isThreeConcealedPons(const GameState& state, const Player& player, +bool isThreeConcealedPons(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/threekans.cc b/src/scoring/yakus/threekans.cc index c499c457..0fafa105 100644 --- a/src/scoring/yakus/threekans.cc +++ b/src/scoring/yakus/threekans.cc @@ -10,10 +10,10 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isThreeKans(const GameState& /* state */, const Player& player, +bool isThreeKans(const GameState& /* state */, const Hand& player, const std::vector& /*branch*/) { int kans = 0; - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type >= SetType::kKan) { kans++; } diff --git a/src/scoring/yakus/threekans.h b/src/scoring/yakus/threekans.h index d090c8f3..a429a972 100644 --- a/src/scoring/yakus/threekans.h +++ b/src/scoring/yakus/threekans.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isThreeKans(const GameState& state, const Player& player, +bool isThreeKans(const GameState& state, const Hand& player, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/triplepon.cc b/src/scoring/yakus/triplepon.cc index 21c71133..2f63e1a8 100644 --- a/src/scoring/yakus/triplepon.cc +++ b/src/scoring/yakus/triplepon.cc @@ -11,7 +11,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isTriplePon(const GameState& /* state */, const Player& player, +bool isTriplePon(const GameState& /* state */, const Hand& player, const std::vector& branch) { std::array bamboo_pon = {}; std::array char_pon = {}; @@ -29,7 +29,7 @@ bool isTriplePon(const GameState& /* state */, const Player& player, } } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : player.melds_range()) { if (meld.type >= SetType::kPon) { if (meld.start.getSuit() == Piece::Type::kBambooSuit) { bamboo_pon.at(meld.start.getPieceNum() - 1) = true; diff --git a/src/scoring/yakus/triplepon.h b/src/scoring/yakus/triplepon.h index ef5458b6..16fda10a 100644 --- a/src/scoring/yakus/triplepon.h +++ b/src/scoring/yakus/triplepon.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isTriplePon(const GameState& state, const Player& player, +bool isTriplePon(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/scoring/yakus/twicepuredoublechi.cc b/src/scoring/yakus/twicepuredoublechi.cc index 20630818..95a473df 100644 --- a/src/scoring/yakus/twicepuredoublechi.cc +++ b/src/scoring/yakus/twicepuredoublechi.cc @@ -11,7 +11,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isTwicePureDoubleChi(const GameState& /*state*/, const Player& player, +bool isTwicePureDoubleChi(const GameState& /*state*/, const Hand& player, const std::vector& branch) { if (player.open) { return false; diff --git a/src/scoring/yakus/twicepuredoublechi.h b/src/scoring/yakus/twicepuredoublechi.h index b569e334..fd107aab 100644 --- a/src/scoring/yakus/twicepuredoublechi.h +++ b/src/scoring/yakus/twicepuredoublechi.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isTwicePureDoubleChi(const GameState& state, const Player& player, +bool isTwicePureDoubleChi(const GameState& state, const Hand& player, const std::vector& branch); } diff --git a/src/statefunctions/decisionfunction.cc b/src/statefunctions/decisionfunction.cc index 1dbaf01b..a5d4e60b 100644 --- a/src/statefunctions/decisionfunction.cc +++ b/src/statefunctions/decisionfunction.cc @@ -17,7 +17,7 @@ namespace mahjong { // TODO(#18): "I really hate this" - alice -bool CanRon(const GameState& state, const Player& player) { +bool CanRon(const GameState& state, const Hand& player) { // If the pending piece is your discard, you can't Ron for (const auto& piece : player.discards) { if (state.pendingPiece == piece) { @@ -26,7 +26,7 @@ bool CanRon(const GameState& state, const Player& player) { } // Build the theoretical hand - auto& tmp_player = const_cast(player); + auto& tmp_player = const_cast(player); tmp_player.live[tmp_player.live_count++] = state.pendingPiece; // If this Ron is occurring due to a concealed kan discard, @@ -49,7 +49,7 @@ bool CanRon(const GameState& state, const Player& player) { return can_ron; } -bool CanKan(const GameState& state, const Player& player) { +bool CanKan(const GameState& state, const Hand& player) { if (Walls::GetRemainingPieces(state) == 0) { return false; } @@ -59,14 +59,14 @@ bool CanKan(const GameState& state, const Player& player) { return CountPieces(player, state.pendingPiece) == 3; } -bool CanPon(const GameState& state, const Player& player) { +bool CanPon(const GameState& state, const Hand& player) { if (player.riichi) { return false; } return CountPieces(player, state.pendingPiece) == 2; } -bool CanChi(const GameState& state, const Player& player) { +bool CanChi(const GameState& state, const Hand& player) { if (player.riichi) { return false; } @@ -91,11 +91,11 @@ bool CanChi(const GameState& state, const Player& player) { return false; } -bool CanTsumo(const GameState& state, const Player& player) { +bool CanTsumo(const GameState& state, const Hand& player) { return isComplete(state, player); } -bool CanConvertedKan(const GameState& state, const Player& player) { +bool CanConvertedKan(const GameState& state, const Hand& player) { if (Walls::GetRemainingPieces(state) == 0) { return false; } @@ -106,7 +106,7 @@ bool CanConvertedKan(const GameState& state, const Player& player) { }); } -bool CanConcealedKan(const GameState& state, const Player& player) { +bool CanConcealedKan(const GameState& state, const Hand& player) { if (Walls::GetRemainingPieces(state) == 0) { return false; } @@ -117,7 +117,7 @@ bool CanConcealedKan(const GameState& state, const Player& player) { return CountPieces(player, state.pendingPiece) == 4; } -bool CanRiichi(const GameState& /*unused*/, const Player& player) { +bool CanRiichi(const GameState& /*unused*/, const Hand& player) { if (player.riichi) { return false; } diff --git a/src/statefunctions/decisionfunction.h b/src/statefunctions/decisionfunction.h index de1e9a93..0ba53eca 100644 --- a/src/statefunctions/decisionfunction.h +++ b/src/statefunctions/decisionfunction.h @@ -8,20 +8,20 @@ namespace mahjong { using DecisionFunction = - std::function; + std::function; struct PossibleDecision { Event::Type type; DecisionFunction func; }; -bool CanKan(const GameState& state, const Player& player); -bool CanPon(const GameState& state, const Player& player); -bool CanChi(const GameState& state, const Player& player); -bool CanRon(const GameState& state, const Player& player); +bool CanKan(const GameState& state, const Hand& player); +bool CanPon(const GameState& state, const Hand& player); +bool CanChi(const GameState& state, const Hand& player); +bool CanRon(const GameState& state, const Hand& player); -bool CanTsumo(const GameState& state, const Player& player); -bool CanConcealedKan(const GameState& state, const Player& player); -bool CanConvertedKan(const GameState& state, const Player& player); -bool CanRiichi(const GameState& state, const Player& player); +bool CanTsumo(const GameState& state, const Hand& player); +bool CanConcealedKan(const GameState& state, const Hand& player); +bool CanConvertedKan(const GameState& state, const Hand& player); +bool CanRiichi(const GameState& state, const Hand& player); } // namespace mahjong diff --git a/src/statefunctions/gamestates/chi.cc b/src/statefunctions/gamestates/chi.cc index 64a7cbe7..6882b9ff 100644 --- a/src/statefunctions/gamestates/chi.cc +++ b/src/statefunctions/gamestates/chi.cc @@ -16,7 +16,7 @@ namespace mahjong { namespace { -Piece GetChiStart(const Player& player, Piece p) { +Piece GetChiStart(const Hand& player, Piece p) { if (CountPieces(player, p - 2) > 0 && CountPieces(player, p - 1) > 0) { return p - 2; } @@ -46,7 +46,7 @@ std::unique_ptr Chi(std::unique_ptr state) { state->players.at(state->currentPlayer).riichiPieceDiscard++; } - Player& player = state->players.at(state->lastCaller); + Hand& player = state->players.at(state->lastCaller); player.open = true; state->currentPlayer = state->lastCaller; diff --git a/src/statefunctions/gamestates/concealedkan.cc b/src/statefunctions/gamestates/concealedkan.cc index 2a306fed..b0245606 100644 --- a/src/statefunctions/gamestates/concealedkan.cc +++ b/src/statefunctions/gamestates/concealedkan.cc @@ -30,7 +30,7 @@ std::unique_ptr ConcealedKan(std::unique_ptr state) { state->nextState = StateFunctionType::kError; return state; } - Player& player = state->players.at(state->currentPlayer); + Hand& player = state->players.at(state->currentPlayer); player.melds[player.meld_count++] = Meld{ .type = SetType::kConcealedKan, .start = state->pendingPiece, diff --git a/src/statefunctions/gamestates/convertedkan.cc b/src/statefunctions/gamestates/convertedkan.cc index 5c9da342..160e2fed 100644 --- a/src/statefunctions/gamestates/convertedkan.cc +++ b/src/statefunctions/gamestates/convertedkan.cc @@ -31,7 +31,7 @@ std::unique_ptr ConvertedKan(std::unique_ptr state) { return state; } - Player& player =state->players[state->currentPlayer]; + Hand& player = state->players[state->currentPlayer]; if (auto* meld = std::ranges::find(player.melds, Meld{ .type = SetType::kPon, diff --git a/src/statefunctions/gamestates/discard.cc b/src/statefunctions/gamestates/discard.cc index 8832c965..80b2dfa5 100644 --- a/src/statefunctions/gamestates/discard.cc +++ b/src/statefunctions/gamestates/discard.cc @@ -35,7 +35,7 @@ std::unique_ptr Discard(std::unique_ptr state) { }; std::array need_decision = {false, false, false, false}; - for(const Player& player : state->players){ + for (const Hand& player : state->players) { if (player.id == state->currentPlayer) { continue; } @@ -54,7 +54,7 @@ std::unique_ptr Discard(std::unique_ptr state) { } Event decision = kDeclineEvent; - for(Player& player : state->players){ + for (Hand& player : state->players) { if (need_decision.at(player.id)) { Event temp_decision = GetValidDecisionOrThrow(*state, player, /*inPlayer=*/false); diff --git a/src/statefunctions/gamestates/draw.cc b/src/statefunctions/gamestates/draw.cc index b087283c..f8537402 100644 --- a/src/statefunctions/gamestates/draw.cc +++ b/src/statefunctions/gamestates/draw.cc @@ -13,7 +13,7 @@ std::unique_ptr Draw(std::unique_ptr state) { state->currentPlayer = (state->currentPlayer + 1) % 4; state->turnNum++; state->pendingPiece = Walls::TakePiece(*state); - Player& player =state->players[state->currentPlayer]; + Hand& player = state->players[state->currentPlayer]; player.live[player.live_count++] = state->pendingPiece; state->nextState = StateFunctionType::kPlayerPlayer; return state; diff --git a/src/statefunctions/gamestates/error.cc b/src/statefunctions/gamestates/error.cc index 9636945e..46c5a16d 100644 --- a/src/statefunctions/gamestates/error.cc +++ b/src/statefunctions/gamestates/error.cc @@ -3,7 +3,6 @@ #include "statefunctions/router.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/statefunction.h" namespace mahjong { diff --git a/src/statefunctions/gamestates/exhaust.cc b/src/statefunctions/gamestates/exhaust.cc index 29409310..5ae4dfa1 100644 --- a/src/statefunctions/gamestates/exhaust.cc +++ b/src/statefunctions/gamestates/exhaust.cc @@ -4,7 +4,6 @@ #include "analysis/util.h" #include "statefunctions/router.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/statefunction.h" namespace mahjong { diff --git a/src/statefunctions/gamestates/gameend.cc b/src/statefunctions/gamestates/gameend.cc index 4956d569..81f45d72 100644 --- a/src/statefunctions/gamestates/gameend.cc +++ b/src/statefunctions/gamestates/gameend.cc @@ -4,7 +4,6 @@ #include "statefunctions/router.h" #include "types/event.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/statefunction.h" namespace mahjong { diff --git a/src/statefunctions/gamestates/gamestart.cc b/src/statefunctions/gamestates/gamestart.cc index ec70fcd2..59b87dfa 100644 --- a/src/statefunctions/gamestates/gamestart.cc +++ b/src/statefunctions/gamestates/gamestart.cc @@ -3,7 +3,6 @@ #include "statefunctions/router.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/settings.h" #include "types/statefunction.h" diff --git a/src/statefunctions/gamestates/kan.cc b/src/statefunctions/gamestates/kan.cc index 3e123264..8a3de206 100644 --- a/src/statefunctions/gamestates/kan.cc +++ b/src/statefunctions/gamestates/kan.cc @@ -31,7 +31,7 @@ std::unique_ptr Kan(std::unique_ptr state) { state->players.at(state->currentPlayer).riichiPieceDiscard++; } - Player& player =state->players.at(state->lastCaller); + Hand& player = state->players.at(state->lastCaller); player.open = true; state->currentPlayer = state->lastCaller; state->lastCall = state->turnNum; diff --git a/src/statefunctions/gamestates/kandiscard.cc b/src/statefunctions/gamestates/kandiscard.cc index 17a614c3..c71932ee 100644 --- a/src/statefunctions/gamestates/kandiscard.cc +++ b/src/statefunctions/gamestates/kandiscard.cc @@ -16,7 +16,7 @@ namespace mahjong { namespace { std::unique_ptr KanDiscard(std::unique_ptr state) { std::array need_decision = {false, false, false, false}; - for(const Player& player : state->players){ + for (const Hand& player : state->players) { if (player.id == state->currentPlayer) { continue; } @@ -34,7 +34,7 @@ std::unique_ptr KanDiscard(std::unique_ptr state) { } bool have_ronned = false; - for(Player& player : state->players){ + for (Hand& player : state->players) { if (need_decision.at(player.id)) { const Event temp_decision = GetValidDecisionOrThrow(*state, player, /*inPlayer=*/false); diff --git a/src/statefunctions/gamestates/playerhand.cc b/src/statefunctions/gamestates/playerhand.cc index 81e3ba70..d0c84a8e 100644 --- a/src/statefunctions/gamestates/playerhand.cc +++ b/src/statefunctions/gamestates/playerhand.cc @@ -23,7 +23,7 @@ std::unique_ptr PlayerPlayer(std::unique_ptr state) { PossibleDecision{.type = Event::kConvertedKan, .func = CanConvertedKan}, PossibleDecision{.type = Event::kRiichi, .func = CanRiichi}, PossibleDecision{.type = Event::kDiscard, - .func = [](const GameState&, const Player& player) { + .func = [](const GameState&, const Hand& player) { return !player.riichi; }}}; @@ -50,8 +50,9 @@ std::unique_ptr PlayerPlayer(std::unique_ptr state) { decision.decision = true; state->nextState = StateFunctionType::kDiscard; } else { - decision = GetValidDecisionOrThrow(*state, state->players[state->currentPlayer], - /*inPlayer=*/true); + decision = + GetValidDecisionOrThrow(*state, state->players[state->currentPlayer], + /*inPlayer=*/true); } // note riichi handling is a lil borked on the player agency side diff --git a/src/statefunctions/gamestates/pon.cc b/src/statefunctions/gamestates/pon.cc index 1881bf63..aa980b9c 100644 --- a/src/statefunctions/gamestates/pon.cc +++ b/src/statefunctions/gamestates/pon.cc @@ -33,7 +33,7 @@ std::unique_ptr Pon(std::unique_ptr state) { state->players.at(state->currentPlayer).riichiPieceDiscard++; } - Player& player = state->players.at(state->lastCaller); + Hand& player = state->players.at(state->lastCaller); state->currentPlayer = state->lastCaller; state->lastCall = state->turnNum; state->concealedKan = false; diff --git a/src/statefunctions/gamestates/replacement.cc b/src/statefunctions/gamestates/replacement.cc index 41b9265d..ac3aca94 100644 --- a/src/statefunctions/gamestates/replacement.cc +++ b/src/statefunctions/gamestates/replacement.cc @@ -16,7 +16,7 @@ namespace mahjong { namespace { std::unique_ptr Replacement(std::unique_ptr state) { const Piece draw = Walls::TakeReplacementTile(*state); - Player& player =state->players.at(state->currentPlayer); + Hand& player = state->players.at(state->currentPlayer); player.live[player.live_count++] = draw; state->pendingPiece = draw; diff --git a/src/statefunctions/gamestates/riichi.cc b/src/statefunctions/gamestates/riichi.cc index 75cde37e..9cc99992 100644 --- a/src/statefunctions/gamestates/riichi.cc +++ b/src/statefunctions/gamestates/riichi.cc @@ -30,7 +30,7 @@ std::unique_ptr Riichi(std::unique_ptr state) { .decision = false, // decision }); - Player& player =state->players[state->currentPlayer]; + Hand& player = state->players[state->currentPlayer]; player.riichiRound = state->turnNum; player.riichiPieceDiscard = player.discards_count; player.riichi = true; diff --git a/src/statefunctions/gamestates/ron.cc b/src/statefunctions/gamestates/ron.cc index ac505b01..62ab5d31 100644 --- a/src/statefunctions/gamestates/ron.cc +++ b/src/statefunctions/gamestates/ron.cc @@ -15,21 +15,21 @@ namespace mahjong { namespace { std::unique_ptr Ron(std::unique_ptr state) { - Player& caller_player = state->players[state->lastCaller]; + Hand& caller_player = state->players[state->lastCaller]; caller_player.live[caller_player.live_count++] = state->pendingPiece; std::array basic_points = {}; - Player& curr_player = state->players[state->currentPlayer]; + Hand& curr_player = state->players[state->currentPlayer]; if (curr_player.riichi && curr_player.discards_count == curr_player.riichiPieceDiscard) { state->riichiSticks--; curr_player.riichi = false; } - for (Player& player : state->players) { + for (Hand& player : state->players) { if (player.hasRonned) { AlertPlayers(*state, Event{ .type = Event::kRon, // type - .player = player.id, // player + .player = player.id, // player .piece = static_cast( state->pendingPiece.toUint8_t()), // piece .decision = false, // decision @@ -41,7 +41,7 @@ std::unique_ptr Ron(std::unique_ptr state) { } } int payment = 0; - for (Player& player : state->players) { + for (Hand& player : state->players) { if (player.hasRonned) { player.score += 1000 * state->riichiSticks; state->riichiSticks = 0; diff --git a/src/statefunctions/gamestates/roundstart.cc b/src/statefunctions/gamestates/roundstart.cc index f1ffd231..ffbdd7a8 100644 --- a/src/statefunctions/gamestates/roundstart.cc +++ b/src/statefunctions/gamestates/roundstart.cc @@ -9,7 +9,6 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/statefunction.h" #include "types/walls.h" #include "types/winds.h" diff --git a/src/statefunctions/statecontroller.cc b/src/statefunctions/statecontroller.cc index 1be82f9e..8acd112b 100644 --- a/src/statefunctions/statecontroller.cc +++ b/src/statefunctions/statecontroller.cc @@ -12,7 +12,6 @@ #include "controllers/controllermanager.h" #include "statefunctions/router.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/settings.h" #include "types/statefunction.h" diff --git a/src/statefunctions/stateutilities.cc b/src/statefunctions/stateutilities.cc index 17e7d8d4..b09314ed 100644 --- a/src/statefunctions/stateutilities.cc +++ b/src/statefunctions/stateutilities.cc @@ -30,12 +30,12 @@ void AlertPlayers(const GameState& state, Event e) { } // Count number of piece p that are in given players hands -uint8_t CountPieces(const Player& player, Piece p) { +uint8_t CountPieces(const Hand& player, Piece p) { return std::ranges::count(player.live_range(), p); } // Remove an instance of piece p from given players hand -uint8_t RemovePieces(Player& player, Piece p, uint8_t count) { +uint8_t RemovePieces(Hand& player, Piece p, uint8_t count) { uint8_t removed = 0; count = std::min(CountPieces(player, p), count); const auto match_piece = [&](Piece _p) { @@ -51,7 +51,7 @@ uint8_t RemovePieces(Player& player, Piece p, uint8_t count) { } // Discard an instance of piece p from given players hand -void DiscardPiece(Player& player, Piece p) { +void DiscardPiece(Hand& player, Piece p) { RemovePieces(player, p, /*count=*/1); player.discards[player.discards_count++] = p; } @@ -65,12 +65,12 @@ Piece AskForDiscard(const GameState& state) { .decision = true, // decision }); - return Piece( - GetValidDecisionOrThrow(state, state.players[state.currentPlayer], /*inPlayer=*/true) - .piece); + return Piece(GetValidDecisionOrThrow( + state, state.players[state.currentPlayer], /*inPlayer=*/true) + .piece); } -Event GetValidDecisionOrThrow(const GameState& state, const Player& player, +Event GetValidDecisionOrThrow(const GameState& state, const Hand& player, bool inPlayer) { Event decision; bool valid = false; @@ -101,7 +101,7 @@ Event GetValidDecisionOrThrow(const GameState& state, const Player& player, return decision; } -bool ValidateDecision(const GameState& state, const Player& player, +bool ValidateDecision(const GameState& state, const Hand& player, Event decision, bool inPlayer) { if (decision.type > Event::kDiscard) { return false; diff --git a/src/statefunctions/stateutilities.h b/src/statefunctions/stateutilities.h index 32964ca6..a0072e2f 100644 --- a/src/statefunctions/stateutilities.h +++ b/src/statefunctions/stateutilities.h @@ -12,15 +12,15 @@ struct GameState; Wind GetSeat(int round, int player); -uint8_t RemovePieces(Player& player, Piece p, uint8_t count); -void DiscardPiece(Player& player, Piece p); +uint8_t RemovePieces(Hand& player, Piece p, uint8_t count); +void DiscardPiece(Hand& player, Piece p); void AlertPlayers(const GameState& state, Event e); Piece AskForDiscard(const GameState& state); -uint8_t CountPieces(const Player& player, Piece p); -bool ValidateDecision(const GameState& state, const Player& player, +uint8_t CountPieces(const Hand& player, Piece p); +bool ValidateDecision(const GameState& state, const Hand& player, Event decision, bool inPlayer); -Event GetValidDecisionOrThrow(const GameState& state, const Player& player, +Event GetValidDecisionOrThrow(const GameState& state, const Hand& player, bool inPlayer); } // namespace mahjong diff --git a/src/types/event.h b/src/types/event.h index d6d52c5d..59ce79d6 100644 --- a/src/types/event.h +++ b/src/types/event.h @@ -2,7 +2,6 @@ #include #include - namespace mahjong { struct Event { diff --git a/src/types/gamestate.h b/src/types/gamestate.h index 1b66a72e..72dfd235 100644 --- a/src/types/gamestate.h +++ b/src/types/gamestate.h @@ -27,7 +27,7 @@ struct GameState { bool concealedKan = false; Piece pendingPiece = Piece(Piece::Type::kError); - std::array players; + std::array players; std::array livingWall; std::array deadWall; diff --git a/src/types/hand.h b/src/types/hand.h index 10170f55..8cf70f6a 100644 --- a/src/types/hand.h +++ b/src/types/hand.h @@ -7,7 +7,7 @@ #include "types/settings.h" namespace mahjong { -struct Player { +struct Hand { int id; std::array discards; int discards_count = 0; diff --git a/src/types/typeprinter.cc b/src/types/typeprinter.cc index bec31537..18c98f12 100644 --- a/src/types/typeprinter.cc +++ b/src/types/typeprinter.cc @@ -63,7 +63,7 @@ std::ostream& operator<<(std::ostream& os, const mahjong::GameState& state) { return os; } -std::ostream& operator<<(std::ostream& os, const mahjong::Player& player) { +std::ostream& operator<<(std::ostream& os, const mahjong::Hand& player) { os << "{ open: " << player.open; os << " riichi: " << player.riichi; os << " riichiPieceDiscard: " << player.riichiPieceDiscard; diff --git a/src/types/typeprinter.h b/src/types/typeprinter.h index f1414e2e..8208f340 100644 --- a/src/types/typeprinter.h +++ b/src/types/typeprinter.h @@ -9,14 +9,14 @@ struct Player; class Node; struct Meld; class Walls; -struct Player; +struct Hand; } // namespace mahjong std::ostream& operator<<(std::ostream& os, const mahjong::Event& e); std::ostream& operator<<(std::ostream& os, const mahjong::GameState& state); -std::ostream& operator<<(std::ostream& os, const mahjong::Player& player); +std::ostream& operator<<(std::ostream& os, const mahjong::Hand& player); std::ostream& operator<<(std::ostream& os, const mahjong::Node& node); diff --git a/src/types/walls.cc b/src/types/walls.cc index fa417e8f..90bb4718 100644 --- a/src/types/walls.cc +++ b/src/types/walls.cc @@ -6,7 +6,6 @@ #include #include "types/gamestate.h" -#include "types/hand.h" #include "types/pieces.h" #include "types/piecetype.h" #include "types/settings.h" diff --git a/src/types/yaku.h b/src/types/yaku.h index 5db13bc3..c5e64cd9 100644 --- a/src/types/yaku.h +++ b/src/types/yaku.h @@ -8,7 +8,7 @@ namespace mahjong { -using yakuFunc = std::function&)>; using Han = int; diff --git a/tests/api/game_control.test.cc b/tests/api/game_control.test.cc index d43075e9..1c0c6794 100644 --- a/tests/api/game_control.test.cc +++ b/tests/api/game_control.test.cc @@ -145,7 +145,7 @@ TEST(Api, ObserveGameStatePlayersAndDiscards) { // Check that hands are copied (after round start, players should have hands) for (int player = 0; player < 4; player++) { const api::CPlayer& c_player = observed.hands[player]; - const mahjong::Player& cpp_player = state->players[player]; + const mahjong::Hand& cpp_player = state->players[player]; // Check live pieces EXPECT_EQ(c_player.livePieceCount, static_cast(cpp_player.live_count)); @@ -171,7 +171,8 @@ TEST(Api, ObserveGameStatePlayersAndDiscards) { } // Check discards using CPlayer structure - EXPECT_EQ(c_player.discardCount, static_cast(cpp_player.discards_count)); + EXPECT_EQ(c_player.discardCount, + static_cast(cpp_player.discards_count)); for (int discard = 0; discard < c_player.discardCount; discard++) { EXPECT_EQ( c_player.discards[discard], diff --git a/tests/count_pieces.test.cc b/tests/count_pieces.test.cc index de851643..08e988fc 100644 --- a/tests/count_pieces.test.cc +++ b/tests/count_pieces.test.cc @@ -9,7 +9,7 @@ namespace mahjong { TEST(CountPieces, CountPieces) { - Player player; + Hand player; player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; player.live_count = 4; diff --git a/tests/discard_piece.test.cc b/tests/discard_piece.test.cc index 6afca8f0..2e3a82f6 100644 --- a/tests/discard_piece.test.cc +++ b/tests/discard_piece.test.cc @@ -1,15 +1,14 @@ #include -#include #include "statefunctions/stateutilities.h" -#include "types/hand.h" #include "types/pieces.h" +#include "types/hand.h" namespace mahjong { TEST(DiscardPiece, DiscardsCorrectPiece) { - Player player; + Hand player; player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; player.live_count = 4; @@ -18,7 +17,7 @@ TEST(DiscardPiece, DiscardsCorrectPiece) { } TEST(DiscardPiece, DoesntDiscardInCorrectPiece) { - Player player; + Hand player; player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; player.live_count = 4; diff --git a/tests/game_play.test.cc b/tests/game_play.test.cc index 93950f1f..1e162c45 100644 --- a/tests/game_play.test.cc +++ b/tests/game_play.test.cc @@ -14,7 +14,7 @@ namespace mahjong { TEST(GamePlay, Furiten) { auto state = GameState(); - Player& player = state.players[0]; + Hand& player = state.players[0]; HandFromNotation("123m456p234678s44m", &player); player.open = false; EXPECT_TRUE(isComplete(state, player)); diff --git a/tests/remove_pieces.test.cc b/tests/remove_pieces.test.cc index b355cddb..abeb0417 100644 --- a/tests/remove_pieces.test.cc +++ b/tests/remove_pieces.test.cc @@ -9,7 +9,7 @@ namespace mahjong { TEST(RemovePieces, RemoveCorrectAmount) { - Player player; + Hand player; player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; player.live_count = 4; @@ -18,7 +18,7 @@ TEST(RemovePieces, RemoveCorrectAmount) { } TEST(RemovePieces, RemoveOnlyTheOnesAvailable) { - Player player; + Hand player; player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; player.live_count = 4; @@ -27,7 +27,7 @@ TEST(RemovePieces, RemoveOnlyTheOnesAvailable) { } TEST(RemovePieces, OnlyRemovesOne) { - Player player; + Hand player; player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; player.live_count = 4; @@ -36,7 +36,7 @@ TEST(RemovePieces, OnlyRemovesOne) { } TEST(RemovePieces, RemovesZeroWhenPieceDoesntExist) { - Player player; + Hand player; player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; player.live_count = 4; diff --git a/tests/rules/calls.test.cc b/tests/rules/calls.test.cc index ffd955d9..4a9022f9 100644 --- a/tests/rules/calls.test.cc +++ b/tests/rules/calls.test.cc @@ -53,11 +53,11 @@ TEST(Calls, AcceptPon) { auto state = InitializeTestRound(12345, std::move(controllers)); // Override with hopeless hands - Player& player0 = state->players[0]; + Hand& player0 = state->players[0]; // 14 Pieces because has drawn in InitializeTestRound. HandFromNotation("11447m2258p33699s", &player0); // Has the pair of nine bamboo 13 Pieces, yet to draw. - Player& player1 = state->players[1]; + Hand& player1 = state->players[1]; HandFromNotation("13579m99s246p135z", &player1); // Advance to pon event diff --git a/tests/utils/gamestate_utils.cc b/tests/utils/gamestate_utils.cc index 3e7b7d9c..f8fc27c7 100644 --- a/tests/utils/gamestate_utils.cc +++ b/tests/utils/gamestate_utils.cc @@ -12,7 +12,6 @@ #include "statefunctions/router.h" #include "statefunctions/statecontroller.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/settings.h" #include "types/statefunction.h" #include "utils/playercontrollerfake.h" @@ -60,8 +59,8 @@ std::unique_ptr CreateTestGameState(uint64_t seed) { } std::unique_ptr InitializeTestRound( - uint64_t seed, - std::array, kNumPlayers> playerControllers) { + uint64_t seed, std::array, kNumPlayers> + playerControllers) { auto state = std::make_unique(); state->seed = seed; diff --git a/tests/utils/handformer.cc b/tests/utils/handformer.cc index 705c8c17..cdcd136c 100644 --- a/tests/utils/handformer.cc +++ b/tests/utils/handformer.cc @@ -93,7 +93,7 @@ std::vector HandFromNotation(const std::string& notation) { return result; } -void HandFromNotation(const std::string& notation, Player* hand) { +void HandFromNotation(const std::string& notation, Hand* hand) { std::vector hand_vec = HandFromNotation(notation); hand->live_count = hand_vec.size(); std::ranges::move(hand_vec, hand->live.begin()); diff --git a/tests/utils/handformer.h b/tests/utils/handformer.h index 01676219..0f2f6290 100644 --- a/tests/utils/handformer.h +++ b/tests/utils/handformer.h @@ -10,7 +10,7 @@ namespace mahjong { std::vector HandFromNotation(const std::string& notation); -void HandFromNotation(const std::string& notation, Player* hand); +void HandFromNotation(const std::string& notation, Hand* hand); bool IsValidNotation(const std::string& notation); std::string PlayerToNotation(const std::vector& hand); diff --git a/tests/yakus/afterkan.test.cc b/tests/yakus/afterkan.test.cc index d33256dd..37b8a56e 100644 --- a/tests/yakus/afterkan.test.cc +++ b/tests/yakus/afterkan.test.cc @@ -16,7 +16,7 @@ namespace mahjong::yaku { TEST(isAfterAKan, 1Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m789m1111z999s55z", &player); game_state.currentPlayer = 0; @@ -35,7 +35,7 @@ TEST(isAfterAKan, 1Han) { TEST(isAfterAKan, DoesntApply) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m789m1111z999s55z", &player); game_state.currentPlayer = 0; @@ -54,7 +54,7 @@ TEST(isAfterAKan, DoesntApply) { TEST(isAfterAKan, WrongPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m789m1111z999s55z", &player); game_state.currentPlayer = 2; diff --git a/tests/yakus/allpon.test.cc b/tests/yakus/allpon.test.cc index d5cf9f86..3d4baa5c 100644 --- a/tests/yakus/allpon.test.cc +++ b/tests/yakus/allpon.test.cc @@ -19,7 +19,7 @@ namespace mahjong::yaku { TEST(isAllPons, 2Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m222p888s666z44m", &player); auto root = breakdownHand(player.live_range()); @@ -35,7 +35,7 @@ TEST(isAllPons, 2Han) { TEST(isAllPons, WithKans) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m222p666z44m", &player); player.melds[player.meld_count++] = Meld{ .type = SetType::kKan, @@ -56,7 +56,7 @@ TEST(isAllPons, WithKans) { TEST(isAllPons, ConcealedKan) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m222p666z44m", &player); player.melds[player.meld_count++] = Meld{ .type = SetType::kConcealedKan, @@ -77,7 +77,7 @@ TEST(isAllPons, ConcealedKan) { TEST(isAllPons, BadPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m222p666z789m44m", &player); player.open = false; diff --git a/tests/yakus/allsimples.test.cc b/tests/yakus/allsimples.test.cc index e25ada28..6e8b7fd0 100644 --- a/tests/yakus/allsimples.test.cc +++ b/tests/yakus/allsimples.test.cc @@ -16,7 +16,7 @@ namespace mahjong::yaku { TEST(isAllSimples, 1Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("222m333p444s555p88m", &player); auto root = breakdownHand(player.live_range()); @@ -32,7 +32,7 @@ TEST(isAllSimples, 1Han) { TEST(isAllSimples, BadPlayerHonors) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("222m333p444s111z88m", &player); auto root = breakdownHand(player.live_range()); @@ -48,7 +48,7 @@ TEST(isAllSimples, BadPlayerHonors) { TEST(isAllSimples, BadPlayerTerminals) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("222m333p444s111m88m", &player); auto root = breakdownHand(player.live_range()); diff --git a/tests/yakus/allterminalsandhonors.test.cc b/tests/yakus/allterminalsandhonors.test.cc index f255206d..39702784 100644 --- a/tests/yakus/allterminalsandhonors.test.cc +++ b/tests/yakus/allterminalsandhonors.test.cc @@ -20,7 +20,7 @@ namespace mahjong::yaku { TEST(isAllTerminalsAndHonors, 2Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("222z111p111m999s66z", &player); player.open = false; @@ -37,7 +37,7 @@ TEST(isAllTerminalsAndHonors, 2Han) { TEST(isAllTerminalsAndHonors, BadPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("222z111p111m888s66z", &player); player.open = false; @@ -54,7 +54,7 @@ TEST(isAllTerminalsAndHonors, BadPlayer) { TEST(isAllTerminalsAndHonors, CanBeOpen) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("222z111m999s66z", &player); player.open = true; player.melds[player.meld_count++] = Meld{ diff --git a/tests/yakus/blessingofman.test.cc b/tests/yakus/blessingofman.test.cc index 0c3c888a..60676f7c 100644 --- a/tests/yakus/blessingofman.test.cc +++ b/tests/yakus/blessingofman.test.cc @@ -15,7 +15,7 @@ namespace mahjong::yaku { TEST(isBlessingOfMan, 5Han) { auto game_state = GameState(); - Player& player =game_state.players[3]; + Hand& player = game_state.players[3]; HandFromNotation("123m123p444m111z55m", &player); player.open = false; player.id = 3; @@ -40,7 +40,7 @@ TEST(isBlessingOfMan, 5Han) { TEST(isBlessingOfMan, MustBeARon) { auto game_state = GameState(); - Player& player =game_state.players[3]; + Hand& player = game_state.players[3]; HandFromNotation("123m123p444m111z55m", &player); player.open = false; @@ -64,7 +64,7 @@ TEST(isBlessingOfMan, MustBeARon) { TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m123p444m111z55m", &player); player.open = false; @@ -88,7 +88,7 @@ TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { TEST(isBlessingOfMan, NoCalledMustHaveOccured) { auto game_state = GameState(); - Player& player =game_state.players[3]; + Hand& player = game_state.players[3]; HandFromNotation("123m123p444m111z55m", &player); player.open = false; diff --git a/tests/yakus/concealedhand.test.cc b/tests/yakus/concealedhand.test.cc index db418279..2f6b0e9b 100644 --- a/tests/yakus/concealedhand.test.cc +++ b/tests/yakus/concealedhand.test.cc @@ -12,7 +12,7 @@ namespace mahjong::yaku { TEST(isFullyConcealedHand, 1Han) { auto game_state = GameState(); - Player& player = game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("555m555p555s111z44m", &player); player.open = false; game_state.currentPlayer = 0; @@ -22,7 +22,7 @@ TEST(isFullyConcealedHand, 1Han) { TEST(isFullyConcealedHand, MustTsumo) { auto game_state = GameState(); - Player& player = game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("555m555p555s111z44m", &player); player.open = false; game_state.currentPlayer = 1; @@ -32,7 +32,7 @@ TEST(isFullyConcealedHand, MustTsumo) { TEST(isFullyConcealedHand, MustBeClosedPlayer) { auto game_state = GameState(); - Player& player = game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("555m555p555s111z44m", &player); player.open = true; game_state.currentPlayer = 0; @@ -42,7 +42,7 @@ TEST(isFullyConcealedHand, MustBeClosedPlayer) { TEST(isFullyConcealedHand, MustHavePiecesRemainingInWall) { auto game_state = GameState(); - Player& player = game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("555m555p555s111z44m", &player); player.open = false; game_state.currentPlayer = 0; diff --git a/tests/yakus/concealedpon.test.cc b/tests/yakus/concealedpon.test.cc index 850b23ea..d9ad7357 100644 --- a/tests/yakus/concealedpon.test.cc +++ b/tests/yakus/concealedpon.test.cc @@ -17,7 +17,7 @@ namespace mahjong::yaku { TEST(isThreeConcealedPons, 2Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m111p111s666z44m", &player); player.open = false; @@ -34,7 +34,7 @@ TEST(isThreeConcealedPons, 2Han) { TEST(isThreeConcealedPons, PonsMustBeConcealed) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m111p111s44m", &player); player.melds[player.meld_count++] = Meld{ .type = SetType::kChi, @@ -55,7 +55,7 @@ TEST(isThreeConcealedPons, PonsMustBeConcealed) { TEST(isThreeConcealedPons, CanHaveAdditionalOpenPon) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m111p111s44m", &player); player.melds[player.meld_count++] = Meld{ .type = SetType::kPon, @@ -76,7 +76,7 @@ TEST(isThreeConcealedPons, CanHaveAdditionalOpenPon) { TEST(isThreeConcealedPons, PonsMustBeConcealedNegative) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m111p234s44m", &player); player.melds[player.meld_count++] = Meld{ .type = SetType::kPon, @@ -97,7 +97,7 @@ TEST(isThreeConcealedPons, PonsMustBeConcealedNegative) { TEST(isThreeConcealedPons, BadPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m111p234567s44m", &player); player.open = false; diff --git a/tests/yakus/dragonpon.test.cc b/tests/yakus/dragonpon.test.cc index c4c99f13..219eb4e8 100644 --- a/tests/yakus/dragonpon.test.cc +++ b/tests/yakus/dragonpon.test.cc @@ -15,7 +15,7 @@ namespace mahjong::yaku { TEST(isWindOrDragonPon, WhiteDragon) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m555z11z", &player); auto root = breakdownHand(player.live_range()); @@ -31,7 +31,7 @@ TEST(isWindOrDragonPon, WhiteDragon) { TEST(isWindOrDragonPon, GreenDragon) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m666z11z", &player); auto root = breakdownHand(player.live_range()); @@ -47,7 +47,7 @@ TEST(isWindOrDragonPon, GreenDragon) { TEST(isWindOrDragonPon, RedDragon) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m777z11z", &player); auto root = breakdownHand(player.live_range()); @@ -63,7 +63,7 @@ TEST(isWindOrDragonPon, RedDragon) { TEST(isWindOrDragonPon, Kan) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m7777z11z", &player); auto root = breakdownHand(player.live_range()); @@ -79,7 +79,7 @@ TEST(isWindOrDragonPon, Kan) { TEST(isWindOrDragonPon, CanWhenOpen) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m777z11z", &player); player.open = true; @@ -96,7 +96,7 @@ TEST(isWindOrDragonPon, CanWhenOpen) { TEST(isWindOrDragonPon, BadPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m222p11p", &player); auto root = breakdownHand(player.live_range()); diff --git a/tests/yakus/fullflush.test.cc b/tests/yakus/fullflush.test.cc index 67b7045f..ddccadfb 100644 --- a/tests/yakus/fullflush.test.cc +++ b/tests/yakus/fullflush.test.cc @@ -20,7 +20,7 @@ namespace mahjong::yaku { TEST(isFullFlush, 5Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m222m345m99m", &player); player.open = true; player.melds[player.meld_count++] = Meld{ @@ -41,7 +41,7 @@ TEST(isFullFlush, 5Han) { TEST(isFullFlush, 6Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m222m345m666m99m", &player); player.open = false; @@ -58,7 +58,7 @@ TEST(isFullFlush, 6Han) { TEST(isFullFlush, BadPlayerHonors) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m222m111z666m99m", &player); player.open = false; @@ -75,7 +75,7 @@ TEST(isFullFlush, BadPlayerHonors) { TEST(isFullFlush, BadPlayerSuit) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m222m111p666m99m", &player); player.open = false; @@ -92,7 +92,7 @@ TEST(isFullFlush, BadPlayerSuit) { TEST(isFullFlush, BadPlayerFullFlushHonors) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111z222z333z444z55z", &player); player.open = false; diff --git a/tests/yakus/halfflush.test.cc b/tests/yakus/halfflush.test.cc index 941bc3c8..3fd35257 100644 --- a/tests/yakus/halfflush.test.cc +++ b/tests/yakus/halfflush.test.cc @@ -20,7 +20,7 @@ namespace mahjong::yaku { TEST(isHalfFlush, 2Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("11m234m111z222z", &player); player.open = true; player.melds[player.meld_count++] = Meld{ @@ -41,7 +41,7 @@ TEST(isHalfFlush, 2Han) { TEST(isHalfFlush, 3Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("11m234m777m111z222z", &player); player.open = false; @@ -58,7 +58,7 @@ TEST(isHalfFlush, 3Han) { TEST(isHalfFlush, BadPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("11m234m111p222z", &player); player.open = true; player.melds[player.meld_count++] = Meld{ @@ -79,7 +79,7 @@ TEST(isHalfFlush, BadPlayer) { TEST(isHalfFlush, FullFlushIncompatible) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("11m234m888m777m", &player); player.open = true; player.melds[player.meld_count++] = Meld{ diff --git a/tests/yakus/littlethreedragons.test.cc b/tests/yakus/littlethreedragons.test.cc index 202d7eb7..4a8bdb69 100644 --- a/tests/yakus/littlethreedragons.test.cc +++ b/tests/yakus/littlethreedragons.test.cc @@ -20,7 +20,7 @@ namespace mahjong::yaku { TEST(isLittleThreeDragons, 2Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("555z666z111m222p77z", &player); player.open = false; @@ -37,7 +37,7 @@ TEST(isLittleThreeDragons, 2Han) { TEST(isLittleThreeDragons, WhenOpen) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("666z111m222p77z", &player); player.open = true; player.melds[player.meld_count++] = Meld{ @@ -58,7 +58,7 @@ TEST(isLittleThreeDragons, WhenOpen) { TEST(isLittleThreeDragons, BadPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("666z111m222p77s", &player); player.open = true; player.melds[player.meld_count++] = Meld{ diff --git a/tests/yakus/mixedtriplechi.test.cc b/tests/yakus/mixedtriplechi.test.cc index ec2bd051..473804ad 100644 --- a/tests/yakus/mixedtriplechi.test.cc +++ b/tests/yakus/mixedtriplechi.test.cc @@ -16,7 +16,7 @@ namespace mahjong::yaku { TEST(isMixedTripleChi, Open) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123p123m123s555p11z", &player); player.open = true; @@ -33,7 +33,7 @@ TEST(isMixedTripleChi, Open) { TEST(isMixedTripleChi, Closed) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123p123m123s555p11z", &player); player.open = false; @@ -50,7 +50,7 @@ TEST(isMixedTripleChi, Closed) { TEST(isMixedTripleChi, BadPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123p123p123s555p11z", &player); player.open = false; diff --git a/tests/yakus/outsidehand.test.cc b/tests/yakus/outsidehand.test.cc index 1d443ff4..c2a914ab 100644 --- a/tests/yakus/outsidehand.test.cc +++ b/tests/yakus/outsidehand.test.cc @@ -16,7 +16,7 @@ namespace mahjong::yaku { TEST(isOutsideHand, Open) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m789m111z999s55z", &player); player.open = true; @@ -33,7 +33,7 @@ TEST(isOutsideHand, Open) { TEST(isOutsideHand, Closed) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m789m111z999s55z", &player); player.open = false; @@ -50,7 +50,7 @@ TEST(isOutsideHand, Closed) { TEST(isOutsideHand, NoChi) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m111p111s999m66z", &player); auto root = breakdownHand(player.live_range()); @@ -66,7 +66,7 @@ TEST(isOutsideHand, NoChi) { TEST(isOutsideHand, BadPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m234p111s999m66z", &player); auto root = breakdownHand(player.live_range()); diff --git a/tests/yakus/pinfu.test.cc b/tests/yakus/pinfu.test.cc index 96ee8a0c..a1a2fe23 100644 --- a/tests/yakus/pinfu.test.cc +++ b/tests/yakus/pinfu.test.cc @@ -18,7 +18,7 @@ namespace mahjong::yaku { TEST(isPinfu, 1Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456p234678s44m", &player); player.open = false; game_state.pendingPiece = Piece(kFourPin); @@ -36,7 +36,7 @@ TEST(isPinfu, 1Han) { TEST(isPinfu, BadPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m555p234678s44m", &player); player.open = false; game_state.pendingPiece = Piece(kTwoBamboo); @@ -54,7 +54,7 @@ TEST(isPinfu, BadPlayer) { TEST(isPinfu, CantBeOpen) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456p234678s44m", &player); player.open = true; game_state.pendingPiece = Piece(kFourPin); @@ -72,7 +72,7 @@ TEST(isPinfu, CantBeOpen) { TEST(isPinfu, NeedTwoWait) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456p234678s44m", &player); player.open = false; game_state.pendingPiece = Piece(kFivePin); diff --git a/tests/yakus/puredoublechi.test.cc b/tests/yakus/puredoublechi.test.cc index 3e71a737..8117b892 100644 --- a/tests/yakus/puredoublechi.test.cc +++ b/tests/yakus/puredoublechi.test.cc @@ -16,7 +16,7 @@ namespace mahjong::yaku { TEST(isPureDoubleChi, 1Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("234m234m555p888s88p", &player); player.open = false; @@ -33,7 +33,7 @@ TEST(isPureDoubleChi, 1Han) { TEST(isPureDoubleChi, BadPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("234m123m555p888s88p", &player); player.open = false; @@ -50,7 +50,7 @@ TEST(isPureDoubleChi, BadPlayer) { TEST(isPureDoubleChi, MustBeConcealed) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("234m234m555p888s88p", &player); player.open = true; diff --git a/tests/yakus/purestraight.test.cc b/tests/yakus/purestraight.test.cc index be9f3701..e1ebf69d 100644 --- a/tests/yakus/purestraight.test.cc +++ b/tests/yakus/purestraight.test.cc @@ -16,7 +16,7 @@ namespace mahjong::yaku { TEST(isPureStraight, Open) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m789m555p11z", &player); player.open = true; @@ -33,7 +33,7 @@ TEST(isPureStraight, Open) { TEST(isPureStraight, Closed) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m789m555p11z", &player); player.open = false; @@ -50,7 +50,7 @@ TEST(isPureStraight, Closed) { TEST(isPureStraight, BadPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m999m555p11z", &player); player.open = false; diff --git a/tests/yakus/riichi.test.cc b/tests/yakus/riichi.test.cc index a2c33214..08841747 100644 --- a/tests/yakus/riichi.test.cc +++ b/tests/yakus/riichi.test.cc @@ -15,7 +15,7 @@ namespace mahjong::yaku { TEST(isRiichi, Riichi) { auto game_state = GameState(); - Player& player = game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("555m555p555s111z44m", &player); player.riichi = true; @@ -28,7 +28,7 @@ TEST(isRiichi, Riichi) { TEST(isRiichi, Ippatsu) { auto game_state = GameState(); - Player& player = game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("555m555p555s111z44m", &player); player.riichi = true; @@ -41,7 +41,7 @@ TEST(isRiichi, Ippatsu) { TEST(isRiichi, DoubleRiichi) { auto game_state = GameState(); - Player& player = game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("555m555p555s111z44m", &player); player.riichi = true; @@ -54,7 +54,7 @@ TEST(isRiichi, DoubleRiichi) { TEST(isRiichi, NoRiichi) { auto game_state = GameState(); - Player& player = game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("555m555p555s111z44m", &player); player.riichi = false; diff --git a/tests/yakus/robbingkan.test.cc b/tests/yakus/robbingkan.test.cc index ef65ea8d..d0adc38d 100644 --- a/tests/yakus/robbingkan.test.cc +++ b/tests/yakus/robbingkan.test.cc @@ -16,7 +16,7 @@ namespace mahjong::yaku { TEST(isRobbingAKan, 1Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m789m1111z999s55z", &player); game_state.players[0].hasRonned = true; game_state.nextState = StateFunctionType::kKanDiscard; @@ -34,7 +34,7 @@ TEST(isRobbingAKan, 1Han) { TEST(isRobbingAKan, DoesntApply) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m789m1111z999s55z", &player); game_state.players[0].hasRonned = true; game_state.nextState = StateFunctionType::kPon; diff --git a/tests/yakus/sevenpairs.test.cc b/tests/yakus/sevenpairs.test.cc index b55191fb..3b57b09f 100644 --- a/tests/yakus/sevenpairs.test.cc +++ b/tests/yakus/sevenpairs.test.cc @@ -16,7 +16,7 @@ namespace mahjong::yaku { TEST(isSevenPairs, 2Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("11m22p33s44z55m11z66z", &player); player.open = false; @@ -33,7 +33,7 @@ TEST(isSevenPairs, 2Han) { TEST(isSevenPairs, MustBeConcealed) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("11m22p33s44z55m11z66z", &player); player.open = true; @@ -50,7 +50,7 @@ TEST(isSevenPairs, MustBeConcealed) { TEST(isSevenPairs, UniquePairsOnly) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("1111m22p33s44z11z66z", &player); player.open = false; diff --git a/tests/yakus/terminalinsets.test.cc b/tests/yakus/terminalinsets.test.cc index e0ad4331..bcf244fa 100644 --- a/tests/yakus/terminalinsets.test.cc +++ b/tests/yakus/terminalinsets.test.cc @@ -19,7 +19,7 @@ namespace mahjong::yaku { TEST(isTerminalsInAllSets, 2Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m789m111p11s", &player); player.open = true; player.melds[player.meld_count++] = Meld{ @@ -40,7 +40,7 @@ TEST(isTerminalsInAllSets, 2Han) { TEST(isTerminalsInAllSets, 3Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m789m111p789p11s", &player); player.open = false; @@ -57,7 +57,7 @@ TEST(isTerminalsInAllSets, 3Han) { TEST(isTerminalsInAllSets, BadPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m789m222p11s", &player); player.open = true; player.open = true; diff --git a/tests/yakus/triplekan.test.cc b/tests/yakus/triplekan.test.cc index 07c021bf..d02ed76a 100644 --- a/tests/yakus/triplekan.test.cc +++ b/tests/yakus/triplekan.test.cc @@ -32,7 +32,7 @@ TEST(isThreeKans, 2Han) { }; auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("666z22m", &player); player.melds = {meld_a, meld_b, meld_c}; player.meld_count = 3; @@ -68,7 +68,7 @@ TEST(isThreeKans, WithOtherMelds) { }; auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("22m", &player); player.melds = {meld_a, meld_b, meld_c, meld_d}; player.meld_count = 4; @@ -96,7 +96,7 @@ TEST(isThreeKans, BadPlayer) { }; auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("777p666z22m", &player); player.melds = {meld_a, meld_b}; player.meld_count = 2; @@ -128,7 +128,7 @@ TEST(isThreeKans, AllConcealed) { }; auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("666z22m", &player); player.melds = {meld_a, meld_b, meld_c}; player.meld_count = 3; diff --git a/tests/yakus/triplepon.test.cc b/tests/yakus/triplepon.test.cc index 6ec4acfe..2fb594b8 100644 --- a/tests/yakus/triplepon.test.cc +++ b/tests/yakus/triplepon.test.cc @@ -16,7 +16,7 @@ namespace mahjong::yaku { TEST(isTriplePon, 2Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m111p111s666z44m", &player); auto root = breakdownHand(player.live_range()); @@ -32,7 +32,7 @@ TEST(isTriplePon, 2Han) { TEST(isTriplePon, BadPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("111m111p222m666z44m", &player); auto root = breakdownHand(player.live_range()); diff --git a/tests/yakus/twicepuredoublechi.test.cc b/tests/yakus/twicepuredoublechi.test.cc index cd8471c4..be530233 100644 --- a/tests/yakus/twicepuredoublechi.test.cc +++ b/tests/yakus/twicepuredoublechi.test.cc @@ -16,7 +16,7 @@ namespace mahjong::yaku { TEST(isTwicePureDoubleChi, 3Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("789p789p234m234m11z", &player); player.open = false; @@ -33,7 +33,7 @@ TEST(isTwicePureDoubleChi, 3Han) { TEST(isTwicePureDoubleChi, MustBeConcealed) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("789p789p234m234m11z", &player); player.open = true; @@ -50,7 +50,7 @@ TEST(isTwicePureDoubleChi, MustBeConcealed) { TEST(isTwicePureDoubleChi, BadPlayer) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("789p789p234m567m11z", &player); player.open = false; diff --git a/tests/yakus/underthesea.test.cc b/tests/yakus/underthesea.test.cc index 3f14c0c4..256b6de6 100644 --- a/tests/yakus/underthesea.test.cc +++ b/tests/yakus/underthesea.test.cc @@ -15,7 +15,7 @@ namespace mahjong::yaku { TEST(isBottomOfTheSea, 1Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m789m111z999s55z", &player); game_state.livingWallIndex = kLivingWallCount; @@ -32,7 +32,7 @@ TEST(isBottomOfTheSea, 1Han) { TEST(isBottomOfTheSea, 1HanRonned) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m789m111z999s55z", &player); game_state.livingWallIndex = kLivingWallCount; game_state.players[0].hasRonned = true; @@ -50,7 +50,7 @@ TEST(isBottomOfTheSea, 1HanRonned) { TEST(isBottomOfTheSea, DoesntApply) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m789m111z999s55z", &player); auto root = breakdownHand(player.live_range()); diff --git a/tests/yakus/windpons.test.cc b/tests/yakus/windpons.test.cc index 61a9abe2..5bb7ea20 100644 --- a/tests/yakus/windpons.test.cc +++ b/tests/yakus/windpons.test.cc @@ -15,7 +15,7 @@ namespace mahjong::yaku { TEST(isWindOrDragonPon, SeatWind) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m444z55z", &player); game_state.roundNum = 1; @@ -35,7 +35,7 @@ TEST(isWindOrDragonPon, SeatWind) { TEST(isWindOrDragonPon, SeatWindKan) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m4444z55z", &player); game_state.roundNum = 1; @@ -52,7 +52,7 @@ TEST(isWindOrDragonPon, SeatWindKan) { TEST(isWindOrDragonPon, PrevalentWind) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m111z55z", &player); game_state.roundNum = 1; @@ -69,7 +69,7 @@ TEST(isWindOrDragonPon, PrevalentWind) { TEST(isWindOrDragonPon, PrevalentWindKan) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m1111z55z", &player); game_state.roundNum = 1; @@ -86,7 +86,7 @@ TEST(isWindOrDragonPon, PrevalentWindKan) { TEST(isWindOrDragonPon, Dealer2Han) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m111z55z", &player); game_state.roundNum = 0; @@ -104,7 +104,7 @@ TEST(isWindOrDragonPon, Dealer2Han) { TEST(isWindOrDragonPon, Dealer2HanKan) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m1111z55z", &player); game_state.roundNum = 0; @@ -122,7 +122,7 @@ TEST(isWindOrDragonPon, Dealer2HanKan) { TEST(isWindOrDragonPon, NotSeatOrPrevalent) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m222z55z", &player); game_state.roundNum = 0; @@ -140,7 +140,7 @@ TEST(isWindOrDragonPon, NotSeatOrPrevalent) { TEST(isWindOrDragonPon, NoWind) { auto game_state = GameState(); - Player& player =game_state.players[0]; + Hand& player = game_state.players[0]; HandFromNotation("123m456m666m55z", &player); game_state.roundNum = 0; From 10cffb370b0fc40c876dafc9b8b60353d5386df1 Mon Sep 17 00:00:00 2001 From: alice Hartley Date: Fri, 5 Sep 2025 21:30:29 -0700 Subject: [PATCH 13/14] Clean-up changes. --- src/analysis/analysis.cc | 8 +-- src/analysis/analysis.h | 3 +- src/analysis/handtree.h | 3 - src/analysis/util.h | 1 - src/api/gamestate.cc | 14 ++-- src/api/types.h | 14 ++-- src/controllers/thricebot.cc | 8 +-- src/controllers/thricebot.h | 6 +- src/scoring/scoring.cc | 2 +- src/scoring/scoring.h | 2 +- src/scoring/yakus/allgreen.cc | 1 - src/scoring/yakus/fullyconcealedhand.cc | 2 +- src/scoring/yakus/maxbranches.cc | 1 - src/scoring/yakus/outsidehand.cc | 4 +- src/statefunctions/decisionfunction.cc | 19 ++--- src/statefunctions/gamestates/chi.cc | 71 +++++++++---------- src/statefunctions/gamestates/concealedkan.cc | 4 +- src/statefunctions/gamestates/convertedkan.cc | 23 +++--- src/statefunctions/gamestates/discard.cc | 2 +- src/statefunctions/gamestates/draw.cc | 2 +- src/statefunctions/gamestates/exhaust.cc | 16 ++--- src/statefunctions/gamestates/gamestart.cc | 11 +-- src/statefunctions/gamestates/kan.cc | 13 ++-- src/statefunctions/gamestates/kandiscard.cc | 2 +- src/statefunctions/gamestates/playerhand.cc | 13 ++-- src/statefunctions/gamestates/pon.cc | 30 ++++---- src/statefunctions/gamestates/replacement.cc | 4 +- src/statefunctions/gamestates/riichi.cc | 16 ++--- src/statefunctions/gamestates/ron.cc | 23 +++--- src/statefunctions/gamestates/roundend.cc | 30 ++++---- src/statefunctions/gamestates/roundstart.cc | 12 ++-- src/statefunctions/gamestates/tsumo.cc | 30 ++++---- src/statefunctions/statecontroller.cc | 4 +- src/statefunctions/stateutilities.cc | 24 +++---- src/statefunctions/stateutilities.h | 4 +- src/types/gamestate.h | 1 - src/types/statefunction.h | 2 +- src/types/typeprinter.cc | 20 +++--- src/types/typeprinter.h | 5 +- tests/api/game_control.test.cc | 51 +++++++------ tests/can_chi.test.cc | 28 ++++---- tests/rules/basic_rules.test.cc | 10 +-- tests/utils/gamestate_utils.h | 1 - tests/utils/handformer.cc | 2 +- tests/utils/handformer.h | 3 +- tests/utils/handformer.test.cc | 34 ++++----- tests/yakus/allpon.test.cc | 2 +- tests/yakus/allsimples.test.cc | 4 +- tests/yakus/allterminalsandhonors.test.cc | 2 +- tests/yakus/concealedpon.test.cc | 2 +- tests/yakus/dragonpon.test.cc | 2 +- tests/yakus/fullflush.test.cc | 6 +- tests/yakus/halfflush.test.cc | 2 +- tests/yakus/littlethreedragons.test.cc | 2 +- tests/yakus/mixedtriplechi.test.cc | 2 +- tests/yakus/outsidehand.test.cc | 2 +- tests/yakus/pinfu.test.cc | 2 +- tests/yakus/puredoublechi.test.cc | 2 +- tests/yakus/purestraight.test.cc | 2 +- tests/yakus/terminalinsets.test.cc | 2 +- tests/yakus/triplekan.test.cc | 2 +- tests/yakus/triplepon.test.cc | 2 +- tests/yakus/twicepuredoublechi.test.cc | 2 +- tools/driver/main.cc | 4 +- 64 files changed, 297 insertions(+), 326 deletions(-) diff --git a/src/analysis/analysis.cc b/src/analysis/analysis.cc index 43d0768e..5cde3e4b 100644 --- a/src/analysis/analysis.cc +++ b/src/analysis/analysis.cc @@ -22,10 +22,10 @@ void countPieces(Breakdown* b) { } } // namespace -std::vector AnalyzeHand(const Hand& player, const bool only_complete) { +std::vector AnalyzeHand(const Hand& hand, const bool only_complete) { Branch base_branch; - base_branch.open = !player.melds.empty(); - for (const auto& meld : player.melds_range()) { + base_branch.open = !hand.melds.empty(); + for (const Meld& meld : hand.melds_range()) { switch (meld.type) { case SetType::kChi: base_branch.chis.emplace_back(meld.start); @@ -42,7 +42,7 @@ std::vector AnalyzeHand(const Hand& player, const bool only_complete) { } } std::vector branches; - const std::unique_ptr root = breakdownHand(player.live_range()); + const std::unique_ptr root = breakdownHand(hand.live_range()); for (const auto& branch_vec : Node::AsBranchVectors(root.get())) { branches.push_back(base_branch); Branch& branch = branches.back(); diff --git a/src/analysis/analysis.h b/src/analysis/analysis.h index 923e5594..aa16f4dd 100644 --- a/src/analysis/analysis.h +++ b/src/analysis/analysis.h @@ -3,7 +3,6 @@ #include #include "analysis/handnode.h" -#include "types/gamestate.h" #include "types/hand.h" #include "types/piecetype.h" @@ -19,5 +18,5 @@ struct Branch { }; std::unique_ptr breakdownHand(const std::span& pieces); -std::vector AnalyzeHand(const Hand& player, bool only_complete = false); +std::vector AnalyzeHand(const Hand& hand, bool only_complete = false); } // namespace mahjong diff --git a/src/analysis/handtree.h b/src/analysis/handtree.h index 8850c34f..96ccfd96 100644 --- a/src/analysis/handtree.h +++ b/src/analysis/handtree.h @@ -4,9 +4,7 @@ #include "analysis/handnode.h" #include "types/piecetype.h" - namespace mahjong { - struct Breakdown { std::unique_ptr rootNode; Node* currentNode{}; @@ -14,7 +12,6 @@ struct Breakdown { std::map counts; std::map possibilities; std::vector pieces; - int pieces_size; }; void driver(Breakdown* b); diff --git a/src/analysis/util.h b/src/analysis/util.h index e0123add..f72f9af3 100644 --- a/src/analysis/util.h +++ b/src/analysis/util.h @@ -3,7 +3,6 @@ #include #include "analysis/analysis.h" -#include "types/gamestate.h" #include "types/hand.h" #include "types/piecetype.h" #include "types/sets.h" diff --git a/src/api/gamestate.cc b/src/api/gamestate.cc index f89dc3c3..87917934 100644 --- a/src/api/gamestate.cc +++ b/src/api/gamestate.cc @@ -26,8 +26,8 @@ CStateFunctionType ConvertStateFunctionType(mahjong::StateFunctionType func) { return kRoundStart; case mahjong::StateFunctionType::kDraw: return kDraw; - case mahjong::StateFunctionType::kPlayerPlayer: - return kPlayerPlayer; + case mahjong::StateFunctionType::kPlayerHand: + return kPlayerHand; case mahjong::StateFunctionType::kPon: return kPon; case mahjong::StateFunctionType::kChi: @@ -145,20 +145,20 @@ CObservedGameState ObserveGameState(mahjong::GameState* state) { observed.points[i] = state->players[i].points; observed.hasRonned[i] = state->players[i].hasRonned; - // Convert Player to CPlayer + // Convert Hand to CHand const auto& cpp_hand = state->players[i]; - CPlayer& c_hand = observed.hands[i]; + CHand& c_hand = observed.hands[i]; // Live pieces const int live_piece_count = static_cast(cpp_hand.live_count); - c_hand.livePieceCount = std::min(live_piece_count, kMaxLivePlayerSize); + c_hand.livePieceCount = std::min(live_piece_count, kMaxLiveHandSize); for (int j = 0; j < c_hand.livePieceCount; j++) { c_hand.livePieces[j] = static_cast(cpp_hand.live[j].toUint8_t()); } // Melds const int meld_count = cpp_hand.meld_count; - c_hand.meldCount = std::min(meld_count, kMaxMeldsPerPlayer); + c_hand.meldCount = std::min(meld_count, kMaxMeldsPerHand); for (int j = 0; j < c_hand.meldCount; j++) { c_hand.melds[j].type = static_cast(cpp_hand.melds[j].type); c_hand.melds[j].start = @@ -172,7 +172,7 @@ CObservedGameState ObserveGameState(mahjong::GameState* state) { c_hand.discards[j] = static_cast(discards[j].toUint8_t()); } - // Player properties + // Hand properties c_hand.open = cpp_hand.open; c_hand.riichi = cpp_hand.riichi; c_hand.riichiPieceDiscard = static_cast(cpp_hand.riichiPieceDiscard); diff --git a/src/api/types.h b/src/api/types.h index 6d171454..2683306f 100644 --- a/src/api/types.h +++ b/src/api/types.h @@ -6,8 +6,8 @@ namespace api { extern "C" { -static const int kMaxLivePlayerSize = 14; // Maximum 14 pieces (13 + 1 drawn) -static const int kMaxMeldsPerPlayer = 4; // Maximum 4 melds possible +static const int kMaxLiveHandSize = 14; // Maximum 14 pieces (13 + 1 drawn) +static const int kMaxMeldsPerHand = 4; // Maximum 4 melds possible static const int kMaxDiscardsPerPlayer = 27; // Flow interruption from calls can allow the max discards to go up // to 27. @@ -41,7 +41,7 @@ enum CStateFunctionType { kGameStart = 1, kRoundStart = 2, kDraw = 3, - kPlayerPlayer = 4, + kPlayerHand = 4, kPon = 5, kChi = 6, kKan = 7, @@ -63,10 +63,10 @@ struct CMeld { CPiece start; }; -struct CPlayer { - CPiece livePieces[kMaxLivePlayerSize]; // Live pieces +struct CHand { + CPiece livePieces[kMaxLiveHandSize]; // Live pieces int livePieceCount; // Number of live pieces - CMeld melds[kMaxMeldsPerPlayer]; // Melds + CMeld melds[kMaxMeldsPerHand]; // Melds int meldCount; // Number of melds CPiece discards[kMaxDiscardsPerPlayer]; // Discards int discardCount; // Number of discards @@ -91,7 +91,7 @@ struct CObservedGameState { int scores[4]; // Temporary round score changes int points[4]; // Player points bool hasRonned[4]; // Which players have declared ron this turn - CPlayer hands[4]; // Player hands with live pieces, melds, and discards + CHand hands[4]; // Player hands with live pieces, melds, and discards CStateFunctionType prevState; // Previous state function CStateFunctionType currState; // Current state function CStateFunctionType nextState; // Next state function diff --git a/src/controllers/thricebot.cc b/src/controllers/thricebot.cc index 50365127..c957a11a 100644 --- a/src/controllers/thricebot.cc +++ b/src/controllers/thricebot.cc @@ -20,7 +20,7 @@ REGISTER_PLAYER_CONTROLLER(ThriceBot); void ThriceBot::RoundStart(std::vector _hand, Wind s, Wind p) { for (const Piece m : _hand) { - PlayerTile h; + HandTile h; h.piece = m; if (m.isHonor()) { h.weight = kHonorWeight; @@ -54,8 +54,8 @@ void ThriceBot::assignweights() { } } -ThriceBot::PlayerTile ThriceBot::assignTileWeight(PlayerTile h1) { - PlayerTile h; +ThriceBot::HandTile ThriceBot::assignTileWeight(HandTile h1) { + HandTile h; h.piece = h1.piece; h.weight = h1.weight; for (auto& i : hand_) { @@ -89,7 +89,7 @@ void ThriceBot::ReceiveEvent(Event e) { } if (e.type == Event::kDiscard && e.player == pid_) { - PlayerTile h; + HandTile h; h.piece = Piece(e.piece); if (h.piece.isHonor()) { h.weight = kHonorWeight; diff --git a/src/controllers/thricebot.h b/src/controllers/thricebot.h index e309896b..274fa271 100644 --- a/src/controllers/thricebot.h +++ b/src/controllers/thricebot.h @@ -14,7 +14,7 @@ namespace mahjong { class ThriceBot : public PlayerController { public: - struct PlayerTile { + struct HandTile { Piece piece; float weight{}; }; @@ -34,11 +34,11 @@ class ThriceBot : public PlayerController { private: void assignweights(); Piece popDiscard(); - PlayerTile assignTileWeight(PlayerTile h1); + HandTile assignTileWeight(HandTile h1); void checkDiscard(); bool checkTile(Piece p); - std::vector hand_; + std::vector hand_; std::array discarded_ = {}; Event lastEvent_; Wind swind_; diff --git a/src/scoring/scoring.cc b/src/scoring/scoring.cc index efb48e96..137d5819 100644 --- a/src/scoring/scoring.cc +++ b/src/scoring/scoring.cc @@ -59,7 +59,7 @@ const int kFuRounding = 10; } // namespace -Score scorePlayer(const GameState& state, const Hand& player) { +Score scoreHand(const GameState& state, const Hand& player) { auto root = breakdownHand(player.live_range()); Score s; s.han = 0; diff --git a/src/scoring/scoring.h b/src/scoring/scoring.h index 2865efee..65c4907c 100644 --- a/src/scoring/scoring.h +++ b/src/scoring/scoring.h @@ -7,7 +7,7 @@ #include "types/score.h" namespace mahjong { -Score scorePlayer(const GameState& state, const Hand& player); +Score scoreHand(const GameState& state, const Hand& player); int getBasicPoints(Score s); diff --git a/src/scoring/yakus/allgreen.cc b/src/scoring/yakus/allgreen.cc index 62efdcb7..11021a27 100644 --- a/src/scoring/yakus/allgreen.cc +++ b/src/scoring/yakus/allgreen.cc @@ -16,7 +16,6 @@ bool isAllGreen(const GameState& /*state*/, const Hand& player, return false; } } - for (const auto& meld : player.melds_range()) { if (!meld.start.isGreen()) { return false; diff --git a/src/scoring/yakus/fullyconcealedhand.cc b/src/scoring/yakus/fullyconcealedhand.cc index d694f43c..ac393696 100644 --- a/src/scoring/yakus/fullyconcealedhand.cc +++ b/src/scoring/yakus/fullyconcealedhand.cc @@ -18,7 +18,7 @@ bool isFullyConcealedHand(const GameState& state, const Hand& player, REGISTER_YAKU({ .id = "fullyconcealedhand", - .name = "Fully Concealed Player", + .name = "Fully Concealed Hand", .type = Yaku::kClosed, .value = 1, .is_yaku_func = yaku::isFullyConcealedHand, diff --git a/src/scoring/yakus/maxbranches.cc b/src/scoring/yakus/maxbranches.cc index e2fe8e2b..7c165309 100644 --- a/src/scoring/yakus/maxbranches.cc +++ b/src/scoring/yakus/maxbranches.cc @@ -15,7 +15,6 @@ bool isMaxBranches(const GameState& /*state*/, const Hand& player, const int suit = player.live[0].getSuit(); std::array sets = {}; const std::array final = {3, 3, 2, 2, 2, 2}; - for (const auto& piece : player.live_range()) { if (piece.getSuit() != suit) { return false; diff --git a/src/scoring/yakus/outsidehand.cc b/src/scoring/yakus/outsidehand.cc index 2f2582aa..a341c3ef 100644 --- a/src/scoring/yakus/outsidehand.cc +++ b/src/scoring/yakus/outsidehand.cc @@ -42,14 +42,14 @@ bool isOutsideHand(const GameState& state, const Hand& player, } } // Terminals in all Sets and All Terminals and Honors are more valuable and - // score instead of Outside Player. + // score instead of Outside Hand. return chi && !isTerminalsInAllSets(state, player, branch) && !isAllTerminalsAndHonors(state, player); } REGISTER_YAKU({ .id = "outsidehand", - .name = "Outside Player", + .name = "Outside Hand", .type = Yaku::kBonusWhenClosed, .value = 1, .is_yaku_func = yaku::isOutsideHand, diff --git a/src/statefunctions/decisionfunction.cc b/src/statefunctions/decisionfunction.cc index a5d4e60b..f5ba99cf 100644 --- a/src/statefunctions/decisionfunction.cc +++ b/src/statefunctions/decisionfunction.cc @@ -9,7 +9,6 @@ #include "statefunctions/stateutilities.h" #include "types/gamestate.h" #include "types/hand.h" -#include "types/pieces.h" #include "types/piecetype.h" #include "types/sets.h" #include "types/walls.h" @@ -26,27 +25,17 @@ bool CanRon(const GameState& state, const Hand& player) { } // Build the theoretical hand - auto& tmp_player = const_cast(player); + Hand tmp_player = player; tmp_player.live[tmp_player.live_count++] = state.pendingPiece; // If this Ron is occurring due to a concealed kan discard, if (state.concealedKan) { // If it happens to be a ron for a thirteen orphans, - // it's allowed and you can ron - if (yaku::isThirteenOrphans(state, player)) { - tmp_player.live[--tmp_player.live_count] = kError; - return true; - } - - // otherwise, you can't - tmp_player.live[--tmp_player.live_count] = kError; - return false; + // it's allowed and you can ron otherwise, you can't. + return yaku::isThirteenOrphans(state, player); } - // if not a concealed kan, check if it's complete - const bool can_ron = isComplete(state, player); - tmp_player.live[--tmp_player.live_count] = kError; - return can_ron; + return isComplete(state, player); } bool CanKan(const GameState& state, const Hand& player) { diff --git a/src/statefunctions/gamestates/chi.cc b/src/statefunctions/gamestates/chi.cc index 6882b9ff..46c1abab 100644 --- a/src/statefunctions/gamestates/chi.cc +++ b/src/statefunctions/gamestates/chi.cc @@ -16,40 +16,57 @@ namespace mahjong { namespace { -Piece GetChiStart(const Hand& player, Piece p) { - if (CountPieces(player, p - 2) > 0 && CountPieces(player, p - 1) > 0) { - return p - 2; +Piece GetChiStart(const Hand& hand, Piece piece) { + if (CountPieces(hand, piece - 2) > 0 && CountPieces(hand, piece - 1) > 0) { + return piece - 2; } - if (CountPieces(player, p - 1) > 0 && CountPieces(player, p + 1) > 0) { - return p - 1; + if (CountPieces(hand, piece - 1) > 0 && CountPieces(hand, piece + 1) > 0) { + return piece - 1; } - if (CountPieces(player, p + 1) > 0 && CountPieces(player, p + 2) > 0) { - return p; + if (CountPieces(hand, piece + 1) > 0 && CountPieces(hand, piece + 2) > 0) { + return piece; } return kError; } std::unique_ptr Chi(std::unique_ptr state) { + if (Hand& player = state->players[state->currentPlayer]; + player.riichi && player.discards_count == player.riichiPieceDiscard) { + player.riichiPieceDiscard++; + } + + state->currentPlayer = state->lastCaller; + state->lastCall = state->turnNum; + state->concealedKan = false; + state->turnNum++; + + Hand& player = state->players[state->currentPlayer]; + player.open = true; // only gives a single one of the chis // ui oof - const Piece chi_start = - GetChiStart(state->players[state->lastCaller], state->pendingPiece); + const Piece chi_start = GetChiStart(player, state->pendingPiece); if (chi_start == kError) { std::cerr << "Failed to get start of Chi" << '\n'; state->nextState = StateFunctionType::kError; return state; } - if (state->players.at(state->currentPlayer).riichi && - state->players.at(state->currentPlayer).discards_count == - state->players.at(state->currentPlayer).riichiPieceDiscard) { - state->players.at(state->currentPlayer).riichiPieceDiscard++; + for (int i = 0; i < 3; ++i) { + if (chi_start + i == state->pendingPiece) { + continue; + } + if (RemovePieces(player, chi_start + i, + /*count=*/1) != 1) { + std::cerr << "Not Enough Pieces to remove in Chi" << '\n'; + state->nextState = StateFunctionType::kError; + return state; + } } - Hand& player = state->players.at(state->lastCaller); - - player.open = true; - state->currentPlayer = state->lastCaller; + player.melds[player.meld_count++] = Meld{ + .type = SetType::kChi, + .start = chi_start, + }; AlertPlayers( *state, @@ -60,26 +77,6 @@ std::unique_ptr Chi(std::unique_ptr state) { .decision = false, // decision }); - player.live[player.live_count++] = state->pendingPiece; - state->lastCall = state->turnNum; - state->concealedKan = false; - state->turnNum++; - - if (RemovePieces(state->players[state->lastCaller], chi_start, /*count=*/1) != - 1 || - RemovePieces(state->players[state->lastCaller], chi_start + 1, - /*count=*/1) != 1 || - RemovePieces(state->players[state->lastCaller], chi_start + 2, - /*count=*/1) != 1) { - std::cerr << "Not Enough Pieces to remove in Chi" << '\n'; - state->nextState = StateFunctionType::kError; - return state; - } - player.melds[player.meld_count++] = Meld{ - .type = SetType::kChi, - .start = chi_start, - }; - state->pendingPiece = AskForDiscard(*state); state->nextState = StateFunctionType::kDiscard; diff --git a/src/statefunctions/gamestates/concealedkan.cc b/src/statefunctions/gamestates/concealedkan.cc index b0245606..c1f28a02 100644 --- a/src/statefunctions/gamestates/concealedkan.cc +++ b/src/statefunctions/gamestates/concealedkan.cc @@ -24,13 +24,13 @@ std::unique_ptr ConcealedKan(std::unique_ptr state) { state->pendingPiece.toUint8_t()), // piece .decision = false, // decision }); - if (RemovePieces(state->players[state->currentPlayer], state->pendingPiece, + Hand& player = state->players[state->currentPlayer]; + if (RemovePieces(player, state->pendingPiece, /*count=*/4) != 4) { std::cerr << "Not Enough pieces to remove in ConcealedKan" << '\n'; state->nextState = StateFunctionType::kError; return state; } - Hand& player = state->players.at(state->currentPlayer); player.melds[player.meld_count++] = Meld{ .type = SetType::kConcealedKan, .start = state->pendingPiece, diff --git a/src/statefunctions/gamestates/convertedkan.cc b/src/statefunctions/gamestates/convertedkan.cc index 160e2fed..7c9e0eba 100644 --- a/src/statefunctions/gamestates/convertedkan.cc +++ b/src/statefunctions/gamestates/convertedkan.cc @@ -24,27 +24,22 @@ std::unique_ptr ConvertedKan(std::unique_ptr state) { state->pendingPiece.toUint8_t()), // piece .decision = false, // decision }); - if (RemovePieces(state->players[state->currentPlayer], state->pendingPiece, + Hand& player = state->players[state->currentPlayer]; + if (RemovePieces(player, state->pendingPiece, /*count=*/1) != 1) { std::cerr << "Not Enough pieces to remove in ConvertedKan" << '\n'; state->nextState = StateFunctionType::kError; return state; } - - Hand& player = state->players[state->currentPlayer]; - if (auto* meld = std::ranges::find(player.melds, - Meld{ - .type = SetType::kPon, - .start = state->pendingPiece, - }); - meld != player.melds.end()) { - meld->type = SetType::kKan; - state->nextState = StateFunctionType::kKanDiscard; + Meld* meld = std::ranges::find( + player.melds, Meld{.type = SetType::kPon, .start = state->pendingPiece}); + if (meld == player.melds.end()) { + std::cerr << "Could Not find matching pon" << '\n'; + state->nextState = StateFunctionType::kError; return state; } - - std::cerr << "Could Not find matching pon" << '\n'; - state->nextState = StateFunctionType::kError; + meld->type = SetType::kKan; + state->nextState = StateFunctionType::kKanDiscard; return state; } } // namespace diff --git a/src/statefunctions/gamestates/discard.cc b/src/statefunctions/gamestates/discard.cc index 80b2dfa5..3e45762f 100644 --- a/src/statefunctions/gamestates/discard.cc +++ b/src/statefunctions/gamestates/discard.cc @@ -57,7 +57,7 @@ std::unique_ptr Discard(std::unique_ptr state) { for (Hand& player : state->players) { if (need_decision.at(player.id)) { Event temp_decision = - GetValidDecisionOrThrow(*state, player, /*inPlayer=*/false); + GetValidDecisionOrThrow(*state, player, /*inHand=*/false); if (temp_decision.type < decision.type) { // lower is higher priority temp_decision.player = player.id; temp_decision.piece = diff --git a/src/statefunctions/gamestates/draw.cc b/src/statefunctions/gamestates/draw.cc index f8537402..c8035d07 100644 --- a/src/statefunctions/gamestates/draw.cc +++ b/src/statefunctions/gamestates/draw.cc @@ -15,7 +15,7 @@ std::unique_ptr Draw(std::unique_ptr state) { state->pendingPiece = Walls::TakePiece(*state); Hand& player = state->players[state->currentPlayer]; player.live[player.live_count++] = state->pendingPiece; - state->nextState = StateFunctionType::kPlayerPlayer; + state->nextState = StateFunctionType::kPlayerHand; return state; } } // namespace diff --git a/src/statefunctions/gamestates/exhaust.cc b/src/statefunctions/gamestates/exhaust.cc index 5ae4dfa1..e3310735 100644 --- a/src/statefunctions/gamestates/exhaust.cc +++ b/src/statefunctions/gamestates/exhaust.cc @@ -14,8 +14,8 @@ std::unique_ptr Exhaust(std::unique_ptr state) { int total_winners = 0; for (int i = 0; i < 4; i++) { // TODO(#21): Implement no tenpai if you have all pieces of your wait - if (state->players.at(i).riichi || !getWaits(state->players[i]).empty()) { - winning_players.at(i) = 1; + if (state->players[i].riichi || !getWaits(state->players[i]).empty()) { + winning_players[i] = 1; total_winners++; } } @@ -25,24 +25,24 @@ std::unique_ptr Exhaust(std::unique_ptr state) { } if (total_winners < 4 && total_winners > 0) { for (int i = 0; i < 4; i++) { - if (winning_players.at(i) != 0) { - state->players.at(i).score = 3000 / total_winners; + if (winning_players[i] != 0) { + state->players[i].score = 3000 / total_winners; } else { switch (total_winners) { case 1: - state->players.at(i).score = -1000; + state->players[i].score = -1000; break; case 2: - state->players.at(i).score = -1500; + state->players[i].score = -1500; break; case 3: - state->players.at(i).score = -3000; + state->players[i].score = -3000; break; default: break; } } - if (state->players.at(i).riichi) { + if (state->players[i].riichi) { state->players[i].score -= 1000; } } diff --git a/src/statefunctions/gamestates/gamestart.cc b/src/statefunctions/gamestates/gamestart.cc index 59b87dfa..42d8bd70 100644 --- a/src/statefunctions/gamestates/gamestart.cc +++ b/src/statefunctions/gamestates/gamestart.cc @@ -1,8 +1,8 @@ -#include #include #include "statefunctions/router.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/settings.h" #include "types/statefunction.h" @@ -10,10 +10,11 @@ namespace mahjong { namespace { std::unique_ptr GameStart(std::unique_ptr state) { - for (int i = 0; i < 4; i++) { - state->players[i].id = i; - state->players[i].points = kStartingPoints; - state->controllers[i]->GameStart(i); + int i = 0; + for (Hand& player : state->players) { + player.id = i++; + player.points = kStartingPoints; + state->controllers[player.id]->GameStart(player.id); } state->g.seed(state->seed); state->nextState = StateFunctionType::kRoundStart; diff --git a/src/statefunctions/gamestates/kan.cc b/src/statefunctions/gamestates/kan.cc index 8a3de206..a9475e84 100644 --- a/src/statefunctions/gamestates/kan.cc +++ b/src/statefunctions/gamestates/kan.cc @@ -25,19 +25,18 @@ std::unique_ptr Kan(std::unique_ptr state) { .decision = false, // decision }); - if (state->players.at(state->currentPlayer).riichi && - state->players.at(state->currentPlayer).discards_count == - state->players.at(state->currentPlayer).riichiPieceDiscard) { - state->players.at(state->currentPlayer).riichiPieceDiscard++; + if (Hand& player = state->players[state->currentPlayer]; + player.riichi && player.discards_count == player.riichiPieceDiscard) { + player.riichiPieceDiscard++; } - Hand& player = state->players.at(state->lastCaller); - player.open = true; - state->currentPlayer = state->lastCaller; state->lastCall = state->turnNum; state->concealedKan = false; state->turnNum++; + state->currentPlayer = state->lastCaller; + Hand& player = state->players[state->currentPlayer]; + player.open = true; if (RemovePieces(player, state->pendingPiece, /*count=*/3) != 3) { std::cerr << "Not Enough Pieces to remove in kan" << '\n'; diff --git a/src/statefunctions/gamestates/kandiscard.cc b/src/statefunctions/gamestates/kandiscard.cc index c71932ee..2039e47c 100644 --- a/src/statefunctions/gamestates/kandiscard.cc +++ b/src/statefunctions/gamestates/kandiscard.cc @@ -37,7 +37,7 @@ std::unique_ptr KanDiscard(std::unique_ptr state) { for (Hand& player : state->players) { if (need_decision.at(player.id)) { const Event temp_decision = - GetValidDecisionOrThrow(*state, player, /*inPlayer=*/false); + GetValidDecisionOrThrow(*state, player, /*inHand=*/false); if (temp_decision.type == Event::kRon) { player.hasRonned = true; have_ronned = true; diff --git a/src/statefunctions/gamestates/playerhand.cc b/src/statefunctions/gamestates/playerhand.cc index d0c84a8e..ee4173a3 100644 --- a/src/statefunctions/gamestates/playerhand.cc +++ b/src/statefunctions/gamestates/playerhand.cc @@ -12,11 +12,12 @@ #include "types/hand.h" #include "types/piecetype.h" #include "types/statefunction.h" +#include "types/typeprinter.h" namespace mahjong { namespace { -std::unique_ptr PlayerPlayer(std::unique_ptr state) { +std::unique_ptr PlayerHand(std::unique_ptr state) { const std::vector decisions = { PossibleDecision{.type = Event::kTsumo, .func = CanTsumo}, PossibleDecision{.type = Event::kConcealedKan, .func = CanConcealedKan}, @@ -27,9 +28,10 @@ std::unique_ptr PlayerPlayer(std::unique_ptr state) { return !player.riichi; }}}; + const Hand& player = state->players[state->currentPlayer]; bool decision_asked = false; for (const auto& [decision, decisionIsPossible] : decisions) { - if (decisionIsPossible(*state, state->players[state->currentPlayer])) { + if (decisionIsPossible(*state, player)) { decision_asked = true; state->controllers.at(state->currentPlayer) ->ReceiveEvent(Event{ @@ -50,9 +52,8 @@ std::unique_ptr PlayerPlayer(std::unique_ptr state) { decision.decision = true; state->nextState = StateFunctionType::kDiscard; } else { - decision = - GetValidDecisionOrThrow(*state, state->players[state->currentPlayer], - /*inPlayer=*/true); + decision = GetValidDecisionOrThrow(*state, player, + /*inHand=*/true); } // note riichi handling is a lil borked on the player agency side @@ -88,5 +89,5 @@ std::unique_ptr PlayerPlayer(std::unique_ptr state) { } } // namespace -REGISTER_ROUTE(PlayerPlayer, StateFunctionType::kPlayerPlayer); +REGISTER_ROUTE(PlayerHand, StateFunctionType::kPlayerHand); } // namespace mahjong diff --git a/src/statefunctions/gamestates/pon.cc b/src/statefunctions/gamestates/pon.cc index aa980b9c..d23b5270 100644 --- a/src/statefunctions/gamestates/pon.cc +++ b/src/statefunctions/gamestates/pon.cc @@ -17,29 +17,19 @@ namespace mahjong { namespace { std::unique_ptr Pon(std::unique_ptr state) { - state->players.at(state->lastCaller).open = true; - - AlertPlayers(*state, Event{ - .type = Event::kPon, // type - .player = state->lastCaller, // player - .piece = static_cast( - state->pendingPiece.toUint8_t()), // piece - .decision = false, // decision - }); - - if (state->players.at(state->currentPlayer).riichi && - state->players.at(state->currentPlayer).discards_count == - state->players.at(state->currentPlayer).riichiPieceDiscard) { - state->players.at(state->currentPlayer).riichiPieceDiscard++; + if (Hand& player = state->players[state->currentPlayer]; + player.riichi && player.discards_count == player.riichiPieceDiscard) { + player.riichiPieceDiscard++; } - Hand& player = state->players.at(state->lastCaller); state->currentPlayer = state->lastCaller; state->lastCall = state->turnNum; state->concealedKan = false; state->turnNum++; - if (RemovePieces(state->players[state->lastCaller], state->pendingPiece, + Hand& player = state->players.at(state->currentPlayer); + player.open = true; + if (RemovePieces(player, state->pendingPiece, /*count=*/2) != 2) { std::cerr << "Not enough pieces to remove in Pon" << '\n'; state->nextState = StateFunctionType::kError; @@ -50,6 +40,14 @@ std::unique_ptr Pon(std::unique_ptr state) { .start = state->pendingPiece, }; + AlertPlayers(*state, Event{ + .type = Event::kPon, // type + .player = state->lastCaller, // player + .piece = static_cast( + state->pendingPiece.toUint8_t()), // piece + .decision = false, // decision + }); + state->pendingPiece = AskForDiscard(*state); state->nextState = StateFunctionType::kDiscard; diff --git a/src/statefunctions/gamestates/replacement.cc b/src/statefunctions/gamestates/replacement.cc index ac3aca94..3574cdfc 100644 --- a/src/statefunctions/gamestates/replacement.cc +++ b/src/statefunctions/gamestates/replacement.cc @@ -16,7 +16,7 @@ namespace mahjong { namespace { std::unique_ptr Replacement(std::unique_ptr state) { const Piece draw = Walls::TakeReplacementTile(*state); - Hand& player = state->players.at(state->currentPlayer); + Hand& player = state->players[state->currentPlayer]; player.live[player.live_count++] = draw; state->pendingPiece = draw; @@ -29,7 +29,7 @@ std::unique_ptr Replacement(std::unique_ptr state) { .decision = false, // decision }); - state->nextState = StateFunctionType::kPlayerPlayer; + state->nextState = StateFunctionType::kPlayerHand; return state; } } // namespace diff --git a/src/statefunctions/gamestates/riichi.cc b/src/statefunctions/gamestates/riichi.cc index 9cc99992..46bd24ae 100644 --- a/src/statefunctions/gamestates/riichi.cc +++ b/src/statefunctions/gamestates/riichi.cc @@ -16,10 +16,14 @@ namespace mahjong { namespace { std::unique_ptr Riichi(std::unique_ptr state) { + Hand& player = state->players[state->currentPlayer]; + player.riichiRound = state->turnNum; + player.riichiPieceDiscard = player.discards_count; + player.riichi = true; + // TODO(#22): Ask the players if they want to riichi - state->pendingPiece = getPossibleWaits(state->players[state->currentPlayer]) - .begin() - ->second.front(); + state->pendingPiece = getPossibleWaits(player).begin()->second.front(); + state->riichiSticks++; AlertPlayers(*state, Event{ @@ -30,12 +34,6 @@ std::unique_ptr Riichi(std::unique_ptr state) { .decision = false, // decision }); - Hand& player = state->players[state->currentPlayer]; - player.riichiRound = state->turnNum; - player.riichiPieceDiscard = player.discards_count; - player.riichi = true; - state->riichiSticks++; - state->nextState = StateFunctionType::kDiscard; return state; } diff --git a/src/statefunctions/gamestates/ron.cc b/src/statefunctions/gamestates/ron.cc index 62ab5d31..8e9d5be6 100644 --- a/src/statefunctions/gamestates/ron.cc +++ b/src/statefunctions/gamestates/ron.cc @@ -15,16 +15,17 @@ namespace mahjong { namespace { std::unique_ptr Ron(std::unique_ptr state) { - Hand& caller_player = state->players[state->lastCaller]; - caller_player.live[caller_player.live_count++] = state->pendingPiece; - - std::array basic_points = {}; - Hand& curr_player = state->players[state->currentPlayer]; - if (curr_player.riichi && - curr_player.discards_count == curr_player.riichiPieceDiscard) { + if (Hand& player = state->players[state->currentPlayer]; + player.riichi && player.discards_count == player.riichiPieceDiscard) { state->riichiSticks--; - curr_player.riichi = false; + player.riichi = false; } + + state->players[state->lastCaller] + .live[state->players[state->lastCaller].live_count++] = + state->pendingPiece; + + std::array basic_points = {}; for (Hand& player : state->players) { if (player.hasRonned) { AlertPlayers(*state, Event{ @@ -34,7 +35,7 @@ std::unique_ptr Ron(std::unique_ptr state) { state->pendingPiece.toUint8_t()), // piece .decision = false, // decision }); - basic_points.at(player.id) = getBasicPoints(scorePlayer(*state, player)); + basic_points.at(player.id) = getBasicPoints(scoreHand(*state, player)); } if (player.riichi) { player.score -= 1000; @@ -67,7 +68,7 @@ std::unique_ptr Ron(std::unique_ptr state) { state->players[state->currentPlayer].score -= payment; - if (state->players.at(state->roundNum % 4).hasRonned) { + if (state->players[state->roundNum % 4].hasRonned) { state->counters++; } else { state->roundNum++; @@ -76,7 +77,7 @@ std::unique_ptr Ron(std::unique_ptr state) { bool allzeros = true; for (int i = 0; i < 4; i++) { - if (state->players.at(i).score != 0) { + if (state->players[i].score != 0) { allzeros = false; } } diff --git a/src/statefunctions/gamestates/roundend.cc b/src/statefunctions/gamestates/roundend.cc index 03e42b28..21977747 100644 --- a/src/statefunctions/gamestates/roundend.cc +++ b/src/statefunctions/gamestates/roundend.cc @@ -31,14 +31,13 @@ std::unique_ptr RoundEnd(std::unique_ptr state) { if (state->roundNum > last_round && state->riichiSticks > 0) { std::vector winners; int highscore = -100000; - for (int i = 0; i < 4; i++) { - if (state->players[i].points + state->players.at(i).score > highscore) { - highscore = state->players[i].points + state->players.at(i).score; + for (const Hand& player : state->players) { + if (player.points + player.score > highscore) { + highscore = player.points + player.score; winners.clear(); - winners.push_back(i); - } else if (state->players[i].points + state->players.at(i).score == - highscore) { - winners.push_back(i); + winners.push_back(player.id); + } else if (player.points + player.score == highscore) { + winners.push_back(player.id); } } for (const auto& winner : winners) { @@ -48,15 +47,14 @@ std::unique_ptr RoundEnd(std::unique_ptr state) { } // TODO(#17): Scoring - for (int i = 0; i < 4; i++) { - AlertPlayers( - *state, - Event{.type = Event::kPointDiff, - .player = i, - .piece = static_cast(state->players.at(i).score / 100), - .decision = false}); - state->players[i].points += state->players.at(i).score; - state->players[i].score = 0; + for (Hand& player : state->players) { + AlertPlayers(*state, + Event{.type = Event::kPointDiff, + .player = player.id, + .piece = static_cast(player.score / 100), + .decision = false}); + player.points += player.score; + player.score = 0; } // TODO (#14): for now naively increment the round number diff --git a/src/statefunctions/gamestates/roundstart.cc b/src/statefunctions/gamestates/roundstart.cc index ffbdd7a8..0a44c3de 100644 --- a/src/statefunctions/gamestates/roundstart.cc +++ b/src/statefunctions/gamestates/roundstart.cc @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -9,6 +8,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/statefunction.h" #include "types/walls.h" #include "types/winds.h" @@ -18,13 +18,13 @@ namespace mahjong { namespace { std::unique_ptr RoundStart(std::unique_ptr state) { Walls::New(*state); - for (size_t i = 0; i < 4; i++) { + for (Hand& player : state->players) { auto hand = Walls::TakeHand(*state); - state->controllers.at(i)->RoundStart( - hand, static_cast((i + 3 * (state->roundNum % 4)) % 4), + state->controllers.at(player.id)->RoundStart( + hand, static_cast((player.id + 3 * (state->roundNum % 4)) % 4), (state->roundNum > 3) ? kSouth : kEast); - state->players[i].live_count = hand.size(); - std::ranges::move(hand, state->players[i].live.begin()); + player.live_count = hand.size(); + std::ranges::move(hand, player.live.begin()); } AlertPlayers(*state, diff --git a/src/statefunctions/gamestates/tsumo.cc b/src/statefunctions/gamestates/tsumo.cc index 30e6d4c9..e404f3e3 100644 --- a/src/statefunctions/gamestates/tsumo.cc +++ b/src/statefunctions/gamestates/tsumo.cc @@ -7,6 +7,7 @@ #include "statefunctions/stateutilities.h" #include "types/event.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/piecetype.h" #include "types/statefunction.h" @@ -21,22 +22,23 @@ std::unique_ptr Tsumo(std::unique_ptr state) { state->pendingPiece.toUint8_t()), // piece .decision = false, // decision }); - const int basic_points = - getBasicPoints(scorePlayer(*state, state->players[state->currentPlayer])); - state->players[state->currentPlayer].score += state->riichiSticks * 1000; + + Hand& winning_player = state->players[state->currentPlayer]; + const int basic_points = getBasicPoints(scoreHand(*state, winning_player)); + winning_player.score += state->riichiSticks * 1000; state->riichiSticks = 0; - state->players[state->currentPlayer].score += state->counters * 300; + winning_player.score += state->counters * 300; - for (int i = 0; i < 4; i++) { - if (i == state->currentPlayer) { - if (state->players.at(state->currentPlayer).riichi) { - state->players.at(i).score -= 1000; + for (Hand& player : state->players) { + if (player.id == winning_player.id) { + if (player.riichi) { + player.score -= 1000; } continue; } int amount = 0; if (state->currentPlayer == state->roundNum % 4 || - i == state->roundNum % 4) { + player.id == state->roundNum % 4) { amount = 2 * basic_points; } else { amount = basic_points; @@ -44,12 +46,12 @@ std::unique_ptr Tsumo(std::unique_ptr state) { if ((amount % 100) != 0) { amount = amount + (100 - (amount % 100)); } - state->players.at(i).score -= amount; - state->players.at(i).score -= state->counters * 100; - if (state->players.at(i).riichi) { - state->players.at(i).score -= 1000; + player.score -= amount; + player.score -= state->counters * 100; + if (player.riichi) { + player.score -= 1000; } - state->players[state->currentPlayer].score += amount; + winning_player.score += amount; } if (state->currentPlayer == state->roundNum % 4) { diff --git a/src/statefunctions/statecontroller.cc b/src/statefunctions/statecontroller.cc index 8acd112b..b4f3d559 100644 --- a/src/statefunctions/statecontroller.cc +++ b/src/statefunctions/statecontroller.cc @@ -42,8 +42,8 @@ void ExitGame(int game) { std::unique_ptr InitGameState(const GameSettings& settings) { auto state = std::make_unique(); for (int i = 0; i < 4; i++) { - state->controllers.at(i) = ControllerManager::Instance().NewController( - settings.seatControllers.at(i)); + state->controllers[i] = ControllerManager::Instance().NewController( + settings.seatControllers[i]); } if (settings.seed != 0U) { state->seed = settings.seed; diff --git a/src/statefunctions/stateutilities.cc b/src/statefunctions/stateutilities.cc index b09314ed..1a261d2e 100644 --- a/src/statefunctions/stateutilities.cc +++ b/src/statefunctions/stateutilities.cc @@ -57,7 +57,7 @@ void DiscardPiece(Hand& player, Piece p) { } Piece AskForDiscard(const GameState& state) { - state.controllers.at(state.currentPlayer) + state.controllers[state.currentPlayer] ->ReceiveEvent(Event{ .type = Event::kDiscard, // type .player = state.currentPlayer, // player @@ -66,23 +66,23 @@ Piece AskForDiscard(const GameState& state) { }); return Piece(GetValidDecisionOrThrow( - state, state.players[state.currentPlayer], /*inPlayer=*/true) + state, state.players[state.currentPlayer], /*inHand=*/true) .piece); } Event GetValidDecisionOrThrow(const GameState& state, const Hand& player, - bool inPlayer) { + bool inHand) { Event decision; bool valid = false; int i = 0; while (!valid) { if (i > 100) { Event replacement_decision = decision; - replacement_decision.type = inPlayer ? Event::kDiscard : Event::kDecline; - if (inPlayer) { + replacement_decision.type = inHand ? Event::kDiscard : Event::kDecline; + if (inHand) { replacement_decision.piece = player.live_range().back().toUint8_t(); } - if (ValidateDecision(state, player, replacement_decision, inPlayer)) { + if (ValidateDecision(state, player, replacement_decision, inHand)) { return replacement_decision; } std::cerr @@ -90,26 +90,26 @@ Event GetValidDecisionOrThrow(const GameState& state, const Hand& player, << '\n'; std::cerr << "Decision.type: " << decision.type << " Decision.piece " << decision.piece << " player: " << player.id - << " inPlayer: " << (inPlayer ? "true" : "false") << '\n'; + << " inHand: " << (inHand ? "true" : "false") << '\n'; std::cerr << "ERROR: was not able to recover from invalid event." << '\n'; throw 0xBAD22222; } i++; - decision = state.controllers.at(player.id)->RetrieveDecision(); - valid = ValidateDecision(state, player, decision, inPlayer); + decision = state.controllers[player.id]->RetrieveDecision(); + valid = ValidateDecision(state, player, decision, inHand); } return decision; } bool ValidateDecision(const GameState& state, const Hand& player, - Event decision, bool inPlayer) { + Event decision, bool inHand) { if (decision.type > Event::kDiscard) { return false; } - if (decision.type > Event::kDecline && !inPlayer) { + if (decision.type > Event::kDecline && !inHand) { return false; } - if (decision.type < Event::kTsumo && inPlayer) { + if (decision.type < Event::kTsumo && inHand) { return false; } switch (decision.type) { diff --git a/src/statefunctions/stateutilities.h b/src/statefunctions/stateutilities.h index a0072e2f..9e605527 100644 --- a/src/statefunctions/stateutilities.h +++ b/src/statefunctions/stateutilities.h @@ -19,8 +19,8 @@ void AlertPlayers(const GameState& state, Event e); Piece AskForDiscard(const GameState& state); uint8_t CountPieces(const Hand& player, Piece p); bool ValidateDecision(const GameState& state, const Hand& player, - Event decision, bool inPlayer); + Event decision, bool inHand); Event GetValidDecisionOrThrow(const GameState& state, const Hand& player, - bool inPlayer); + bool inHand); } // namespace mahjong diff --git a/src/types/gamestate.h b/src/types/gamestate.h index 72dfd235..c4bc57a0 100644 --- a/src/types/gamestate.h +++ b/src/types/gamestate.h @@ -6,7 +6,6 @@ #include "controllers/playercontroller.h" #include "types/hand.h" -#include "types/meld.h" #include "types/piecetype.h" #include "types/settings.h" #include "types/statefunction.h" diff --git a/src/types/statefunction.h b/src/types/statefunction.h index bc16490c..2adefdf4 100644 --- a/src/types/statefunction.h +++ b/src/types/statefunction.h @@ -13,7 +13,7 @@ enum class StateFunctionType { kGameStart, kRoundStart, kDraw, - kPlayerPlayer, + kPlayerHand, kPon, kChi, kKan, diff --git a/src/types/typeprinter.cc b/src/types/typeprinter.cc index 18c98f12..387d4243 100644 --- a/src/types/typeprinter.cc +++ b/src/types/typeprinter.cc @@ -63,28 +63,28 @@ std::ostream& operator<<(std::ostream& os, const mahjong::GameState& state) { return os; } -std::ostream& operator<<(std::ostream& os, const mahjong::Hand& player) { - os << "{ open: " << player.open; - os << " riichi: " << player.riichi; - os << " riichiPieceDiscard: " << player.riichiPieceDiscard; - os << " riichiRound: " << player.riichiRound; +std::ostream& operator<<(std::ostream& os, const mahjong::Hand& hand) { + os << "{ open: " << hand.open; + os << " riichi: " << hand.riichi; + os << " riichiPieceDiscard: " << hand.riichiPieceDiscard; + os << " riichiRound: " << hand.riichiRound; os << " live: [" << '\n'; os << "hasRonned: " << '\n'; - os << "hasRonned: {" << player.hasRonned << "}" << '\n'; - os << " points: " << player.points; - for (const auto& piece : player.live_range()) { + os << "hasRonned: {" << hand.hasRonned << "}" << '\n'; + os << " points: " << hand.points; + for (const auto& piece : hand.live_range()) { os << piece.toStr() << ", "; } os << "]" << '\n'; os << "melds: [" << '\n'; - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { os << "{ type: " << meld.typeToStr(); os << ", start: " << meld.start.toStr() << "}"; os << ", "; } os << "]" << '\n'; os << "discards: [" << '\n'; - for (const auto& piece : player.discards) { + for (const auto& piece : hand.discards) { os << piece.toStr() << ", "; } os << "]" << '\n'; diff --git a/src/types/typeprinter.h b/src/types/typeprinter.h index 8208f340..820e8f80 100644 --- a/src/types/typeprinter.h +++ b/src/types/typeprinter.h @@ -5,18 +5,17 @@ namespace mahjong { struct Event; struct GameState; -struct Player; +struct Hand; class Node; struct Meld; class Walls; -struct Hand; } // namespace mahjong std::ostream& operator<<(std::ostream& os, const mahjong::Event& e); std::ostream& operator<<(std::ostream& os, const mahjong::GameState& state); -std::ostream& operator<<(std::ostream& os, const mahjong::Hand& player); +std::ostream& operator<<(std::ostream& os, const mahjong::Hand& hand); std::ostream& operator<<(std::ostream& os, const mahjong::Node& node); diff --git a/tests/api/game_control.test.cc b/tests/api/game_control.test.cc index 1c0c6794..e769df5e 100644 --- a/tests/api/game_control.test.cc +++ b/tests/api/game_control.test.cc @@ -130,7 +130,7 @@ TEST(Api, ObserveGameStateAfterAdvancement) { api::FreeGameState(state); } -TEST(Api, ObserveGameStatePlayersAndDiscards) { +TEST(Api, ObserveGameStateHandsAndDiscards) { const api::CGameSettings settings = kDefaultSettings; mahjong::GameState* state = api::InitGameState(&settings); @@ -144,47 +144,46 @@ TEST(Api, ObserveGameStatePlayersAndDiscards) { // Check that hands are copied (after round start, players should have hands) for (int player = 0; player < 4; player++) { - const api::CPlayer& c_player = observed.hands[player]; - const mahjong::Hand& cpp_player = state->players[player]; + const api::CHand& c_hand = observed.hands[player]; + const mahjong::Hand& cpp_hand = state->players[player]; // Check live pieces - EXPECT_EQ(c_player.livePieceCount, static_cast(cpp_player.live_count)); - for (int piece = 0; piece < api::kMaxLivePlayerSize; piece++) { - if (piece < c_player.livePieceCount) { - EXPECT_EQ(c_player.livePieces[piece], - static_cast(cpp_player.live[piece].toUint8_t())); + EXPECT_EQ(c_hand.livePieceCount, static_cast(cpp_hand.live_count)); + for (int piece = 0; piece < api::kMaxLiveHandSize; piece++) { + if (piece < c_hand.livePieceCount) { + EXPECT_EQ(c_hand.livePieces[piece], + static_cast(cpp_hand.live[piece].toUint8_t())); } else { // Should be filled with error pieces - EXPECT_EQ(c_player.livePieces[piece], + EXPECT_EQ(c_hand.livePieces[piece], static_cast(mahjong::Piece::Type::kError)); } } // Check melds - EXPECT_EQ(c_player.meldCount, cpp_player.meld_count); - for (int meld = 0; meld < c_player.meldCount; meld++) { - EXPECT_EQ(static_cast(c_player.melds[meld].type), - static_cast(cpp_player.melds[meld].type)); + EXPECT_EQ(c_hand.meldCount, cpp_hand.meld_count); + for (int meld = 0; meld < c_hand.meldCount; meld++) { + EXPECT_EQ(static_cast(c_hand.melds[meld].type), + static_cast(cpp_hand.melds[meld].type)); EXPECT_EQ( - c_player.melds[meld].start, - static_cast(cpp_player.melds[meld].start.toUint8_t())); + c_hand.melds[meld].start, + static_cast(cpp_hand.melds[meld].start.toUint8_t())); } - // Check discards using CPlayer structure - EXPECT_EQ(c_player.discardCount, - static_cast(cpp_player.discards_count)); - for (int discard = 0; discard < c_player.discardCount; discard++) { + // Check discards using CHand structure + EXPECT_EQ(c_hand.discardCount, static_cast(cpp_hand.discards_count)); + for (int discard = 0; discard < c_hand.discardCount; discard++) { EXPECT_EQ( - c_player.discards[discard], - static_cast(cpp_player.discards[discard].toUint8_t())); + c_hand.discards[discard], + static_cast(cpp_hand.discards[discard].toUint8_t())); } // Check hand properties - EXPECT_EQ(c_player.open, cpp_player.open); - EXPECT_EQ(c_player.riichi, cpp_player.riichi); - EXPECT_EQ(c_player.riichiPieceDiscard, - static_cast(cpp_player.riichiPieceDiscard)); - EXPECT_EQ(c_player.riichiRound, cpp_player.riichiRound); + EXPECT_EQ(c_hand.open, cpp_hand.open); + EXPECT_EQ(c_hand.riichi, cpp_hand.riichi); + EXPECT_EQ(c_hand.riichiPieceDiscard, + static_cast(cpp_hand.riichiPieceDiscard)); + EXPECT_EQ(c_hand.riichiRound, cpp_hand.riichiRound); } api::FreeGameState(state); diff --git a/tests/can_chi.test.cc b/tests/can_chi.test.cc index d02fbbb7..e9e94af0 100644 --- a/tests/can_chi.test.cc +++ b/tests/can_chi.test.cc @@ -4,6 +4,7 @@ #include "statefunctions/decisionfunction.h" #include "types/gamestate.h" +#include "types/hand.h" #include "types/pieces.h" #include "types/piecetype.h" @@ -13,34 +14,37 @@ TEST(CanChi, EastShouldChiOnNorth) { GameState state; state.pendingPiece = kOneCharacter; state.currentPlayer = 3; - state.players[0].live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; - state.players[0].live_count = 3; - EXPECT_TRUE(CanChi(state, state.players[0])); + Hand& player = state.players[0]; + player.live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; + player.live_count = 3; + EXPECT_TRUE(CanChi(state, player)); state.pendingPiece = kTwoCharacter; - EXPECT_TRUE(CanChi(state, state.players[0])); + EXPECT_TRUE(CanChi(state, player)); state.pendingPiece = kThreeCharacter; - EXPECT_TRUE(CanChi(state, state.players[0])); + EXPECT_TRUE(CanChi(state, player)); state.pendingPiece = kFourCharacter; - EXPECT_TRUE(CanChi(state, state.players[0])); + EXPECT_TRUE(CanChi(state, player)); } TEST(CanChi, EastShouldNotChiOnSouth) { GameState state; state.pendingPiece = kOneCharacter; state.currentPlayer = 1; - state.players[0].live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; - state.players[0].live_count = 3; - EXPECT_FALSE(CanChi(state, state.players[0])); + Hand& player = state.players[0]; + player.live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; + player.live_count = 3; + EXPECT_FALSE(CanChi(state, player)); } TEST(CanChi, NoChiOnHonor) { GameState state; state.pendingPiece = kOneCharacter; state.currentPlayer = 3; - state.players[0].live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; - state.players[0].live_count = 3; + Hand& player = state.players[0]; + player.live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; + player.live_count = 3; state.pendingPiece = kWhiteDragon; - EXPECT_FALSE(CanChi(state, state.players[0])); + EXPECT_FALSE(CanChi(state, player)); } } // namespace mahjong diff --git a/tests/rules/basic_rules.test.cc b/tests/rules/basic_rules.test.cc index aa06d154..f54cf447 100644 --- a/tests/rules/basic_rules.test.cc +++ b/tests/rules/basic_rules.test.cc @@ -33,7 +33,7 @@ TEST(GameSetup, playerScore) { } } -TEST(RoundSetup, playerPlayers) { +TEST(RoundSetup, playerHands) { auto state = CreateTestGameState(); // Advance through Round Start state = AdvanceThroughState(std::move(state), StateFunctionType::kRoundStart); @@ -86,7 +86,7 @@ TEST(TurnOrder, playerRotation) { EXPECT_EQ(state->turnNum, turn); state = AdvanceGameState(std::move(state)); - EXPECT_EQ(state->currState, StateFunctionType::kPlayerPlayer); + EXPECT_EQ(state->currState, StateFunctionType::kPlayerHand); state = AdvanceGameState(std::move(state)); EXPECT_EQ(state->currState, StateFunctionType::kDiscard); state = AdvanceGameState(std::move(state)); @@ -127,14 +127,14 @@ TEST(StateMachine, earlyGameTransitions) { // Advance through Round Start state = AdvanceThroughState(std::move(state), StateFunctionType::kRoundStart); - // Verify early game transitions (RoundStart -> Draw -> PlayerPlayer) + // Verify early game transitions (RoundStart -> Draw -> PlayerHand) // After round start, next state should be draw EXPECT_EQ(state->nextState, StateFunctionType::kDraw); state = AdvanceGameState(std::move(state)); EXPECT_EQ(state->currState, StateFunctionType::kDraw); // After draw, next state should be player hand - EXPECT_EQ(state->nextState, StateFunctionType::kPlayerPlayer); + EXPECT_EQ(state->nextState, StateFunctionType::kPlayerHand); } TEST(DiscardMechanics, discardDecreasesTileCount) { @@ -146,7 +146,7 @@ TEST(DiscardMechanics, discardDecreasesTileCount) { // Move through player hand to discard state = AdvanceGameState(std::move(state)); - EXPECT_EQ(state->currState, StateFunctionType::kPlayerPlayer); + EXPECT_EQ(state->currState, StateFunctionType::kPlayerHand); EXPECT_EQ(state->nextState, StateFunctionType::kDiscard); const int discards_before = state->players[0].discards_count; diff --git a/tests/utils/gamestate_utils.h b/tests/utils/gamestate_utils.h index c84611f2..7875aade 100644 --- a/tests/utils/gamestate_utils.h +++ b/tests/utils/gamestate_utils.h @@ -3,7 +3,6 @@ #include "controllers/playercontroller.h" #include "types/gamestate.h" -#include "types/hand.h" #include "types/settings.h" #include "types/statefunction.h" diff --git a/tests/utils/handformer.cc b/tests/utils/handformer.cc index cdcd136c..77b9389d 100644 --- a/tests/utils/handformer.cc +++ b/tests/utils/handformer.cc @@ -134,7 +134,7 @@ bool IsValidNotation(const std::string& notation) { return current_set.empty(); } -std::string PlayerToNotation(const std::vector& hand) { +std::string HandToNotation(const std::vector& hand) { std::map> suit_and_tiles; for (const auto& t : hand) { diff --git a/tests/utils/handformer.h b/tests/utils/handformer.h index 0f2f6290..6595f5bc 100644 --- a/tests/utils/handformer.h +++ b/tests/utils/handformer.h @@ -3,7 +3,6 @@ #include #include -#include "types/gamestate.h" #include "types/hand.h" #include "types/piecetype.h" @@ -12,6 +11,6 @@ namespace mahjong { std::vector HandFromNotation(const std::string& notation); void HandFromNotation(const std::string& notation, Hand* hand); bool IsValidNotation(const std::string& notation); -std::string PlayerToNotation(const std::vector& hand); +std::string HandToNotation(const std::vector& hand); } // namespace mahjong diff --git a/tests/utils/handformer.test.cc b/tests/utils/handformer.test.cc index 87b0afac..f1a88bf0 100644 --- a/tests/utils/handformer.test.cc +++ b/tests/utils/handformer.test.cc @@ -10,28 +10,28 @@ namespace mahjong { -TEST(PlayerFormer, HandFromNotationFormSet) { +TEST(HandFormer, HandFromNotationFormSet) { const std::vector hand = {Piece(kOneBamboo), Piece(kTwoBamboo), Piece(kThreeBamboo)}; auto result = HandFromNotation("123s"); EXPECT_EQ(result, hand); } -TEST(PlayerFormer, HandFromNotationFormWithManySuits) { +TEST(HandFormer, HandFromNotationFormWithManySuits) { const std::vector hand = {Piece(kOneBamboo), Piece(kTwoBamboo), Piece(kThreeBamboo), Piece(kFourCharacter)}; auto result = HandFromNotation("123s4m"); EXPECT_EQ(result, hand); } -TEST(PlayerFormer, HandFromNotationFormRedFives) { +TEST(HandFormer, HandFromNotationFormRedFives) { const std::vector hand = {Piece(kRedFiveCharacter), Piece(kRedFiveBamboo), Piece(kRedFivePin)}; auto result = HandFromNotation("0m0s0p"); EXPECT_EQ(result, hand); } -TEST(PlayerFormer, HandFromNotationFormHonors) { +TEST(HandFormer, HandFromNotationFormHonors) { const std::vector hand = {Piece(kEastWind), Piece(kSouthWind), Piece(kWestWind), Piece(kNorthWind), Piece(kWhiteDragon), Piece(kGreenDragon), @@ -40,7 +40,7 @@ TEST(PlayerFormer, HandFromNotationFormHonors) { EXPECT_EQ(result, hand); } -TEST(PlayerFormer, HandFromNotationFormTerminals) { +TEST(HandFormer, HandFromNotationFormTerminals) { const std::vector hand = {Piece(kOneCharacter), Piece(kNineCharacter), Piece(kOneBamboo), Piece(kNineBamboo), Piece(kOnePin), Piece(kNinePin)}; @@ -48,20 +48,20 @@ TEST(PlayerFormer, HandFromNotationFormTerminals) { EXPECT_EQ(result, hand); } -TEST(PlayerFormer, HandFromNotationInvalidPiece) { +TEST(HandFormer, HandFromNotationInvalidPiece) { const std::vector hand = {Piece(Piece::kError)}; auto result = HandFromNotation("7g"); EXPECT_EQ(result, hand); } -TEST(PlayerFormer, HandFromNotationInvalidPieceSet) { +TEST(HandFormer, HandFromNotationInvalidPieceSet) { const std::vector hand = {Piece(Piece::kError), Piece(Piece::kError), Piece(Piece::kError)}; auto result = HandFromNotation("799g"); EXPECT_EQ(result, hand); } -TEST(PlayerFormer, IsValidNotationWithValidNotations) { +TEST(HandFormer, IsValidNotationWithValidNotations) { EXPECT_TRUE(IsValidNotation("123s")); EXPECT_TRUE(IsValidNotation("123s456m")); EXPECT_TRUE(IsValidNotation("11z22z33z")); @@ -72,7 +72,7 @@ TEST(PlayerFormer, IsValidNotationWithValidNotations) { EXPECT_TRUE(IsValidNotation("")); } -TEST(PlayerFormer, IsValidNotationWithInvaildNotations) { +TEST(HandFormer, IsValidNotationWithInvaildNotations) { EXPECT_FALSE(IsValidNotation("123")); EXPECT_FALSE(IsValidNotation("123g456m")); EXPECT_FALSE(IsValidNotation("11z22z33")); @@ -80,35 +80,35 @@ TEST(PlayerFormer, IsValidNotationWithInvaildNotations) { EXPECT_FALSE(IsValidNotation("8z")); } -TEST(PlayerFormer, PlayerToNotationSingleSet) { +TEST(HandFormer, HandToNotationSingleSet) { const std::vector hand = {Piece(kOneBamboo), Piece(kTwoBamboo), Piece(kThreeBamboo)}; - EXPECT_EQ(PlayerToNotation(hand), "123s"); + EXPECT_EQ(HandToNotation(hand), "123s"); } -TEST(PlayerFormer, PlayerToNotationMultipleSets) { +TEST(HandFormer, HandToNotationMultipleSets) { const std::vector hand = { Piece(kOneBamboo), Piece(kTwoBamboo), Piece(kThreeBamboo), Piece(kFourPin), Piece(kFivePin), Piece(kSixPin), Piece(kNineCharacter), Piece(kEastWind), Piece(kWestWind), }; - EXPECT_EQ(PlayerToNotation(hand), "13z123s456p9m"); + EXPECT_EQ(HandToNotation(hand), "13z123s456p9m"); } -TEST(PlayerFormer, PlayerToNotationSkipsErrorPieces) { +TEST(HandFormer, HandToNotationSkipsErrorPieces) { const std::vector hand = { Piece(kOneBamboo), Piece(Piece::kError), Piece(kThreeBamboo), }; - EXPECT_EQ(PlayerToNotation(hand), "13s"); + EXPECT_EQ(HandToNotation(hand), "13s"); } -TEST(PlayerFormer, PlayerToNotationRedFives) { +TEST(HandFormer, HandToNotationRedFives) { const std::vector hand = { Piece(kFiveBamboo), Piece(kRedFiveBamboo), }; - EXPECT_EQ(PlayerToNotation(hand), "50s"); + EXPECT_EQ(HandToNotation(hand), "50s"); } } // namespace mahjong diff --git a/tests/yakus/allpon.test.cc b/tests/yakus/allpon.test.cc index 3d4baa5c..061f7be1 100644 --- a/tests/yakus/allpon.test.cc +++ b/tests/yakus/allpon.test.cc @@ -75,7 +75,7 @@ TEST(isAllPons, ConcealedKan) { FAIL(); } -TEST(isAllPons, BadPlayer) { +TEST(isAllPons, BadHand) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("111m222p666z789m44m", &player); diff --git a/tests/yakus/allsimples.test.cc b/tests/yakus/allsimples.test.cc index 6e8b7fd0..aa3b45b8 100644 --- a/tests/yakus/allsimples.test.cc +++ b/tests/yakus/allsimples.test.cc @@ -30,7 +30,7 @@ TEST(isAllSimples, 1Han) { FAIL(); } -TEST(isAllSimples, BadPlayerHonors) { +TEST(isAllSimples, BadHandHonors) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("222m333p444s111z88m", &player); @@ -46,7 +46,7 @@ TEST(isAllSimples, BadPlayerHonors) { SUCCEED(); } -TEST(isAllSimples, BadPlayerTerminals) { +TEST(isAllSimples, BadHandTerminals) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("222m333p444s111m88m", &player); diff --git a/tests/yakus/allterminalsandhonors.test.cc b/tests/yakus/allterminalsandhonors.test.cc index 39702784..d8bbadfb 100644 --- a/tests/yakus/allterminalsandhonors.test.cc +++ b/tests/yakus/allterminalsandhonors.test.cc @@ -35,7 +35,7 @@ TEST(isAllTerminalsAndHonors, 2Han) { FAIL(); } -TEST(isAllTerminalsAndHonors, BadPlayer) { +TEST(isAllTerminalsAndHonors, BadHand) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("222z111p111m888s66z", &player); diff --git a/tests/yakus/concealedpon.test.cc b/tests/yakus/concealedpon.test.cc index d9ad7357..88a31e08 100644 --- a/tests/yakus/concealedpon.test.cc +++ b/tests/yakus/concealedpon.test.cc @@ -95,7 +95,7 @@ TEST(isThreeConcealedPons, PonsMustBeConcealedNegative) { SUCCEED(); } -TEST(isThreeConcealedPons, BadPlayer) { +TEST(isThreeConcealedPons, BadHand) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("111m111p234567s44m", &player); diff --git a/tests/yakus/dragonpon.test.cc b/tests/yakus/dragonpon.test.cc index 219eb4e8..91bc7120 100644 --- a/tests/yakus/dragonpon.test.cc +++ b/tests/yakus/dragonpon.test.cc @@ -94,7 +94,7 @@ TEST(isWindOrDragonPon, CanWhenOpen) { FAIL(); } -TEST(isWindOrDragonPon, BadPlayer) { +TEST(isWindOrDragonPon, BadHand) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("123m456m222p11p", &player); diff --git a/tests/yakus/fullflush.test.cc b/tests/yakus/fullflush.test.cc index ddccadfb..ec5fd268 100644 --- a/tests/yakus/fullflush.test.cc +++ b/tests/yakus/fullflush.test.cc @@ -56,7 +56,7 @@ TEST(isFullFlush, 6Han) { FAIL(); } -TEST(isFullFlush, BadPlayerHonors) { +TEST(isFullFlush, BadHandHonors) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("111m222m111z666m99m", &player); @@ -73,7 +73,7 @@ TEST(isFullFlush, BadPlayerHonors) { SUCCEED(); } -TEST(isFullFlush, BadPlayerSuit) { +TEST(isFullFlush, BadHandSuit) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("111m222m111p666m99m", &player); @@ -90,7 +90,7 @@ TEST(isFullFlush, BadPlayerSuit) { SUCCEED(); } -TEST(isFullFlush, BadPlayerFullFlushHonors) { +TEST(isFullFlush, BadHandFullFlushHonors) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("111z222z333z444z55z", &player); diff --git a/tests/yakus/halfflush.test.cc b/tests/yakus/halfflush.test.cc index 3fd35257..af10b2b1 100644 --- a/tests/yakus/halfflush.test.cc +++ b/tests/yakus/halfflush.test.cc @@ -56,7 +56,7 @@ TEST(isHalfFlush, 3Han) { FAIL(); } -TEST(isHalfFlush, BadPlayer) { +TEST(isHalfFlush, BadHand) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("11m234m111p222z", &player); diff --git a/tests/yakus/littlethreedragons.test.cc b/tests/yakus/littlethreedragons.test.cc index 4a8bdb69..960fac9c 100644 --- a/tests/yakus/littlethreedragons.test.cc +++ b/tests/yakus/littlethreedragons.test.cc @@ -56,7 +56,7 @@ TEST(isLittleThreeDragons, WhenOpen) { FAIL(); } -TEST(isLittleThreeDragons, BadPlayer) { +TEST(isLittleThreeDragons, BadHand) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("666z111m222p77s", &player); diff --git a/tests/yakus/mixedtriplechi.test.cc b/tests/yakus/mixedtriplechi.test.cc index 473804ad..2a88dbe6 100644 --- a/tests/yakus/mixedtriplechi.test.cc +++ b/tests/yakus/mixedtriplechi.test.cc @@ -48,7 +48,7 @@ TEST(isMixedTripleChi, Closed) { FAIL(); } -TEST(isMixedTripleChi, BadPlayer) { +TEST(isMixedTripleChi, BadHand) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("123p123p123s555p11z", &player); diff --git a/tests/yakus/outsidehand.test.cc b/tests/yakus/outsidehand.test.cc index c2a914ab..720d7c04 100644 --- a/tests/yakus/outsidehand.test.cc +++ b/tests/yakus/outsidehand.test.cc @@ -64,7 +64,7 @@ TEST(isOutsideHand, NoChi) { SUCCEED(); } -TEST(isOutsideHand, BadPlayer) { +TEST(isOutsideHand, BadHand) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("111m234p111s999m66z", &player); diff --git a/tests/yakus/pinfu.test.cc b/tests/yakus/pinfu.test.cc index a1a2fe23..c1be1f59 100644 --- a/tests/yakus/pinfu.test.cc +++ b/tests/yakus/pinfu.test.cc @@ -34,7 +34,7 @@ TEST(isPinfu, 1Han) { FAIL(); } -TEST(isPinfu, BadPlayer) { +TEST(isPinfu, BadHand) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("123m555p234678s44m", &player); diff --git a/tests/yakus/puredoublechi.test.cc b/tests/yakus/puredoublechi.test.cc index 8117b892..437e4c8a 100644 --- a/tests/yakus/puredoublechi.test.cc +++ b/tests/yakus/puredoublechi.test.cc @@ -31,7 +31,7 @@ TEST(isPureDoubleChi, 1Han) { FAIL(); } -TEST(isPureDoubleChi, BadPlayer) { +TEST(isPureDoubleChi, BadHand) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("234m123m555p888s88p", &player); diff --git a/tests/yakus/purestraight.test.cc b/tests/yakus/purestraight.test.cc index e1ebf69d..c878a1c2 100644 --- a/tests/yakus/purestraight.test.cc +++ b/tests/yakus/purestraight.test.cc @@ -48,7 +48,7 @@ TEST(isPureStraight, Closed) { FAIL(); } -TEST(isPureStraight, BadPlayer) { +TEST(isPureStraight, BadHand) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("123m456m999m555p11z", &player); diff --git a/tests/yakus/terminalinsets.test.cc b/tests/yakus/terminalinsets.test.cc index bcf244fa..c00d4581 100644 --- a/tests/yakus/terminalinsets.test.cc +++ b/tests/yakus/terminalinsets.test.cc @@ -55,7 +55,7 @@ TEST(isTerminalsInAllSets, 3Han) { FAIL(); } -TEST(isTerminalsInAllSets, BadPlayer) { +TEST(isTerminalsInAllSets, BadHand) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("123m789m222p11s", &player); diff --git a/tests/yakus/triplekan.test.cc b/tests/yakus/triplekan.test.cc index d02ed76a..76971454 100644 --- a/tests/yakus/triplekan.test.cc +++ b/tests/yakus/triplekan.test.cc @@ -85,7 +85,7 @@ TEST(isThreeKans, WithOtherMelds) { FAIL(); } -TEST(isThreeKans, BadPlayer) { +TEST(isThreeKans, BadHand) { const Meld meld_a = { .type = SetType::kConcealedKan, .start = Piece(kOneBamboo), diff --git a/tests/yakus/triplepon.test.cc b/tests/yakus/triplepon.test.cc index 2fb594b8..08342f03 100644 --- a/tests/yakus/triplepon.test.cc +++ b/tests/yakus/triplepon.test.cc @@ -30,7 +30,7 @@ TEST(isTriplePon, 2Han) { FAIL(); } -TEST(isTriplePon, BadPlayer) { +TEST(isTriplePon, BadHand) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("111m111p222m666z44m", &player); diff --git a/tests/yakus/twicepuredoublechi.test.cc b/tests/yakus/twicepuredoublechi.test.cc index be530233..c95ae256 100644 --- a/tests/yakus/twicepuredoublechi.test.cc +++ b/tests/yakus/twicepuredoublechi.test.cc @@ -48,7 +48,7 @@ TEST(isTwicePureDoubleChi, MustBeConcealed) { SUCCEED(); } -TEST(isTwicePureDoubleChi, BadPlayer) { +TEST(isTwicePureDoubleChi, BadHand) { auto game_state = GameState(); Hand& player = game_state.players[0]; HandFromNotation("789p789p234m567m11z", &player); diff --git a/tools/driver/main.cc b/tools/driver/main.cc index 9721b8ff..46d7d1e0 100644 --- a/tools/driver/main.cc +++ b/tools/driver/main.cc @@ -79,8 +79,8 @@ int main() { // state->lastCall = 36; // state->pendingPiece = kNineCharacter; // state->roundNum = 2; - // state->players[0].live = {kNineCharacter,kNineCharacter,kNineCharacter,kOnePin,kTwoPin,kThreePin,kEastWind,kEastWind}; - // state->players[0].melds = { + // state->hands[0].live = {kNineCharacter,kNineCharacter,kNineCharacter,kOnePin,kTwoPin,kThreePin,kEastWind,kEastWind}; + // state->hands[0].melds = { // { // Meld::kChi, // kThreeBamboo From c1917b7b2a70b3b7e9f52f102f58ce2b947fff5e Mon Sep 17 00:00:00 2001 From: alice Date: Sun, 14 Sep 2025 15:29:24 -0700 Subject: [PATCH 14/14] rename player to hand. --- CMakeLists.txt | 28 ++++---- src/api/gamestate.cc | 8 +-- src/scoring/scoring.cc | 52 +++++++------- src/scoring/scoring.h | 8 +-- src/scoring/yakus/afterakan.cc | 4 +- src/scoring/yakus/afterakan.h | 2 +- src/scoring/yakus/allgreen.cc | 6 +- src/scoring/yakus/allgreen.h | 2 +- src/scoring/yakus/allhonors.cc | 6 +- src/scoring/yakus/allhonors.h | 2 +- src/scoring/yakus/allpons.cc | 4 +- src/scoring/yakus/allpons.h | 2 +- src/scoring/yakus/allsimples.cc | 6 +- src/scoring/yakus/allsimples.h | 2 +- src/scoring/yakus/allterminals.cc | 6 +- src/scoring/yakus/allterminals.h | 2 +- src/scoring/yakus/allterminalsandhonors.cc | 6 +- src/scoring/yakus/allterminalsandhonors.h | 2 +- src/scoring/yakus/bigfourwinds.cc | 4 +- src/scoring/yakus/bigfourwinds.h | 2 +- src/scoring/yakus/bigthreedragons.cc | 4 +- src/scoring/yakus/bigthreedragons.h | 2 +- src/scoring/yakus/blessingofearth.cc | 6 +- src/scoring/yakus/blessingofearth.h | 2 +- src/scoring/yakus/blessingofheaven.cc | 8 +-- src/scoring/yakus/blessingofheaven.h | 2 +- src/scoring/yakus/blessingofman.cc | 8 +-- src/scoring/yakus/blessingofman.h | 2 +- src/scoring/yakus/bottomofthesea.cc | 2 +- src/scoring/yakus/bottomofthesea.h | 2 +- src/scoring/yakus/doubleriichi.cc | 5 +- src/scoring/yakus/doubleriichi.h | 2 +- src/scoring/yakus/fourconcealedpon.cc | 6 +- src/scoring/yakus/fourconcealedpon.h | 2 +- src/scoring/yakus/fourkans.cc | 4 +- src/scoring/yakus/fourkans.h | 2 +- src/scoring/yakus/fullflush.cc | 10 +-- src/scoring/yakus/fullflush.h | 2 +- src/scoring/yakus/fullyconcealedhand.cc | 4 +- src/scoring/yakus/fullyconcealedhand.h | 2 +- src/scoring/yakus/halfflush.cc | 10 +-- src/scoring/yakus/halfflush.h | 2 +- src/scoring/yakus/honorpon.cc | 26 +++---- src/scoring/yakus/honorpon.h | 10 +-- src/scoring/yakus/ippatsu.cc | 8 +-- src/scoring/yakus/ippatsu.h | 2 +- src/scoring/yakus/littlefourwinds.cc | 4 +- src/scoring/yakus/littlefourwinds.h | 2 +- src/scoring/yakus/littlethreedragons.cc | 4 +- src/scoring/yakus/littlethreedragons.h | 2 +- src/scoring/yakus/maxbranches.cc | 10 +-- src/scoring/yakus/maxbranches.h | 2 +- src/scoring/yakus/mixedtriplechi.cc | 4 +- src/scoring/yakus/mixedtriplechi.h | 2 +- src/scoring/yakus/ninegates.cc | 10 +-- src/scoring/yakus/ninegates.h | 2 +- src/scoring/yakus/outsidehand.cc | 8 +-- src/scoring/yakus/outsidehand.h | 2 +- src/scoring/yakus/pinfu.cc | 8 +-- src/scoring/yakus/pinfu.h | 2 +- src/scoring/yakus/puredoublechi.cc | 6 +- src/scoring/yakus/puredoublechi.h | 2 +- src/scoring/yakus/purestraight.cc | 4 +- src/scoring/yakus/purestraight.h | 2 +- src/scoring/yakus/riichi.cc | 5 +- src/scoring/yakus/riichi.h | 2 +- src/scoring/yakus/robbingakan.cc | 4 +- src/scoring/yakus/robbingakan.h | 2 +- src/scoring/yakus/sevenpairs.cc | 4 +- src/scoring/yakus/sevenpairs.h | 2 +- src/scoring/yakus/terminalsinallsets.cc | 4 +- src/scoring/yakus/terminalsinallsets.h | 2 +- src/scoring/yakus/thirteenorphans.cc | 6 +- src/scoring/yakus/thirteenorphans.h | 2 +- src/scoring/yakus/threeconcealedpons.cc | 4 +- src/scoring/yakus/threeconcealedpons.h | 2 +- src/scoring/yakus/threekans.cc | 4 +- src/scoring/yakus/threekans.h | 2 +- src/scoring/yakus/triplepon.cc | 4 +- src/scoring/yakus/triplepon.h | 2 +- src/scoring/yakus/twicepuredoublechi.cc | 4 +- src/scoring/yakus/twicepuredoublechi.h | 2 +- src/statefunctions/decisionfunction.cc | 71 +++++++++--------- src/statefunctions/decisionfunction.h | 18 ++--- src/statefunctions/gamestates/chi.cc | 16 ++--- src/statefunctions/gamestates/concealedkan.cc | 6 +- src/statefunctions/gamestates/convertedkan.cc | 8 +-- src/statefunctions/gamestates/discard.cc | 22 +++--- src/statefunctions/gamestates/draw.cc | 4 +- src/statefunctions/gamestates/exhaust.cc | 14 ++-- src/statefunctions/gamestates/gamestart.cc | 8 +-- src/statefunctions/gamestates/kan.cc | 14 ++-- src/statefunctions/gamestates/kandiscard.cc | 16 ++--- src/statefunctions/gamestates/playerhand.cc | 10 +-- src/statefunctions/gamestates/pon.cc | 14 ++-- src/statefunctions/gamestates/replacement.cc | 4 +- src/statefunctions/gamestates/riichi.cc | 10 +-- src/statefunctions/gamestates/ron.cc | 47 ++++++------ src/statefunctions/gamestates/roundend.cc | 33 +++++---- src/statefunctions/gamestates/roundstart.cc | 12 ++-- src/statefunctions/gamestates/tsumo.cc | 28 ++++---- src/statefunctions/stateutilities.cc | 69 +++++++++--------- src/statefunctions/stateutilities.h | 12 ++-- src/types/gamestate.h | 2 +- src/types/typeprinter.cc | 4 +- tests/api/game_control.test.cc | 10 +-- tests/can_chi.test.cc | 30 ++++---- tests/count_pieces.test.cc | 14 ++-- tests/discard_piece.test.cc | 23 +++--- tests/game_play.test.cc | 12 ++-- tests/remove_pieces.test.cc | 40 +++++------ tests/rules/basic_rules.test.cc | 20 +++--- tests/rules/calls.test.cc | 16 ++--- tests/setup.test.cc | 2 +- tests/utils/gamestate_utils.test.cc | 4 +- tests/yakus/afterkan.test.cc | 24 +++---- tests/yakus/allpon.test.cc | 42 +++++------ tests/yakus/allsimples.test.cc | 24 +++---- tests/yakus/allterminalsandhonors.test.cc | 32 ++++----- tests/yakus/blessingofman.test.cc | 50 ++++++------- tests/yakus/concealedhand.test.cc | 32 ++++----- tests/yakus/concealedpon.test.cc | 56 +++++++-------- tests/yakus/dragonpon.test.cc | 50 ++++++------- tests/yakus/fullflush.test.cc | 52 +++++++------- tests/yakus/halfflush.test.cc | 46 ++++++------ tests/yakus/littlethreedragons.test.cc | 34 ++++----- tests/yakus/mixedtriplechi.test.cc | 30 ++++---- tests/yakus/outsidehand.test.cc | 36 +++++----- tests/yakus/pinfu.test.cc | 40 +++++------ tests/yakus/puredoublechi.test.cc | 30 ++++---- tests/yakus/purestraight.test.cc | 30 ++++---- tests/yakus/riichi.test.cc | 38 +++++----- tests/yakus/robbingkan.test.cc | 20 +++--- tests/yakus/sevenpairs.test.cc | 30 ++++---- tests/yakus/terminalinsets.test.cc | 36 +++++----- tests/yakus/triplekan.test.cc | 56 +++++++-------- tests/yakus/triplepon.test.cc | 16 ++--- tests/yakus/twicepuredoublechi.test.cc | 30 ++++---- tests/yakus/underthesea.test.cc | 26 +++---- tests/yakus/windpons.test.cc | 72 +++++++++---------- 140 files changed, 979 insertions(+), 988 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1db40fb1..d35b4f52 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,19 +94,17 @@ if(libmahjong_build_tests) add_subdirectory(tests) endif() -if(libmahjong_use_clang_utils) - find_program(clang_format_path NAMES clang-format) - if(clang_format_path) - set(clang_format_flags -i) - get_target_property(libmahjong_sources libmahjong SOURCES) - get_target_property(libmahjong_includes libmahjong HEADER_SET) - set(format_files ${libmahjong_sources} ${libmahjong_includes} - ${test_sources} ${tool_sources}) - add_custom_target( - format - COMMAND ${clang_format_path} ${clang_format_flags} ${format_files} - WORKING_DIRECTORY ${libmahjong_SOURCE_DIR} - VERBATIM) - set_target_properties(format PROPERTIES FOLDER code_utils) - endif() +find_program(clang_format_path NAMES clang-format) +if(clang_format_path) + set(clang_format_flags -i) + get_target_property(libmahjong_sources libmahjong SOURCES) + get_target_property(libmahjong_includes libmahjong HEADER_SET) + set(format_files ${libmahjong_sources} ${libmahjong_includes} ${test_sources} + ${tool_sources}) + add_custom_target( + format + COMMAND ${clang_format_path} ${clang_format_flags} ${format_files} + WORKING_DIRECTORY ${libmahjong_SOURCE_DIR} + VERBATIM) + set_target_properties(format PROPERTIES FOLDER code_utils) endif() diff --git a/src/api/gamestate.cc b/src/api/gamestate.cc index 87917934..b4966d0b 100644 --- a/src/api/gamestate.cc +++ b/src/api/gamestate.cc @@ -141,12 +141,12 @@ CObservedGameState ObserveGameState(mahjong::GameState* state) { // Player data for (int i = 0; i < 4; i++) { - observed.scores[i] = state->players[i].score; - observed.points[i] = state->players[i].points; - observed.hasRonned[i] = state->players[i].hasRonned; + observed.scores[i] = state->hands[i].score; + observed.points[i] = state->hands[i].points; + observed.hasRonned[i] = state->hands[i].hasRonned; // Convert Hand to CHand - const auto& cpp_hand = state->players[i]; + const auto& cpp_hand = state->hands[i]; CHand& c_hand = observed.hands[i]; // Live pieces diff --git a/src/scoring/scoring.cc b/src/scoring/scoring.cc index 137d5819..3e9343cd 100644 --- a/src/scoring/scoring.cc +++ b/src/scoring/scoring.cc @@ -59,13 +59,13 @@ const int kFuRounding = 10; } // namespace -Score scoreHand(const GameState& state, const Hand& player) { - auto root = breakdownHand(player.live_range()); +Score scoreHand(const GameState& state, const Hand& hand) { + auto root = breakdownHand(hand.live_range()); Score s; s.han = 0; s.yakuman = 0; s.fu = 0; - if (!root->IsComplete() && !yaku::isThirteenOrphans(state, player)) { + if (!root->IsComplete() && !yaku::isThirteenOrphans(state, hand)) { return s; } for (const auto& branch : Node::AsBranchVectors(root.get())) { @@ -77,10 +77,10 @@ Score scoreHand(const GameState& state, const Hand& player) { } for (const auto& yaku : Yakus::Instance().GetYakus()) { - if (yaku.type == Yaku::kClosed && player.open) { + if (yaku.type == Yaku::kClosed && hand.open) { continue; } - if (!yaku.is_yaku_func(state, player, branch)) { + if (!yaku.is_yaku_func(state, hand, branch)) { continue; } switch (yaku.type) { @@ -89,7 +89,7 @@ Score scoreHand(const GameState& state, const Hand& player) { branchscore.han += yaku.value; break; case Yaku::kBonusWhenClosed: - branchscore.han += yaku.value + (player.open ? 0 : 1); + branchscore.han += yaku.value + (hand.open ? 0 : 1); break; case Yaku::kYakuman: branchscore.yakuman++; @@ -98,12 +98,12 @@ Score scoreHand(const GameState& state, const Hand& player) { } for (const auto& dora : Walls::GetDoras(state)) { - for (const auto& p : player.live_range()) { + for (const auto& p : hand.live_range()) { if (p == dora) { branchscore.han++; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.start == dora) { branchscore.han++; } @@ -117,7 +117,7 @@ Score scoreHand(const GameState& state, const Hand& player) { } } } - branchscore.fu = getFu(state, player, branch); + branchscore.fu = getFu(state, hand, branch); if (getBasicPoints(branchscore) > getBasicPoints(s)) { s = branchscore; } @@ -156,30 +156,30 @@ int getBasicPoints(Score s) { const int kSevenpairs = 25; -int getFu(const GameState& state, const Hand& player, +int getFu(const GameState& state, const Hand& hand, const std::vector& branch) { - if (yaku::isSevenPairs(state, player, branch)) { + if (yaku::isSevenPairs(state, hand, branch)) { return kSevenpairs; } - if (yaku::isPinfu(state, player, branch)) { - if (player.hasRonned) { + if (yaku::isPinfu(state, hand, branch)) { + if (hand.hasRonned) { return kPinfuDiscard; } return kPinfuSelfdraw; } int fu = 0; - if (!player.open && player.hasRonned) { + if (!hand.open && hand.hasRonned) { fu = kConcealedDiscard; } else { fu = kOpenOrSelfdraw; } - const bool open = player.open; - if (isOpenPinfu(state, player, branch)) { + const bool open = hand.open; + if (isOpenPinfu(state, hand, branch)) { fu += kOpenpinfu; - } else if (!player.hasRonned) { + } else if (!hand.hasRonned) { fu += kSelfdraw; } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.type == SetType::kKan) { if (!meld.start.isHonor() && !meld.start.isTerminal()) { fu += open ? kSimplekan : kCsimplekan; @@ -233,7 +233,7 @@ int getFu(const GameState& state, const Hand& player, (kFuRounding - (fu % kFuRounding)); // rounding up to multiple of ten } -bool isOpenPinfu(const GameState& state, const Hand& player, +bool isOpenPinfu(const GameState& state, const Hand& hand, const std::vector& branch) { for (const auto* node : branch) { if (node->type() == SetType::kPon) { @@ -252,17 +252,17 @@ bool isOpenPinfu(const GameState& state, const Hand& player, } } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.type > SetType::kChi) { return false; } } - return getWaits(player, state.pendingPiece).size() >= 2; + return getWaits(hand, state.pendingPiece).size() >= 2; } -bool isComplete(const GameState& state, const Hand& player) { - auto root = breakdownHand(player.live_range()); - if (!root->IsComplete() && !yaku::isThirteenOrphans(state, player)) { +bool isComplete(const GameState& state, const Hand& hand) { + auto root = breakdownHand(hand.live_range()); + if (!root->IsComplete() && !yaku::isThirteenOrphans(state, hand)) { return false; } for (const auto& branch : Node::AsBranchVectors(root.get())) { @@ -272,8 +272,8 @@ bool isComplete(const GameState& state, const Hand& player) { continue; } if (std::ranges::any_of(Yakus::Instance().GetYakus(), - [&state, player, &branch](const auto& yaku) { - return yaku.is_yaku_func(state, player, branch); + [&state, hand, &branch](const auto& yaku) { + return yaku.is_yaku_func(state, hand, branch); })) { return true; } diff --git a/src/scoring/scoring.h b/src/scoring/scoring.h index 65c4907c..84fed5bb 100644 --- a/src/scoring/scoring.h +++ b/src/scoring/scoring.h @@ -7,15 +7,15 @@ #include "types/score.h" namespace mahjong { -Score scoreHand(const GameState& state, const Hand& player); +Score scoreHand(const GameState& state, const Hand& hand); int getBasicPoints(Score s); -int getFu(const GameState& state, const Hand& player, +int getFu(const GameState& state, const Hand& hand, const std::vector& branch); -bool isOpenPinfu(const GameState& state, const Hand& player, +bool isOpenPinfu(const GameState& state, const Hand& hand, const std::vector& branch); -bool isComplete(const GameState& state, const Hand& player); +bool isComplete(const GameState& state, const Hand& hand); } // namespace mahjong diff --git a/src/scoring/yakus/afterakan.cc b/src/scoring/yakus/afterakan.cc index 69615fd1..f14f48c6 100644 --- a/src/scoring/yakus/afterakan.cc +++ b/src/scoring/yakus/afterakan.cc @@ -10,9 +10,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAfterAKan(const GameState& state, const Hand& player, +bool isAfterAKan(const GameState& state, const Hand& hand, const std::vector& /*branch*/) { - if (state.currentPlayer != player.id) { + if (state.currentPlayer != hand.id) { return false; } if (state.prevState == StateFunctionType::kReplacement) { diff --git a/src/scoring/yakus/afterakan.h b/src/scoring/yakus/afterakan.h index dafc6380..0e969bcd 100644 --- a/src/scoring/yakus/afterakan.h +++ b/src/scoring/yakus/afterakan.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isAfterAKan(const GameState& state, const Hand& player, +bool isAfterAKan(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allgreen.cc b/src/scoring/yakus/allgreen.cc index 11021a27..51f4605f 100644 --- a/src/scoring/yakus/allgreen.cc +++ b/src/scoring/yakus/allgreen.cc @@ -9,14 +9,14 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllGreen(const GameState& /*state*/, const Hand& player, +bool isAllGreen(const GameState& /*state*/, const Hand& hand, const std::vector& /*branch*/) { - for (const auto& piece : player.live_range()) { + for (const auto& piece : hand.live_range()) { if (!piece.isGreen()) { return false; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (!meld.start.isGreen()) { return false; } diff --git a/src/scoring/yakus/allgreen.h b/src/scoring/yakus/allgreen.h index 3c940df2..a1c38259 100644 --- a/src/scoring/yakus/allgreen.h +++ b/src/scoring/yakus/allgreen.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isAllGreen(const GameState& state, const Hand& player, +bool isAllGreen(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allhonors.cc b/src/scoring/yakus/allhonors.cc index c6219427..1135e327 100644 --- a/src/scoring/yakus/allhonors.cc +++ b/src/scoring/yakus/allhonors.cc @@ -9,14 +9,14 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllHonors(const GameState& /*state*/, const Hand& player, +bool isAllHonors(const GameState& /*state*/, const Hand& hand, const std::vector& /*branch*/) { - for (const auto& piece : player.live_range()) { + for (const auto& piece : hand.live_range()) { if (!piece.isHonor()) { return false; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (!meld.start.isHonor()) { return false; } diff --git a/src/scoring/yakus/allhonors.h b/src/scoring/yakus/allhonors.h index ffbd0780..9f93e1dd 100644 --- a/src/scoring/yakus/allhonors.h +++ b/src/scoring/yakus/allhonors.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isAllHonors(const GameState& state, const Hand& player, +bool isAllHonors(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allpons.cc b/src/scoring/yakus/allpons.cc index 10393288..3cec08ff 100644 --- a/src/scoring/yakus/allpons.cc +++ b/src/scoring/yakus/allpons.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllPons(const GameState& /* state */, const Hand& player, +bool isAllPons(const GameState& /* state */, const Hand& hand, const std::vector& branch) { int pons = 0; for (const auto* node : branch) { @@ -18,7 +18,7 @@ bool isAllPons(const GameState& /* state */, const Hand& player, pons++; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.type == SetType::kKan || meld.type == SetType::kPon || meld.type == SetType::kConcealedKan) { pons++; diff --git a/src/scoring/yakus/allpons.h b/src/scoring/yakus/allpons.h index 5a7981d7..695236bd 100644 --- a/src/scoring/yakus/allpons.h +++ b/src/scoring/yakus/allpons.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isAllPons(const GameState& state, const Hand& player, +bool isAllPons(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/allsimples.cc b/src/scoring/yakus/allsimples.cc index ed1df6b8..2c24ea6e 100644 --- a/src/scoring/yakus/allsimples.cc +++ b/src/scoring/yakus/allsimples.cc @@ -9,14 +9,14 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllSimples(const GameState& /* state */, const Hand& player, +bool isAllSimples(const GameState& /* state */, const Hand& hand, const std::vector& /*branch*/) { - for (const auto& piece : player.live_range()) { + for (const auto& piece : hand.live_range()) { if (piece.isHonor() || piece.isTerminal()) { return false; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.start.isHonor() || meld.start.isTerminal()) { return false; } diff --git a/src/scoring/yakus/allsimples.h b/src/scoring/yakus/allsimples.h index 0e4d61d5..e9c8de63 100644 --- a/src/scoring/yakus/allsimples.h +++ b/src/scoring/yakus/allsimples.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isAllSimples(const GameState& state, const Hand& player, +bool isAllSimples(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allterminals.cc b/src/scoring/yakus/allterminals.cc index 3ea5e4c5..021f4eba 100644 --- a/src/scoring/yakus/allterminals.cc +++ b/src/scoring/yakus/allterminals.cc @@ -9,14 +9,14 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isAllTerminals(const GameState& /*state*/, const Hand& player, +bool isAllTerminals(const GameState& /*state*/, const Hand& hand, const std::vector& /*branch*/) { - for (const auto& piece : player.live_range()) { + for (const auto& piece : hand.live_range()) { if (!piece.isTerminal()) { return false; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (!meld.start.isTerminal()) { return false; } diff --git a/src/scoring/yakus/allterminals.h b/src/scoring/yakus/allterminals.h index 92edd20c..1efa4270 100644 --- a/src/scoring/yakus/allterminals.h +++ b/src/scoring/yakus/allterminals.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isAllTerminals(const GameState& state, const Hand& player, +bool isAllTerminals(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/allterminalsandhonors.cc b/src/scoring/yakus/allterminalsandhonors.cc index fe0ac67f..98cc9a2d 100644 --- a/src/scoring/yakus/allterminalsandhonors.cc +++ b/src/scoring/yakus/allterminalsandhonors.cc @@ -10,14 +10,14 @@ namespace mahjong::yaku { bool isAllTerminalsAndHonors( - const GameState& /*state*/, const Hand& player, + const GameState& /*state*/, const Hand& hand, const std::vector& /*branch*/) { - for (const auto& piece : player.live_range()) { + for (const auto& piece : hand.live_range()) { if (!piece.isHonor() && !piece.isTerminal()) { return false; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (!meld.start.isHonor() && !meld.start.isTerminal()) { return false; } diff --git a/src/scoring/yakus/allterminalsandhonors.h b/src/scoring/yakus/allterminalsandhonors.h index 326fbc79..87b33340 100644 --- a/src/scoring/yakus/allterminalsandhonors.h +++ b/src/scoring/yakus/allterminalsandhonors.h @@ -7,7 +7,7 @@ namespace mahjong::yaku { bool isAllTerminalsAndHonors( - const GameState& state, const Hand& player, + const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/bigfourwinds.cc b/src/scoring/yakus/bigfourwinds.cc index 0eed780c..e3d7cfd3 100644 --- a/src/scoring/yakus/bigfourwinds.cc +++ b/src/scoring/yakus/bigfourwinds.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBigFourWinds(const GameState& /*state*/, const Hand& player, +bool isBigFourWinds(const GameState& /*state*/, const Hand& hand, const std::vector& branch) { int pons = 0; for (const auto* node : branch) { @@ -28,7 +28,7 @@ bool isBigFourWinds(const GameState& /*state*/, const Hand& player, } pons++; } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { switch (meld.start.toUint8_t()) { case Piece::Type::kEastWind: case Piece::Type::kSouthWind: diff --git a/src/scoring/yakus/bigfourwinds.h b/src/scoring/yakus/bigfourwinds.h index bd5f813c..4c74242f 100644 --- a/src/scoring/yakus/bigfourwinds.h +++ b/src/scoring/yakus/bigfourwinds.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isBigFourWinds(const GameState& state, const Hand& player, +bool isBigFourWinds(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/bigthreedragons.cc b/src/scoring/yakus/bigthreedragons.cc index 0ddd2bb3..e2e03486 100644 --- a/src/scoring/yakus/bigthreedragons.cc +++ b/src/scoring/yakus/bigthreedragons.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBigThreeDragons(const GameState& /*state*/, const Hand& player, +bool isBigThreeDragons(const GameState& /*state*/, const Hand& hand, const std::vector& branch) { int pons = 0; for (const auto* node : branch) { @@ -27,7 +27,7 @@ bool isBigThreeDragons(const GameState& /*state*/, const Hand& player, } pons++; } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { switch (meld.start.toUint8_t()) { case Piece::Type::kRedDragon: case Piece::Type::kGreenDragon: diff --git a/src/scoring/yakus/bigthreedragons.h b/src/scoring/yakus/bigthreedragons.h index 22fc2fba..a484fc69 100644 --- a/src/scoring/yakus/bigthreedragons.h +++ b/src/scoring/yakus/bigthreedragons.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isBigThreeDragons(const GameState& state, const Hand& player, +bool isBigThreeDragons(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/blessingofearth.cc b/src/scoring/yakus/blessingofearth.cc index f73eb81f..e15ed01f 100644 --- a/src/scoring/yakus/blessingofearth.cc +++ b/src/scoring/yakus/blessingofearth.cc @@ -9,9 +9,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBlessingOfEarth(const GameState& state, const Hand& player, +bool isBlessingOfEarth(const GameState& state, const Hand& hand, const std::vector& /*branch*/) { - if (player.open) { + if (hand.open) { return false; } if (state.turnNum > 3) { @@ -20,7 +20,7 @@ bool isBlessingOfEarth(const GameState& state, const Hand& player, if (state.lastCall >= 0) { return false; } - if (player.hasRonned) { + if (hand.hasRonned) { return false; } return true; diff --git a/src/scoring/yakus/blessingofearth.h b/src/scoring/yakus/blessingofearth.h index 12bae67c..527b61e1 100644 --- a/src/scoring/yakus/blessingofearth.h +++ b/src/scoring/yakus/blessingofearth.h @@ -7,7 +7,7 @@ namespace mahjong::yaku { bool isBlessingOfEarth( - const GameState& state, const Hand& player, + const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/blessingofheaven.cc b/src/scoring/yakus/blessingofheaven.cc index ef06d82d..dccda98f 100644 --- a/src/scoring/yakus/blessingofheaven.cc +++ b/src/scoring/yakus/blessingofheaven.cc @@ -9,15 +9,15 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBlessingOfHeaven(const GameState& state, const Hand& player, +bool isBlessingOfHeaven(const GameState& state, const Hand& hand, const std::vector& /*branch*/) { - if (player.open) { + if (hand.open) { return false; } - if (player.id != 0) { + if (hand.id != 0) { return false; } - if (state.players[0].hasRonned) { + if (state.hands[0].hasRonned) { return false; } if (state.turnNum != 0) { diff --git a/src/scoring/yakus/blessingofheaven.h b/src/scoring/yakus/blessingofheaven.h index a77f89de..e8c4cbeb 100644 --- a/src/scoring/yakus/blessingofheaven.h +++ b/src/scoring/yakus/blessingofheaven.h @@ -7,7 +7,7 @@ namespace mahjong::yaku { bool isBlessingOfHeaven( - const GameState& state, const Hand& player, + const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/blessingofman.cc b/src/scoring/yakus/blessingofman.cc index 2a701979..e38a69a2 100644 --- a/src/scoring/yakus/blessingofman.cc +++ b/src/scoring/yakus/blessingofman.cc @@ -9,18 +9,18 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBlessingOfMan(const GameState& state, const Hand& player, +bool isBlessingOfMan(const GameState& state, const Hand& hand, const std::vector& /*branch*/) { - if (player.open) { + if (hand.open) { return false; } - if (state.turnNum > player.id) { + if (state.turnNum > hand.id) { return false; } if (state.lastCall >= 0) { return false; } - if (player.hasRonned) { + if (hand.hasRonned) { return true; } return false; diff --git a/src/scoring/yakus/blessingofman.h b/src/scoring/yakus/blessingofman.h index bb6a73be..6cc05573 100644 --- a/src/scoring/yakus/blessingofman.h +++ b/src/scoring/yakus/blessingofman.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isBlessingOfMan(const GameState& state, const Hand& player, +bool isBlessingOfMan(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/bottomofthesea.cc b/src/scoring/yakus/bottomofthesea.cc index c1904460..7277fc26 100644 --- a/src/scoring/yakus/bottomofthesea.cc +++ b/src/scoring/yakus/bottomofthesea.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isBottomOfTheSea(const GameState& state, const Hand& /*player*/, +bool isBottomOfTheSea(const GameState& state, const Hand& /*hand*/, const std::vector& /*branch*/) { return Walls::GetRemainingPieces(state) == 0; } diff --git a/src/scoring/yakus/bottomofthesea.h b/src/scoring/yakus/bottomofthesea.h index c9cb0347..f6327bfc 100644 --- a/src/scoring/yakus/bottomofthesea.h +++ b/src/scoring/yakus/bottomofthesea.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isBottomOfTheSea(const GameState& state, const Hand& player, +bool isBottomOfTheSea(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/doubleriichi.cc b/src/scoring/yakus/doubleriichi.cc index eecc44d1..4fd220ba 100644 --- a/src/scoring/yakus/doubleriichi.cc +++ b/src/scoring/yakus/doubleriichi.cc @@ -9,10 +9,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isDoubleRiichi(const GameState& state, const Hand& player, +bool isDoubleRiichi(const GameState& state, const Hand& hand, const std::vector& /*branch*/) { - return player.riichi && !player.open && - (state.turnNum < 4 && state.lastCall < 0); + return hand.riichi && !hand.open && (state.turnNum < 4 && state.lastCall < 0); } REGISTER_YAKU({ diff --git a/src/scoring/yakus/doubleriichi.h b/src/scoring/yakus/doubleriichi.h index 64776db7..1903703b 100644 --- a/src/scoring/yakus/doubleriichi.h +++ b/src/scoring/yakus/doubleriichi.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isDoubleRiichi(const GameState& state, const Hand& player, +bool isDoubleRiichi(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/fourconcealedpon.cc b/src/scoring/yakus/fourconcealedpon.cc index 1a9d5469..8e554932 100644 --- a/src/scoring/yakus/fourconcealedpon.cc +++ b/src/scoring/yakus/fourconcealedpon.cc @@ -10,9 +10,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isFourConcealedPon(const GameState& /*state*/, const Hand& player, +bool isFourConcealedPon(const GameState& /*state*/, const Hand& hand, const std::vector& branch) { - if (player.open) { + if (hand.open) { return false; } int concealed_pons = 0; @@ -21,7 +21,7 @@ bool isFourConcealedPon(const GameState& /*state*/, const Hand& player, concealed_pons++; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.type == SetType::kConcealedKan) { concealed_pons++; } diff --git a/src/scoring/yakus/fourconcealedpon.h b/src/scoring/yakus/fourconcealedpon.h index 5cac68a9..df74846a 100644 --- a/src/scoring/yakus/fourconcealedpon.h +++ b/src/scoring/yakus/fourconcealedpon.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isFourConcealedPon(const GameState& state, const Hand& player, +bool isFourConcealedPon(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/fourkans.cc b/src/scoring/yakus/fourkans.cc index de173b93..a6d0abc8 100644 --- a/src/scoring/yakus/fourkans.cc +++ b/src/scoring/yakus/fourkans.cc @@ -10,10 +10,10 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isFourKans(const GameState& /*state*/, const Hand& player, +bool isFourKans(const GameState& /*state*/, const Hand& hand, const std::vector& /*branch*/) { int kans = 0; - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.type >= SetType::kKan) { kans++; } diff --git a/src/scoring/yakus/fourkans.h b/src/scoring/yakus/fourkans.h index 9b2daf67..a563274b 100644 --- a/src/scoring/yakus/fourkans.h +++ b/src/scoring/yakus/fourkans.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isFourKans(const GameState& state, const Hand& player, +bool isFourKans(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/fullflush.cc b/src/scoring/yakus/fullflush.cc index 3e4b2322..7e86a392 100644 --- a/src/scoring/yakus/fullflush.cc +++ b/src/scoring/yakus/fullflush.cc @@ -9,18 +9,18 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isFullFlush(const GameState& /*state*/, const Hand& player, +bool isFullFlush(const GameState& /*state*/, const Hand& hand, const std::vector& /*branch*/) { - if (player.live[0].isHonor()) { + if (hand.live[0].isHonor()) { return false; } - const int suit = player.live[0].getSuit(); - for (const auto& piece : player.live_range()) { + const int suit = hand.live[0].getSuit(); + for (const auto& piece : hand.live_range()) { if (piece.getSuit() != suit) { return false; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.start.getSuit() != suit) { return false; } diff --git a/src/scoring/yakus/fullflush.h b/src/scoring/yakus/fullflush.h index bcab996d..517362eb 100644 --- a/src/scoring/yakus/fullflush.h +++ b/src/scoring/yakus/fullflush.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isFullFlush(const GameState& state, const Hand& player, +bool isFullFlush(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/fullyconcealedhand.cc b/src/scoring/yakus/fullyconcealedhand.cc index ac393696..199346af 100644 --- a/src/scoring/yakus/fullyconcealedhand.cc +++ b/src/scoring/yakus/fullyconcealedhand.cc @@ -10,9 +10,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isFullyConcealedHand(const GameState& state, const Hand& player, +bool isFullyConcealedHand(const GameState& state, const Hand& hand, const std::vector& /*branch*/) { - return state.currentPlayer == player.id && !player.open && + return state.currentPlayer == hand.id && !hand.open && Walls::GetRemainingPieces(state) > 0; } diff --git a/src/scoring/yakus/fullyconcealedhand.h b/src/scoring/yakus/fullyconcealedhand.h index 92278350..2321abd5 100644 --- a/src/scoring/yakus/fullyconcealedhand.h +++ b/src/scoring/yakus/fullyconcealedhand.h @@ -7,7 +7,7 @@ namespace mahjong::yaku { bool isFullyConcealedHand( - const GameState& state, const Hand& player, + const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/halfflush.cc b/src/scoring/yakus/halfflush.cc index f0e4e978..f6a3453e 100644 --- a/src/scoring/yakus/halfflush.cc +++ b/src/scoring/yakus/halfflush.cc @@ -10,11 +10,11 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isHalfFlush(const GameState& state, const Hand& player, +bool isHalfFlush(const GameState& state, const Hand& hand, const std::vector& /*branch*/) { - const int suit = player.live[0].getSuit(); + const int suit = hand.live[0].getSuit(); bool honors = false; - for (const auto& piece : player.live_range()) { + for (const auto& piece : hand.live_range()) { if (piece.isHonor()) { honors = true; continue; @@ -23,7 +23,7 @@ bool isHalfFlush(const GameState& state, const Hand& player, return false; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.start.isHonor()) { honors = true; continue; @@ -33,7 +33,7 @@ bool isHalfFlush(const GameState& state, const Hand& player, } } // Full Flush scores instead of Half Flush. - return honors && !isFullFlush(state, player); + return honors && !isFullFlush(state, hand); } REGISTER_YAKU({ diff --git a/src/scoring/yakus/halfflush.h b/src/scoring/yakus/halfflush.h index f5bf23fc..a361fdad 100644 --- a/src/scoring/yakus/halfflush.h +++ b/src/scoring/yakus/halfflush.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isHalfFlush(const GameState& state, const Hand& player, +bool isHalfFlush(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/honorpon.cc b/src/scoring/yakus/honorpon.cc index 4800574b..db7e9db0 100644 --- a/src/scoring/yakus/honorpon.cc +++ b/src/scoring/yakus/honorpon.cc @@ -15,7 +15,7 @@ namespace mahjong::yaku { namespace { -bool findPon(const GameState& /* state */, const Hand& player, +bool findPon(const GameState& /* state */, const Hand& hand, const std::vector& branch, const Piece& piece) { for (const auto* node : branch) { @@ -23,7 +23,7 @@ bool findPon(const GameState& /* state */, const Hand& player, return true; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.type >= SetType::kPon && meld.start == piece) { return true; } @@ -33,31 +33,31 @@ bool findPon(const GameState& /* state */, const Hand& player, } // namespace -bool isSeatWind(const GameState& state, const Hand& player, +bool isSeatWind(const GameState& state, const Hand& hand, const std::vector& branch) { - return findPon(state, player, branch, - Piece::fromWind(GetSeat(state.roundNum, player.id))); + return findPon(state, hand, branch, + Piece::fromWind(GetSeat(state.roundNum, hand.id))); } -bool isPrevalentWind(const GameState& state, const Hand& player, +bool isPrevalentWind(const GameState& state, const Hand& hand, const std::vector& branch) { - return findPon(state, player, branch, + return findPon(state, hand, branch, Piece::fromWind(state.roundNum > 3 ? kSouth : kEast)); } -bool isGreenDragon(const GameState& state, const Hand& player, +bool isGreenDragon(const GameState& state, const Hand& hand, const std::vector& branch) { - return findPon(state, player, branch, kGreenDragon); + return findPon(state, hand, branch, kGreenDragon); } -bool isRedDragon(const GameState& state, const Hand& player, +bool isRedDragon(const GameState& state, const Hand& hand, const std::vector& branch) { - return findPon(state, player, branch, kRedDragon); + return findPon(state, hand, branch, kRedDragon); } -bool isWhiteDragon(const GameState& state, const Hand& player, +bool isWhiteDragon(const GameState& state, const Hand& hand, const std::vector& branch) { - return findPon(state, player, branch, kWhiteDragon); + return findPon(state, hand, branch, kWhiteDragon); } REGISTER_YAKUS({ diff --git a/src/scoring/yakus/honorpon.h b/src/scoring/yakus/honorpon.h index 5108626f..31dad3c2 100644 --- a/src/scoring/yakus/honorpon.h +++ b/src/scoring/yakus/honorpon.h @@ -6,18 +6,18 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isSeatWind(const GameState& state, const Hand& player, +bool isSeatWind(const GameState& state, const Hand& hand, const std::vector& branch); -bool isPrevalentWind(const GameState& state, const Hand& player, +bool isPrevalentWind(const GameState& state, const Hand& hand, const std::vector& branch); -bool isGreenDragon(const GameState& state, const Hand& player, +bool isGreenDragon(const GameState& state, const Hand& hand, const std::vector& branch); -bool isRedDragon(const GameState& state, const Hand& player, +bool isRedDragon(const GameState& state, const Hand& hand, const std::vector& branch); -bool isWhiteDragon(const GameState& state, const Hand& player, +bool isWhiteDragon(const GameState& state, const Hand& hand, const std::vector& branch); } // namespace mahjong::yaku diff --git a/src/scoring/yakus/ippatsu.cc b/src/scoring/yakus/ippatsu.cc index c606771f..6c368131 100644 --- a/src/scoring/yakus/ippatsu.cc +++ b/src/scoring/yakus/ippatsu.cc @@ -11,11 +11,11 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isIppatsu(const GameState& state, const Hand& player, +bool isIppatsu(const GameState& state, const Hand& hand, const std::vector& /*branch*/) { - return (isRiichi(state, player) || isDoubleRiichi(state, player)) && - (state.turnNum - player.riichiRound <= 4 && - state.lastCall < player.riichiRound); + return (isRiichi(state, hand) || isDoubleRiichi(state, hand)) && + (state.turnNum - hand.riichiRound <= 4 && + state.lastCall < hand.riichiRound); } REGISTER_YAKU({ diff --git a/src/scoring/yakus/ippatsu.h b/src/scoring/yakus/ippatsu.h index eab15d26..b3bc9a6f 100644 --- a/src/scoring/yakus/ippatsu.h +++ b/src/scoring/yakus/ippatsu.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isIppatsu(const GameState& state, const Hand& player, +bool isIppatsu(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/littlefourwinds.cc b/src/scoring/yakus/littlefourwinds.cc index 0757d847..3250efe7 100644 --- a/src/scoring/yakus/littlefourwinds.cc +++ b/src/scoring/yakus/littlefourwinds.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isLittleFourWinds(const GameState& /*state*/, const Hand& player, +bool isLittleFourWinds(const GameState& /*state*/, const Hand& hand, const std::vector& branch) { bool pair = false; int pons = 0; @@ -36,7 +36,7 @@ bool isLittleFourWinds(const GameState& /*state*/, const Hand& player, if (!pair) { return false; } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { switch (meld.start.toUint8_t()) { case Piece::Type::kEastWind: case Piece::Type::kSouthWind: diff --git a/src/scoring/yakus/littlefourwinds.h b/src/scoring/yakus/littlefourwinds.h index 449d7cba..65603ecd 100644 --- a/src/scoring/yakus/littlefourwinds.h +++ b/src/scoring/yakus/littlefourwinds.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isLittleFourWinds(const GameState& state, const Hand& player, +bool isLittleFourWinds(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/littlethreedragons.cc b/src/scoring/yakus/littlethreedragons.cc index a892601c..a4e2674c 100644 --- a/src/scoring/yakus/littlethreedragons.cc +++ b/src/scoring/yakus/littlethreedragons.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isLittleThreeDragons(const GameState& /*state*/, const Hand& player, +bool isLittleThreeDragons(const GameState& /*state*/, const Hand& hand, const std::vector& branch) { bool pair = false; int pons = 0; @@ -33,7 +33,7 @@ bool isLittleThreeDragons(const GameState& /*state*/, const Hand& player, if (!pair) { return false; } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { switch (meld.start.toUint8_t()) { case Piece::Type::kRedDragon: case Piece::Type::kGreenDragon: diff --git a/src/scoring/yakus/littlethreedragons.h b/src/scoring/yakus/littlethreedragons.h index c3cca0a6..c01a308b 100644 --- a/src/scoring/yakus/littlethreedragons.h +++ b/src/scoring/yakus/littlethreedragons.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isLittleThreeDragons(const GameState& state, const Hand& player, +bool isLittleThreeDragons(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/maxbranches.cc b/src/scoring/yakus/maxbranches.cc index 7c165309..7bb71fdf 100644 --- a/src/scoring/yakus/maxbranches.cc +++ b/src/scoring/yakus/maxbranches.cc @@ -9,13 +9,13 @@ #include "types/sets.h" namespace mahjong::yaku { -bool isMaxBranches(const GameState& /*state*/, const Hand& player, +bool isMaxBranches(const GameState& /*state*/, const Hand& hand, const std::vector& /*branch*/) { - const int start = player.live[0].getPieceNum(); - const int suit = player.live[0].getSuit(); + const int start = hand.live[0].getPieceNum(); + const int suit = hand.live[0].getSuit(); std::array sets = {}; const std::array final = {3, 3, 2, 2, 2, 2}; - for (const auto& piece : player.live_range()) { + for (const auto& piece : hand.live_range()) { if (piece.getSuit() != suit) { return false; } @@ -24,7 +24,7 @@ bool isMaxBranches(const GameState& /*state*/, const Hand& player, } sets.at(piece.getPieceNum() - start)++; } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.start.getSuit() != suit) { return false; } diff --git a/src/scoring/yakus/maxbranches.h b/src/scoring/yakus/maxbranches.h index 4b56f0ca..7eecefeb 100644 --- a/src/scoring/yakus/maxbranches.h +++ b/src/scoring/yakus/maxbranches.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isMaxBranches(const GameState& state, const Hand& player, +bool isMaxBranches(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/mixedtriplechi.cc b/src/scoring/yakus/mixedtriplechi.cc index 45e423da..3983de7b 100644 --- a/src/scoring/yakus/mixedtriplechi.cc +++ b/src/scoring/yakus/mixedtriplechi.cc @@ -11,7 +11,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isMixedTripleChi(const GameState& /* state */, const Hand& player, +bool isMixedTripleChi(const GameState& /* state */, const Hand& hand, const std::vector& branch) { const int k_piecesinasuit = 9; std::array bamboo_chi = {}; @@ -30,7 +30,7 @@ bool isMixedTripleChi(const GameState& /* state */, const Hand& player, } } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.type == SetType::kChi) { if (meld.start.getSuit() == Piece::Type::kBambooSuit) { bamboo_chi.at(meld.start.getPieceNum()) = true; diff --git a/src/scoring/yakus/mixedtriplechi.h b/src/scoring/yakus/mixedtriplechi.h index 4dedfc54..e8c6abc3 100644 --- a/src/scoring/yakus/mixedtriplechi.h +++ b/src/scoring/yakus/mixedtriplechi.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isMixedTripleChi(const GameState& state, const Hand& player, +bool isMixedTripleChi(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/ninegates.cc b/src/scoring/yakus/ninegates.cc index e1c32f65..3ea55c9e 100644 --- a/src/scoring/yakus/ninegates.cc +++ b/src/scoring/yakus/ninegates.cc @@ -11,15 +11,15 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isNineGates(const GameState& state, const Hand& player, +bool isNineGates(const GameState& state, const Hand& hand, const std::vector& branch) { - if (player.open) { + if (hand.open) { return false; } - if (!isFullFlush(state, player, branch)) { + if (!isFullFlush(state, hand, branch)) { return false; } - if (player.open) { + if (hand.open) { return false; } std::map pieces; @@ -27,7 +27,7 @@ bool isNineGates(const GameState& state, const Hand& player, pieces.at(i) = 0; } bool duplicate = false; - for (const auto& piece : player.live_range()) { + for (const auto& piece : hand.live_range()) { if (pieces.contains(piece.getPieceNum())) { if ((pieces[piece.getPieceNum()] != 0) && !piece.isTerminal()) { if (duplicate) { diff --git a/src/scoring/yakus/ninegates.h b/src/scoring/yakus/ninegates.h index af2385a8..d0e2c096 100644 --- a/src/scoring/yakus/ninegates.h +++ b/src/scoring/yakus/ninegates.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isNineGates(const GameState& state, const Hand& player, +bool isNineGates(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/outsidehand.cc b/src/scoring/yakus/outsidehand.cc index a341c3ef..b60089a9 100644 --- a/src/scoring/yakus/outsidehand.cc +++ b/src/scoring/yakus/outsidehand.cc @@ -12,7 +12,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isOutsideHand(const GameState& state, const Hand& player, +bool isOutsideHand(const GameState& state, const Hand& hand, const std::vector& branch) { bool chi = false; for (const auto* node : branch) { @@ -28,7 +28,7 @@ bool isOutsideHand(const GameState& state, const Hand& player, } } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.type == SetType::kChi) { if (meld.start.isTerminal() || (meld.start + 2).isTerminal()) { chi = true; @@ -43,8 +43,8 @@ bool isOutsideHand(const GameState& state, const Hand& player, } // Terminals in all Sets and All Terminals and Honors are more valuable and // score instead of Outside Hand. - return chi && !isTerminalsInAllSets(state, player, branch) && - !isAllTerminalsAndHonors(state, player); + return chi && !isTerminalsInAllSets(state, hand, branch) && + !isAllTerminalsAndHonors(state, hand); } REGISTER_YAKU({ diff --git a/src/scoring/yakus/outsidehand.h b/src/scoring/yakus/outsidehand.h index db41d7b0..f8c7f9b2 100644 --- a/src/scoring/yakus/outsidehand.h +++ b/src/scoring/yakus/outsidehand.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isOutsideHand(const GameState& state, const Hand& player, +bool isOutsideHand(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/pinfu.cc b/src/scoring/yakus/pinfu.cc index fc8ac41a..bf242afd 100644 --- a/src/scoring/yakus/pinfu.cc +++ b/src/scoring/yakus/pinfu.cc @@ -13,9 +13,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isPinfu(const GameState& state, const Hand& player, +bool isPinfu(const GameState& state, const Hand& hand, const std::vector& branch) { - if (player.open) { + if (hand.open) { return false; } for (const auto* node : branch) { @@ -39,13 +39,13 @@ bool isPinfu(const GameState& state, const Hand& player, return false; } if (node->start() == - Piece::fromWind(GetSeat(state.roundNum, player.id))) { + Piece::fromWind(GetSeat(state.roundNum, hand.id))) { return false; } } } } - return getWaits(player, state.pendingPiece).size() >= 2; + return getWaits(hand, state.pendingPiece).size() >= 2; } REGISTER_YAKU({ diff --git a/src/scoring/yakus/pinfu.h b/src/scoring/yakus/pinfu.h index 7a57fb56..d311a2bf 100644 --- a/src/scoring/yakus/pinfu.h +++ b/src/scoring/yakus/pinfu.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isPinfu(const GameState& state, const Hand& player, +bool isPinfu(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/puredoublechi.cc b/src/scoring/yakus/puredoublechi.cc index 0780fad2..b36ec578 100644 --- a/src/scoring/yakus/puredoublechi.cc +++ b/src/scoring/yakus/puredoublechi.cc @@ -12,9 +12,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isPureDoubleChi(const GameState& state, const Hand& player, +bool isPureDoubleChi(const GameState& state, const Hand& hand, const std::vector& branch) { - if (player.open) { + if (hand.open) { return false; } for (size_t i = 0; i < branch.size(); i++) { @@ -27,7 +27,7 @@ bool isPureDoubleChi(const GameState& state, const Hand& player, } if (branch.at(i)->type() == branch[j]->type() && branch.at(i)->start() == branch[j]->start()) { - return !isTwicePureDoubleChi(state, player, branch); + return !isTwicePureDoubleChi(state, hand, branch); } } } diff --git a/src/scoring/yakus/puredoublechi.h b/src/scoring/yakus/puredoublechi.h index a7bc57ca..970b4a62 100644 --- a/src/scoring/yakus/puredoublechi.h +++ b/src/scoring/yakus/puredoublechi.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isPureDoubleChi(const GameState& state, const Hand& player, +bool isPureDoubleChi(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/purestraight.cc b/src/scoring/yakus/purestraight.cc index 867bbd9f..7700c95e 100644 --- a/src/scoring/yakus/purestraight.cc +++ b/src/scoring/yakus/purestraight.cc @@ -11,7 +11,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isPureStraight(const GameState& /* state */, const Hand& player, +bool isPureStraight(const GameState& /* state */, const Hand& hand, const std::vector& branch) { const int k_firstchistart = 1; const int k_secondchistart = 4; @@ -42,7 +42,7 @@ bool isPureStraight(const GameState& /* state */, const Hand& player, } } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.type == SetType::kChi) { int ind = 0; if (meld.start.getPieceNum() == k_firstchistart) { diff --git a/src/scoring/yakus/purestraight.h b/src/scoring/yakus/purestraight.h index 62985ebe..7d2d4134 100644 --- a/src/scoring/yakus/purestraight.h +++ b/src/scoring/yakus/purestraight.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isPureStraight(const GameState& state, const Hand& player, +bool isPureStraight(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/riichi.cc b/src/scoring/yakus/riichi.cc index c847820c..e469ddf7 100644 --- a/src/scoring/yakus/riichi.cc +++ b/src/scoring/yakus/riichi.cc @@ -9,10 +9,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isRiichi(const GameState& state, const Hand& player, +bool isRiichi(const GameState& state, const Hand& hand, const std::vector& /*branch*/) { - return player.riichi && !player.open && - (state.turnNum > 4 || state.lastCall < 0); + return hand.riichi && !hand.open && (state.turnNum > 4 || state.lastCall < 0); } REGISTER_YAKU({ diff --git a/src/scoring/yakus/riichi.h b/src/scoring/yakus/riichi.h index 924d8dce..5b273737 100644 --- a/src/scoring/yakus/riichi.h +++ b/src/scoring/yakus/riichi.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isRiichi(const GameState& state, const Hand& player, +bool isRiichi(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/robbingakan.cc b/src/scoring/yakus/robbingakan.cc index d3d694df..7952f863 100644 --- a/src/scoring/yakus/robbingakan.cc +++ b/src/scoring/yakus/robbingakan.cc @@ -10,9 +10,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isRobbingAKan(const GameState& state, const Hand& player, +bool isRobbingAKan(const GameState& state, const Hand& hand, const std::vector& /*branch*/) { - if (!player.hasRonned) { + if (!hand.hasRonned) { return false; } if (state.nextState == StateFunctionType::kKanDiscard) { diff --git a/src/scoring/yakus/robbingakan.h b/src/scoring/yakus/robbingakan.h index cf1ab3ac..d11bcdf6 100644 --- a/src/scoring/yakus/robbingakan.h +++ b/src/scoring/yakus/robbingakan.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isRobbingAKan(const GameState& state, const Hand& player, +bool isRobbingAKan(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/sevenpairs.cc b/src/scoring/yakus/sevenpairs.cc index 57f06a2b..47b867b6 100644 --- a/src/scoring/yakus/sevenpairs.cc +++ b/src/scoring/yakus/sevenpairs.cc @@ -12,9 +12,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isSevenPairs(const GameState& /* state */, const Hand& player, +bool isSevenPairs(const GameState& /* state */, const Hand& hand, const std::vector& branch) { - if (player.open) { + if (hand.open) { return false; } std::set pairs; diff --git a/src/scoring/yakus/sevenpairs.h b/src/scoring/yakus/sevenpairs.h index 4ece168c..9e2f3d3a 100644 --- a/src/scoring/yakus/sevenpairs.h +++ b/src/scoring/yakus/sevenpairs.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isSevenPairs(const GameState& state, const Hand& player, +bool isSevenPairs(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/terminalsinallsets.cc b/src/scoring/yakus/terminalsinallsets.cc index 2dee44ef..b5cfd7b8 100644 --- a/src/scoring/yakus/terminalsinallsets.cc +++ b/src/scoring/yakus/terminalsinallsets.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isTerminalsInAllSets(const GameState& /*state*/, const Hand& player, +bool isTerminalsInAllSets(const GameState& /*state*/, const Hand& hand, const std::vector& branch) { for (const auto* node : branch) { switch (node->type()) { @@ -31,7 +31,7 @@ bool isTerminalsInAllSets(const GameState& /*state*/, const Hand& player, break; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { switch (meld.type) { case SetType::kSingle: return false; diff --git a/src/scoring/yakus/terminalsinallsets.h b/src/scoring/yakus/terminalsinallsets.h index e5bb2fb1..7316ba44 100644 --- a/src/scoring/yakus/terminalsinallsets.h +++ b/src/scoring/yakus/terminalsinallsets.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isTerminalsInAllSets(const GameState& state, const Hand& player, +bool isTerminalsInAllSets(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/thirteenorphans.cc b/src/scoring/yakus/thirteenorphans.cc index 9d1ee124..54a64b6b 100644 --- a/src/scoring/yakus/thirteenorphans.cc +++ b/src/scoring/yakus/thirteenorphans.cc @@ -12,9 +12,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isThirteenOrphans(const GameState& /*state*/, const Hand& player, +bool isThirteenOrphans(const GameState& /*state*/, const Hand& hand, const std::vector& /*branch*/) { - if (player.open) { + if (hand.open) { return false; } std::map pieces = { @@ -25,7 +25,7 @@ bool isThirteenOrphans(const GameState& /*state*/, const Hand& player, {kGreenDragon, false}}; bool duplicate = false; - for (const auto& piece : player.live_range()) { + for (const auto& piece : hand.live_range()) { if (pieces.contains(piece)) { if (pieces[piece]) { duplicate = true; diff --git a/src/scoring/yakus/thirteenorphans.h b/src/scoring/yakus/thirteenorphans.h index 7d66849f..97bae860 100644 --- a/src/scoring/yakus/thirteenorphans.h +++ b/src/scoring/yakus/thirteenorphans.h @@ -7,7 +7,7 @@ namespace mahjong::yaku { bool isThirteenOrphans( - const GameState& state, const Hand& player, + const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/threeconcealedpons.cc b/src/scoring/yakus/threeconcealedpons.cc index f82d907e..fc0599e9 100644 --- a/src/scoring/yakus/threeconcealedpons.cc +++ b/src/scoring/yakus/threeconcealedpons.cc @@ -10,7 +10,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isThreeConcealedPons(const GameState& /* state */, const Hand& player, +bool isThreeConcealedPons(const GameState& /* state */, const Hand& hand, const std::vector& branch) { int concealed_pons = 0; for (const auto* node : branch) { @@ -18,7 +18,7 @@ bool isThreeConcealedPons(const GameState& /* state */, const Hand& player, concealed_pons++; } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.type == SetType::kConcealedKan) { concealed_pons++; } diff --git a/src/scoring/yakus/threeconcealedpons.h b/src/scoring/yakus/threeconcealedpons.h index 4c49c685..b9f26d16 100644 --- a/src/scoring/yakus/threeconcealedpons.h +++ b/src/scoring/yakus/threeconcealedpons.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isThreeConcealedPons(const GameState& state, const Hand& player, +bool isThreeConcealedPons(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/threekans.cc b/src/scoring/yakus/threekans.cc index 0fafa105..6d5f95fa 100644 --- a/src/scoring/yakus/threekans.cc +++ b/src/scoring/yakus/threekans.cc @@ -10,10 +10,10 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isThreeKans(const GameState& /* state */, const Hand& player, +bool isThreeKans(const GameState& /* state */, const Hand& hand, const std::vector& /*branch*/) { int kans = 0; - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.type >= SetType::kKan) { kans++; } diff --git a/src/scoring/yakus/threekans.h b/src/scoring/yakus/threekans.h index a429a972..fc69c69e 100644 --- a/src/scoring/yakus/threekans.h +++ b/src/scoring/yakus/threekans.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isThreeKans(const GameState& state, const Hand& player, +bool isThreeKans(const GameState& state, const Hand& hand, const std::vector& /*unused*/ = {}); } diff --git a/src/scoring/yakus/triplepon.cc b/src/scoring/yakus/triplepon.cc index 2f63e1a8..5492b2ed 100644 --- a/src/scoring/yakus/triplepon.cc +++ b/src/scoring/yakus/triplepon.cc @@ -11,7 +11,7 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isTriplePon(const GameState& /* state */, const Hand& player, +bool isTriplePon(const GameState& /* state */, const Hand& hand, const std::vector& branch) { std::array bamboo_pon = {}; std::array char_pon = {}; @@ -29,7 +29,7 @@ bool isTriplePon(const GameState& /* state */, const Hand& player, } } } - for (const auto& meld : player.melds_range()) { + for (const auto& meld : hand.melds_range()) { if (meld.type >= SetType::kPon) { if (meld.start.getSuit() == Piece::Type::kBambooSuit) { bamboo_pon.at(meld.start.getPieceNum() - 1) = true; diff --git a/src/scoring/yakus/triplepon.h b/src/scoring/yakus/triplepon.h index 16fda10a..d276f9c9 100644 --- a/src/scoring/yakus/triplepon.h +++ b/src/scoring/yakus/triplepon.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isTriplePon(const GameState& state, const Hand& player, +bool isTriplePon(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/scoring/yakus/twicepuredoublechi.cc b/src/scoring/yakus/twicepuredoublechi.cc index 95a473df..3886dfed 100644 --- a/src/scoring/yakus/twicepuredoublechi.cc +++ b/src/scoring/yakus/twicepuredoublechi.cc @@ -11,9 +11,9 @@ #include "types/yaku.h" namespace mahjong::yaku { -bool isTwicePureDoubleChi(const GameState& /*state*/, const Hand& player, +bool isTwicePureDoubleChi(const GameState& /*state*/, const Hand& hand, const std::vector& branch) { - if (player.open) { + if (hand.open) { return false; } int pairs = 0; diff --git a/src/scoring/yakus/twicepuredoublechi.h b/src/scoring/yakus/twicepuredoublechi.h index fd107aab..974af058 100644 --- a/src/scoring/yakus/twicepuredoublechi.h +++ b/src/scoring/yakus/twicepuredoublechi.h @@ -6,7 +6,7 @@ #include "types/hand.h" namespace mahjong::yaku { -bool isTwicePureDoubleChi(const GameState& state, const Hand& player, +bool isTwicePureDoubleChi(const GameState& state, const Hand& hand, const std::vector& branch); } diff --git a/src/statefunctions/decisionfunction.cc b/src/statefunctions/decisionfunction.cc index f5ba99cf..40655ad7 100644 --- a/src/statefunctions/decisionfunction.cc +++ b/src/statefunctions/decisionfunction.cc @@ -16,103 +16,102 @@ namespace mahjong { // TODO(#18): "I really hate this" - alice -bool CanRon(const GameState& state, const Hand& player) { +bool CanRon(const GameState& state, const Hand& hand) { // If the pending piece is your discard, you can't Ron - for (const auto& piece : player.discards) { + for (const auto& piece : hand.discards) { if (state.pendingPiece == piece) { return false; } } // Build the theoretical hand - Hand tmp_player = player; - tmp_player.live[tmp_player.live_count++] = state.pendingPiece; + Hand tmp_hand = hand; + tmp_hand.live[tmp_hand.live_count++] = state.pendingPiece; // If this Ron is occurring due to a concealed kan discard, if (state.concealedKan) { // If it happens to be a ron for a thirteen orphans, // it's allowed and you can ron otherwise, you can't. - return yaku::isThirteenOrphans(state, player); + return yaku::isThirteenOrphans(state, hand); } // if not a concealed kan, check if it's complete - return isComplete(state, player); + return isComplete(state, hand); } -bool CanKan(const GameState& state, const Hand& player) { +bool CanKan(const GameState& state, const Hand& hand) { if (Walls::GetRemainingPieces(state) == 0) { return false; } - if (player.riichi) { + if (hand.riichi) { return false; } - return CountPieces(player, state.pendingPiece) == 3; + return CountPieces(hand, state.pendingPiece) == 3; } -bool CanPon(const GameState& state, const Hand& player) { - if (player.riichi) { +bool CanPon(const GameState& state, const Hand& hand) { + if (hand.riichi) { return false; } - return CountPieces(player, state.pendingPiece) == 2; + return CountPieces(hand, state.pendingPiece) == 2; } -bool CanChi(const GameState& state, const Hand& player) { - if (player.riichi) { +bool CanChi(const GameState& state, const Hand& hand) { + if (hand.riichi) { return false; } if (state.pendingPiece.isHonor()) { return false; } - if (((state.currentPlayer + 1) % 4) != player.id) { + if (((state.currentPlayer + 1) % 4) != hand.id) { return false; } - if (CountPieces(player, state.pendingPiece - 2) > 0 && - CountPieces(player, state.pendingPiece - 1) > 0) { + if (CountPieces(hand, state.pendingPiece - 2) > 0 && + CountPieces(hand, state.pendingPiece - 1) > 0) { return true; } - if (CountPieces(player, state.pendingPiece - 1) > 0 && - CountPieces(player, state.pendingPiece + 1) > 0) { + if (CountPieces(hand, state.pendingPiece - 1) > 0 && + CountPieces(hand, state.pendingPiece + 1) > 0) { return true; } - if (CountPieces(player, state.pendingPiece + 1) > 0 && - CountPieces(player, state.pendingPiece + 2) > 0) { + if (CountPieces(hand, state.pendingPiece + 1) > 0 && + CountPieces(hand, state.pendingPiece + 2) > 0) { return true; } return false; } -bool CanTsumo(const GameState& state, const Hand& player) { - return isComplete(state, player); +bool CanTsumo(const GameState& state, const Hand& hand) { + return isComplete(state, hand); } -bool CanConvertedKan(const GameState& state, const Hand& player) { +bool CanConvertedKan(const GameState& state, const Hand& hand) { if (Walls::GetRemainingPieces(state) == 0) { return false; } - return std::any_of(player.melds.begin(), - player.melds.begin() + player.meld_count, [&](auto meld) { - return meld.type == SetType::kPon && - CountPieces(player, meld.start) == 1; - }); + return std::any_of( + hand.melds.begin(), hand.melds.begin() + hand.meld_count, [&](auto meld) { + return meld.type == SetType::kPon && CountPieces(hand, meld.start) == 1; + }); } -bool CanConcealedKan(const GameState& state, const Hand& player) { +bool CanConcealedKan(const GameState& state, const Hand& hand) { if (Walls::GetRemainingPieces(state) == 0) { return false; } // TODO(#19): Allow riichi concealed kan under the right conditions - if (player.riichi) { + if (hand.riichi) { return false; } - return CountPieces(player, state.pendingPiece) == 4; + return CountPieces(hand, state.pendingPiece) == 4; } -bool CanRiichi(const GameState& /*unused*/, const Hand& player) { - if (player.riichi) { +bool CanRiichi(const GameState& /*unused*/, const Hand& hand) { + if (hand.riichi) { return false; } - if (player.open) { + if (hand.open) { return false; } - return !getPossibleWaits(player).empty(); + return !getPossibleWaits(hand).empty(); } } // namespace mahjong diff --git a/src/statefunctions/decisionfunction.h b/src/statefunctions/decisionfunction.h index 0ba53eca..f7df2d78 100644 --- a/src/statefunctions/decisionfunction.h +++ b/src/statefunctions/decisionfunction.h @@ -8,20 +8,20 @@ namespace mahjong { using DecisionFunction = - std::function; + std::function; struct PossibleDecision { Event::Type type; DecisionFunction func; }; -bool CanKan(const GameState& state, const Hand& player); -bool CanPon(const GameState& state, const Hand& player); -bool CanChi(const GameState& state, const Hand& player); -bool CanRon(const GameState& state, const Hand& player); +bool CanKan(const GameState& state, const Hand& hand); +bool CanPon(const GameState& state, const Hand& hand); +bool CanChi(const GameState& state, const Hand& hand); +bool CanRon(const GameState& state, const Hand& hand); -bool CanTsumo(const GameState& state, const Hand& player); -bool CanConcealedKan(const GameState& state, const Hand& player); -bool CanConvertedKan(const GameState& state, const Hand& player); -bool CanRiichi(const GameState& state, const Hand& player); +bool CanTsumo(const GameState& state, const Hand& hand); +bool CanConcealedKan(const GameState& state, const Hand& hand); +bool CanConvertedKan(const GameState& state, const Hand& hand); +bool CanRiichi(const GameState& state, const Hand& hand); } // namespace mahjong diff --git a/src/statefunctions/gamestates/chi.cc b/src/statefunctions/gamestates/chi.cc index 46c1abab..e72edcb1 100644 --- a/src/statefunctions/gamestates/chi.cc +++ b/src/statefunctions/gamestates/chi.cc @@ -30,9 +30,9 @@ Piece GetChiStart(const Hand& hand, Piece piece) { } std::unique_ptr Chi(std::unique_ptr state) { - if (Hand& player = state->players[state->currentPlayer]; - player.riichi && player.discards_count == player.riichiPieceDiscard) { - player.riichiPieceDiscard++; + if (Hand& hand = state->hands[state->currentPlayer]; + hand.riichi && hand.discards_count == hand.riichiPieceDiscard) { + hand.riichiPieceDiscard++; } state->currentPlayer = state->lastCaller; @@ -40,11 +40,11 @@ std::unique_ptr Chi(std::unique_ptr state) { state->concealedKan = false; state->turnNum++; - Hand& player = state->players[state->currentPlayer]; - player.open = true; + Hand& hand = state->hands[state->currentPlayer]; + hand.open = true; // only gives a single one of the chis // ui oof - const Piece chi_start = GetChiStart(player, state->pendingPiece); + const Piece chi_start = GetChiStart(hand, state->pendingPiece); if (chi_start == kError) { std::cerr << "Failed to get start of Chi" << '\n'; state->nextState = StateFunctionType::kError; @@ -55,7 +55,7 @@ std::unique_ptr Chi(std::unique_ptr state) { if (chi_start + i == state->pendingPiece) { continue; } - if (RemovePieces(player, chi_start + i, + if (RemovePieces(hand, chi_start + i, /*count=*/1) != 1) { std::cerr << "Not Enough Pieces to remove in Chi" << '\n'; state->nextState = StateFunctionType::kError; @@ -63,7 +63,7 @@ std::unique_ptr Chi(std::unique_ptr state) { } } - player.melds[player.meld_count++] = Meld{ + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kChi, .start = chi_start, }; diff --git a/src/statefunctions/gamestates/concealedkan.cc b/src/statefunctions/gamestates/concealedkan.cc index c1f28a02..d0d972c3 100644 --- a/src/statefunctions/gamestates/concealedkan.cc +++ b/src/statefunctions/gamestates/concealedkan.cc @@ -24,14 +24,14 @@ std::unique_ptr ConcealedKan(std::unique_ptr state) { state->pendingPiece.toUint8_t()), // piece .decision = false, // decision }); - Hand& player = state->players[state->currentPlayer]; - if (RemovePieces(player, state->pendingPiece, + Hand& hand = state->hands[state->currentPlayer]; + if (RemovePieces(hand, state->pendingPiece, /*count=*/4) != 4) { std::cerr << "Not Enough pieces to remove in ConcealedKan" << '\n'; state->nextState = StateFunctionType::kError; return state; } - player.melds[player.meld_count++] = Meld{ + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kConcealedKan, .start = state->pendingPiece, }; diff --git a/src/statefunctions/gamestates/convertedkan.cc b/src/statefunctions/gamestates/convertedkan.cc index 7c9e0eba..facf987c 100644 --- a/src/statefunctions/gamestates/convertedkan.cc +++ b/src/statefunctions/gamestates/convertedkan.cc @@ -24,16 +24,16 @@ std::unique_ptr ConvertedKan(std::unique_ptr state) { state->pendingPiece.toUint8_t()), // piece .decision = false, // decision }); - Hand& player = state->players[state->currentPlayer]; - if (RemovePieces(player, state->pendingPiece, + Hand& hand = state->hands[state->currentPlayer]; + if (RemovePieces(hand, state->pendingPiece, /*count=*/1) != 1) { std::cerr << "Not Enough pieces to remove in ConvertedKan" << '\n'; state->nextState = StateFunctionType::kError; return state; } Meld* meld = std::ranges::find( - player.melds, Meld{.type = SetType::kPon, .start = state->pendingPiece}); - if (meld == player.melds.end()) { + hand.melds, Meld{.type = SetType::kPon, .start = state->pendingPiece}); + if (meld == hand.melds.end()) { std::cerr << "Could Not find matching pon" << '\n'; state->nextState = StateFunctionType::kError; return state; diff --git a/src/statefunctions/gamestates/discard.cc b/src/statefunctions/gamestates/discard.cc index 3e45762f..88e5aa45 100644 --- a/src/statefunctions/gamestates/discard.cc +++ b/src/statefunctions/gamestates/discard.cc @@ -25,7 +25,7 @@ std::unique_ptr Discard(std::unique_ptr state) { state->pendingPiece.toUint8_t()), // piece .decision = false, // decision }); - DiscardPiece(state->players[state->currentPlayer], state->pendingPiece); + DiscardPiece(state->hands[state->currentPlayer], state->pendingPiece); const std::vector decisions = { {.type = Event::kChi, .func = CanChi}, @@ -35,14 +35,14 @@ std::unique_ptr Discard(std::unique_ptr state) { }; std::array need_decision = {false, false, false, false}; - for (const Hand& player : state->players) { - if (player.id == state->currentPlayer) { + for (const Hand& hand : state->hands) { + if (hand.id == state->currentPlayer) { continue; } for (const auto& [decision, decisionIsPossible] : decisions) { - if (decisionIsPossible(*state, player)) { - need_decision.at(player.id) = true; - state->controllers.at(player.id)->ReceiveEvent(Event{ + if (decisionIsPossible(*state, hand)) { + need_decision.at(hand.id) = true; + state->controllers.at(hand.id)->ReceiveEvent(Event{ .type = decision, // type .player = state->currentPlayer, // player .piece = @@ -54,18 +54,18 @@ std::unique_ptr Discard(std::unique_ptr state) { } Event decision = kDeclineEvent; - for (Hand& player : state->players) { - if (need_decision.at(player.id)) { + for (Hand& hand : state->hands) { + if (need_decision.at(hand.id)) { Event temp_decision = - GetValidDecisionOrThrow(*state, player, /*inHand=*/false); + GetValidDecisionOrThrow(*state, hand, /*inHand=*/false); if (temp_decision.type < decision.type) { // lower is higher priority - temp_decision.player = player.id; + temp_decision.player = hand.id; temp_decision.piece = static_cast(state->pendingPiece.toUint8_t()); decision = temp_decision; } if (temp_decision.type == Event::kRon) { - player.hasRonned = true; + hand.hasRonned = true; } } } diff --git a/src/statefunctions/gamestates/draw.cc b/src/statefunctions/gamestates/draw.cc index c8035d07..bbd30297 100644 --- a/src/statefunctions/gamestates/draw.cc +++ b/src/statefunctions/gamestates/draw.cc @@ -13,8 +13,8 @@ std::unique_ptr Draw(std::unique_ptr state) { state->currentPlayer = (state->currentPlayer + 1) % 4; state->turnNum++; state->pendingPiece = Walls::TakePiece(*state); - Hand& player = state->players[state->currentPlayer]; - player.live[player.live_count++] = state->pendingPiece; + Hand& hand = state->hands[state->currentPlayer]; + hand.live[hand.live_count++] = state->pendingPiece; state->nextState = StateFunctionType::kPlayerHand; return state; } diff --git a/src/statefunctions/gamestates/exhaust.cc b/src/statefunctions/gamestates/exhaust.cc index e3310735..37d8ad01 100644 --- a/src/statefunctions/gamestates/exhaust.cc +++ b/src/statefunctions/gamestates/exhaust.cc @@ -14,7 +14,7 @@ std::unique_ptr Exhaust(std::unique_ptr state) { int total_winners = 0; for (int i = 0; i < 4; i++) { // TODO(#21): Implement no tenpai if you have all pieces of your wait - if (state->players[i].riichi || !getWaits(state->players[i]).empty()) { + if (state->hands[i].riichi || !getWaits(state->hands[i]).empty()) { winning_players[i] = 1; total_winners++; } @@ -26,24 +26,24 @@ std::unique_ptr Exhaust(std::unique_ptr state) { if (total_winners < 4 && total_winners > 0) { for (int i = 0; i < 4; i++) { if (winning_players[i] != 0) { - state->players[i].score = 3000 / total_winners; + state->hands[i].score = 3000 / total_winners; } else { switch (total_winners) { case 1: - state->players[i].score = -1000; + state->hands[i].score = -1000; break; case 2: - state->players[i].score = -1500; + state->hands[i].score = -1500; break; case 3: - state->players[i].score = -3000; + state->hands[i].score = -3000; break; default: break; } } - if (state->players[i].riichi) { - state->players[i].score -= 1000; + if (state->hands[i].riichi) { + state->hands[i].score -= 1000; } } } diff --git a/src/statefunctions/gamestates/gamestart.cc b/src/statefunctions/gamestates/gamestart.cc index 42d8bd70..067e454b 100644 --- a/src/statefunctions/gamestates/gamestart.cc +++ b/src/statefunctions/gamestates/gamestart.cc @@ -11,10 +11,10 @@ namespace mahjong { namespace { std::unique_ptr GameStart(std::unique_ptr state) { int i = 0; - for (Hand& player : state->players) { - player.id = i++; - player.points = kStartingPoints; - state->controllers[player.id]->GameStart(player.id); + for (Hand& hand : state->hands) { + hand.id = i++; + hand.points = kStartingPoints; + state->controllers[hand.id]->GameStart(hand.id); } state->g.seed(state->seed); state->nextState = StateFunctionType::kRoundStart; diff --git a/src/statefunctions/gamestates/kan.cc b/src/statefunctions/gamestates/kan.cc index a9475e84..9d9582c5 100644 --- a/src/statefunctions/gamestates/kan.cc +++ b/src/statefunctions/gamestates/kan.cc @@ -25,9 +25,9 @@ std::unique_ptr Kan(std::unique_ptr state) { .decision = false, // decision }); - if (Hand& player = state->players[state->currentPlayer]; - player.riichi && player.discards_count == player.riichiPieceDiscard) { - player.riichiPieceDiscard++; + if (Hand& hand = state->hands[state->currentPlayer]; + hand.riichi && hand.discards_count == hand.riichiPieceDiscard) { + hand.riichiPieceDiscard++; } state->lastCall = state->turnNum; @@ -35,15 +35,15 @@ std::unique_ptr Kan(std::unique_ptr state) { state->turnNum++; state->currentPlayer = state->lastCaller; - Hand& player = state->players[state->currentPlayer]; - player.open = true; - if (RemovePieces(player, state->pendingPiece, + Hand& hand = state->hands[state->currentPlayer]; + hand.open = true; + if (RemovePieces(hand, state->pendingPiece, /*count=*/3) != 3) { std::cerr << "Not Enough Pieces to remove in kan" << '\n'; state->nextState = StateFunctionType::kError; return state; } - player.melds[player.meld_count++] = Meld{ + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kKan, .start = state->pendingPiece, }; diff --git a/src/statefunctions/gamestates/kandiscard.cc b/src/statefunctions/gamestates/kandiscard.cc index 2039e47c..2699fd30 100644 --- a/src/statefunctions/gamestates/kandiscard.cc +++ b/src/statefunctions/gamestates/kandiscard.cc @@ -16,12 +16,12 @@ namespace mahjong { namespace { std::unique_ptr KanDiscard(std::unique_ptr state) { std::array need_decision = {false, false, false, false}; - for (const Hand& player : state->players) { - if (player.id == state->currentPlayer) { + for (const Hand& hand : state->hands) { + if (hand.id == state->currentPlayer) { continue; } - if (CanRon(*state, player)) { - need_decision.at(player.id) = true; + if (CanRon(*state, hand)) { + need_decision.at(hand.id) = true; state->controllers.at(state->currentPlayer) ->ReceiveEvent(Event{ .type = Event::kRon, // type @@ -34,12 +34,12 @@ std::unique_ptr KanDiscard(std::unique_ptr state) { } bool have_ronned = false; - for (Hand& player : state->players) { - if (need_decision.at(player.id)) { + for (Hand& hand : state->hands) { + if (need_decision.at(hand.id)) { const Event temp_decision = - GetValidDecisionOrThrow(*state, player, /*inHand=*/false); + GetValidDecisionOrThrow(*state, hand, /*inHand=*/false); if (temp_decision.type == Event::kRon) { - player.hasRonned = true; + hand.hasRonned = true; have_ronned = true; } } diff --git a/src/statefunctions/gamestates/playerhand.cc b/src/statefunctions/gamestates/playerhand.cc index ee4173a3..ded98dfb 100644 --- a/src/statefunctions/gamestates/playerhand.cc +++ b/src/statefunctions/gamestates/playerhand.cc @@ -24,14 +24,14 @@ std::unique_ptr PlayerHand(std::unique_ptr state) { PossibleDecision{.type = Event::kConvertedKan, .func = CanConvertedKan}, PossibleDecision{.type = Event::kRiichi, .func = CanRiichi}, PossibleDecision{.type = Event::kDiscard, - .func = [](const GameState&, const Hand& player) { - return !player.riichi; + .func = [](const GameState&, const Hand& hand) { + return !hand.riichi; }}}; - const Hand& player = state->players[state->currentPlayer]; + const Hand& hand = state->hands[state->currentPlayer]; bool decision_asked = false; for (const auto& [decision, decisionIsPossible] : decisions) { - if (decisionIsPossible(*state, player)) { + if (decisionIsPossible(*state, hand)) { decision_asked = true; state->controllers.at(state->currentPlayer) ->ReceiveEvent(Event{ @@ -52,7 +52,7 @@ std::unique_ptr PlayerHand(std::unique_ptr state) { decision.decision = true; state->nextState = StateFunctionType::kDiscard; } else { - decision = GetValidDecisionOrThrow(*state, player, + decision = GetValidDecisionOrThrow(*state, hand, /*inHand=*/true); } diff --git a/src/statefunctions/gamestates/pon.cc b/src/statefunctions/gamestates/pon.cc index d23b5270..f282b8f7 100644 --- a/src/statefunctions/gamestates/pon.cc +++ b/src/statefunctions/gamestates/pon.cc @@ -17,9 +17,9 @@ namespace mahjong { namespace { std::unique_ptr Pon(std::unique_ptr state) { - if (Hand& player = state->players[state->currentPlayer]; - player.riichi && player.discards_count == player.riichiPieceDiscard) { - player.riichiPieceDiscard++; + if (Hand& hand = state->hands[state->currentPlayer]; + hand.riichi && hand.discards_count == hand.riichiPieceDiscard) { + hand.riichiPieceDiscard++; } state->currentPlayer = state->lastCaller; @@ -27,15 +27,15 @@ std::unique_ptr Pon(std::unique_ptr state) { state->concealedKan = false; state->turnNum++; - Hand& player = state->players.at(state->currentPlayer); - player.open = true; - if (RemovePieces(player, state->pendingPiece, + Hand& hand = state->hands.at(state->currentPlayer); + hand.open = true; + if (RemovePieces(hand, state->pendingPiece, /*count=*/2) != 2) { std::cerr << "Not enough pieces to remove in Pon" << '\n'; state->nextState = StateFunctionType::kError; return state; } - player.melds[player.meld_count++] = Meld{ + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = state->pendingPiece, }; diff --git a/src/statefunctions/gamestates/replacement.cc b/src/statefunctions/gamestates/replacement.cc index 3574cdfc..b3bd1533 100644 --- a/src/statefunctions/gamestates/replacement.cc +++ b/src/statefunctions/gamestates/replacement.cc @@ -16,8 +16,8 @@ namespace mahjong { namespace { std::unique_ptr Replacement(std::unique_ptr state) { const Piece draw = Walls::TakeReplacementTile(*state); - Hand& player = state->players[state->currentPlayer]; - player.live[player.live_count++] = draw; + Hand& hand = state->hands[state->currentPlayer]; + hand.live[hand.live_count++] = draw; state->pendingPiece = draw; AlertPlayers(*state, diff --git a/src/statefunctions/gamestates/riichi.cc b/src/statefunctions/gamestates/riichi.cc index 46bd24ae..71238a4a 100644 --- a/src/statefunctions/gamestates/riichi.cc +++ b/src/statefunctions/gamestates/riichi.cc @@ -16,13 +16,13 @@ namespace mahjong { namespace { std::unique_ptr Riichi(std::unique_ptr state) { - Hand& player = state->players[state->currentPlayer]; - player.riichiRound = state->turnNum; - player.riichiPieceDiscard = player.discards_count; - player.riichi = true; + Hand& hand = state->hands[state->currentPlayer]; + hand.riichiRound = state->turnNum; + hand.riichiPieceDiscard = hand.discards_count; + hand.riichi = true; // TODO(#22): Ask the players if they want to riichi - state->pendingPiece = getPossibleWaits(player).begin()->second.front(); + state->pendingPiece = getPossibleWaits(hand).begin()->second.front(); state->riichiSticks++; AlertPlayers(*state, diff --git a/src/statefunctions/gamestates/ron.cc b/src/statefunctions/gamestates/ron.cc index 8e9d5be6..a29cf546 100644 --- a/src/statefunctions/gamestates/ron.cc +++ b/src/statefunctions/gamestates/ron.cc @@ -15,60 +15,59 @@ namespace mahjong { namespace { std::unique_ptr Ron(std::unique_ptr state) { - if (Hand& player = state->players[state->currentPlayer]; - player.riichi && player.discards_count == player.riichiPieceDiscard) { + if (Hand& hand = state->hands[state->currentPlayer]; + hand.riichi && hand.discards_count == hand.riichiPieceDiscard) { state->riichiSticks--; - player.riichi = false; + hand.riichi = false; } - state->players[state->lastCaller] - .live[state->players[state->lastCaller].live_count++] = - state->pendingPiece; + state->hands[state->lastCaller] + .live[state->hands[state->lastCaller].live_count++] = state->pendingPiece; std::array basic_points = {}; - for (Hand& player : state->players) { - if (player.hasRonned) { + for (Hand& hand : state->hands) { + if (hand.hasRonned) { AlertPlayers(*state, Event{ .type = Event::kRon, // type - .player = player.id, // player + .player = hand.id, // player .piece = static_cast( state->pendingPiece.toUint8_t()), // piece .decision = false, // decision }); - basic_points.at(player.id) = getBasicPoints(scoreHand(*state, player)); + basic_points.at(hand.id) = getBasicPoints(scoreHand(*state, hand)); } - if (player.riichi) { - player.score -= 1000; + if (hand.riichi) { + hand.score -= 1000; } } int payment = 0; - for (Hand& player : state->players) { - if (player.hasRonned) { - player.score += 1000 * state->riichiSticks; + for (Hand& hand : state->hands) { + if (hand.hasRonned) { + hand.score += 1000 * state->riichiSticks; state->riichiSticks = 0; - player.score += 300 * state->counters; + hand.score += 300 * state->counters; payment += 300 * state->counters; - if (player.id == state->roundNum % 4) { - int amount = 6 * basic_points.at(player.id); + if (hand.id == state->roundNum % 4) { + int amount = 6 * basic_points.at(hand.id); if ((amount % 100) != 0) { amount = amount + (100 - (amount % 100)); } - player.score += amount; + hand.score += amount; payment += amount; } else { - int amount = 4 * basic_points.at(player.id); + int amount = 4 * basic_points.at(hand.id); if ((amount % 100) != 0) { amount = amount + (100 - (amount % 100)); } - player.score += amount; + hand.score += amount; payment += amount; } } } - state->players[state->currentPlayer].score -= payment; + state->hands[state->currentPlayer].score -= payment; - if (state->players[state->roundNum % 4].hasRonned) { + if (state->hands[state->roundNum % 4].hasRonned) { state->counters++; } else { state->roundNum++; @@ -77,7 +76,7 @@ std::unique_ptr Ron(std::unique_ptr state) { bool allzeros = true; for (int i = 0; i < 4; i++) { - if (state->players[i].score != 0) { + if (state->hands[i].score != 0) { allzeros = false; } } diff --git a/src/statefunctions/gamestates/roundend.cc b/src/statefunctions/gamestates/roundend.cc index 21977747..f53b545d 100644 --- a/src/statefunctions/gamestates/roundend.cc +++ b/src/statefunctions/gamestates/roundend.cc @@ -21,8 +21,8 @@ std::unique_ptr RoundEnd(std::unique_ptr state) { state->concealedKan = false; state->lastCaller = -1; state->pendingPiece = Piece(Piece::kError); - for (auto& player : state->players) { - player.hasRonned = false; + for (auto& hand : state->hands) { + hand.hasRonned = false; } state->controllers = {}; @@ -31,30 +31,29 @@ std::unique_ptr RoundEnd(std::unique_ptr state) { if (state->roundNum > last_round && state->riichiSticks > 0) { std::vector winners; int highscore = -100000; - for (const Hand& player : state->players) { - if (player.points + player.score > highscore) { - highscore = player.points + player.score; + for (const Hand& hand : state->hands) { + if (hand.points + hand.score > highscore) { + highscore = hand.points + hand.score; winners.clear(); - winners.push_back(player.id); - } else if (player.points + player.score == highscore) { - winners.push_back(player.id); + winners.push_back(hand.id); + } else if (hand.points + hand.score == highscore) { + winners.push_back(hand.id); } } for (const auto& winner : winners) { - state->players.at(winner).score += + state->hands.at(winner).score += (state->riichiSticks * 1000) / winners.size(); } } // TODO(#17): Scoring - for (Hand& player : state->players) { - AlertPlayers(*state, - Event{.type = Event::kPointDiff, - .player = player.id, - .piece = static_cast(player.score / 100), - .decision = false}); - player.points += player.score; - player.score = 0; + for (Hand& hand : state->hands) { + AlertPlayers(*state, Event{.type = Event::kPointDiff, + .player = hand.id, + .piece = static_cast(hand.score / 100), + .decision = false}); + hand.points += hand.score; + hand.score = 0; } // TODO (#14): for now naively increment the round number diff --git a/src/statefunctions/gamestates/roundstart.cc b/src/statefunctions/gamestates/roundstart.cc index 0a44c3de..fdb92f95 100644 --- a/src/statefunctions/gamestates/roundstart.cc +++ b/src/statefunctions/gamestates/roundstart.cc @@ -18,13 +18,13 @@ namespace mahjong { namespace { std::unique_ptr RoundStart(std::unique_ptr state) { Walls::New(*state); - for (Hand& player : state->players) { - auto hand = Walls::TakeHand(*state); - state->controllers.at(player.id)->RoundStart( - hand, static_cast((player.id + 3 * (state->roundNum % 4)) % 4), + for (Hand& hand : state->hands) { + auto draw = Walls::TakeHand(*state); + state->controllers.at(hand.id)->RoundStart( + draw, static_cast((hand.id + 3 * (state->roundNum % 4)) % 4), (state->roundNum > 3) ? kSouth : kEast); - player.live_count = hand.size(); - std::ranges::move(hand, player.live.begin()); + hand.live_count = draw.size(); + std::ranges::move(draw, hand.live.begin()); } AlertPlayers(*state, diff --git a/src/statefunctions/gamestates/tsumo.cc b/src/statefunctions/gamestates/tsumo.cc index e404f3e3..e1f0bb8f 100644 --- a/src/statefunctions/gamestates/tsumo.cc +++ b/src/statefunctions/gamestates/tsumo.cc @@ -23,22 +23,22 @@ std::unique_ptr Tsumo(std::unique_ptr state) { .decision = false, // decision }); - Hand& winning_player = state->players[state->currentPlayer]; - const int basic_points = getBasicPoints(scoreHand(*state, winning_player)); - winning_player.score += state->riichiSticks * 1000; + Hand& winning_hand = state->hands[state->currentPlayer]; + const int basic_points = getBasicPoints(scoreHand(*state, winning_hand)); + winning_hand.score += state->riichiSticks * 1000; state->riichiSticks = 0; - winning_player.score += state->counters * 300; + winning_hand.score += state->counters * 300; - for (Hand& player : state->players) { - if (player.id == winning_player.id) { - if (player.riichi) { - player.score -= 1000; + for (Hand& hand : state->hands) { + if (hand.id == winning_hand.id) { + if (hand.riichi) { + hand.score -= 1000; } continue; } int amount = 0; if (state->currentPlayer == state->roundNum % 4 || - player.id == state->roundNum % 4) { + hand.id == state->roundNum % 4) { amount = 2 * basic_points; } else { amount = basic_points; @@ -46,12 +46,12 @@ std::unique_ptr Tsumo(std::unique_ptr state) { if ((amount % 100) != 0) { amount = amount + (100 - (amount % 100)); } - player.score -= amount; - player.score -= state->counters * 100; - if (player.riichi) { - player.score -= 1000; + hand.score -= amount; + hand.score -= state->counters * 100; + if (hand.riichi) { + hand.score -= 1000; } - winning_player.score += amount; + winning_hand.score += amount; } if (state->currentPlayer == state->roundNum % 4) { diff --git a/src/statefunctions/stateutilities.cc b/src/statefunctions/stateutilities.cc index 1a261d2e..fa99b390 100644 --- a/src/statefunctions/stateutilities.cc +++ b/src/statefunctions/stateutilities.cc @@ -30,14 +30,14 @@ void AlertPlayers(const GameState& state, Event e) { } // Count number of piece p that are in given players hands -uint8_t CountPieces(const Hand& player, Piece p) { - return std::ranges::count(player.live_range(), p); +uint8_t CountPieces(const Hand& hand, Piece p) { + return std::ranges::count(hand.live_range(), p); } // Remove an instance of piece p from given players hand -uint8_t RemovePieces(Hand& player, Piece p, uint8_t count) { +uint8_t RemovePieces(Hand& hand, Piece p, uint8_t count) { uint8_t removed = 0; - count = std::min(CountPieces(player, p), count); + count = std::min(CountPieces(hand, p), count); const auto match_piece = [&](Piece _p) { if (count > removed && p == _p) { removed++; @@ -45,32 +45,31 @@ uint8_t RemovePieces(Hand& player, Piece p, uint8_t count) { } return false; }; - std::ranges::remove_if(player.live, match_piece); - player.live_count -= removed; + std::ranges::remove_if(hand.live, match_piece); + hand.live_count -= removed; return removed; } // Discard an instance of piece p from given players hand -void DiscardPiece(Hand& player, Piece p) { - RemovePieces(player, p, /*count=*/1); - player.discards[player.discards_count++] = p; +void DiscardPiece(Hand& hand, Piece p) { + RemovePieces(hand, p, /*count=*/1); + hand.discards[hand.discards_count++] = p; } Piece AskForDiscard(const GameState& state) { - state.controllers[state.currentPlayer] - ->ReceiveEvent(Event{ - .type = Event::kDiscard, // type - .player = state.currentPlayer, // player - .piece = 0, // piece - .decision = true, // decision - }); + state.controllers[state.currentPlayer]->ReceiveEvent(Event{ + .type = Event::kDiscard, // type + .player = state.currentPlayer, // player + .piece = 0, // piece + .decision = true, // decision + }); - return Piece(GetValidDecisionOrThrow( - state, state.players[state.currentPlayer], /*inHand=*/true) + return Piece(GetValidDecisionOrThrow(state, state.hands[state.currentPlayer], + /*inHand=*/true) .piece); } -Event GetValidDecisionOrThrow(const GameState& state, const Hand& player, +Event GetValidDecisionOrThrow(const GameState& state, const Hand& hand, bool inHand) { Event decision; bool valid = false; @@ -80,29 +79,29 @@ Event GetValidDecisionOrThrow(const GameState& state, const Hand& player, Event replacement_decision = decision; replacement_decision.type = inHand ? Event::kDiscard : Event::kDecline; if (inHand) { - replacement_decision.piece = player.live_range().back().toUint8_t(); + replacement_decision.piece = hand.live_range().back().toUint8_t(); } - if (ValidateDecision(state, player, replacement_decision, inHand)) { + if (ValidateDecision(state, hand, replacement_decision, inHand)) { return replacement_decision; } std::cerr << "WARNING: Player Controller sent invalid event too many times." << '\n'; std::cerr << "Decision.type: " << decision.type << " Decision.piece " - << decision.piece << " player: " << player.id + << decision.piece << " player: " << hand.id << " inHand: " << (inHand ? "true" : "false") << '\n'; std::cerr << "ERROR: was not able to recover from invalid event." << '\n'; throw 0xBAD22222; } i++; - decision = state.controllers[player.id]->RetrieveDecision(); - valid = ValidateDecision(state, player, decision, inHand); + decision = state.controllers[hand.id]->RetrieveDecision(); + valid = ValidateDecision(state, hand, decision, inHand); } return decision; } -bool ValidateDecision(const GameState& state, const Hand& player, - Event decision, bool inHand) { +bool ValidateDecision(const GameState& state, const Hand& hand, Event decision, + bool inHand) { if (decision.type > Event::kDiscard) { return false; } @@ -114,23 +113,23 @@ bool ValidateDecision(const GameState& state, const Hand& player, } switch (decision.type) { case Event::kRon: - return CanRon(state, player); + return CanRon(state, hand); case Event::kKan: - return CanKan(state, player); + return CanKan(state, hand); case Event::kPon: - return CanPon(state, player); + return CanPon(state, hand); case Event::kChi: - return CanChi(state, player); + return CanChi(state, hand); case Event::kTsumo: - return CanTsumo(state, player); + return CanTsumo(state, hand); case Event::kConcealedKan: - return CanConcealedKan(state, player); + return CanConcealedKan(state, hand); case Event::kConvertedKan: - return CanConvertedKan(state, player); + return CanConvertedKan(state, hand); case Event::kRiichi: - return CanRiichi(state, player); + return CanRiichi(state, hand); case Event::kDiscard: - return CountPieces(player, Piece(decision.piece)) > 0; + return CountPieces(hand, Piece(decision.piece)) > 0; case Event::kDecline: return true; default: diff --git a/src/statefunctions/stateutilities.h b/src/statefunctions/stateutilities.h index 9e605527..e98e7e32 100644 --- a/src/statefunctions/stateutilities.h +++ b/src/statefunctions/stateutilities.h @@ -12,15 +12,15 @@ struct GameState; Wind GetSeat(int round, int player); -uint8_t RemovePieces(Hand& player, Piece p, uint8_t count); -void DiscardPiece(Hand& player, Piece p); +uint8_t RemovePieces(Hand& hand, Piece p, uint8_t count); +void DiscardPiece(Hand& hand, Piece p); void AlertPlayers(const GameState& state, Event e); Piece AskForDiscard(const GameState& state); -uint8_t CountPieces(const Hand& player, Piece p); -bool ValidateDecision(const GameState& state, const Hand& player, - Event decision, bool inHand); -Event GetValidDecisionOrThrow(const GameState& state, const Hand& player, +uint8_t CountPieces(const Hand& hand, Piece p); +bool ValidateDecision(const GameState& state, const Hand& hand, Event decision, + bool inHand); +Event GetValidDecisionOrThrow(const GameState& state, const Hand& hand, bool inHand); } // namespace mahjong diff --git a/src/types/gamestate.h b/src/types/gamestate.h index c4bc57a0..2cdfff00 100644 --- a/src/types/gamestate.h +++ b/src/types/gamestate.h @@ -26,7 +26,7 @@ struct GameState { bool concealedKan = false; Piece pendingPiece = Piece(Piece::Type::kError); - std::array players; + std::array hands; std::array livingWall; std::array deadWall; diff --git a/src/types/typeprinter.cc b/src/types/typeprinter.cc index 387d4243..b920f4ca 100644 --- a/src/types/typeprinter.cc +++ b/src/types/typeprinter.cc @@ -35,8 +35,8 @@ std::ostream& operator<<(std::ostream& os, const mahjong::GameState& state) { os << "seed: " << state.seed << '\n'; os << "pendingPiece: " << state.pendingPiece.toStr() << '\n'; os << "hands: " << '\n'; - for (size_t i = 0; i < state.players.size(); i++) { - os << "hand[" << i << "]: {" << state.players.at(i) << "}" << '\n'; + for (size_t i = 0; i < state.hands.size(); i++) { + os << "hand[" << i << "]: {" << state.hands.at(i) << "}" << '\n'; } os << "controllers: " << '\n'; for (size_t i = 0; i < state.controllers.size(); i++) { diff --git a/tests/api/game_control.test.cc b/tests/api/game_control.test.cc index e769df5e..28aa622f 100644 --- a/tests/api/game_control.test.cc +++ b/tests/api/game_control.test.cc @@ -82,9 +82,9 @@ TEST(Api, ObserveGameState) { // Check arrays are properly sized and initialized for (int i = 0; i < 4; i++) { - EXPECT_EQ(observed.scores[i], state->players[i].score); - EXPECT_EQ(observed.points[i], state->players[i].points); - EXPECT_EQ(observed.hasRonned[i], state->players[i].hasRonned); + EXPECT_EQ(observed.scores[i], state->hands[i].score); + EXPECT_EQ(observed.points[i], state->hands[i].points); + EXPECT_EQ(observed.hasRonned[i], state->hands[i].hasRonned); } api::FreeGameState(state); @@ -124,7 +124,7 @@ TEST(Api, ObserveGameStateAfterAdvancement) { // Check points are copied for (int i = 0; i < 4; i++) { - EXPECT_EQ(observed.points[i], state->players[i].points); + EXPECT_EQ(observed.points[i], state->hands[i].points); } api::FreeGameState(state); @@ -145,7 +145,7 @@ TEST(Api, ObserveGameStateHandsAndDiscards) { // Check that hands are copied (after round start, players should have hands) for (int player = 0; player < 4; player++) { const api::CHand& c_hand = observed.hands[player]; - const mahjong::Hand& cpp_hand = state->players[player]; + const mahjong::Hand& cpp_hand = state->hands[player]; // Check live pieces EXPECT_EQ(c_hand.livePieceCount, static_cast(cpp_hand.live_count)); diff --git a/tests/can_chi.test.cc b/tests/can_chi.test.cc index e9e94af0..7e3b003e 100644 --- a/tests/can_chi.test.cc +++ b/tests/can_chi.test.cc @@ -14,37 +14,37 @@ TEST(CanChi, EastShouldChiOnNorth) { GameState state; state.pendingPiece = kOneCharacter; state.currentPlayer = 3; - Hand& player = state.players[0]; - player.live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; - player.live_count = 3; - EXPECT_TRUE(CanChi(state, player)); + Hand& hand = state.hands[0]; + hand.live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; + hand.live_count = 3; + EXPECT_TRUE(CanChi(state, hand)); state.pendingPiece = kTwoCharacter; - EXPECT_TRUE(CanChi(state, player)); + EXPECT_TRUE(CanChi(state, hand)); state.pendingPiece = kThreeCharacter; - EXPECT_TRUE(CanChi(state, player)); + EXPECT_TRUE(CanChi(state, hand)); state.pendingPiece = kFourCharacter; - EXPECT_TRUE(CanChi(state, player)); + EXPECT_TRUE(CanChi(state, hand)); } TEST(CanChi, EastShouldNotChiOnSouth) { GameState state; state.pendingPiece = kOneCharacter; state.currentPlayer = 1; - Hand& player = state.players[0]; - player.live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; - player.live_count = 3; - EXPECT_FALSE(CanChi(state, player)); + Hand& hand = state.hands[0]; + hand.live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; + hand.live_count = 3; + EXPECT_FALSE(CanChi(state, hand)); } TEST(CanChi, NoChiOnHonor) { GameState state; state.pendingPiece = kOneCharacter; state.currentPlayer = 3; - Hand& player = state.players[0]; - player.live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; - player.live_count = 3; + Hand& hand = state.hands[0]; + hand.live = {kOneCharacter, kTwoCharacter, kThreeCharacter}; + hand.live_count = 3; state.pendingPiece = kWhiteDragon; - EXPECT_FALSE(CanChi(state, player)); + EXPECT_FALSE(CanChi(state, hand)); } } // namespace mahjong diff --git a/tests/count_pieces.test.cc b/tests/count_pieces.test.cc index 08e988fc..15e5848a 100644 --- a/tests/count_pieces.test.cc +++ b/tests/count_pieces.test.cc @@ -9,14 +9,14 @@ namespace mahjong { TEST(CountPieces, CountPieces) { - Hand player; - player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; - player.live_count = 4; + Hand hand; + hand.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + hand.live_count = 4; - EXPECT_EQ(CountPieces(player, kOneCharacter), 1); - EXPECT_EQ(CountPieces(player, kFourPin), 1); - EXPECT_EQ(CountPieces(player, kWhiteDragon), 2); - EXPECT_EQ(CountPieces(player, kGreenDragon), 0); + EXPECT_EQ(CountPieces(hand, kOneCharacter), 1); + EXPECT_EQ(CountPieces(hand, kFourPin), 1); + EXPECT_EQ(CountPieces(hand, kWhiteDragon), 2); + EXPECT_EQ(CountPieces(hand, kGreenDragon), 0); } } // namespace mahjong diff --git a/tests/discard_piece.test.cc b/tests/discard_piece.test.cc index 2e3a82f6..0f119ee3 100644 --- a/tests/discard_piece.test.cc +++ b/tests/discard_piece.test.cc @@ -1,28 +1,27 @@ #include - #include "statefunctions/stateutilities.h" -#include "types/pieces.h" #include "types/hand.h" +#include "types/pieces.h" namespace mahjong { TEST(DiscardPiece, DiscardsCorrectPiece) { - Hand player; - player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; - player.live_count = 4; + Hand hand; + hand.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + hand.live_count = 4; - DiscardPiece(player, kOneCharacter); - EXPECT_EQ(player.discards[0], kOneCharacter); + DiscardPiece(hand, kOneCharacter); + EXPECT_EQ(hand.discards[0], kOneCharacter); } TEST(DiscardPiece, DoesntDiscardInCorrectPiece) { - Hand player; - player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; - player.live_count = 4; + Hand hand; + hand.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + hand.live_count = 4; - DiscardPiece(player, kGreenDragon); - EXPECT_EQ(player.live_count, 4); + DiscardPiece(hand, kGreenDragon); + EXPECT_EQ(hand.live_count, 4); } } // namespace mahjong diff --git a/tests/game_play.test.cc b/tests/game_play.test.cc index 1e162c45..c89d33cb 100644 --- a/tests/game_play.test.cc +++ b/tests/game_play.test.cc @@ -14,14 +14,14 @@ namespace mahjong { TEST(GamePlay, Furiten) { auto state = GameState(); - Hand& player = state.players[0]; - HandFromNotation("123m456p234678s44m", &player); - player.open = false; - EXPECT_TRUE(isComplete(state, player)); + Hand& hand = state.hands[0]; + HandFromNotation("123m456p234678s44m", &hand); + hand.open = false; + EXPECT_TRUE(isComplete(state, hand)); state.pendingPiece = Piece(kFourPin); // Place Four Pin in Discard Pile - player.discards = {kFourPin}; - EXPECT_FALSE(CanRon(state, player)); + hand.discards = {kFourPin}; + EXPECT_FALSE(CanRon(state, hand)); } } // namespace mahjong diff --git a/tests/remove_pieces.test.cc b/tests/remove_pieces.test.cc index abeb0417..d2c97763 100644 --- a/tests/remove_pieces.test.cc +++ b/tests/remove_pieces.test.cc @@ -9,39 +9,39 @@ namespace mahjong { TEST(RemovePieces, RemoveCorrectAmount) { - Hand player; - player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; - player.live_count = 4; + Hand hand; + hand.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + hand.live_count = 4; - EXPECT_EQ(RemovePieces(player, kOneCharacter, 1), 1); - EXPECT_EQ(player.live_count, 3); + EXPECT_EQ(RemovePieces(hand, kOneCharacter, 1), 1); + EXPECT_EQ(hand.live_count, 3); } TEST(RemovePieces, RemoveOnlyTheOnesAvailable) { - Hand player; - player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; - player.live_count = 4; + Hand hand; + hand.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + hand.live_count = 4; - EXPECT_EQ(RemovePieces(player, kFourPin, 2), 1); - EXPECT_EQ(player.live_count, 3); + EXPECT_EQ(RemovePieces(hand, kFourPin, 2), 1); + EXPECT_EQ(hand.live_count, 3); } TEST(RemovePieces, OnlyRemovesOne) { - Hand player; - player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; - player.live_count = 4; + Hand hand; + hand.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + hand.live_count = 4; - EXPECT_EQ(RemovePieces(player, kWhiteDragon, 1), 1); - EXPECT_EQ(player.live[2], kWhiteDragon); + EXPECT_EQ(RemovePieces(hand, kWhiteDragon, 1), 1); + EXPECT_EQ(hand.live[2], kWhiteDragon); } TEST(RemovePieces, RemovesZeroWhenPieceDoesntExist) { - Hand player; - player.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; - player.live_count = 4; + Hand hand; + hand.live = {kOneCharacter, kFourPin, kWhiteDragon, kWhiteDragon}; + hand.live_count = 4; - EXPECT_EQ(RemovePieces(player, kGreenDragon, 8), 0); - EXPECT_EQ(player.live_count, 4); + EXPECT_EQ(RemovePieces(hand, kGreenDragon, 8), 0); + EXPECT_EQ(hand.live_count, 4); } } // namespace mahjong diff --git a/tests/rules/basic_rules.test.cc b/tests/rules/basic_rules.test.cc index f54cf447..d20cfc36 100644 --- a/tests/rules/basic_rules.test.cc +++ b/tests/rules/basic_rules.test.cc @@ -19,7 +19,7 @@ TEST(GameSetup, playerCount) { // We just ran game start EXPECT_EQ(state->currState, StateFunctionType::kGameStart); // Number of players is as expected - EXPECT_EQ(state->players.size(), kNumPlayers); + EXPECT_EQ(state->hands.size(), kNumPlayers); } TEST(GameSetup, playerScore) { @@ -29,7 +29,7 @@ TEST(GameSetup, playerScore) { EXPECT_EQ(state->currState, StateFunctionType::kGameStart); // All players have the expected starting points for (int i = 0; i < kNumPlayers; i++) { - EXPECT_EQ(state->players[i].points, kStartingPoints); + EXPECT_EQ(state->hands[i].points, kStartingPoints); } } @@ -40,7 +40,7 @@ TEST(RoundSetup, playerHands) { // Each player should have 13 tiles for (int i = 0; i < kNumPlayers; i++) { - EXPECT_EQ(state->players[i].live_count, 13) + EXPECT_EQ(state->hands[i].live_count, 13) << "Player " << i << " should have 13 tiles"; } } @@ -101,7 +101,7 @@ TEST(DrawMechanics, drawIncreasesTileCount) { // All players start with 13 tiles for (int i = 0; i < kNumPlayers; i++) { - EXPECT_EQ(state->players[i].live_count, 13); + EXPECT_EQ(state->hands[i].live_count, 13); } const int walls_before = Walls::GetRemainingPieces(*state); @@ -111,11 +111,11 @@ TEST(DrawMechanics, drawIncreasesTileCount) { EXPECT_EQ(state->currState, StateFunctionType::kDraw); // Player 0 should now have 14 tiles - EXPECT_EQ(state->players[0].live_count, 14); + EXPECT_EQ(state->hands[0].live_count, 14); // Other players still have 13 for (int i = 1; i < kNumPlayers; i++) { - EXPECT_EQ(state->players[i].live_count, 13); + EXPECT_EQ(state->hands[i].live_count, 13); } // Wall should have one less tile @@ -142,22 +142,22 @@ TEST(DiscardMechanics, discardDecreasesTileCount) { EXPECT_EQ(state->currState, StateFunctionType::kDraw); // Player 0 has 14 tiles after draw - EXPECT_EQ(state->players[0].live_count, 14); + EXPECT_EQ(state->hands[0].live_count, 14); // Move through player hand to discard state = AdvanceGameState(std::move(state)); EXPECT_EQ(state->currState, StateFunctionType::kPlayerHand); EXPECT_EQ(state->nextState, StateFunctionType::kDiscard); - const int discards_before = state->players[0].discards_count; + const int discards_before = state->hands[0].discards_count; state = AdvanceGameState(std::move(state)); EXPECT_EQ(state->currState, StateFunctionType::kDiscard); // Player should be back to 13 tiles - EXPECT_EQ(state->players[0].live_count, 13); + EXPECT_EQ(state->hands[0].live_count, 13); // Discard pile should have increased - EXPECT_EQ(state->players[0].discards_count, discards_before + 1); + EXPECT_EQ(state->hands[0].discards_count, discards_before + 1); } } // namespace mahjong diff --git a/tests/rules/calls.test.cc b/tests/rules/calls.test.cc index 4a9022f9..7b1ba2e5 100644 --- a/tests/rules/calls.test.cc +++ b/tests/rules/calls.test.cc @@ -53,12 +53,12 @@ TEST(Calls, AcceptPon) { auto state = InitializeTestRound(12345, std::move(controllers)); // Override with hopeless hands - Hand& player0 = state->players[0]; + Hand& hand0 = state->hands[0]; // 14 Pieces because has drawn in InitializeTestRound. - HandFromNotation("11447m2258p33699s", &player0); + HandFromNotation("11447m2258p33699s", &hand0); // Has the pair of nine bamboo 13 Pieces, yet to draw. - Hand& player1 = state->players[1]; - HandFromNotation("13579m99s246p135z", &player1); + Hand& hand1 = state->hands[1]; + HandFromNotation("13579m99s246p135z", &hand1); // Advance to pon event // Should take 4 iterations: draw, player hand, discard, and then the pon @@ -74,12 +74,12 @@ TEST(Calls, AcceptPon) { // - State should be kDiscard (Player 1 needs to discard) EXPECT_EQ(state->currentPlayer, 1); EXPECT_EQ(state->currState, StateFunctionType::kDiscard); - EXPECT_EQ(player1.meld_count, 1); - EXPECT_EQ(player1.melds[0].type, SetType::kPon); - EXPECT_EQ(player1.melds[0].start, Piece(Piece::kNineBamboo)); + EXPECT_EQ(hand1.meld_count, 1); + EXPECT_EQ(hand1.melds[0].type, SetType::kPon); + EXPECT_EQ(hand1.melds[0].start, Piece(Piece::kNineBamboo)); // Player 1's live hand should be reduced by 3 tiles (pon + discard) - EXPECT_EQ(player1.live_count, 10); + EXPECT_EQ(hand1.live_count, 10); } } // namespace mahjong diff --git a/tests/setup.test.cc b/tests/setup.test.cc index 125ff6fa..c0a66565 100644 --- a/tests/setup.test.cc +++ b/tests/setup.test.cc @@ -46,7 +46,7 @@ TEST(Setup, Dealing) { ASSERT_NO_THROW(state = Router::Instance().Route( StateFunctionType::kRoundStart)(std::move(state))); for (int i = 0; i < 4; i++) { - EXPECT_EQ(state->players[i].live_count, 13); + EXPECT_EQ(state->hands[i].live_count, 13); } state = Router::Instance().Route(StateFunctionType::kDraw)(std::move(state)); EXPECT_EQ(state->currentPlayer, 0); diff --git a/tests/utils/gamestate_utils.test.cc b/tests/utils/gamestate_utils.test.cc index 66acc629..e3f5dc53 100644 --- a/tests/utils/gamestate_utils.test.cc +++ b/tests/utils/gamestate_utils.test.cc @@ -48,10 +48,10 @@ TEST(GameStateUtils, InitializeTestRoundDefault) { } // Draw occurred - EXPECT_EQ(state->players[0].live_count, 14); + EXPECT_EQ(state->hands[0].live_count, 14); for (int i = 1; i < kNumPlayers; i++) { - EXPECT_EQ(state->players[i].live_count, 13); + EXPECT_EQ(state->hands[i].live_count, 13); } } diff --git a/tests/yakus/afterkan.test.cc b/tests/yakus/afterkan.test.cc index 37b8a56e..f045edba 100644 --- a/tests/yakus/afterkan.test.cc +++ b/tests/yakus/afterkan.test.cc @@ -16,16 +16,16 @@ namespace mahjong::yaku { TEST(isAfterAKan, 1Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m789m1111z999s55z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m789m1111z999s55z", &hand); game_state.currentPlayer = 0; game_state.prevState = StateFunctionType::kReplacement; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAfterAKan(game_state, player, branch)) { + if (isAfterAKan(game_state, hand, branch)) { SUCCEED(); return; } @@ -35,16 +35,16 @@ TEST(isAfterAKan, 1Han) { TEST(isAfterAKan, DoesntApply) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m789m1111z999s55z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m789m1111z999s55z", &hand); game_state.currentPlayer = 0; game_state.prevState = StateFunctionType::kPon; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAfterAKan(game_state, player, branch)) { + if (isAfterAKan(game_state, hand, branch)) { FAIL(); return; } @@ -54,16 +54,16 @@ TEST(isAfterAKan, DoesntApply) { TEST(isAfterAKan, WrongPlayer) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m789m1111z999s55z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m789m1111z999s55z", &hand); game_state.currentPlayer = 2; game_state.prevState = StateFunctionType::kReplacement; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAfterAKan(game_state, player, branch)) { + if (isAfterAKan(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/allpon.test.cc b/tests/yakus/allpon.test.cc index 061f7be1..257daa32 100644 --- a/tests/yakus/allpon.test.cc +++ b/tests/yakus/allpon.test.cc @@ -19,13 +19,13 @@ namespace mahjong::yaku { TEST(isAllPons, 2Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m222p888s666z44m", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("111m222p888s666z44m", &hand); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllPons(game_state, player, branch)) { + if (isAllPons(game_state, hand, branch)) { SUCCEED(); return; } @@ -35,18 +35,18 @@ TEST(isAllPons, 2Han) { TEST(isAllPons, WithKans) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m222p666z44m", &player); - player.melds[player.meld_count++] = Meld{ + Hand& hand = game_state.hands[0]; + HandFromNotation("111m222p666z44m", &hand); + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kKan, .start = Piece(kFivePin), }; - player.open = true; + hand.open = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllPons(game_state, player, branch)) { + if (isAllPons(game_state, hand, branch)) { SUCCEED(); return; } @@ -56,18 +56,18 @@ TEST(isAllPons, WithKans) { TEST(isAllPons, ConcealedKan) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m222p666z44m", &player); - player.melds[player.meld_count++] = Meld{ + Hand& hand = game_state.hands[0]; + HandFromNotation("111m222p666z44m", &hand); + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kConcealedKan, .start = Piece(kFivePin), }; - player.open = false; + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllPons(game_state, player, branch)) { + if (isAllPons(game_state, hand, branch)) { SUCCEED(); return; } @@ -77,14 +77,14 @@ TEST(isAllPons, ConcealedKan) { TEST(isAllPons, BadHand) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m222p666z789m44m", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("111m222p666z789m44m", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllPons(game_state, player, branch)) { + if (isAllPons(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/allsimples.test.cc b/tests/yakus/allsimples.test.cc index aa3b45b8..55ce3f1b 100644 --- a/tests/yakus/allsimples.test.cc +++ b/tests/yakus/allsimples.test.cc @@ -16,13 +16,13 @@ namespace mahjong::yaku { TEST(isAllSimples, 1Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("222m333p444s555p88m", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("222m333p444s555p88m", &hand); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllSimples(game_state, player, branch)) { + if (isAllSimples(game_state, hand, branch)) { SUCCEED(); return; } @@ -32,13 +32,13 @@ TEST(isAllSimples, 1Han) { TEST(isAllSimples, BadHandHonors) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("222m333p444s111z88m", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("222m333p444s111z88m", &hand); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllSimples(game_state, player, branch)) { + if (isAllSimples(game_state, hand, branch)) { FAIL(); return; } @@ -48,13 +48,13 @@ TEST(isAllSimples, BadHandHonors) { TEST(isAllSimples, BadHandTerminals) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("222m333p444s111m88m", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("222m333p444s111m88m", &hand); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllSimples(game_state, player, branch)) { + if (isAllSimples(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/allterminalsandhonors.test.cc b/tests/yakus/allterminalsandhonors.test.cc index d8bbadfb..01de9992 100644 --- a/tests/yakus/allterminalsandhonors.test.cc +++ b/tests/yakus/allterminalsandhonors.test.cc @@ -20,14 +20,14 @@ namespace mahjong::yaku { TEST(isAllTerminalsAndHonors, 2Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("222z111p111m999s66z", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("222z111p111m999s66z", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllTerminalsAndHonors(game_state, player, branch)) { + if (isAllTerminalsAndHonors(game_state, hand, branch)) { SUCCEED(); return; } @@ -37,14 +37,14 @@ TEST(isAllTerminalsAndHonors, 2Han) { TEST(isAllTerminalsAndHonors, BadHand) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("222z111p111m888s66z", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("222z111p111m888s66z", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllTerminalsAndHonors(game_state, player, branch)) { + if (isAllTerminalsAndHonors(game_state, hand, branch)) { FAIL(); return; } @@ -54,18 +54,18 @@ TEST(isAllTerminalsAndHonors, BadHand) { TEST(isAllTerminalsAndHonors, CanBeOpen) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("222z111m999s66z", &player); - player.open = true; - player.melds[player.meld_count++] = Meld{ + Hand& hand = game_state.hands[0]; + HandFromNotation("222z111m999s66z", &hand); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kNinePin), }; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isAllTerminalsAndHonors(game_state, player, branch)) { + if (isAllTerminalsAndHonors(game_state, hand, branch)) { SUCCEED(); return; } diff --git a/tests/yakus/blessingofman.test.cc b/tests/yakus/blessingofman.test.cc index 60676f7c..d2348fe6 100644 --- a/tests/yakus/blessingofman.test.cc +++ b/tests/yakus/blessingofman.test.cc @@ -15,22 +15,22 @@ namespace mahjong::yaku { TEST(isBlessingOfMan, 5Han) { auto game_state = GameState(); - Hand& player = game_state.players[3]; - HandFromNotation("123m123p444m111z55m", &player); - player.open = false; - player.id = 3; + Hand& hand = game_state.hands[3]; + HandFromNotation("123m123p444m111z55m", &hand); + hand.open = false; + hand.id = 3; game_state.turnNum = 1; // No calls have occured game_state.lastCall = -1; - player.hasRonned = true; + hand.hasRonned = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isBlessingOfMan(game_state, player, branch)) { + if (isBlessingOfMan(game_state, hand, branch)) { SUCCEED(); return; } @@ -40,21 +40,21 @@ TEST(isBlessingOfMan, 5Han) { TEST(isBlessingOfMan, MustBeARon) { auto game_state = GameState(); - Hand& player = game_state.players[3]; - HandFromNotation("123m123p444m111z55m", &player); - player.open = false; + Hand& hand = game_state.hands[3]; + HandFromNotation("123m123p444m111z55m", &hand); + hand.open = false; game_state.turnNum = 3; // No calls have occured game_state.lastCall = -1; - player.hasRonned = false; + hand.hasRonned = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isBlessingOfMan(game_state, player, branch)) { + if (isBlessingOfMan(game_state, hand, branch)) { FAIL(); return; } @@ -64,21 +64,21 @@ TEST(isBlessingOfMan, MustBeARon) { TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m123p444m111z55m", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("123m123p444m111z55m", &hand); + hand.open = false; game_state.turnNum = 2; // No calls have occured game_state.lastCall = -1; - player.hasRonned = true; + hand.hasRonned = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isBlessingOfMan(game_state, player, branch)) { + if (isBlessingOfMan(game_state, hand, branch)) { FAIL(); return; } @@ -88,20 +88,20 @@ TEST(isBlessingOfMan, MustBeBeforePlayerFirstTurn) { TEST(isBlessingOfMan, NoCalledMustHaveOccured) { auto game_state = GameState(); - Hand& player = game_state.players[3]; - HandFromNotation("123m123p444m111z55m", &player); - player.open = false; + Hand& hand = game_state.hands[3]; + HandFromNotation("123m123p444m111z55m", &hand); + hand.open = false; game_state.turnNum = 1; game_state.lastCall = 0; - player.hasRonned = true; + hand.hasRonned = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isBlessingOfMan(game_state, player, branch)) { + if (isBlessingOfMan(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/concealedhand.test.cc b/tests/yakus/concealedhand.test.cc index 2f6b0e9b..aefa022e 100644 --- a/tests/yakus/concealedhand.test.cc +++ b/tests/yakus/concealedhand.test.cc @@ -12,44 +12,44 @@ namespace mahjong::yaku { TEST(isFullyConcealedHand, 1Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("555m555p555s111z44m", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("555m555p555s111z44m", &hand); + hand.open = false; game_state.currentPlayer = 0; - EXPECT_TRUE(isFullyConcealedHand(game_state, player)); + EXPECT_TRUE(isFullyConcealedHand(game_state, hand)); } TEST(isFullyConcealedHand, MustTsumo) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("555m555p555s111z44m", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("555m555p555s111z44m", &hand); + hand.open = false; game_state.currentPlayer = 1; - EXPECT_FALSE(isFullyConcealedHand(game_state, player)); + EXPECT_FALSE(isFullyConcealedHand(game_state, hand)); } TEST(isFullyConcealedHand, MustBeClosedPlayer) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("555m555p555s111z44m", &player); - player.open = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("555m555p555s111z44m", &hand); + hand.open = true; game_state.currentPlayer = 0; - EXPECT_FALSE(isFullyConcealedHand(game_state, player)); + EXPECT_FALSE(isFullyConcealedHand(game_state, hand)); } TEST(isFullyConcealedHand, MustHavePiecesRemainingInWall) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("555m555p555s111z44m", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("555m555p555s111z44m", &hand); + hand.open = false; game_state.currentPlayer = 0; // Empty the Wall game_state.livingWallIndex = kLivingWallCount; - EXPECT_FALSE(isFullyConcealedHand(game_state, player)); + EXPECT_FALSE(isFullyConcealedHand(game_state, hand)); } } // namespace mahjong::yaku diff --git a/tests/yakus/concealedpon.test.cc b/tests/yakus/concealedpon.test.cc index 88a31e08..9b5de2b1 100644 --- a/tests/yakus/concealedpon.test.cc +++ b/tests/yakus/concealedpon.test.cc @@ -17,14 +17,14 @@ namespace mahjong::yaku { TEST(isThreeConcealedPons, 2Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m111p111s666z44m", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("111m111p111s666z44m", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeConcealedPons(game_state, player, branch)) { + if (isThreeConcealedPons(game_state, hand, branch)) { SUCCEED(); return; } @@ -34,18 +34,18 @@ TEST(isThreeConcealedPons, 2Han) { TEST(isThreeConcealedPons, PonsMustBeConcealed) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m111p111s44m", &player); - player.melds[player.meld_count++] = Meld{ + Hand& hand = game_state.hands[0]; + HandFromNotation("111m111p111s44m", &hand); + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kChi, .start = kTwoBamboo, }; - player.open = true; + hand.open = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeConcealedPons(game_state, player, branch)) { + if (isThreeConcealedPons(game_state, hand, branch)) { SUCCEED(); return; } @@ -55,18 +55,18 @@ TEST(isThreeConcealedPons, PonsMustBeConcealed) { TEST(isThreeConcealedPons, CanHaveAdditionalOpenPon) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m111p111s44m", &player); - player.melds[player.meld_count++] = Meld{ + Hand& hand = game_state.hands[0]; + HandFromNotation("111m111p111s44m", &hand); + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = kTwoBamboo, }; - player.open = true; + hand.open = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeConcealedPons(game_state, player, branch)) { + if (isThreeConcealedPons(game_state, hand, branch)) { SUCCEED(); return; } @@ -76,18 +76,18 @@ TEST(isThreeConcealedPons, CanHaveAdditionalOpenPon) { TEST(isThreeConcealedPons, PonsMustBeConcealedNegative) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m111p234s44m", &player); - player.melds[player.meld_count++] = Meld{ + Hand& hand = game_state.hands[0]; + HandFromNotation("111m111p234s44m", &hand); + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = kOneBamboo, }; - player.open = true; + hand.open = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeConcealedPons(game_state, player, branch)) { + if (isThreeConcealedPons(game_state, hand, branch)) { FAIL(); return; } @@ -97,14 +97,14 @@ TEST(isThreeConcealedPons, PonsMustBeConcealedNegative) { TEST(isThreeConcealedPons, BadHand) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m111p234567s44m", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("111m111p234567s44m", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeConcealedPons(game_state, player, branch)) { + if (isThreeConcealedPons(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/dragonpon.test.cc b/tests/yakus/dragonpon.test.cc index 91bc7120..d7f3a5d7 100644 --- a/tests/yakus/dragonpon.test.cc +++ b/tests/yakus/dragonpon.test.cc @@ -15,13 +15,13 @@ namespace mahjong::yaku { TEST(isWindOrDragonPon, WhiteDragon) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m555z11z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m555z11z", &hand); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isWhiteDragon(game_state, player, branch)) { + if (isWhiteDragon(game_state, hand, branch)) { SUCCEED(); return; } @@ -31,13 +31,13 @@ TEST(isWindOrDragonPon, WhiteDragon) { TEST(isWindOrDragonPon, GreenDragon) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m666z11z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m666z11z", &hand); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isGreenDragon(game_state, player, branch)) { + if (isGreenDragon(game_state, hand, branch)) { SUCCEED(); return; } @@ -47,13 +47,13 @@ TEST(isWindOrDragonPon, GreenDragon) { TEST(isWindOrDragonPon, RedDragon) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m777z11z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m777z11z", &hand); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isRedDragon(game_state, player, branch)) { + if (isRedDragon(game_state, hand, branch)) { SUCCEED(); return; } @@ -63,13 +63,13 @@ TEST(isWindOrDragonPon, RedDragon) { TEST(isWindOrDragonPon, Kan) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m7777z11z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m7777z11z", &hand); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isRedDragon(game_state, player, branch)) { + if (isRedDragon(game_state, hand, branch)) { SUCCEED(); return; } @@ -79,14 +79,14 @@ TEST(isWindOrDragonPon, Kan) { TEST(isWindOrDragonPon, CanWhenOpen) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m777z11z", &player); - player.open = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m777z11z", &hand); + hand.open = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isRedDragon(game_state, player, branch)) { + if (isRedDragon(game_state, hand, branch)) { SUCCEED(); return; } @@ -96,13 +96,13 @@ TEST(isWindOrDragonPon, CanWhenOpen) { TEST(isWindOrDragonPon, BadHand) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m222p11p", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m222p11p", &hand); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isGreenDragon(game_state, player, branch)) { + if (isGreenDragon(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/fullflush.test.cc b/tests/yakus/fullflush.test.cc index ec5fd268..a1c4af47 100644 --- a/tests/yakus/fullflush.test.cc +++ b/tests/yakus/fullflush.test.cc @@ -20,18 +20,18 @@ namespace mahjong::yaku { TEST(isFullFlush, 5Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m222m345m99m", &player); - player.open = true; - player.melds[player.meld_count++] = Meld{ + Hand& hand = game_state.hands[0]; + HandFromNotation("111m222m345m99m", &hand); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isFullFlush(game_state, player, branch)) { + if (isFullFlush(game_state, hand, branch)) { SUCCEED(); return; } @@ -41,14 +41,14 @@ TEST(isFullFlush, 5Han) { TEST(isFullFlush, 6Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m222m345m666m99m", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("111m222m345m666m99m", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isFullFlush(game_state, player, branch)) { + if (isFullFlush(game_state, hand, branch)) { SUCCEED(); return; } @@ -58,14 +58,14 @@ TEST(isFullFlush, 6Han) { TEST(isFullFlush, BadHandHonors) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m222m111z666m99m", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("111m222m111z666m99m", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isFullFlush(game_state, player, branch)) { + if (isFullFlush(game_state, hand, branch)) { FAIL(); return; } @@ -75,14 +75,14 @@ TEST(isFullFlush, BadHandHonors) { TEST(isFullFlush, BadHandSuit) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m222m111p666m99m", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("111m222m111p666m99m", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isFullFlush(game_state, player, branch)) { + if (isFullFlush(game_state, hand, branch)) { FAIL(); return; } @@ -92,14 +92,14 @@ TEST(isFullFlush, BadHandSuit) { TEST(isFullFlush, BadHandFullFlushHonors) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111z222z333z444z55z", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("111z222z333z444z55z", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isFullFlush(game_state, player, branch)) { + if (isFullFlush(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/halfflush.test.cc b/tests/yakus/halfflush.test.cc index af10b2b1..c3888240 100644 --- a/tests/yakus/halfflush.test.cc +++ b/tests/yakus/halfflush.test.cc @@ -20,18 +20,18 @@ namespace mahjong::yaku { TEST(isHalfFlush, 2Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("11m234m111z222z", &player); - player.open = true; - player.melds[player.meld_count++] = Meld{ + Hand& hand = game_state.hands[0]; + HandFromNotation("11m234m111z222z", &hand); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isHalfFlush(game_state, player, branch)) { + if (isHalfFlush(game_state, hand, branch)) { SUCCEED(); return; } @@ -41,14 +41,14 @@ TEST(isHalfFlush, 2Han) { TEST(isHalfFlush, 3Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("11m234m777m111z222z", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("11m234m777m111z222z", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isHalfFlush(game_state, player, branch)) { + if (isHalfFlush(game_state, hand, branch)) { SUCCEED(); return; } @@ -58,18 +58,18 @@ TEST(isHalfFlush, 3Han) { TEST(isHalfFlush, BadHand) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("11m234m111p222z", &player); - player.open = true; - player.melds[player.meld_count++] = Meld{ + Hand& hand = game_state.hands[0]; + HandFromNotation("11m234m111p222z", &hand); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isHalfFlush(game_state, player, branch)) { + if (isHalfFlush(game_state, hand, branch)) { FAIL(); return; } @@ -79,18 +79,18 @@ TEST(isHalfFlush, BadHand) { TEST(isHalfFlush, FullFlushIncompatible) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("11m234m888m777m", &player); - player.open = true; - player.melds[player.meld_count++] = Meld{ + Hand& hand = game_state.hands[0]; + HandFromNotation("11m234m888m777m", &hand); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kSixCharacter), }; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isHalfFlush(game_state, player, branch)) { + if (isHalfFlush(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/littlethreedragons.test.cc b/tests/yakus/littlethreedragons.test.cc index 960fac9c..38f9c661 100644 --- a/tests/yakus/littlethreedragons.test.cc +++ b/tests/yakus/littlethreedragons.test.cc @@ -20,14 +20,14 @@ namespace mahjong::yaku { TEST(isLittleThreeDragons, 2Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("555z666z111m222p77z", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("555z666z111m222p77z", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isLittleThreeDragons(game_state, player, branch)) { + if (isLittleThreeDragons(game_state, hand, branch)) { SUCCEED(); return; } @@ -37,18 +37,18 @@ TEST(isLittleThreeDragons, 2Han) { TEST(isLittleThreeDragons, WhenOpen) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("666z111m222p77z", &player); - player.open = true; - player.melds[player.meld_count++] = Meld{ + Hand& hand = game_state.hands[0]; + HandFromNotation("666z111m222p77z", &hand); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kWhiteDragon), }; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isLittleThreeDragons(game_state, player, branch)) { + if (isLittleThreeDragons(game_state, hand, branch)) { SUCCEED(); return; } @@ -58,18 +58,18 @@ TEST(isLittleThreeDragons, WhenOpen) { TEST(isLittleThreeDragons, BadHand) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("666z111m222p77s", &player); - player.open = true; - player.melds[player.meld_count++] = Meld{ + Hand& hand = game_state.hands[0]; + HandFromNotation("666z111m222p77s", &hand); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kPon, .start = Piece(kWhiteDragon), }; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isLittleThreeDragons(game_state, player, branch)) { + if (isLittleThreeDragons(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/mixedtriplechi.test.cc b/tests/yakus/mixedtriplechi.test.cc index 2a88dbe6..86505c75 100644 --- a/tests/yakus/mixedtriplechi.test.cc +++ b/tests/yakus/mixedtriplechi.test.cc @@ -16,14 +16,14 @@ namespace mahjong::yaku { TEST(isMixedTripleChi, Open) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123p123m123s555p11z", &player); - player.open = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("123p123m123s555p11z", &hand); + hand.open = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isMixedTripleChi(game_state, player, branch)) { + if (isMixedTripleChi(game_state, hand, branch)) { SUCCEED(); return; } @@ -33,14 +33,14 @@ TEST(isMixedTripleChi, Open) { TEST(isMixedTripleChi, Closed) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123p123m123s555p11z", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("123p123m123s555p11z", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isMixedTripleChi(game_state, player, branch)) { + if (isMixedTripleChi(game_state, hand, branch)) { SUCCEED(); return; } @@ -50,14 +50,14 @@ TEST(isMixedTripleChi, Closed) { TEST(isMixedTripleChi, BadHand) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123p123p123s555p11z", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("123p123p123s555p11z", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isMixedTripleChi(game_state, player, branch)) { + if (isMixedTripleChi(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/outsidehand.test.cc b/tests/yakus/outsidehand.test.cc index 720d7c04..11f1ccbc 100644 --- a/tests/yakus/outsidehand.test.cc +++ b/tests/yakus/outsidehand.test.cc @@ -16,14 +16,14 @@ namespace mahjong::yaku { TEST(isOutsideHand, Open) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m789m111z999s55z", &player); - player.open = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("123m789m111z999s55z", &hand); + hand.open = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isOutsideHand(game_state, player, branch)) { + if (isOutsideHand(game_state, hand, branch)) { SUCCEED(); return; } @@ -33,14 +33,14 @@ TEST(isOutsideHand, Open) { TEST(isOutsideHand, Closed) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m789m111z999s55z", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("123m789m111z999s55z", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isOutsideHand(game_state, player, branch)) { + if (isOutsideHand(game_state, hand, branch)) { SUCCEED(); return; } @@ -50,13 +50,13 @@ TEST(isOutsideHand, Closed) { TEST(isOutsideHand, NoChi) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m111p111s999m66z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("111m111p111s999m66z", &hand); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isOutsideHand(game_state, player, branch)) { + if (isOutsideHand(game_state, hand, branch)) { FAIL(); return; } @@ -66,13 +66,13 @@ TEST(isOutsideHand, NoChi) { TEST(isOutsideHand, BadHand) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m234p111s999m66z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("111m234p111s999m66z", &hand); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isOutsideHand(game_state, player, branch)) { + if (isOutsideHand(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/pinfu.test.cc b/tests/yakus/pinfu.test.cc index c1be1f59..ca911901 100644 --- a/tests/yakus/pinfu.test.cc +++ b/tests/yakus/pinfu.test.cc @@ -18,15 +18,15 @@ namespace mahjong::yaku { TEST(isPinfu, 1Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456p234678s44m", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456p234678s44m", &hand); + hand.open = false; game_state.pendingPiece = Piece(kFourPin); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPinfu(game_state, player, branch)) { + if (isPinfu(game_state, hand, branch)) { SUCCEED(); return; } @@ -36,15 +36,15 @@ TEST(isPinfu, 1Han) { TEST(isPinfu, BadHand) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m555p234678s44m", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("123m555p234678s44m", &hand); + hand.open = false; game_state.pendingPiece = Piece(kTwoBamboo); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPinfu(game_state, player, branch)) { + if (isPinfu(game_state, hand, branch)) { FAIL(); return; } @@ -54,15 +54,15 @@ TEST(isPinfu, BadHand) { TEST(isPinfu, CantBeOpen) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456p234678s44m", &player); - player.open = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456p234678s44m", &hand); + hand.open = true; game_state.pendingPiece = Piece(kFourPin); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPinfu(game_state, player, branch)) { + if (isPinfu(game_state, hand, branch)) { FAIL(); return; } @@ -72,15 +72,15 @@ TEST(isPinfu, CantBeOpen) { TEST(isPinfu, NeedTwoWait) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456p234678s44m", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456p234678s44m", &hand); + hand.open = false; game_state.pendingPiece = Piece(kFivePin); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPinfu(game_state, player, branch)) { + if (isPinfu(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/puredoublechi.test.cc b/tests/yakus/puredoublechi.test.cc index 437e4c8a..123ad6f0 100644 --- a/tests/yakus/puredoublechi.test.cc +++ b/tests/yakus/puredoublechi.test.cc @@ -16,14 +16,14 @@ namespace mahjong::yaku { TEST(isPureDoubleChi, 1Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("234m234m555p888s88p", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("234m234m555p888s88p", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPureDoubleChi(game_state, player, branch)) { + if (isPureDoubleChi(game_state, hand, branch)) { SUCCEED(); return; } @@ -33,14 +33,14 @@ TEST(isPureDoubleChi, 1Han) { TEST(isPureDoubleChi, BadHand) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("234m123m555p888s88p", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("234m123m555p888s88p", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPureDoubleChi(game_state, player, branch)) { + if (isPureDoubleChi(game_state, hand, branch)) { FAIL(); return; } @@ -50,14 +50,14 @@ TEST(isPureDoubleChi, BadHand) { TEST(isPureDoubleChi, MustBeConcealed) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("234m234m555p888s88p", &player); - player.open = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("234m234m555p888s88p", &hand); + hand.open = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPureDoubleChi(game_state, player, branch)) { + if (isPureDoubleChi(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/purestraight.test.cc b/tests/yakus/purestraight.test.cc index c878a1c2..696831ed 100644 --- a/tests/yakus/purestraight.test.cc +++ b/tests/yakus/purestraight.test.cc @@ -16,14 +16,14 @@ namespace mahjong::yaku { TEST(isPureStraight, Open) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m789m555p11z", &player); - player.open = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m789m555p11z", &hand); + hand.open = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPureStraight(game_state, player, branch)) { + if (isPureStraight(game_state, hand, branch)) { SUCCEED(); return; } @@ -33,14 +33,14 @@ TEST(isPureStraight, Open) { TEST(isPureStraight, Closed) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m789m555p11z", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m789m555p11z", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPureStraight(game_state, player, branch)) { + if (isPureStraight(game_state, hand, branch)) { SUCCEED(); return; } @@ -50,14 +50,14 @@ TEST(isPureStraight, Closed) { TEST(isPureStraight, BadHand) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m999m555p11z", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m999m555p11z", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPureStraight(game_state, player, branch)) { + if (isPureStraight(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/riichi.test.cc b/tests/yakus/riichi.test.cc index 08841747..c33340e9 100644 --- a/tests/yakus/riichi.test.cc +++ b/tests/yakus/riichi.test.cc @@ -15,52 +15,52 @@ namespace mahjong::yaku { TEST(isRiichi, Riichi) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("555m555p555s111z44m", &player); - player.riichi = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("555m555p555s111z44m", &hand); + hand.riichi = true; - player.riichiRound = 7; + hand.riichiRound = 7; game_state.turnNum = 15; game_state.lastCall = 2; - EXPECT_TRUE(isRiichi(game_state, player)); + EXPECT_TRUE(isRiichi(game_state, hand)); } TEST(isRiichi, Ippatsu) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("555m555p555s111z44m", &player); - player.riichi = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("555m555p555s111z44m", &hand); + hand.riichi = true; - player.riichiRound = 14; + hand.riichiRound = 14; game_state.turnNum = 15; game_state.lastCall = 2; - EXPECT_TRUE(isIppatsu(game_state, player)); + EXPECT_TRUE(isIppatsu(game_state, hand)); } TEST(isRiichi, DoubleRiichi) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("555m555p555s111z44m", &player); - player.riichi = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("555m555p555s111z44m", &hand); + hand.riichi = true; - player.riichiRound = 1; + hand.riichiRound = 1; game_state.turnNum = 2; game_state.lastCall = -1; - EXPECT_TRUE(isDoubleRiichi(game_state, player)); + EXPECT_TRUE(isDoubleRiichi(game_state, hand)); } TEST(isRiichi, NoRiichi) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("555m555p555s111z44m", &player); - player.riichi = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("555m555p555s111z44m", &hand); + hand.riichi = false; game_state.turnNum = 2; game_state.lastCall = -1; - EXPECT_FALSE(isRiichi(game_state, player)); + EXPECT_FALSE(isRiichi(game_state, hand)); } } // namespace mahjong::yaku diff --git a/tests/yakus/robbingkan.test.cc b/tests/yakus/robbingkan.test.cc index d0adc38d..f802baeb 100644 --- a/tests/yakus/robbingkan.test.cc +++ b/tests/yakus/robbingkan.test.cc @@ -16,15 +16,15 @@ namespace mahjong::yaku { TEST(isRobbingAKan, 1Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m789m1111z999s55z", &player); - game_state.players[0].hasRonned = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("123m789m1111z999s55z", &hand); + game_state.hands[0].hasRonned = true; game_state.nextState = StateFunctionType::kKanDiscard; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isRobbingAKan(game_state, player, branch)) { + if (isRobbingAKan(game_state, hand, branch)) { SUCCEED(); return; } @@ -34,15 +34,15 @@ TEST(isRobbingAKan, 1Han) { TEST(isRobbingAKan, DoesntApply) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m789m1111z999s55z", &player); - game_state.players[0].hasRonned = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("123m789m1111z999s55z", &hand); + game_state.hands[0].hasRonned = true; game_state.nextState = StateFunctionType::kPon; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isRobbingAKan(game_state, player, branch)) { + if (isRobbingAKan(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/sevenpairs.test.cc b/tests/yakus/sevenpairs.test.cc index 3b57b09f..f5f41633 100644 --- a/tests/yakus/sevenpairs.test.cc +++ b/tests/yakus/sevenpairs.test.cc @@ -16,14 +16,14 @@ namespace mahjong::yaku { TEST(isSevenPairs, 2Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("11m22p33s44z55m11z66z", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("11m22p33s44z55m11z66z", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSevenPairs(game_state, player, branch)) { + if (isSevenPairs(game_state, hand, branch)) { SUCCEED(); return; } @@ -33,14 +33,14 @@ TEST(isSevenPairs, 2Han) { TEST(isSevenPairs, MustBeConcealed) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("11m22p33s44z55m11z66z", &player); - player.open = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("11m22p33s44z55m11z66z", &hand); + hand.open = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSevenPairs(game_state, player, branch)) { + if (isSevenPairs(game_state, hand, branch)) { FAIL(); return; } @@ -50,14 +50,14 @@ TEST(isSevenPairs, MustBeConcealed) { TEST(isSevenPairs, UniquePairsOnly) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("1111m22p33s44z11z66z", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("1111m22p33s44z11z66z", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSevenPairs(game_state, player, branch)) { + if (isSevenPairs(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/terminalinsets.test.cc b/tests/yakus/terminalinsets.test.cc index c00d4581..886e2454 100644 --- a/tests/yakus/terminalinsets.test.cc +++ b/tests/yakus/terminalinsets.test.cc @@ -19,18 +19,18 @@ namespace mahjong::yaku { TEST(isTerminalsInAllSets, 2Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m789m111p11s", &player); - player.open = true; - player.melds[player.meld_count++] = Meld{ + Hand& hand = game_state.hands[0]; + HandFromNotation("123m789m111p11s", &hand); + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kChi, .start = Piece(kSevenPin), }; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTerminalsInAllSets(game_state, player, branch)) { + if (isTerminalsInAllSets(game_state, hand, branch)) { SUCCEED(); return; } @@ -40,14 +40,14 @@ TEST(isTerminalsInAllSets, 2Han) { TEST(isTerminalsInAllSets, 3Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m789m111p789p11s", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("123m789m111p789p11s", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTerminalsInAllSets(game_state, player, branch)) { + if (isTerminalsInAllSets(game_state, hand, branch)) { SUCCEED(); return; } @@ -57,19 +57,19 @@ TEST(isTerminalsInAllSets, 3Han) { TEST(isTerminalsInAllSets, BadHand) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m789m222p11s", &player); - player.open = true; - player.open = true; - player.melds[player.meld_count++] = Meld{ + Hand& hand = game_state.hands[0]; + HandFromNotation("123m789m222p11s", &hand); + hand.open = true; + hand.open = true; + hand.melds[hand.meld_count++] = Meld{ .type = SetType::kChi, .start = Piece(kSevenPin), }; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTerminalsInAllSets(game_state, player, branch)) { + if (isTerminalsInAllSets(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/triplekan.test.cc b/tests/yakus/triplekan.test.cc index 76971454..d78ebd9b 100644 --- a/tests/yakus/triplekan.test.cc +++ b/tests/yakus/triplekan.test.cc @@ -32,16 +32,16 @@ TEST(isThreeKans, 2Han) { }; auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("666z22m", &player); - player.melds = {meld_a, meld_b, meld_c}; - player.meld_count = 3; - player.open = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("666z22m", &hand); + hand.melds = {meld_a, meld_b, meld_c}; + hand.meld_count = 3; + hand.open = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeKans(game_state, player, branch)) { + if (isThreeKans(game_state, hand, branch)) { SUCCEED(); return; } @@ -68,16 +68,16 @@ TEST(isThreeKans, WithOtherMelds) { }; auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("22m", &player); - player.melds = {meld_a, meld_b, meld_c, meld_d}; - player.meld_count = 4; - player.open = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("22m", &hand); + hand.melds = {meld_a, meld_b, meld_c, meld_d}; + hand.meld_count = 4; + hand.open = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeKans(game_state, player, branch)) { + if (isThreeKans(game_state, hand, branch)) { SUCCEED(); return; } @@ -96,16 +96,16 @@ TEST(isThreeKans, BadHand) { }; auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("777p666z22m", &player); - player.melds = {meld_a, meld_b}; - player.meld_count = 2; - player.open = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("777p666z22m", &hand); + hand.melds = {meld_a, meld_b}; + hand.meld_count = 2; + hand.open = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeKans(game_state, player, branch)) { + if (isThreeKans(game_state, hand, branch)) { FAIL(); return; } @@ -128,16 +128,16 @@ TEST(isThreeKans, AllConcealed) { }; auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("666z22m", &player); - player.melds = {meld_a, meld_b, meld_c}; - player.meld_count = 3; - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("666z22m", &hand); + hand.melds = {meld_a, meld_b, meld_c}; + hand.meld_count = 3; + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isThreeKans(game_state, player, branch)) { + if (isThreeKans(game_state, hand, branch)) { SUCCEED(); return; } diff --git a/tests/yakus/triplepon.test.cc b/tests/yakus/triplepon.test.cc index 08342f03..b81d36f2 100644 --- a/tests/yakus/triplepon.test.cc +++ b/tests/yakus/triplepon.test.cc @@ -16,13 +16,13 @@ namespace mahjong::yaku { TEST(isTriplePon, 2Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m111p111s666z44m", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("111m111p111s666z44m", &hand); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTriplePon(game_state, player, branch)) { + if (isTriplePon(game_state, hand, branch)) { SUCCEED(); return; } @@ -32,13 +32,13 @@ TEST(isTriplePon, 2Han) { TEST(isTriplePon, BadHand) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("111m111p222m666z44m", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("111m111p222m666z44m", &hand); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTriplePon(game_state, player, branch)) { + if (isTriplePon(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/twicepuredoublechi.test.cc b/tests/yakus/twicepuredoublechi.test.cc index c95ae256..0afdab77 100644 --- a/tests/yakus/twicepuredoublechi.test.cc +++ b/tests/yakus/twicepuredoublechi.test.cc @@ -16,14 +16,14 @@ namespace mahjong::yaku { TEST(isTwicePureDoubleChi, 3Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("789p789p234m234m11z", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("789p789p234m234m11z", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTwicePureDoubleChi(game_state, player, branch)) { + if (isTwicePureDoubleChi(game_state, hand, branch)) { SUCCEED(); return; } @@ -33,14 +33,14 @@ TEST(isTwicePureDoubleChi, 3Han) { TEST(isTwicePureDoubleChi, MustBeConcealed) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("789p789p234m234m11z", &player); - player.open = true; + Hand& hand = game_state.hands[0]; + HandFromNotation("789p789p234m234m11z", &hand); + hand.open = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTwicePureDoubleChi(game_state, player, branch)) { + if (isTwicePureDoubleChi(game_state, hand, branch)) { FAIL(); return; } @@ -50,14 +50,14 @@ TEST(isTwicePureDoubleChi, MustBeConcealed) { TEST(isTwicePureDoubleChi, BadHand) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("789p789p234m567m11z", &player); - player.open = false; + Hand& hand = game_state.hands[0]; + HandFromNotation("789p789p234m567m11z", &hand); + hand.open = false; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isTwicePureDoubleChi(game_state, player, branch)) { + if (isTwicePureDoubleChi(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/underthesea.test.cc b/tests/yakus/underthesea.test.cc index 256b6de6..db7b4c96 100644 --- a/tests/yakus/underthesea.test.cc +++ b/tests/yakus/underthesea.test.cc @@ -15,14 +15,14 @@ namespace mahjong::yaku { TEST(isBottomOfTheSea, 1Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m789m111z999s55z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m789m111z999s55z", &hand); game_state.livingWallIndex = kLivingWallCount; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isBottomOfTheSea(game_state, player, branch)) { + if (isBottomOfTheSea(game_state, hand, branch)) { SUCCEED(); return; } @@ -32,15 +32,15 @@ TEST(isBottomOfTheSea, 1Han) { TEST(isBottomOfTheSea, 1HanRonned) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m789m111z999s55z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m789m111z999s55z", &hand); game_state.livingWallIndex = kLivingWallCount; - game_state.players[0].hasRonned = true; + game_state.hands[0].hasRonned = true; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isBottomOfTheSea(game_state, player, branch)) { + if (isBottomOfTheSea(game_state, hand, branch)) { SUCCEED(); return; } @@ -50,13 +50,13 @@ TEST(isBottomOfTheSea, 1HanRonned) { TEST(isBottomOfTheSea, DoesntApply) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m789m111z999s55z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m789m111z999s55z", &hand); - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isBottomOfTheSea(game_state, player, branch)) { + if (isBottomOfTheSea(game_state, hand, branch)) { FAIL(); return; } diff --git a/tests/yakus/windpons.test.cc b/tests/yakus/windpons.test.cc index 5bb7ea20..bf4000ea 100644 --- a/tests/yakus/windpons.test.cc +++ b/tests/yakus/windpons.test.cc @@ -15,16 +15,16 @@ namespace mahjong::yaku { TEST(isWindOrDragonPon, SeatWind) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m444z55z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m444z55z", &hand); game_state.roundNum = 1; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); auto branches = Node::AsBranchVectors(root.get()); for (const auto& branch : branches) { - if (isSeatWind(game_state, player, branch)) { + if (isSeatWind(game_state, hand, branch)) { SUCCEED(); return; } @@ -35,14 +35,14 @@ TEST(isWindOrDragonPon, SeatWind) { TEST(isWindOrDragonPon, SeatWindKan) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m4444z55z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m4444z55z", &hand); game_state.roundNum = 1; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSeatWind(game_state, player, branch)) { + if (isSeatWind(game_state, hand, branch)) { SUCCEED(); return; } @@ -52,14 +52,14 @@ TEST(isWindOrDragonPon, SeatWindKan) { TEST(isWindOrDragonPon, PrevalentWind) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m111z55z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m111z55z", &hand); game_state.roundNum = 1; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPrevalentWind(game_state, player, branch)) { + if (isPrevalentWind(game_state, hand, branch)) { SUCCEED(); return; } @@ -69,14 +69,14 @@ TEST(isWindOrDragonPon, PrevalentWind) { TEST(isWindOrDragonPon, PrevalentWindKan) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m1111z55z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m1111z55z", &hand); game_state.roundNum = 1; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isPrevalentWind(game_state, player, branch)) { + if (isPrevalentWind(game_state, hand, branch)) { SUCCEED(); return; } @@ -86,15 +86,15 @@ TEST(isWindOrDragonPon, PrevalentWindKan) { TEST(isWindOrDragonPon, Dealer2Han) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m111z55z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m111z55z", &hand); game_state.roundNum = 0; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSeatWind(game_state, player, branch) && - isPrevalentWind(game_state, player, branch)) { + if (isSeatWind(game_state, hand, branch) && + isPrevalentWind(game_state, hand, branch)) { SUCCEED(); return; } @@ -104,15 +104,15 @@ TEST(isWindOrDragonPon, Dealer2Han) { TEST(isWindOrDragonPon, Dealer2HanKan) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m1111z55z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m1111z55z", &hand); game_state.roundNum = 0; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSeatWind(game_state, player, branch) && - isPrevalentWind(game_state, player, branch)) { + if (isSeatWind(game_state, hand, branch) && + isPrevalentWind(game_state, hand, branch)) { SUCCEED(); return; } @@ -122,15 +122,15 @@ TEST(isWindOrDragonPon, Dealer2HanKan) { TEST(isWindOrDragonPon, NotSeatOrPrevalent) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m222z55z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m222z55z", &hand); game_state.roundNum = 0; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSeatWind(game_state, player, branch) || - isPrevalentWind(game_state, player, branch)) { + if (isSeatWind(game_state, hand, branch) || + isPrevalentWind(game_state, hand, branch)) { FAIL(); return; } @@ -140,15 +140,15 @@ TEST(isWindOrDragonPon, NotSeatOrPrevalent) { TEST(isWindOrDragonPon, NoWind) { auto game_state = GameState(); - Hand& player = game_state.players[0]; - HandFromNotation("123m456m666m55z", &player); + Hand& hand = game_state.hands[0]; + HandFromNotation("123m456m666m55z", &hand); game_state.roundNum = 0; - auto root = breakdownHand(player.live_range()); + auto root = breakdownHand(hand.live_range()); for (const auto& branch : Node::AsBranchVectors(root.get())) { - if (isSeatWind(game_state, player, branch) || - isPrevalentWind(game_state, player, branch)) { + if (isSeatWind(game_state, hand, branch) || + isPrevalentWind(game_state, hand, branch)) { FAIL(); return; }