無機野

ここはお前の日記帳

麻雀のルール改良案

現行のルールはあまりにも複雑すぎる
麻雀が普及していく中でルールを統一する機会を逃した結果論理的な合理性もなくゲームの面白さに寄与しない歴史的な経緯だけ残った


現行の問題点(とおれが感じていること)
・初学者に対して不親切
覚えることがあまりにも多すぎる

・そもそも整合性がないルールが残っている
ちょっと違うけどブラックジャックのインシュランスとか通常のルールではまず使わないじゃんみたいなやつ
明槓をする局面があまりにも限られすぎる
あと符計算とか

・複雑さがゲームとしての深みに寄与していない
複雑さはゲームとしての深みの必要条件ではない

・運の要素が強すぎる
運と技術の適切な塩梅から明らかに逸脱している
実力を見るのに最低1000半荘は必要など正気ではない


改良案
・点数計算の簡素化
符計算を廃止して子100020004000800親15003000600012000に統一
ピンフ七対子のすり合わせが必要かもしれない

・役の調整
正直ここはあまり弄りたくない
飜数の調整、いくつかのローカル役の追加、
カンは明槓暗槓問わず1ハン、即ノリ(廃止する符計算とのすり合わせ)

・リーチ後放銃のツモ扱い
リーチ後放銃が大きすぎる運要素の要因と思われる
ツモ扱いとすることで実力ウェイトを上げる
牌がすべて見えている、手で使い切っている等の目無しリーチも許可
ノーテンリーチの罰則の強化(放銃時の支払い増額等)
このままだとリーチが強すぎるので一発裏無し、そもそも一発裏も強すぎる運要素

・赤アリ、アリアリ
現代的なスピード麻雀に対応する
まあこのへんは好みの問題でもある

・食い変えアリ、リーチ後のカン常にアリ
ここらへんは初学者にとって余計に覚えないといけないルールなのでいっそのこと廃止する
そもそもルールを把握するのにスジの理解が必要なのは不親切
また技術介入の余地も上がる

・牌の誤倒の罰則化
誤倒の度に各プレイヤーに1000点ずつ支払いなど
ただこの辺は牌を見るまたは見せるコストになりかねないので難しい

・競技での対局時計の導入


ここらへんがいい塩梅か
ゲームに参加するために最低限身に着けないといけない知識を減らし、必須ではないもののゲームに勝利するために考慮すべき思考を増やす方向がいい
シンプルなルールはゲームの奥行きと相反しない、例としてどうぶつタワーバトル

ポーカーくらい役がシンプルだと一番いいけどあれは手が5枚のみだからできること
麻雀もいっそのこと手を減らすことも考えられる(すずめ雀など)けど既存のルールと乖離しすぎる

Mリーグのルールはまだ発表されてなかったと思うけどあれはどんなルール採用するんだろうね

ノートPC激アツ問題

lenovoのmiix720使ってるけどi7なのでかなり熱い、夏場だし
バッテリー設定からCPUのパフォーマンス66%とかにしたら熱いのは収まってぬるいくらいになったしバッテリーも倍くらい保つようになったし最高や
i7なんていらんかったんや

追記:win10デフォでオンになってるっぽいゲーム録画うんたらかんたらみたいなやつコンパネから切るだけで相当よくなった
ゲームしようがしてまいがいつ何時巻き戻って画面キャプチャできるように常時録画してるっぽい?
cpu自体はつよつよなので別に負荷がかかってるわけではないけどとにかく発熱がやばい
特に使う機能でもないので切ると吉

スルツキー方程式の導出

