12A猫で学んだこと-Memoir-

...What are you learning now?

PowerpointをPythonで使うための検討

サマリー

注意

技術系エントリの常ですが、問題が発生しても、こちらでは一切責任を取れません。自己責任でお願いします。

実行環境

自分の実行環境は以下となっています。

はじめに

2つの方針があります。

  • ファイル自体を生成する (python-pptx)
  • Powerpointのアプリケーション自体を操作する (COM操作)

このエントリ中では、
ファイル自体を生成することを静的なpptx操作
アプリケーション自体を操作することを動的なpptx操作
と呼びたいと思います。

静的なpptx操作 (python-pptxによる.pptxファイル出力)

pptx ファイルは.zip ファイルです。
解凍を行うと色々なフォルダやファイルが生成されます。
ファイルの形式はXMLです。
Office Open XML
というフォーマットがあります。
つまり、Powerpoint のソフトウェアをもっていなくても
フォーマットに適合したファイル群さえ作成することができれば、
Powerpointで開けるファイルを作ることができます。
Office Open XML の仕様について自分は詳しくないのですが、 かなり複雑という印象を持っています。
ありがたいことに、pythonでライブラリが作成されています。

python Object のクラスとXML の相互変換を行ってくれます。

非常に助かります。作者のscannyさんに感謝です。

動的なpptx操作 (COM操作によるPowerpointの操作)

python-pptxを使ってできることは.pptx ファイルの作成なので
Powerpointのソフトウェアを動かすことはできません。
Powerpointのソフトウェアを動かすためよく使われるのはVisual Basic for Applicationsです。
プログラムを書くことで、Powerpointの操作を行うことができます。
例えば、下記のようなサイトを参照させていただけます。

しかし、やりたいことはpythonPowerpointを使うことです。VBAの利用ではありません。

(少し古い)技術ですが、アプリケーション間の通信を行うためのCommon Object Model
というフレームワークがあります。 これを用いるとpython から Powerpointが公開しているインターフェースにアクセスすることができます。
しかし、COMを利用するための手順もかなり煩雑です。
ありがたいことに、COM を利用するためのライブラリがあります。

pip install comtypes  

にてインストールを行った後、下記のスクリプトを実行するとHello, Powerpoint.
というテキストボックスが表示されたスライドが生成されます。

import os  
from comtypes import client  
  
if __name__ == "__main__":  
    application = client.CreateObject("Powerpoint.Application")  
    application.Visible = True  
    presentation = application.Presentations.Add()  
    slides = presentation.Slides     
  
    # Reference * https://www.relief.jp/docs/powerpoint-vba-make-new-presentation.html  
    # ppLayoutBlank = 12  
    slide = slides.Add(len(slides) + 1, 12)   
  
    # Reference:  
    # * https://docs.microsoft.com/en-us/office/vba/api/powerpoint.shapes.addtextbox  
    # * https://docs.microsoft.com/en-us/office/vba/api/office.msotextorientation  
  
    shape = slide.shapes.AddTextBox(Orientation=1, Left=100, Top=100, Width=500, Height=50)  
    shape.TextFrame.TextRange.Font.Color.RGB = 0x000000  
    shape.TextFrame.TextRange.text = "Hello, Powerpoint."  
    shape.TextEffect.FontSize = 36  
  
    current_folder = os.getcwd()  
    presentation.SaveAs(os.path.join(current_folder, "sample.pptx"))  

スクリプトとして使っただけでは、あまりpythonの良さが見えてきませんね。
他のライブラリとの連携を視野に入れつつ、自分用にカスタマイズしていくことが
ポイントになる気がします。

終わりに

このエントリだけでは片手落ちの感があるので、来月もこの関連のネタでいきたいと思っています。
そういえば、来月は12月...

  • 年末で色々忙しい時...
  • 綺麗な雪が降り積もる時...
  • 大人の恋人の人たちが楽しい思い出を作る時...

自分のところにサンタクロースさんが来てくれるといいなぁ。
来月がいい1か月になりますように!

付録: 静的なpptx操作 V.S 動的なpptx操作

  • 静的なpptx操作 (python-pptxによる.pptxファイル出力)
  • 動的なpptx操作 (COM操作によるPowerpointの操作)

どちらを使ったほうがいいかはケースバイケースですが、 動的なpptx操作には以下のような特徴があります。

  • インタラクティブな操作を行いやすい
  • 信頼性に不安がある (例: プログラムの実行のユーザー操作の衝突からくるエラー)

したがって、

  • プログラムだけで処理を完結させたいとき
  • 定型的なスライドをたくさん作りたい

というときには静的なpptx操作の方が向いているでしょう。

逆に、

  • Powerpointの操作自体を楽にしたい
  • スライドのデザインを考えながら作業をしたい

