Coverage Report

Created: 2025-09-03 03:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/nix/store/i1aar97n7b4yf8rk94p66if25brfvvdx-gqvzl8a5pvrg3xj44q0msrndcripi8dk-source/src/scoring/yakus/ninegates.cc
Line
Count
Source
1
#include "scoring/yakus/ninegates.h"
2
3
#include <map>
4
#include <vector>
5
6
#include "analysis/handnode.h"
7
#include "scoring/yakus.h"
8
#include "scoring/yakus/fullflush.h"
9
#include "types/gamestate.h"
10
#include "types/yaku.h"
11
12
namespace mahjong::yaku {
13
bool isNineGates(const GameState& state, int player,
14
0
                 const std::vector<const mahjong::Node*>& branch) {
15
0
  if (state.hands.at(player).open) {
16
0
    return false;
17
0
  }
18
0
  if (!isFullFlush(state, player, branch)) {
19
0
    return false;
20
0
  }
21
0
  if (state.hands.at(player).open) {
22
0
    return false;
23
0
  }
24
0
  std::map<int, int> pieces;
25
0
  for (int i = 1; i < 10; i++) {
26
0
    pieces.at(i) = 0;
27
0
  }
28
0
  bool duplicate = false;
29
0
  for (const auto& piece : state.hands.at(player).live) {
30
0
    if (pieces.contains(piece.getPieceNum())) {
31
0
      if ((pieces[piece.getPieceNum()] != 0) && !piece.isTerminal()) {
32
0
        if (duplicate) {
33
0
          return false;
34
0
        }
35
0
        duplicate = true;
36
0
      } else {
37
0
        pieces[piece.getPieceNum()]++;
38
0
      }
39
0
    }
40
0
  }
41
0
  if (!duplicate) {
42
0
    return false;
43
0
  }
44
0
  for (const auto& [piece, count] : pieces) {
45
0
    if ((piece == 1 || piece == 9)) {
46
0
      if (count != 3) {
47
0
        return false;
48
0
      }
49
0
    } else if (count != 1) {
50
0
      return false;
51
0
    }
52
0
  }
53
0
  return true;
54
0
}
55
56
REGISTER_YAKU({
57
    .id = "ninegates",
58
    .name = "Nine Gates",
59
    .type = Yaku::kYakuman,
60
    .value = 1,
61
    .is_yaku_func = yaku::isNineGates,
62
});
63
}  // namespace mahjong::yaku