通常の効用最大化は
\displaystyle \max~~u(\vec{x})=なんらかの関数 但しxは財ベクトル
\displaystyle s.t.~~\vec{p}\cdot\vec{x}=m 但しpは価格ベクトル、\displaystyle \vec{p}・\vec{x}内積を意味する 不等号ならKKT条件
また、支出最小化を考えると
\displaystyle \min~~m=\vec{p}・\vec{x}
\displaystyle s.t.~~u(\vec{x})=u uは所与
前者の解を需要関数\displaystyle \vec{x}(\vec{p},m)、後者の解を補償需要関数\displaystyle \vec{h}(\vec{p},u)と呼ぶ。(当然hも財ベクトル)
両者の解は最適点で同一、つまり \displaystyle \vec{x}(\vec{p},m)=\vec{h}(\vec{p},u) となる(双対性)
この場合、\displaystyle m=\vec{p}\cdot\vec{x}(\vec{p},m)=\vec{p}\cdot\vec{h}(\vec{p},u)なのでmは\displaystyle m(\vec{p},u)とかける
つまり \displaystyle \vec{x}(\vec{p},m(\vec{p},u))=\vec{h}(\vec{p},u) となる
\displaystyle i財価格\displaystyle p_i偏微分すると
\displaystyle \frac{d\vec{x}(\vec{p},m(\vec{p},u))}{dp_i}=\frac{d\vec{h}(\vec{p},u)}{dp_i}
\displaystyle \vec{x}\displaystyle \vec{h}はベクトルなので、\displaystyle N財あるうちの第\displaystyle i財について個別に見ると
\displaystyle \frac{dx_i(\vec{p},m(\vec{p},u))}{dp_i}=\frac{dh_i(\vec{p},u)}{dp_i}
左辺\displaystyle =\sum_{j=1}^{J}\frac{∂x_i}{∂p_j}\frac{dp_j}{dp_i}+\frac{∂x_i}{∂m}\frac{∂m}{∂p_i}
※多変数関数の連鎖律 \displaystyle \frac{d}{dx}f(g(x),h(x))=\frac{∂f}{∂g}\frac{dg}{dx}+\frac{∂f}{∂h}\frac{dh}{dx}
これの第1項について、\displaystyle j≠iである\displaystyle \frac{dp_j}{dp_i}については定数に対する微分操作になり=0であり、
また\displaystyle \frac{dp_i}{dp_i}は当然1なので結局
左辺\displaystyle =\frac{∂x_i}{∂p_i}+\frac{∂x_i}{∂m}\frac{∂m}{∂p_i}
これの第2項にある\displaystyle \frac{∂m}{∂p_i}はシェファードの補題より補償需要関数\displaystyle h_i(\vec{p},u)と等しい
※シェファードの補題:支出関数を価格で微分すると補償需要関数が出てくる
(というかそのように支出関数を定義している、支出関数:\displaystyle m(\vec{p},u)=\vec{p}\cdot \vec{h}(\vec{p},u) )
左辺\displaystyle =\frac{∂x_i}{∂p_i}+\frac{∂x_i}{∂m}h_i(\vec{p},u)
右辺と合わせて
\displaystyle \frac{∂x_i}{∂p_i}=\frac{∂h_i}{∂p_i}-\frac{∂x_i}{∂m}h_i(\vec{p},u)
右辺第1項は代替効果、第2項は所得効果

例:2財のみで\displaystyle p_1=20、p_2=30、u(x_1,x_2)=x_1*x_2、m=1200のとき、
効用最大化問題を解くと(中略)\displaystyle x_1=30、x_2=20、u=600
支出最小化を解いても同様に\displaystyle h_1=30、h_2=20
この時第1財の価格がわずかに上昇した時の代替効果と所得効果はそれぞれいくらか
\displaystyle \frac{∂x_1}{∂p_1}=\frac{∂h_1}{∂p_1}-\frac{∂x_1}{∂m}h_1 にあてはめていくと
\displaystyle h_i(p_1,p_2,u):h_1=(\frac{p_2 u}{p_1})^{\frac{1}{2}}
\displaystyle \frac{∂h_1}{∂p_1}=-\frac{1}{2}(p_2 u)^{\frac{1}{2}}p_1^{-\frac{3}{2}}=-\frac{3}{4}
\displaystyle x_1(p_1,p_2,m):x_1=\frac{m}{2p_1}
\displaystyle \frac{∂x_1}{∂m}=\frac{1}{2p_1}
\displaystyle \frac{∂x_1}{∂m}h_1(p_1,p_2,u)=3/4
というわけで代替効果-3/4、所得効果は-3/4
全部効果は\displaystyle \frac{∂x_1}{∂p_1}=-\frac{m}{2}p_1^{-2}=-\frac{3}{2}であり整合的
ちなみにこの第1財は両効果とも負なので正常財
合っとるかは知らん

iphoneで小説を読む

要約:青空文庫のように整形されてない文章、例えばネットに落ちてる怪文書をiphoneで読みたいという場合、i文庫sを購入しましょう
i文庫sは最高

アプリは今のとこkinoppyが読みやすい
ただzipを読み込むとたまに死ぬ
生txtよりもpdfにしといたほうが何かと読みやすいという点では勝る
ではどのように変換するか、google driveのdocsを使う
txtをコピペで読み込み、設定は余白1.5~2cmあたり、用紙サイズlegal、フォントメイリオで文字サイズ20か
これでpdf出力できるので完璧

kinoppyマジでzip読み込むとたまに死んで全部やり直し問題がウザすぎて250円でi文庫s導入
これがまた使いやすくて最高 生txt読みやすいしpdf余白調製あるしついでに青空読めるしもうこれでよい

● 特殊記号使われると表記崩れる問題
→❤が機種依存なので♥に置換、あと”ゔ〰〰〰〰〰〰❤❤❤❤”も機種依存だけどそこまで深刻ではないので放置
utf-8で保存してオールおけー

●i文庫ではzip読み込めん問題
→pic2pdfでpdf化してオールおけー
→でもなぜかfile explorer でftp転送するとpdfがバグる
→sendanywherで送ることで解決 マジでわからん

熾天使をマリガン時デッキ戻しした場合にその後引く確率

タイトル通り
エイラと違って8Tまで持ってても仕方ないので基本戻す

import random as rd
import matplotlib.pyplot as plt
import collections as col

target = 3 #セラフ
others = 40 - target
m = 2 #マリガン枚数
time = 1000000 #試行回数

def mulligan():
    """熾天使をマリガンで戻した場合、何ターンまでに引いてるか。todo キャントリやプリプリの考慮"""
    x = [] #ターゲットが来たターンから成るリスト。0は初手orマリガンで来た場合、それ以外は来たターン。後攻は-1ターンして考える
    for j in range(time):
        deck = []
        hand = []     
        for i in range(target):
            deck.append("t")
        for i in range(others):
            deck.append("o")
        rd.shuffle(deck) #デッキ作成&まぜまぜ完了 
        for i in range(3):
            hand.append(deck.pop()) #マリガン前初手引き
        tnum = col.Counter(hand)
        for i in range(tnum["t"]): #初手熾天使あるならdeckに戻して
            hand.remove("t")
            deck.append("t")
        rd.shuffle(deck)
        for i in range(tnum["t"]):
            hand.append(deck.pop()) #戻した数だけカード引く
        if "t" in hand:
            x.append(0) #初手熾天使が有って、それマリガンで戻してもまた来た場合
            continue  
        for i in range(37): #マリガンしてターゲットが無い場合
            if deck.pop() == "t":
                x.append(i+1)
                break
        
    plt.hist(x,bins=max(x))
    aaa = col.Counter(x)

    totalprb = 0
    for i in range(16):
        prb = (aaa[i]/time)*100
        totalprb += prb
        print(i,"ターン目までにターゲットを引いている確率",totalprb,"%")

mulligan()
print("マリガン",m,"枚")
print(time,"回試行")

0 ターン目までにターゲットを引いている確率 1.7543 %
1 ターン目までにターゲットを引いている確率 9.7392 %
2 ターン目までにターゲットを引いている確率 17.2676 %
3 ターン目までにターゲットを引いている確率 24.321400000000004 %
4 ターン目までにターゲットを引いている確率 31.010200000000005 %
5 ターン目までにターゲットを引いている確率 37.276900000000005 %
6 ターン目までにターゲットを引いている確率 43.1884 %
7 ターン目までにターゲットを引いている確率 48.6363 %
8 ターン目までにターゲットを引いている確率 53.756099999999996 %
9 ターン目までにターゲットを引いている確率 58.5391 %
10 ターン目までにターゲットを引いている確率 62.986799999999995 %
11 ターン目までにターゲットを引いている確率 67.0842 %
12 ターン目までにターゲットを引いている確率 70.90419999999999 %
13 ターン目までにターゲットを引いている確率 74.40259999999999 %
14 ターン目までにターゲットを引いている確率 77.6117 %
15 ターン目までにターゲットを引いている確率 80.5283 %
マリガン 2 枚 熾天使3枚
1000000 回試行
f:id:moppii:20161206164107p:plain