というときには動的なpptx操作の方が向いているでしょう。

Halloween 前の日記

こんばんは。 StudentSです。 何とか達者でやっております。
Halloween ですねー

本日外にでると、 魔女や吸血鬼などの神秘的で攻撃的なシンボルの衣装に身を包み、歩く人たちの姿がありました。

  • Trick or Treat! - " お菓子をくれないと、悪戯しちゃうぞ!"
  • Trick or Treat! - "君は甲斐性無しなんだから、騙されても文句はないよね?"
  • Trick or Treat! - "ボクを騙してもいいし、やさしく接してくれてもどっちでもいい。(でも、貴方から何かをされたい)"

単純なフレーズを深読みすると、いろいろな妄想が広がりますねー

さて、2か月近く生産性のないブログとなっておりますが、今回も生み出せなかったですね...
読者が誰もいなくても、他人にとって何の価値もなくても、自分自身にとって価値のあるものを、少しづつでも創っていくことってすごく大事だと思うんですよね...

もうちょっと、休みの時間は続くと思いますが、また頑張れるときが来ると信じて。
No learning, No life. ちょっとずつでも、できないことをできるようにしていくことが大切だということは 忘れずに...

寒くなってきましたが、お体にお気をつけください。 お互い、来月がいい一か月になりますように!

雑多な夏の日記の1ページ

こんにちは。StudentSです。
まだまだ暑い夏が続きますね。 季節の変わり目は体調が崩れやすい時期なのでお互い体に気を付けたいですよね。

人狼は...視点整理に難ありですねー 感想戦で振り返ると、論理パズル的に気づくことを失念していますね。
まぁ、気づくことができるようになっているのはいい傾向なのかもしれませんー

最近、はたらく細胞というアニメを見ました。

「雑菌め、この体の血球に手を出して生きてかえれると思うなよ!」
「白血球は自分の命を犠牲にしても、他の細胞を守るんだ!」
「お兄ちゃん助けてくれてありがとうございました。 また会えるかな。」

(はたらく細胞 第6話「赤芽球と骨髄球」より)

いや~ 赤芽球も骨髄球も可愛いです!
リピート再生しながら、ソースコードのバグとのたたかいですー

今月のブログのエントリはプログラミングの練習です。

の記事で

  • RMQ (Range Minimum Query)

    • 問題: 配列が与えられる。指定した区間内の最小値のインデックスを求めよ。
  • LCA (Least Common Ancestor)

    • 問題 : ツリーが与えられる。2つのノードの共通祖先の中で最もルートから遠いものを求めよ。

の効率的な解き方や、線形時間でそれぞれの問題を相互変換するアルゴリズムが紹介されていました。 整理をしていないですが、自分の実装を

以下雑感を...

  • 効率的なデータ構造を考えるとき、$\sqrt{N}$, $\log(N)$ のオーダーでの処理ができるかを考える視点は役に立つ時があるかも
  • 出てくる問題のサイズが限られているのであれば、メモ化は有効な選択なのだろうなー
  • 問題同士の変換を思いつくのはすごいなー

自分用のメモだけど、
何とか今月もブログを書くことができたー!

暑い夏、 ぬるぬるシステムを考えた (5月は夏、6月は夏、7月は夏)

エントリのまとめ

f:id:StudentS:20180730222737p:plain f:id:StudentS:20180730222745p:plain f:id:StudentS:20180730222751p:plain f:id:StudentS:20180730222858p:plain

はじめに

このエントリは下記のNulさんからのTweetへの回答です。

https://ruru-jinro.net/log5/log456479.html

上記の村で使用された「定跡」について、「完全な成立条件/最低使用条件/不成立条件、占い結果の出し方、4日目の占い結果を○にする条件、CCOを入れない理由、村陣営の反論への対策、負け筋」などについて、定跡体系を中心に考察せよ。どうでしょう。

Tweetを読んだあと、ログを読ませていただきました。

「Nulさんうまいなぁ...面白いプレーだったなぁ。」
さぁ、暖かいルイボスティーを飲んで寝ようー!
おやすみなさい!

これが最初の感想でした。
だけど、Nul先生から、きちんと解析せよ と言われてしまいました...これはレポートの宿題ですねー
生徒としては、レポートの提出は嫌な時もありますが、単位のためには頑張らなきゃいけない時もありますね。

人の発言から思考をトレースし、想像力を膨らませて色々なことを考えるのが人狼
私は人狼をします...おそらく、色々な意味で今回の内容は重くなるはず...

(2018-06-24 追記)

下記のようなヒントをいただきました。

将棋の木村定跡に似ている

