Libsaki
Core library of Pancake Mahjong
action.h
1 #ifndef SAKI_ACTION_H
2 #define SAKI_ACTION_H
3 
4 #include "tile.h"
5 #include "who.h"
6 
7 
8 
9 namespace saki
10 {
11 
12 
13 
14 enum ActCode {
15  // the order is priority, lower to higher, or does not matter
16  // *** SYNC with stringOf(ActCode) ***
17  NOTHING, PASS, SWAP_OUT, SPIN_OUT, SWAP_RIICHI, SPIN_RIICHI,
18  CHII_AS_LEFT, CHII_AS_MIDDLE, CHII_AS_RIGHT,
19  PON, DAIMINKAN, ANKAN, KAKAN, TSUMO, RON,
20  RYUUKYOKU, END_TABLE, NEXT_ROUND, DICE,
21  IRS_CHECK, IRS_CLICK,
22  NUM_ACTCODE
23 };
24 
25 
26 
27 class Action
28 {
29 public:
30  Action()
31  : mAct(ActCode::NOTHING)
32  {
33  }
34 
35  explicit Action(ActCode act)
36  : mAct(act)
37  , mArg(0) // use zero to guarentee equality
38  {
39  assert(!argIsOneT37()
40  && !isCp()
41  && mAct != ActCode::ANKAN
42  && mAct != ActCode::KAKAN
43  && mAct != ActCode::IRS_CHECK);
44  }
45 
46  explicit Action(ActCode act, int arg)
47  : mAct(act)
48  , mArg(arg)
49  {
50  assert(mAct == ActCode::KAKAN);
51  }
52 
53  explicit Action(ActCode act, unsigned mask)
54  : mAct(act)
55  , mMask(mask)
56  {
57  assert(mAct == ActCode::IRS_CHECK);
58  }
59 
60  explicit Action(ActCode act, const T37 &t)
61  : mAct(act)
62  , mT37(t)
63  {
64  assert(argIsOneT37());
65  }
66 
67  explicit Action(ActCode act, T34 t)
68  : mAct(act)
69  , mT34(t)
70  {
71  assert(mAct == ActCode::ANKAN);
72  }
73 
74  explicit Action(ActCode act, int showAka5, const T37 &t)
75  : mAct(act)
76  , mArg(showAka5)
77  , mT37(t)
78  {
79  assert(isCp());
80  }
81 
82  Action(const Action &copy) = default;
83  Action &operator=(const Action &assign) = default;
84  ~Action() = default;
85 
86  bool argIsOneT37() const
87  {
88  return mAct == ActCode::SWAP_OUT || mAct == ActCode::SWAP_RIICHI;
89  }
90 
91  bool argIsOneIntegral() const
92  {
93  return mAct == ActCode::KAKAN || mAct == ActCode::IRS_CHECK;
94  }
95 
96  ActCode act() const
97  {
98  return mAct;
99  }
100 
101  const T37 &t37() const
102  {
103  assert(argIsOneT37() || isCp());
104  return mT37;
105  }
106 
107  T34 t34() const
108  {
109  assert(mAct == ActCode::ANKAN);
110  return mT34;
111  }
112 
113  int showAka5() const
114  {
115  assert(isCp());
116  return mArg;
117  }
118 
119  int barkId() const
120  {
121  assert(mAct == ActCode::KAKAN);
122  return mArg;
123  }
124 
125  unsigned mask() const
126  {
127  assert(mAct == ActCode::IRS_CHECK);
128  return mMask;
129  }
130 
131  bool isDiscard() const
132  {
133  return mAct == ActCode::SWAP_OUT || mAct == ActCode::SPIN_OUT;
134  }
135 
136  bool isRiichi() const
137  {
138  return mAct == ActCode::SWAP_RIICHI || mAct == ActCode::SPIN_RIICHI;
139  }
140 
141  bool isChii() const
142  {
143  return mAct == ActCode::CHII_AS_LEFT
144  || mAct == ActCode::CHII_AS_MIDDLE
145  || mAct == ActCode::CHII_AS_RIGHT;
146  }
147 
148  bool isCp() const
149  {
150  return mAct == ActCode::CHII_AS_LEFT
151  || mAct == ActCode::CHII_AS_MIDDLE
152  || mAct == ActCode::CHII_AS_RIGHT
153  || mAct == ActCode::PON;
154  }
155 
156  bool isCpdmk() const
157  {
158  return isCp() || mAct == ActCode::DAIMINKAN;
159  }
160 
161  bool isIrs() const
162  {
163  return mAct == ActCode::IRS_CHECK || mAct == ActCode::IRS_CLICK;
164  }
165 
166  bool operator==(const Action &that) const
167  {
168  if (mAct != that.mAct)
169  return false;
170 
171  if (argIsOneT37())
172  return mT37 == that.mT37;
173 
174  if (isCp())
175  return mArg == that.mArg && mT37 == that.mT37;
176 
177  if (argIsOneIntegral())
178  return mArg == that.mArg;
179 
180  return true;
181  }
182 
183  Action toRiichi() const
184  {
185  if (isRiichi())
186  return *this;
187 
188  assert(isDiscard());
189  return mAct == ActCode::SPIN_OUT ? Action(ActCode::SPIN_RIICHI)
190  : Action(ActCode::SWAP_RIICHI, mT37);
191  }
192 
193  Action toDiscard() const
194  {
195  if (isDiscard())
196  return *this;
197 
198  assert(isRiichi());
199  return mAct == ActCode::SPIN_RIICHI ? Action(ActCode::SPIN_OUT)
200  : Action(ActCode::SWAP_OUT, mT37);
201  }
202 
203 private:
204  ActCode mAct;
205  union
206  {
207  int mArg;
208  unsigned mMask;
209  };
210  union
211  {
212  T37 mT37;
213  T34 mT34;
214  };
215 
216  static_assert(sizeof(int) == sizeof(unsigned), "mArg representing ability");
217 };
218 
219 
220 
221 } // namespace saki
222 
223 
224 
225 #endif // SAKI_ACTION_H
Definition: tile.h:25
Definition: action.h:27
Definition: ai.cpp:18
Definition: tile.h:353