0 ターン目までにターゲットを引いている確率 0.7992000000000001 %
1 ターン目までにターゲットを引いている確率 6.1516 %
2 ターン目までにターゲットを引いている確率 11.3437 %
3 ターン目までにターゲットを引いている確率 16.4056 %
4 ターン目までにターゲットを引いている確率 21.298000000000002 %
5 ターン目までにターゲットを引いている確率 26.0973 %
6 ターン目までにターゲットを引いている確率 30.713900000000002 %
7 ターン目までにターゲットを引いている確率 35.1751 %
8 ターン目までにターゲットを引いている確率 39.5017 %
9 ターン目までにターゲットを引いている確率 43.6909 %
10 ターン目までにターゲットを引いている確率 47.727599999999995 %
11 ターン目までにターゲットを引いている確率 51.61619999999999 %
12 ターン目までにターゲットを引いている確率 55.34459999999999 %
13 ターン目までにターゲットを引いている確率 58.85809999999999 %
14 ターン目までにターゲットを引いている確率 62.27709999999999 %
15 ターン目までにターゲットを引いている確率 65.5645 %
マリガン 2 枚 熾天使2枚
1000000 回試行
f:id:moppii:20161206164440p:plain

実際はキャントリ持ちやプリプリがあるのでもうちょっと早くなる
キャントリについては積んでる枚数多いだろうしターンを読み替えるだけで近似できそうな気はするけどプリプリの影響はでかいのでそういうのも考えないといけない、そのうちやる

マリガンした時に目的のカードが第nターンまでに手にある確率

例えば3積みしたカードをnターン目までに引く確率は何%か、みたいなちょっと混んだ確率を計算するとき、厳密に確率計算するよりとりあえずコード書いてシミュレーションしてみたほうがよっぽど都合の良い場合がある
というわけで3積みしたエイラや御旗や超越やらをマリガンした場合に引いてくる確率を計算してみた

import random as rd
import matplotlib.pyplot as plt
import collections as col

target = 3 #セラフ
others = 40 - target
m = 3 #マリガン枚数
time = 1000000 #試行回数

def mulligan():
    x = [] #ターゲットが来たターンから成るリスト。0は初手orマリガンで来た場合、それ以外は来たターン。後攻は-1ターンして考える
    for j in range(time):
        deck = []
        hand = []
        for i in range(target):
            deck.append("t")
        for i in range(others):
            deck.append("o")
        rd.shuffle(deck) #デッキ作成&まぜまぜ完了
        for i in range(3):
            hand.append(deck.pop()) #マリガン前初手引き
        if "t" in hand:
            x.append(0) #マリガン前に来たら終了
            continue
        else: #マリガンしても来なかったら
            for i in range(m):
                deck.append(hand.pop())
            rd.shuffle(deck)
            for i in range(m):
                hand.append(deck.pop())
            if "t" in hand:
                x.append(0)
                continue #マリガンして来たら終了
            rd.shuffle(deck)
            for k in range(37): #マリガンしてもターゲットが無い場合
                aaa = deck.pop()
                if aaa == "t":
                    x.append(k+1)
                    break
        
#    print("deck",deck,len(deck))
#    print("hand",hand,len(hand))
#    print("x",x,len(x))
    plt.hist(x,bins=max(x))
    aaa = col.Counter(x)

    ppp = 0
    for i in range(21):
        p = (aaa[i]/time)*100
        ppp += p
        print(i,"ターン目にターゲットを引いている確率",ppp,"%")

mulligan()
print(time,"回試行")
print("マリガン",m,"枚")

これをマリガンの枚数別に回してみる
上からノーチェンジ、1枚2枚フルマリガン
後攻は1T目2枚引きなので-1ターン考慮すること

0 ターン目にターゲットを引いている確率 21.3183 %
1 ターン目にターゲットを引いている確率 27.6999 %
2 ターン目にターゲットを引いている確率 33.7504 %
3 ターン目にターゲットを引いている確率 39.4381 %
4 ターン目にターゲットを引いている確率 44.790099999999995 %
5 ターン目にターゲットを引いている確率 49.821099999999994 %
6 ターン目にターゲットを引いている確率 54.517999999999994 %
7 ターン目にターゲットを引いている確率 58.94689999999999 %
8 ターン目にターゲットを引いている確率 63.048199999999994 %
9 ターン目にターゲットを引いている確率 66.8643 %
10 ターン目にターゲットを引いている確率 70.4036 %
11 ターン目にターゲットを引いている確率 73.6943 %
12 ターン目にターゲットを引いている確率 76.7449 %
13 ターン目にターゲットを引いている確率 79.52720000000001 %
14 ターン目にターゲットを引いている確率 82.09120000000001 %
15 ターン目にターゲットを引いている確率 84.42180000000002 %
16 ターン目にターゲットを引いている確率 86.53670000000002 %
17 ターン目にターゲットを引いている確率 88.44090000000003 %
18 ターン目にターゲットを引いている確率 90.16450000000003 %
19 ターン目にターゲットを引いている確率 91.72060000000003 %
20 ターン目にターゲットを引いている確率 93.09680000000003 %
1000000 回試行
マリガン 0 枚
f:id:moppii:20161206002331p:plain

0 ターン目にターゲットを引いている確率 27.693099999999998 %
1 ターン目にターゲットを引いている確率 33.5411 %
2 ターン目にターゲットを引いている確率 39.0525 %
3 ターン目にターゲットを引いている確率 44.2825 %
4 ターン目にターゲットを引いている確率 49.2106 %
5 ターン目にターゲットを引いている確率 53.8245 %
6 ターン目にターゲットを引いている確率 58.1519 %
7 ターン目にターゲットを引いている確率 62.201499999999996 %
8 ターン目にターゲットを引いている確率 66.0148 %
9 ターン目にターゲットを引いている確率 69.50269999999999 %
10 ターン目にターゲットを引いている確率 72.7652 %
11 ターン目にターゲットを引いている確率 75.8128 %
12 ターン目にターゲットを引いている確率 78.5983 %
13 ターン目にターゲットを引いている確率 81.172 %
14 ターン目にターゲットを引いている確率 83.5312 %
15 ターン目にターゲットを引いている確率 85.6756 %
16 ターン目にターゲットを引いている確率 87.6478 %
17 ターン目にターゲットを引いている確率 89.43690000000001 %
18 ターン目にターゲットを引いている確率 91.03460000000001 %
19 ターン目にターゲットを引いている確率 92.46020000000001 %
20 ターン目にターゲットを引いている確率 93.72140000000002 %
1000000 回試行
マリガン 1 枚
f:id:moppii:20161206002357p:plain

0 ターン目にターゲットを引いている確率 33.1351 %
1 ターン目にターゲットを引いている確率 38.5676 %
2 ターン目にターゲットを引いている確率 43.6727 %
3 ターン目にターゲットを引いている確率 48.5297 %
4 ターン目にターゲットを引いている確率 53.0668 %
5 ターン目にターゲットを引いている確率 57.3196 %
6 ターン目にターゲットを引いている確率 61.3138 %
7 ターン目にターゲットを引いている確率 65.0617 %
8 ターン目にターゲットを引いている確率 68.5632 %
9 ターン目にターゲットを引いている確率 71.7999 %
10 ターン目にターゲットを引いている確率 74.81559999999999 %
11 ターン目にターゲットを引いている確率 77.64699999999999 %
12 ターン目にターゲットを引いている確率 80.22789999999999 %
13 ターン目にターゲットを引いている確率 82.58359999999999 %
14 ターン目にターゲットを引いている確率 84.7405 %
15 ターン目にターゲットを引いている確率 86.73729999999999 %
16 ターン目にターゲットを引いている確率 88.56429999999999 %
17 ターン目にターゲットを引いている確率 90.20169999999999 %
18 ターン目にターゲットを引いている確率 91.68749999999999 %
19 ターン目にターゲットを引いている確率 92.97989999999999 %
20 ターン目にターゲットを引いている確率 94.14999999999999 %
1000000 回試行
マリガン 2 枚
f:id:moppii:20161206002504p:plain