wikipediaを読んだのですが、さっぱり分からなかったです。
将棋の経験を積んで実際に自分で並べてみないと理解できないのでしょうね。
将棋は分からないながらも、つかめたポイントは2つ。

  1. 先手勝利まで研究が終わっていることから、完成された定跡とも言われている
  2. ただし、問題点として、先手の疑問手に対して、後手が悪手で返すという前提が存在する

条件付きで狼の勝利が確定する戦略である
というのがNulさんからのメッセージだと思っています。

(2018-07-18 追記)

とここまで書いた6月....7月後半まで手が付けられていませんでした。
そして、NulさんのTweetに以下の言及がありました。

※某人に出した問題についてちょこっとだけ言及
①同じ○進行でも真の占い先の中身と狼の占い先の中身、○の位置によって成立不成立が分かれたり、成立が不完全になったりします
②2−1が前提ですが、ある条件を満たすと上記以外でも不成立になります
この辺はしっかり詰めた方がポイント高いかな?

実は勝ちの定跡より
①「この手を使うと村の〜という反論があるので、〜という定跡部分はこれを対策している」
②「この手を使うと〜という理由でまず負けるので、まず使われない」
③「この状況なら〜という理由で負けるので、この形を回避する必要がある」
とかの方が大事だったりします

上記のポイント全てに応対できてはいませんが、 以下が自分のレポートになります。

1. 「定跡」の定義について

まず、Nulさんの「定跡」の定義が分からない状況からのスタートです。
前に同村させていただいた時、「ぬるぬるシステム」という単語を聞いた覚えはありました。
しかし、内容はよくわかりません。

何かを解析するときには、定義が明確でないと、その解析結果は曖昧になります。
最初に、この記事中での「定跡」の定義を明確にする必要があります。
提示された村のログとNulさんからの問題、素朴な自分の第一感を統合すると、

  • [エントリ上での『定跡』の定義] 2-1初日〇進行の時、2日目の夜に霊能者を噛み、3日目に仲間に狼騙りが身内切りをする。猫/狩CCOはなし。

とするのがいいと感じました。

この定義がNulさんの言動に適合していることを確かめます。
Nulさんの参加村数は多いので、全ての村を調べるのは諦めます。
NulさんがPLとして参加した村のうち、「ぬるぬるシステム」という単語が使用された村のログから確認を行いました。

調査結果からのまとめは

  • 霊能者を噛んで、●を出す戦略であるということ (CO数2-1の場合)
  • 初期の「ぬるぬるシステム」は3日目の●に対して、猫又CCOを入れていたが、CCOをしないようになった
  • 投票情報などを使って、(霊能者死亡のなかで) 2日目に吊れたのは村人であるという主張を行う傾向が見られる

といったところでしょうか。

調査結果の詳細は 付録A.「ぬるぬるシステム」のワードの言及村について を参照ください。

少なくとも、上記の定義は現在の「ぬるぬるシステム」として、大きくずれている気がしなかったです。

2. 「定跡」の解析について

自分のスタンスから行くと、厳密な解析は無理 、 というのが最初の一言になります。

ぬるぬるシステムが勝率が高い定跡かどうかは、村の進行次第で決まります。
村の進行をfixした時の勝率の導出は論理パズルとして原理的には可能だけれど、 場合分けが多すぎてできません。(終)

(付録B. 本ブログの解析の基本的な方針を参照)

しかし、この主張では全く面白みがありません。
厳密 ではないけれど、語ることができる定性的な論点を考えます。
以下の議論は、自分の感じる「るる鯖の12A猫の進行傾向」に基づく考察です。

[最低使用条件]

最初に思いつくのは、「初日のグレランで狼が処刑されないこと」ですね。
LWの状態で猫潜伏にはできないと考えます。
他には、対抗の占い師に〇を出さないことです。
占い師が吊れなくなってしまう可能性が極めて高くなってしまうので。

また、2日目で狩人、霊能平和が出た時に、猫又CCOなしのまま戦略を使うことはかなり厳しいという感覚を持ちます。
出来なくはないと思いますが、
狩人/猫又関連で破綻する可能性は上がるし、3日目の夜以降、残った潜伏狼が猫噛みを行った場合、
狼騙りの占い候補視点LWになるのは、占い師候補吊りを行う強い要素になります。

だからこそ、逆をついて、霊能者平和の時に●を打つという手もあると思うのですが、

  • 村の進行役の思考がどれだけ霊能生存下での身内切り●に信用を置くか。
  • 猫又・狩人の位置を推測できるか?

という要素と天秤にかけることになるでしょうね。

[完全な成立条件] について

厳密な意味では"完全"ではないのですが、村陣営が「身内切り + COなしは"絶対に"ない」
という進行をするのであれば、この戦略は極めて有効でしょうね。
猫又や狩人・狂人関連の兼ね合いにおいて相当な不運が重ならない限り、
ほぼ、勝利確定といっていいでしょう。

