Libsaki
Core library of Pancake Mahjong
meld.h
1 #ifndef SAKI_MELD_H
2 #define SAKI_MELD_H
3 
4 #include "tile.h"
5 
6 #include <initializer_list>
7 #include <ostream>
8 #include <algorithm>
9 
10 
11 
12 namespace saki
13 {
14 
15 
16 
17 class M37
18 {
19 public:
20  enum class Type
21  {
22  // *** SYNC with string_enum.cpp ***
23  CHII, PON, DAIMINKAN, ANKAN, KAKAN
24  };
25 
26  M37() = default; // garbage value
27  M37(const M37 &copy) = default;
28  M37 &operator=(const M37 &assign) = default;
29  ~M37() = default;
30 
31  static M37 chii(const T37 &l, const T37 &m, const T37 &r, int lay)
32  {
33  M37 bark(Type::CHII, lay, { l, m, r });
34  return bark;
35  }
36 
37  static M37 pon(const T37 &l, const T37 &m, const T37 &r, int lay)
38  {
39  assert(lay == 0 || lay == 1 || lay == 2);
40  M37 bark(Type::PON, lay, { l, m, r });
41  return bark;
42  }
43 
44  static M37 daiminkan(const T37 &l, const T37 &m, const T37 &r, const T37 &x,
45  int lay)
46  {
47  assert(lay == 0 || lay == 1 || lay == 2);
48  M37 bark(Type::DAIMINKAN, lay, { l, m, r, x });
49  return bark;
50  }
51 
52  static M37 ankan(const T37 &l, const T37 &m, const T37 &r, const T37 &x)
53  {
54  M37 bark(Type::ANKAN, -1, { l, m, r, x });
55  return bark;
56  }
57 
58  void kakan(const T37 &x)
59  {
60  assert(mType == Type::PON);
61  mTiles.pushBack(x);
62  mType = Type::KAKAN;
63  }
64 
65  Type type() const
66  {
67  return mType;
68  }
69 
70  int layIndex() const
71  {
72  return mLay;
73  }
74 
75  unsigned uLayIndex() const
76  {
77  return static_cast<unsigned>(mLay);
78  }
79 
80  const util::Stactor<T37, 4> &tiles() const
81  {
82  return mTiles;
83  }
84 
85  const T37 &operator[](int i) const
86  {
87  return mTiles[static_cast<size_t>(i)];
88  }
89 
90  bool isCpdmk() const
91  {
92  return mType == Type::CHII
93  || mType == Type::PON
94  || mType == Type::DAIMINKAN;
95  }
96 
97  bool isKan() const
98  {
99  return mType == Type::DAIMINKAN
100  || mType == Type::ANKAN
101  || mType == Type::KAKAN;
102  }
103 
104  bool has(T34 t) const
105  {
106  switch (mType) {
107  case Type::CHII:
108  return t == mTiles[0] || t == mTiles[1] || t == mTiles[2];
109  default:
110  return t == mTiles[0];
111  }
112  }
113 
114 private:
115  M37(Type type, int lay, std::initializer_list<T37> tiles)
116  : mType(type)
117  , mLay(lay)
118  , mTiles(tiles)
119  {
120  }
121 
122 private:
123  Type mType;
124  int mLay;
125  util::Stactor<T37, 4> mTiles;
126 };
127 
128 inline int operator%(T34 ind, const M37 &m)
129 {
130  const auto &ts = m.tiles();
131  auto res = std::count(ts.begin(), ts.end(), ind.dora());
132  return static_cast<int>(res);
133 }
134 
135 inline std::ostream &operator<<(std::ostream &os, const M37 &m)
136 {
137  for (const T37 &t : m.tiles()) {
138  os << (t.isAka5() ? 0 : t.val());
139  }
140 
141  os << T34::charOf(m[0].suit());
142  return os;
143 }
144 
145 
146 
147 } // namespace saki
148 
149 
150 
151 #endif // SAKI_MELD_H
Definition: tile.h:25
Definition: ai.cpp:18
Definition: tile.h:353
Definition: meld.h:17
Stactor = statically allocated vector.
Definition: stactor.h:247