0 ターン目にターゲットを引いている確率 38.209900000000005 %
1 ターン目にターゲットを引いている確率 43.217400000000005 %
2 ターン目にターゲットを引いている確率 47.984700000000004 %
3 ターン目にターゲットを引いている確率 52.41760000000001 %
4 ターン目にターゲットを引いている確率 56.569300000000005 %
5 ターン目にターゲットを引いている確率 60.4986 %
6 ターン目にターゲットを引いている確率 64.1774 %
7 ターン目にターゲットを引いている確率 67.63210000000001 %
8 ターン目にターゲットを引いている確率 70.89260000000002 %
9 ターン目にターゲットを引いている確率 73.89020000000002 %
10 ターン目にターゲットを引いている確率 76.67410000000002 %
11 ターン目にターゲットを引いている確率 79.24760000000002 %
12 ターン目にターゲットを引いている確率 81.62980000000002 %
13 ターン目にターゲットを引いている確率 83.83390000000001 %
14 ターン目にターゲットを引いている確率 85.85800000000002 %
15 ターン目にターゲットを引いている確率 87.72270000000002 %
16 ターン目にターゲットを引いている確率 89.40250000000002 %
17 ターン目にターゲットを引いている確率 90.90200000000002 %
18 ターン目にターゲットを引いている確率 92.26930000000002 %
19 ターン目にターゲットを引いている確率 93.48920000000001 %
20 ターン目にターゲットを引いている確率 94.5588 %
1000000 回試行
マリガン 3 枚
f:id:moppii:20161206002536p:plain

というわけでフルマリガンすると1T目には4割方手に入っているという結果に
正直想像以上に高いというか、実際フルマリガンすることも稀なのでこれで妥当という感じはする

matplotlibで二項分布を表示する(だけ)

先の記事で書いたコードだけどnumpy.random.binomial()で実際にサンプリングした数字からなるリストを作ってそっからヒストグラムつくるみたいなよく考えたら(よく考えなくても)頭悪いことしてたの今更気づいて、自分で単純なベルヌーイ試行だっつってんだからそのまま二項分布のグラフ書けばいいじゃねえかと思って書いた
range(x)が0から始まるリストを返すのにだけ気をつけて書くとこんな感じ

import matplotlib.pyplot as plt
import scipy.misc as scm #組合せ計算用

p = 1.5/100 #レジェンド
pack = 50
time = pack*8

def unko():
    aaa = []
    for j in range(time-1):
        elm = scm.comb(time,j) * (p**(j)) * ((1-p)**(time-j))
        aaa.append(elm)
    print(aaa,sum(aaa)) #表示される数は*100すると%表示になる。そっちのが見やすいか?
    plt.plot(aaa)

unko()

[0.014428036055035228, 0.043833398877860821, 0.088556816007048775, 0.13384665972638971, (以下略)
1.0
f:id:moppii:20161130115543p:plain

オッ

import matplotlib.pyplot as plt
import scipy.misc as scm #組合せ計算用

p = 1.5/100 #レジェンド
pack = 50
time = pack*8

def unko():
    aaa = []
    for j in range(time-1):
        elm = scm.comb(time,j) * (p**(j)) * ((1-p)**(time-j))
        aaa.append(elm)
    print(aaa,sum(aaa)) #表示される数は*100すると%表示になる。そっちのが見やすいか?
    plt.plot(aaa)
    plt.xlim([0,20]) #x軸を0から20までに絞る

unko()

<f:id:moppii:20161130115706p:plain

ちなみにこの50パックという数字は9800円課金してそのままガチャ回した時の確率である
この分布の平均と標準偏差はそれぞれ

m = time*p
s = (time*p*(1-p))**(1/2)
print(m-s,m+s)

3.5689508437713564 8.431049156228644

なので諭吉放りこむとおよそ3回に2回は3~8枚引ける計算になる
これやっぱリセマラすべきなんじゃ…