村の進行と場合分けが多岐に渡るので、その"ほぼ"の境界線の引くのは非常に難しいのですが、
例えば、狂人死亡済みで霊能者を噛んで●を吊った後、

  • 狩人がすべて平和を出し、
  • 吊り余裕のある状態でその狩人を狼騙り視点●にしてしまい、
  • 潜伏狼が対抗狩人COをすると詰み進行になる。

というのが、 村陣営が「身内切り + COなしは"絶対に"ない」という前提で動いた場合に
狼陣営が負ける条件の一例だと思います。
このような、非常に発生しにくい事象の時のみだけだと考えています。

[不成立条件], [負け筋]について

逆に、この戦略を村側に読まれた場合、極めて不利な戦いを強いられますね。

  • 3日目占いの決め打ちで狼騙りが吊られる + 身内切り(or 狂人の誤爆)を読まれて、翌日に●先が処刑される

これが最悪のパターンでしょうか。 狩人の平和や猫噛みも若干の恐怖ですが、1平和だけの偶数進行だったりする場合はそこまで痛手ではないような場合も多いでしょうね。

[占い結果の出し方]

4日目の占い結果について

●出しを躊躇する一番の要因は狩人が平和を出すことでしょうね。 狩人を●にしてしまっては狂人がうまく立ち回ってくれないと勝利は苦しくなるでしょうね。

4日目素村に●を打って、自身が噛まれない違和感を作り出したいと思うところですが、 狩人に●を打つことは避けたいですよね。

なので、4日目に平和がでることは〇結果を打つ要因になると考えています。

逆に、非狩人を決め打てるところがあることや、4日目に平和が発生しないことは●打ちを行う要素になります。
狩人や猫に●を出す危険性と2連続●結果による信頼・噛み筋の違和感を消せる利得の計算は、村の状況を読みながらといったところでしょうか。

[村陣営の反論への対策]

「霊能者を噛んで仲間に●を出す狼騙りが少ない」ことを軸に、反論する材料はたくさんありますね。

  • 自分の●を吊ってゲームが続いている。初日のグレランで狼が吊れたCCOなしの身内切りを主張することになるけれど、どっちを主張するの?
  • 霊能者を噛んで、身内切りをする意味がない。
  • 身内切りなら、狩人CCOや猫又CCOが入っているはず。

人狼において、主張の材料は何でも使うと思います。
この戦略は比較的レアケースです。そして、狼の吊り1を村陣営に与える、心理的に行いにくい"味方を殺す"作戦を採用しています。
したがって、 統計面・心理面の両面から要素を引っ張ってくることができます。

(統計の観点から主張を作る時、 直接、"統計"というワードを使うことは少ないと思いますが。 "考えにくい" / "あり得ない"などレアケース想起させるワードを使うことは一般的だとみています。 )

逆に 村陣営の多くが

  • 「比較的レアケースである、狼の霊能噛み身内切りCOなしを、レアケースとして扱わない」
  • 人狼プレイヤーは心理的にも身内切りを躊躇なく行う、または積極的に行う」

という前提を持っている場合、システム特有の反論は効果的ではありません。

[CCOを入れない理由]

猫又/狩人CCOをすると、狼の身内切りを追うPLが多いから。 この一言に尽きると思っています。
Nulさん自身が霊界で言っているように、戦略を取る人が少ない = 狼陣営の作戦として身内切りCOなしを考慮する村陣営が少ないから成立する作戦です。
また、狩人CCOの場合に(展開次第ではありますが、)

  • (真狩人を噛んだ場合)狩人が死亡しているのにも関わらず、狼騙りが噛まれない違和感がある or 猫又に●を打ってしまう可能性がある の2拓
  • (真狩人を噛まない場合)真狩人が狼として認識される場合がある

などのリスクもあります。

真狂 - 真の2-1のケースが多くなり、村が真狂の可能性を強く追うようになるのは不利に働く要素

この戦略が機能しているのは、2-1 + 霊能者噛みでの村の進行が、非常に真狼に比重が置かれているからだと考えています。
狂人には誤爆という要素があります。 狼騙りの●が狂人の誤爆とみなされる可能性が高くなることは『定跡』にとって不利に働くでしょう。
(LW狼騙り、猫潜伏のケースはできるだけ狼視点できるだけ防ぎたいはず)
狩人が死亡していたりすればいいのですが、最後の最後で詰み進行を採用される可能性は上がると思います。

「Nulさんが入村している可能性が高い」ことは、この『定跡』は不利に働く要素

繰り返しになりますが、この『定跡』が成立している理由は「霊能噛み + 狼騙りの身内切りをするPLが少ない」からです。 Nulさん自身もログで言及されていますが、『定跡』を採用するプレイヤーの存在確率が高い場合、 『定跡』を読まれることが多くなるでしょう。

