Skip to content

Instantly share code, notes, and snippets.

@Muratam
Last active March 13, 2023 12:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Muratam/da580c0c3360610adae883b9d8eaccef to your computer and use it in GitHub Desktop.
Save Muratam/da580c0c3360610adae883b9d8eaccef to your computer and use it in GitHub Desktop.

The Mahjong Language

プログラムコードは 🀀🀁🀂🀃🀄🀅🀆 🀇🀈🀉🀊🀋🀌🀍🀎🀏 🀐🀑🀒🀓🀔🀕🀖🀗🀘 🀙🀚🀛🀜🀝🀞🀟🀠🀡 の文字列のみで構成される。

言葉の定義

  • 牌: 「🀀🀁🀂🀃🀄🀅🀆 🀇🀈🀉🀊🀋🀌🀍🀎🀏 🀐🀑🀒🀓🀔🀕🀖🀗🀘 🀙🀚🀛🀜🀝🀞🀟🀠🀡」の34種類の麻雀牌を表す文字のいずれか1文字
  • 山: 牌のみで構成される文字列。長さに制限はない
  • 雀士: この言語を解釈し、実行する仮想的な人物. 以下を持つ.
    • 手牌: 長さ13の山。初期値「🀄🀄🀄🀄🀄🀄🀄🀄🀄🀄🀄🀄🀄」
    • PC(Program Counter): int64型の数。初期値 0。
    • R,L,I: int64型の数。初期値 0。
    • MEM: 長さ65536のint64型の配列。全て初期値は0。
  • ロン牌: 山[PC]。[] は文字列へのunicode単位での0-indexedな添字演算。
    • 厳密には 山[((PC % 山の長さ) + 山の長さ) % 山の長さ]. % は剰余計算.
    • 山の長さが0の場合は未定義.
  • 役: 文字列の集合
  • ロン: ロン牌と雀士の手牌から役を得ること。詳しくは後述

プログラムの実行

以下の順序で行う。

  1. コードを山として読み込む。牌以外の種類の文字はすべて無視する。
  2. 雀士はロン牌をロンできるならロンし,得た役に後述の「役の演算」を行う。
  3. 雀士はロン牌を手牌の最後(右端)に加え、最前(左端)の牌を捨てる。
  4. 雀士はPCに1を足す
  5. 2.に戻る

ロン

雀士の手牌とロン牌を「麻雀天鳳四麻での手牌と門前ロンでのあたり牌」と考えて、役を得る。日本麻雀の計算として基本的には [麻雀天鳳のルール-段位戦4人打ち]https://tenhou.net/man/#RULE) を使用するが、以下が異なる。

  • フリテン・同巡・途中流局・河・流し満貫・リーチ・ダブリー・ツモ・海底・人和・ドラ・アガリ・王牌・パオ・チー・ポン・カン・ウマ・赤ドラ・サドンデス・トビ・点数という概念はこの言語には存在しない。
  • 自風は東固定。場風は北固定。
  • 同じ牌が5枚以上手牌に含まれている場合は役は得られない。常識的に考えて不正な手牌なので。

役の演算

  • 以下の順序で上から順に見ていき、役の中に該当するものがあれば、描かれている内容の演算を実行する。演算説明としてC++20で定義されている関数・演算を用いる。
    • I はMEMへのアクセス用途の変数として使われる
      • MEM[I] は、厳密にはMEMの長さLとして、 MEM[((I%L)+L)%L] としてアクセスする。
    • R は計算結果を一時的に保存するためのレジスタ変数として使われる
    • L は更に一時的な変数を保持するための変数として使われる
    • ロン牌のunicode値 は 0x1f000 ~ 0x1f021 の値となる

R - PC R - I R - MEM[I] - stdio

  • 🀃: MEM[I] = getchar()
  • 🀀: putchar(MEM[I])
  • 🀆: R = MEM[I]
  • 🀅: MEM[I] = R
  • 🀄: swap(R, MEM[I])
  • 断么九: R = L
  • 一盃口: L = R
  • 平和: swap(R, L)
  • 一気通貫: PC = R
  • 三色同順: PC += R
  • 混老頭: I = 0
  • 三色同刻: I -= 1
  • 対々和: I += 1
  • 三暗刻: I -= 1
  • 二盃口: R = PC
  • 七対子: R = ロン牌のunicode値 - 0x1f000
  • 混全帯幺九: R += 1
  • 純全帯幺九: R *= 2
  • 混一色: I += R
  • 清一色: I = R
  • 小三元: R = (R < 0 ? -1 : R > 0 ? 1 : 0)
  • 大三元: R = (R < MEM[I] ? -1 : R > MEM[I] ? 1 : 0)
  • 緑一色: R += MEM[I]
  • 字一色: R -= MEM[I]
  • 清老頭: R *= MEM[I]
  • 大四喜: R /= MEM[I]
  • 小四喜: R %= MEM[I]
  • 四暗刻単騎: I += 1
  • 九蓮宝燈: R = I
  • 国士無双: R = 0
  • 国士無双十三面待ち: R != 0 ならプログラムを終了する
  • 純正九蓮宝燈: プログラムを終了する

サンプルプログラム

Hello, World!

🀊🀊🀇🀇🀐🀐🀑🀑🀒🀒🀉🀉...続く

コメント付きサンプルプログラム

0=🀀🀁🀂🀃🀄🀅🀆7=🀇🀈🀉🀊🀋🀌🀍🀎🀏16=🀐🀑🀒🀓🀔🀕🀖🀗🀘25=🀙🀚🀛🀜🀝🀞🀟🀠🀡 Hello, World!

72 101 108 108 111 44 32 87 111 114 108 100 33 を作って出力
72 { R = 9; R *= 2; R *= 2; put }
🀊🀊🀒🀑🀒🀑🀐🀐🀇🀇🀉🀉; 🀈🀙🀐🀈🀙🀐; 🀒; 🀋🀋🀋🀀🀀🀀🀌🀍🀎🀞🀟🀠🀒;
頑張って上記のように使用する牌を短縮してもいいが、面倒な場合は以下のように雑に🀅で埋めてもよい
+29 { MEM[I] = R; R = 29; R += MEM[I]; put }
🀅🀅🀅🀅🀅🀅🀅🀅🀅🀅🀅🀅🀅;
🀔🀓🀒🀋🀊🀊🀉🀉🀈🀇🀇;
...続く
+7 { MEM[I] = R; R = 7; R += MEM[I]; put; put }
+3 { MEM[I] = R; R = 3; R += MEM[I]; put; }
44 { R = 22; R *= 2; put }
32 { R = 32; put }
87 { R *= 2; R += 23; put }
+24 { MEM[I] = R; R = 24; R += MEM[I]; put; }
+3 { MEM[I] = R; R = 3; R += MEM[I]; put; }
-6 { MEM[I] = R; R = 6; R -= MEM[I]; put; }
-8 { MEM[I] = R; R = 8; R -= MEM[I]; put; }
33 { R = 33; put; }
exit

Hello World の実行過程

🀄🀄 🀊🀊🀒🀑🀒🀑🀐🀐🀇🀇🀉🀉
🀒🀑🀐🀐🀇🀇🀉🀉 🀈🀙🀐🀈🀙🀐
🀑🀐🀐🀇🀇🀉🀉🀈🀙🀐🀈🀙🀐 🀒
🀒 🀋🀋🀋🀀🀀🀀🀌🀍🀎🀞🀟🀠🀒
...続く

cat

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment