Skip to content

固有形

定義

除去可能面子
\(3N+1\)(または\(3N+2\))聴牌形\(h \in H\)に対して, その面子を除いても聴牌を維持するものを除去可能面子と定義する.
固定面子
除去可能面子のうち, 待ちを不変に保つものを固定面子と定義する.

固定面子を用いて以下の 3 種類の固有形を定義する.

\(3N+1\)聴牌固有形
\(h \in H\)\(3N+1\)聴牌形で固定面子を持たないならば, \(h \in H\)\(3N+1\)聴牌固有形である.
\(3N+2\)聴牌固有形
\(h^n \in H^n\)\(3N+2\)聴牌形であるが\(3N+2\)和了形ではなく固定面子を持たないならば, \(h^n \in H^n\)\(3N+2\)聴牌固有形である.
\(3N+2\)和了聴牌固有形
\(h^n \in H^n\)\(3N+2\)聴牌形であると同時に\(3N+2\)和了形であり固定面子を持たないならば, \(h^n \in H^n\)\(3N+2\)和了聴牌固有形である.

固有形の分類

任意の\(3N+1\)聴牌固有形は以下のいずれかのパターンに分類される.

  • \(3N+2\)聴牌固有形 1 つと雀頭の組み合わせ(雀頭固定型)
  • \(3N+2\)和了聴牌固有形 2 つの組み合わせ(シャボ型)
  • 上記以外(一体型)

ソースコード

固定面子の取り扱いには注意が必要である. 除去可能面子を除いた後の手牌の待ちを\(W'\), 元の手牌の待ちを\(W\)とすると基本的には\(W' \subseteq{W}\)となる. しかし, 2222345 のような 4 枚使いが含まれる手牌の場合, 除去可能面子 222 を除くと 2 が待ちに含まれるようになるから\(W' \supset{W}\)となり得る. そこで\(W' = W\)となる除去可能面子を固定面子とするのではなく\(W' \supseteq{W}\)となる除去可能面子を固定面子とみなす. 5 枚目の牌を待ちに含めるのであれば\(W' \supset{W}\)となることはなく 2222345 は固有形にはならない. 5 枚目の牌を待ちに含める場合においても 2222345 のような手牌を固有形としないようにするため上記定義の修正を行った.

3N+1 聴牌固有形判定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
bool isuf1(int* h)
{
  auto wait = isrh1(h);

  for (int i = 0; i < 9; ++i) {
    if (h[i] >= 3) {
      h[i] -= 3;
      auto tmp = isrh1(h);
      h[i] += 3;

      if (((~wait | tmp) & ((1 << 9) - 1)) == (1 << 9) - 1) {
        return false;
      }
    }
  }
  for (int i = 0; i < 7; ++i) {
    if (h[i] >= 1 && h[i + 1] >= 1 && h[i + 2] >= 1) {
      --h[i];
      --h[i + 1];
      --h[i + 2];
      auto tmp = isrh1(h);
      ++h[i];
      ++h[i + 1];
      ++h[i + 2];

      if (((~wait | tmp) & ((1 << 9) - 1)) == (1 << 9) - 1) {
        return false;
      }
    }
  }
  return true;
}

3N+2 聴牌固有形判定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
bool isuf2(int* h)
{
  auto wait = isrh2(h);

  for (int i = 0; i < 9; ++i) {
    if (h[i] >= 3) {
      h[i] -= 3;
      auto tmp = isrh2(h);
      h[i] += 3;

      if (((~wait | tmp) & ((1 << 9) - 1)) == (1 << 9) - 1) {
        return false;
      }
    }
  }
  for (int i = 0; i < 7; ++i) {
    if (h[i] >= 1 && h[i + 1] >= 1 && h[i + 2] >= 1) {
      --h[i];
      --h[i + 1];
      --h[i + 2];
      auto tmp = isrh2(h);
      ++h[i];
      ++h[i + 1];
      ++h[i + 2];

      if (((~wait | tmp) & ((1 << 9) - 1)) == (1 << 9) - 1) {
        return false;
      }
    }
  }
  return true;
}

3N+2 和了聴牌固有形判定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
bool iswr2(int* h)
{
  auto wait = isrh2(h);

  for (int i = 0; i < 9; ++i) {
    if (h[i] >= 3) {
      h[i] -= 3;
      auto tmp = isrh2(h);

      if (((~wait | tmp) & ((1 << 9) - 1)) == (1 << 9) - 1 && iswh2(h)) {
        h[i] += 3;
        return false;
      }
      else h[i] += 3;
    }
  }
  for (int i = 0; i < 7; i++) {
    if (h[i] >= 1 && h[i + 1] >= 1 && h[i + 2] >= 1) {
      --h[i];
      --h[i + 1];
      --h[i + 2];
      auto tmp = isrh2(h);

      if (((~wait | tmp) & ((1 << 9) - 1)) == (1 << 9) - 1 && iswh2(h)) {
        ++h[i];
        ++h[i + 1];
        ++h[i + 2];
        return false;
      }
      else {
        ++h[i];
        ++h[i + 1];
        ++h[i + 2];
      }
    }
  }
  return true;
}