現実のるる鯖の村で採用される村の戦略をNulさんはよく知っていると思います。 村陣営が実際に多く採用する戦略の弱点を考えて、この戦略が有効だと考えている。 だからこそ、「Nulさんが参加している可能性が高い」という情報が出ることには警戒しているのだろうな。 と想像します。 Nulさんの取りうる戦略を知っている人が進行役になると、「身内切りCO無しはレアケース」という主張点が活かせません。

中の人読みが全くできない自分に対しては意味のない警戒ですが!

感想

勝率の高いプレイヤーの方々は

  1. ゲーム中の進行を読む力に長けている
  2. 読んだ進行を前提として"良い"戦略を導出できる

この2つの点に優れている方が多い気がします。
これは、論理力とるる鯖での経験・観察眼が組み合わされていると考えています。

じゃんけんで例えると、

  • 相手が何を出すかを事前にある程度予想できる
  • 相手の出す手を見てから自分の出す手を決定できる

というような感じでしょうか。
そういうじゃんけんができる人は強いはずです。

勝率の高いプレイヤーの方々がゲームの進行を読むことができる一因は、村の進行の定常性にあると考えています。
ある期間、村の進行のパターンの幅が限られていれば、その間、『定跡』のような考え方が成立すると思います。

しかし、村の進行も変化します。
例えば、2015年ぐらいには、初日〇展開で占い師が3人COしたときは占いローラーにする進行が定着していた記憶があります。
現在、2018年夏は、占いローラーの進行はほとんど採用されていないようです。

実は最初にNulさんから"定跡"という言葉を聞いた時、自分は違和感を感じました。
ある時期と環境を切り取れば、確かに"定跡"として成立する戦略は存在すると思うのですが、
将棋や囲碁などのゲームとは違って、"読みあい"の要素が強いこのゲームで不変の「定跡」は存在しないのではないだろうか。と。
高勝率の「定跡」が定着した場合、「定跡」の逆を突くような戦略が多く採用されるはずです。
そして、戦略の流行り廃りが生まれて、村/狼陣営の勝率は均衡解付近で振動する...
これが勝率という観点からの、自分の人狼ゲームの戦略の基本的な見方です。

この考え方にも一理あるとは思います。しかし、これは実際の人狼ゲームで高勝率を目指す姿勢とずれています。
上手いプレイヤーの方々は環境についての知見を深め、 その環境下で最適な行動を探求しているという印象を持ちました。
自分だって、(あんまりうまくいっているとは思いませんが、) 実際のゲームをするときには、村の進行パターンに適合するような勝ち筋を最初に考えます。

実際の人狼ゲームをするということは、環境に対する情報を利用するという側面は必ずある。 
そして、環境をFixしたときに有利になる戦略が"定跡"として考えられていると感じました。 

頭の体操にまた、自分も人狼に参加させていただきたいと思います。
自分たちが、上手い人たちの「定跡」に思考をめぐらし、戦略の可能性を十分に考慮することができれば、上手い人たちは別な手を編み出していくと思います。
鮮やかに騙されてばかりなのは、ちょっと悔しいところもありますが、勝敗にかかわらずエンターテイメントを感じるのが人狼ゲームの面白さだと信じています。

次はどんな風に騙されるのかなぁ? それとも、一矢報いることができるのかなぁ?
レアケースを追いすぎちゃって負けちゃうことがあってもいいよね!

なんて思いながら、また楽しませていただきたいと思います。

最後に

この機会を作ってくださったNulさんに感謝を。
色々なところで不足している部分があるのですが、これが今の自分の実力でしょうね。
それでも、今回は自分なりに全力で人狼をやったつもりです。

数年前、勝率重視進行のPLの方に対しては苦手意識がありました。
勝率探求の姿勢はどうしても、感想戦においてミスを責める姿勢ことにつながる傾向があるから。
その中で、「感想戦の穏やかさと勝利の探求は両立できる」ということを教えてくださったPLさん
という印象が一番強いです。
もちろん、強くて村中ではボコボコにされるわけで、その印象も強く残っていますー

また、同村させていただいたときはよろしくお願いします。
メタとかは関係ないですね。だって、特殊な状況じゃない限り、自分はNulさんかどうかを読むことができないので。
...自分も透けにくくなっているかもしれませんよ!!! (希望)

夏の終わりに

いや、8月はまだ夏で暑いですが...

7月の終わり、このエントリの追記は終わります。
人狼だって、このブログだって、自分勝手に気ままにやっているけれど、
誰かにとって、エンターテイメントを感じられる何かを作れたら楽しんだろうなー

でも、一番大切なのは、自分が面白いと思うことだと信じていますねー
このブログを書いているときには、色々な意味で人狼をやらせていただいている気分でした。

暑い日が続くけれど、体に気をつけていきましょうー!
おやすみなさいー 明日がいい日になりますように!

付録A.「ぬるぬるシステム」のワードの言及村について

2018年7月某日までにおいて、Nulさんが12A猫に参加した村を対象に調査を行いました。

ぬるぬるシステムってこんなもんだしね。結局は互角なんだよ。
システム使っていい? 霊噛み身内切りから入るやつ

この村では初日に身内票をしていますね。そして、「猫又CCOを入れて良い」と相方の方に提案しています

2-2型というのがあるんですね...結果的にこの村では使っていないようです。

コメントは差し控えさせていただきたいと思います。

3日目平和が出て同じところに占いから2●。そして猫又CCOが入りました。
その状況に対して、平和が出たら身内切りはしないほうが良いというコメントです。

意図が汲み取れなかったので、言及はなしです。

どうやら、最初は猫又CCOを使っていたようですが、それを使わないようにしたようですね。

「ぬるぬるシステム」が何なのか? という議論が霊界でなされています。
1人の参加者の方が 『「ぬるぬるシステムって2-1霊能噛み身内切り戦術」のことを言っているのかね』
という発言を残しています。

狼の占い騙りとして、ぬるぬるシステムを使おうとしたけれど、対抗占いに〇を出したので止めた村。
この2日目の村のNulさん(CN:世話好きミミ)さんの発言には特筆すべきものがありますね。

「ミミの真切るからミミ吊ります」じゃなくて「取り敢えず真狂主張してるから吊ります」ってなんのゲームしに来たの?って言いたくなるわ

まず、前提として、ぬるぬるシステム自体が 村の真狼重視進行という要素を利用しています。
なので、Nulさんは「統計的に2-1展開の時に真狼が多い/村が真狼読みの進行を行うことは多い」ことを熟知しており、
なおかつゲーム中にその事実を利用しているのです。
本来真狼が多い → 真狂主張しているミミさんが真とは考えにくい → 吊り
というロジックに対して、
統計的事実を使って、ゲームを進行を決めるのは面白くない という観点からの反論を行っています。

もちろん、どんな状況でも要素を拾って主張を作るのが人狼ゲームの醍醐味だと思うので、素直にうまいなーと思うのですが、
ログ収集でNulさんの発言を追ってきた身としては、
「Nulさん自身が、村の進行を(統計的に)読んで進行を考えているPLじゃないですかー」
というツッコミを入れたくなりました。

付録B. 本ブログの解析の基本的な方針

勝率の観点から「良い進行・戦略」を主張する方針として、2つあります。

  1. 他陣営の戦略を(確率分布として)Fixし、そのFixした状態で進行の勝率を算出しての比較
  2. 他陣営がどんな戦略を採用したとしても、自陣営にとって最も勝率の高くなる戦略であることを証明

1.の例は占い3COの時、「狼が3COしている」と仮定(Fix)するなら占い全吊りがよいという主張などです。(極端な例ですが)
2.の例としては、狩人の護衛指示による詰み進行です。

今回の「定跡」の良さについて、2.の方針では主張できないです。
反例を提示することは簡単で、「狼陣営が常にこの『定跡』を使う」ということが村陣営が分かっているならば、
「3日目の●は狼。そして、3日目に●を出した占い候補は狼」という前提で村陣営が進行できます。

1.からの証明が必要になるのですが、この解析には村の戦略のFixが必要になります。
Fixされた村の戦略ごとに、Nulさんの問題に対する答えが定まる。というが自分の返答になります。
(実際問題としては、戦略のFixも大変だし、Fixした後の計算も大変ですね...)

提出締め切り日の占いCO

今月は何も書けなかったですね。 Student風に言えば、締め切り間際のレポートですみませんと1枚書いて提出する感じですね。

占いCO レポート〇
月末ということでレポートを書こうと思いました。結果は〇。 純白の白!
純白ってキュート! ラブリーな漆黒ではありませんでした。
"レポートを書くという行為"、"カードをドローするという行為"、"占いを行う行為"というのは
全て"可能性を狭める"という共通点を持っています。観測は非可逆操作ですよね!
まだ、私は、自分の可能性を狭めたくない!!! だから、レポートをかけないんです!

試験のほうでも〇結果しか引けない気がしますが、結果は占ってみないと分かりません。
選択式の問題を多くしてくれると、こちらの陣営としても勝負ができそうです。

... 7月の後半週は頑張る....

(Python/Role Play) Brother's protection -Example of Descriptor-

こんにちは。StudentSです。
最近、Fluent Pythonという本を読んでいます。

自分の中の朧げな「こんなことがしてみたい」というのを楽にできるようになりたいですね。
ありがたいことに世界の方々のおかげで技術が進歩しているけれど、自分が技術を楽しんだり、面白いことを創り出すためには、自分の能力を上げなきゃいけないんだろうなと思う5月の夕方です。

人狼に参加させて感じていることは、色々なバックグランドの人がいるから面白いということです。
その人の人狼以外の趣味が、人狼のゲーム中の思考のパターンに反映されるんだろうなと感じます。

  • 論理性の強いゲームが趣味の人は始めに、詰み進行の探索や確率論に基づく最適進行を考えるだろうし。
  • 人間観察が得意な人は始めに、発言を精査するだろうし。

様々な要素があるゲームだからこそ、色々なアプローチを見ることができるんだと思います。

不器用な私は、残念ながらプレイヤーごとの思考体系を読んで戦略を立てるのが苦手ですが、 他の参加者やGMさんの考え方に触れて刺激をもらっています。

自分ができるようになりたい、と思ったことができるようになっていけば、 また、少し違った人狼プレーもできると信じて。 このブログは自分の個人的なメモだけれど、それでも定期的に書くことには何か意味があると思うのです。

話しがすごく脱線しましたが、 今月のブログの内容です。
PythonにDescriptorという仕組みがあって、今まで勘違いしていたので会話口調でメモを作成しました。
Fluent Pythonと下記のページが元ネタです。

さて、このエントリの対象者は次の人です

  • Pythonを知っている
  • 私のRole Playを楽しんでくれる慈悲深い人である

登場人物は、Pythonの課題が出された高校生。課題を解くためにChatで友達としゃべりながら取り組んでいるようです。

とある高校生の就寝前

今日もお疲れ様! わたしはまだ、Pythonの課題が終わっていないから眠れないんだ... 課題は妹を守るっていうってふざけた問題なんだけど、 たぶん、これはインスタンス属性へのアクセスをフックすることができればいいんだ。

まずさ、Pythonの基本として クラスのみんなで決めたことよりも、自分が決めたことが優先される が基本だよね。 だから、クラスの属性よりも自分が設定した属性のほうが優先されるよね。

class Player:
    description = "Player"
    def __init__(self):
        pass

if __name__ == "__main__":
    student = Player()
    assert  "description" not in student.__dict__, "attribute does not exist in __dict__"
    assert student.description ==  Player.description == "Player"

    #student.description = "StudentS"
    setattr(student, "description", "StudentS")
    assert  "description" in student.__dict__, "attribute exists in __dict__"

    del student.description

    assert  "description" not in student.__dict__, "attribute does not exist in __dict__"
    assert student.description ==  Player.description == "Player"

何もしないと、属性を自由に書き換えられてしまうんだけど、属性へのアクセスの仕方を変えることができるのがDesciptorなんだ。 今日の課題となって渡されているプログラムはこれ。

class Teacher:
    def __call__(self, girl):
        raise RuntimeError("検閲により削除")

class You:
    """ [Implement]
    """

class Imoto:
    boy_friend = You()

    def check(self):
        if isinstance(self.boy_friend, You):
            print("やっぱり、お兄ちゃんはまだ私がいないとだめだなぁ!")
        elif isinstance(self.boy_friend, Teacher):
            print("お兄ちゃんなんてどうでもいい!")
            self.act()
        elif isinstance(self.boy_friend, You):
            print("たどり着くのは難しいって分かっている。")
            print("この穏やかな関係を1回壊して、もう1回関係を作り直さなきゃいけないから。")
            print("でも、ここが、お兄ちゃんとの理想の関係。")
            print("私たちの到達点だよ!")

    def act(self):
        self.boy_friend(self)

if __name__ == "__main__":
    """ :今日の課題:
    君の妹はとても可愛い。幼いながらも知的で純粋な目を僕に向けてくれる。
    冷めた目で僕を嘲笑する君とは大違いだよ。兄弟で全然性格が違うね。
    僕は君の妹に僕だけをみていて欲しいと強く願うんだ...

    君は可愛い妹の兄だ。
    上記は職員の新年会で酒に酔ったとある教師がつぶやいていた文章である。
    教師の妹に対するアプローチをYouクラスを実装することで制限せよ。
    1. Runtime Error を発生させないようにせよ
    2. Imotoクラスcheck関数で"ここが、お兄ちゃんとの理想の関係。"が表示されるパスを通るようにせよ。
    """
    imoto = Imoto()
    teacher = Teacher() 
    imoto.boy_friend = teacher
    imoto.check()

問題設定がひどいよね。 なんで兄限定にしてんだか。 フィクションの兄妹関係に幻想もちすぎじゃないの?
pythonのコードと同じぐらいのどーでもいい文章量...この設定不要でしょ。
しかもさ、教師として教師の売春をネタにするって自虐が強すぎるし。

まぁ、文句はあるけれど1問目から考えていこうか。

大切なところは

imoto.boy_friend = Teacher()

だね。ここでimotoの属性が書き換えられちゃてる。
他のプログラミング言語だったら、アクセス修飾子をつけることで解決できるよね。
JAVAC++privateとか。恋人とかの話は簡単にするものじゃないから、privateにしておくべきだよね。
わたしに妹はいないけれど、もしいたら、"好き"とかそういう話はきっと2人っきりのときにしかしないよ。

そうそう、Descriptorの話。

class You:
    """ [Implement]
    """
    def __get__(self, obj, type=None):
        pass

    def __set__(self, obj, value):
        pass

細かいところは、Tutorial をみるとして、 get, setを定義しておけば、インスタンスの属性のアクセスの時にget関数やset関数を呼び出してくれる。

これがDescriptorの役割だね。

問題1だけならとっても簡単。 Descriptorを使ってteacherboy_friend 属性に代入するところの処理を無視するようにすればいいだけ。

class You:
    def __set__(self, obj, value):
        pass

最低限これだけ書けば、少なくとも、妹のboy_friend属性は守ることができるね。 本当は、

class You:
    def __set__(self, obj, value):
        if isinstance(value, Teacher):
            del value

ってしたいけどね! こうすれば、ふざけた教師は消せるからね。

はい。これで1問目は終わり。 次の問題がちょっと難しいね...

if isinstance(self.boy_friend, You):
    print("やっぱり、お兄ちゃんはまだ私がいないとだめだなぁ!")
elif isinstance(self.boy_friend, Teacher):
    print("お兄ちゃんなんてどうでもいい!")
    self.act()
elif isinstance(self.boy_friend, You):
    print("たどり着くのは難しいって分かっている。")
    print("1回壊して、もう1回関係を作り直さなきゃいけないから。")
    print("でも、ここが、お兄ちゃんとの理想の関係。")
    print("私たちの到達点だよ!")

このプログラムはひどいよね。 if/elifで同じ条件を使うって、馬鹿なの?
素直にこの部分を書き直せよっていいたい。すごく言いたいなー

それにさ、この問題の作成者のImotoという概念の使い方が低俗だと思うんだよね。
ちょっとした環境の変化で家族関係が変わってしまうのは考えにくいはずだよ。
兄弟の関係性にだけ焦点をあてて、ちょっと刺激的な文章を書けばいいと考えている
作者の"甘さ"が透けるんだよ。
人間どうしの関わりを観察するとき、定型的な関係を記号的にとらえるだけじゃ駄目だよね。

あ、問題の話だったねー
そうだね、君の言う通り早く宿題を終わらせるのが大事だよね。
この"歪んだ関係"を直すためには、歪んだプログラムが必要だね。
副作用、変数にアクセスする度に結果が変わる仕組みを使うしかないね。

class You:
    flag = False
    def __get__(self, obj, type=None):
        if not You.flag:
            You.flag = True
            return None
        return self

    def __set__(self, obj, value):
        pass

クラス変数を使ってこうすればできるけどさ、これはひどいよねー
こんなのdebug用にboy_friend属性にアクセスしただけでも破綻するプログラムだもんね。

歪んだ関数自体を直すという発想からは、関数自体を書き換えるという方針がありだね。
関数自体の中のパスを通すという課題からは少しずれてしまっているかもしれないけれど。
まあ、これもひどいプログラムだよ....

class You:
    def dummy_check(self, obj):
            print("たどり着くのは難しいって分かっている。")
            print("この穏やかな関係を1回壊して、もう1回関係を作り直さなきゃいけないから。")
            print("でも、ここが、お兄ちゃんとの理想の関係。")
            print("私たちの到達点だよ!")

    def __set__(self, obj, value):
        setattr(obj, "check", lambda: self.dummy_check(obj))

なんか疲れたなー
もう夜の2時か...なすごく不毛な宿題だったような気がする。
プログラムを読むより、日本語を読んでいた時間の方が長いような気がするねー
君とぼんやりでも話ながらやらないと、精神的にきつかったよ。
ごめんね、こんな時間まで付き合わせちゃって。 お互い早く寝たいよねー
ここまで付き合ってくれてありがと。
君の宿題も終わったよね。 また明日、学校でね。

今月の反省

  • RPの主人公は幼馴染の男の子とチャットしながら宿題をやっている女の子を目指しました。 ちょっと失敗感..
  • やりたいことが不明瞭になっていますね。 RPの中途半端さと、Python Descriptorの説明もどっちも中途半端なような気がします。 問題だけに焦点を当てるならもう少し短くまとめてもよかったし...
  • 文章の論旨が非常に不明確ですね。これは呪殺対応にてこずっていた偽でしょう。多分狂人。