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

...What are you learning now?

動画化村を振り返ってみたよ!

はじめに

「都合の良いことだけを並べて、他の人を説得する」
人狼ゲームでは、これが必要になりますよね。
情けなくても、みっともない暴論を振りかざし、
「やめて! 私を吊らないで! 吊るべき敵はあいつだよ!」
と主張を作るのが、人狼ゲームの面白さ。

だけど、情報処理能力の関係上、村の最中だけでは、深い議論が出来ないときがあります。
さらに、ゲーム中は、PLとしての立場が視野を狭くする傾向にあります。

参加した村を振りかえり、改善点を探すことで、
もっと、面白い主張を作ることができるかもしれない。
今回はそれをやってみたいと思います。
題材は、

No.343651「【動画化村】12A猫」村

禅乃蓮(ぜんのはす) さんが動画にして作成してくださった村

こんな人狼ゲームのお話【10】-配役12A猫 by 禅乃蓮(ぜんのはす) ゲーム/動画 - ニコニコ動画

です。
参加した『男の子』に振り返って、語ってもらおうと思います。 なお、ネタバレを含むのでご了承ください。

ボクの動画化村参加記録

おはよー! 動画化村に参加させてもらった男の子だよ!
この夏も暑いなって思いながら村を歩くと、
短いスカートや半袖の女の子が多くて、ちょっとどきどきしちゃう。
慌てて目をそらすんだけど、ボクが不自然に見られちゃうし。ちょっと見えちゃうし…
でも、仕方ないよね….だ、だって男の子だもん。夏って不思議な季節だね!

参加した村のことを思い出して、考えたことを書くつもりだよ。
学校の読書感想文とかが苦手だから、いい文章が書けるか不安だけど、 頑張るね!

大体の内容のまとめはこんな感じだよ!

  • 狼騙り初手○による囲い。猫噛み破綻は考慮する?

    • 4-1 展開なら意味が無い。
    • 3-1 展開なら薄く意味がある。
  • まろんさんからの○結果を使った村アピール

    • 真占い生存、2W死亡の可能性がある状況下で狂人は○を重ねない。
  • [おまけ] 「男の子が狼」という主張の例。

詳細を読みたい所だけ斜め読みしてくれたら嬉しいな。

狼騙り初手○による囲い。猫噛み破綻は考慮する?

(発言:3:4, 5:9) <注: 村中の発言日:発言番号を表しているよ。例えば、発言3:4は、3日目の発言4だね。>

…でもね、ボクが狼だとしたら、噛み役はどうすると考えるのかな?
○で狼を囲ったら、(霊能が噛めて●を隠せたとしても)
その騙り役の○が噛めなくなるよね!だから、狼の○では囲っていないと
考えるのが自然じゃないかな?

(発言3:4 一部抜粋)

いい文章になっていないけど、

「狼が2騙りをした場合、潜伏狼を初手で囲わない。理由は、その騙り役の○を潜伏狼が噛んで猫だと破綻するから。」

というのが、発言3:4でボクが言おうとしていたことだね。

これは今回の村のように

  • 4-1展開
  • 占いローラーが完遂される

状況だと、成り立たないことだね。

だって、

  • 占いローラー中に騙りが猫噛みをする場合は、破綻前提の噛み
  • 占いローラー中に騙りが猫噛みできない場合、猫噛み = LWの死亡

だから。

上の指摘点が問題になるのは、

  • 3-1(真狼狼)でローラーが途中で止まる

ケースなんだ。

「2W残りで潜伏役と騙り狼が生存している。」
この時、囲われた潜伏役の○が、騙り狼の別の○を噛んだ時、噛み先が猫又だと破綻してしまうよね。
この意味で噛み先が制限されてしまう。というのが、
発言3:4でボクがいいたかったこと。
狼が2騙りを行うときは、
「4-1を狙うよりも、3-1で真狼狼を真狼狂と誤認させたい」
という気持ちが強いだろうからね。
3-1だった場合想定ケースの主張は通ると思うな。

だけど、上の主張はあくまでも1つの要素を取り出しているだけ。

  • 4-1になった場合は、関係ない

という「意味がない」という主張だけじゃなくて

囲わないことで、

  • (狼狼-真)の2-1展開になった場合、グレーランダムで潜伏狼が吊れてしまう可能性がある
  • (真狼狼-真)の3-1展開で占いローラーが止まっても、囲わないとグレー詰めで指定される可能性がある

とか、そういうデメリットの要素も上げることが出来るから。

「総合的にどっちがいいの?」という問いに対してのシンプルな答えはないけれど、
ボクは狼騙りの○もらいだったから。自分にとって都合のいい要素を取り出して主張したんだ。

まろんさんからの○結果を使った村アピール

村の最中にボクが言えなかった主張。
まろんさんと新人さんのどっちが狂だと思う?」という質問に対して、
ボクは、発言5:23で、

新人刑事が狂人だとボクは思うよ。対抗の○に意識がいくのは狂人特有の動きだからね。

と答えている。これは、感情論、フィーリングに訴えかける主張だね。
少しロジカルな主張を付け加えることができたなぁ。と思ったよ。
それは、「まろんさんが狂だとしたら、自分○は狂人にとって、戦略の幅を狭める結果だよ!」 という主張。

5日目の霊界発言で、有像無像さんが話していたね。

まろん狂人で見た場合この展開で真の〇に重ねて確定〇は極力作る展開は避けたいはず
霊能結果を見る前出していましたし下手に〇打つのはリスクが高かったのではないかと

これくらいのすんごい薄い根拠の(男の子)村置きではありましたが

ボクなりの解釈と主張で言葉にするね!

まろんさんが狂人だと仮定するね。
まろんさんが狂人だとすると、誰が真かは2日目の段階で分からないよね。
そして、朝の段階でユウリさん狼が露呈。
2日目の吊りは新人刑事さんだった。
まろんさんの視点では2通りのケースがあるね。

  • A 新人さんが○、真の可能性
  • B 新人さんが●、狼の可能性

Aのケースだけを考えるのなら、狂人視点、グレーに対しての色はフラット。自分○の結果はあり得るね。

でも、Bのケースを考えたらどうかな?
猫噛みがあって新人さんが●だったら、
このケースでは、狂人視点、○を打つべきは「グレーの狼っぽい所」だよ。
村の進行として、占い師候補のグレー詰め/占い師吊りという両方の進行の可能性があるけれど、
狼が囲えた場合、

  • グレー詰めの進行になった時、狼を保護できる。
  • 占いローラーが続いた時に、真狂占いの○結果は狼にとって有利に働く。 (例えば、狼を囲えた後で真が狼を見つけても、狂人が確実に村の場所に●を打っているように見せられるよね。)

以上2点によって、狼有利な状況となるから。

さらに、シンプルに考えるなら、 AとBのケースのどちらを中心に考えるべきかは、以下の観点からBのケースだと言えるね。

  • 新人さんが○ or ●の確率は大体 1/3 or 2/3 だと考えられる。Bのケースの方が発生しやすい。
  • Bのケースは、狼陣営にとって苦しい展開となっている。(狂人のサポートが必要な状況)

発生しやすくて、悪い状況を想定しておくのが自然だよね。
だから、Bの可能性をみないのは不合理だと思うんだ。
まろんさんが狂だとしたら、相当に不自然な選択をとったことになる。
これが、まろんさん真の根拠だよ!

というのが、村の最中にできなかった、少しだけロジカルな主張。

もちろん、この主張に反論をつくることは簡単にできるよね。

  • ボク(男の子)が○結果を無視してでも、狂人視点狼として分かるようなグレーだった。
  • ボク(男の子)が狼だった場合、上記の議論で村アピールができる。その状況を作るために、ボク狼を読んでギャンブルをした。

こんな感じかな。

でも、有象無象さんがまとめてくれたように、発言を無視してシンプルに考えると、3日目の状況で

  • 真の可能性がある○先に○を重ねるのは、狂人として不利に働く可能性が高い戦術である。

というのは、ロジック上、ある程度の説得力を持っていると思うんだ。

だから、こういう主張ができたら良かったなーと振り返って思ったよ!

実際は、まろんさんは狂人。自分●をほぼ決め打って○を出しているみたいだった。
多分、まろんさんは勝負を賭けたんだよね! そして、自分が狼だったら、上の要素を使って村アピールができるよね。

その他いろいろ

最終日の反省点。

ボクの発言5:4は、鳳さんの発言4:5を踏まえた上で行うべきものだったよね。 読めていなかったよ…

発言2:29 「女の子に『豚』っていったら駄目だね…」

可愛い豚の鳴き真似をした、豚鼻幸子 (豚系女子) さんに 「豚」って言っていたね。 「豚」って言われて傷つく女の子もいるみたい。 あんまり言わない方がいいみたいだなぁ。

仲良くなるには時間が必要…

発言2:12の

  • 「おとこなら誰でもいい」
  • 「誰でもいいけど付き合って」

っていうのは、無責任じゃないかなぁ。
仲良くなっていく為には時間が必要だと思ったね。
ボクは、誰でもいいような人と付き合いたくないよ。

ボクはまだ子供で恋愛とかよく分からないけれど、
困った時や大変な時に助け合える人と関係を築いていく。
っていうのが恋愛なんじゃないかな、って想像しているよ。

大人になったら、そんな素敵な女の子に出会えるといいなぁ。
そして、ボクもその人にとっていい男の子になりたいな。

おまけ

井上美羽さんっていう人狼プレイヤーが、自分狼の主張を作ってくれた。おまけとしてのせておくね。

Summary

端的にまとめますね。

  • 男の子は狼。狼騙り初手○先を村陣営アピールに利用している狼。

以下の2つが証拠。

  • 「狼騙りが初手○囲いをしない」主張が実際とは違う3-1の場合前提。実際に4-1となる前(初日夜)に主張を作っていた証拠。
  • 思考の前提に「霊能者噛み・色隠し」の意識がある。噛みの戦略を考えていた狼の証拠。
Detail

少し長くなるけれど、以下が詳細です。

[3-1の場合でしか成立しない主張]

男の子は発言3:4で

  • 「囲いの○猫噛みによる破綻露呈」を防ぐために、2騙り中の狼騙りが潜伏狼に初手○を打たない

と主張をしているわね。

これは、今回の村のように 4-1の展開になった地点で、占い騙りの狼が猫噛みを狙うので、成り立たない主張。
3-1の展開の場合であったら、「囲いの○猫噛みによる破綻露呈を防ぐため、狼騙りが初手○を潜伏狼に出さない」 という主張は、弱いけれども成立する。
でも、男の子から、「3-1の場合だったら…」という発言はない。
実際は4-1展開だったのに、当然のように「たられば」の3-1のケースでの主張しているわ。
前提条件への言及がないのは、彼が、2日目昼4-1展開になる前に主張を作ったからですね。
2日目前に主張を作ることが出来る理由は、
「男の子が狼で初日の夜に仲間から○を出されることが分かっていた」から。
それ以外の理由は存在しないですよね。

狼が2騙りであったら、4-1よりも3-1の方を望むでしょうし、
初日夜に主張を作るとき、希望的観測が前提条件として彼の思考に入ったのでしょうね。

[霊能者噛み・色隠しへの意識]

さらに、発言3:4で「霊能者噛みの色隠しが発生した場合に…」といっているわね。これはおかしい。
占い狼2騙りで、吊られた狼占いが破綻したとしても、何も問題はないわ。他に潜伏狼がいないんだから。
それにもかかわらず、「霊能者噛み・色隠し」という単語が出てくるのは、

  • 初めから狼騙りの初手○を村要素として使おうとした
  • 意識が噛みの戦略に向けられていた

という2つの要因しかないですわ。

前者の要因は、[3-1でしか成立しない主張]と同じで初日夜に主張を作っていたからですわね。
後者の要因は、毎晩の噛み先決定のときの思考が、村アピール考察を作るときの思考に混ざったのでしょうね。
おそらく、初日の夜に決めた主張の大枠に、噛み先決定の時の「思いつき」を付け加えたのだわ。
該当箇所の発言が括弧"()“で括られていることが、付記的な内容だったことを示唆しています。

以上2つが、男の子が狼、とくに

  • 初日の夜に考えた「2騙りで狼騙りが初手○で潜伏狼を囲わない」 という理論を押し通す潜伏狼

であることを明確に示す証拠ですわ。

補足・まろんさん真視 + まろん吊り容認は狼の村アピールだった。

さらに、 発言3:39, 3:42から以下のことも分かるわ。

  • 男の子はまろんさん真の印象を主張しつつ、まろんさん吊りを止めない。

これは、狼でしかあり得ない行動。

  • 偶数進行で狂人のまろんさんを吊らせる必要があった。
  • まろんさんからの○を村アピールに使う必要があった。

この2つを同時に行う必要から、中途半端なまろん擁護になったのよ。
村陣営なら、まろんさんが真と思うのであれば、豚系女子(豚鼻幸子)さん吊りを主張すべき場面だったわ。
男の子は『占い師候補の真贋判定に決定的な違いはない』と言っているけれど、
例えば、3日目の結果からは、猫に○を出した豚系女子(豚鼻幸子)さんの狂目が低いというのがシンプルな考察だよね。
単純な考察の提出もせずに「まろん真目でみて、まろん吊りを推す」というのは、 狂人を吊らせる必要がある狼だったから。

あとがき

迷った所

まろんさんの擁護の中途半端さの扱いに悩んだよね。まろんさん擁護の中途半端さを積極的に狼誘導につかうと、
まろん真の時男の子は村人だよね』となって、誘導が逆に働いてしまうかもしれない。
だから、『男の子が狼』と思ってくれる人への確度を高めるためには使える主張かもしれないけど、
『どっちだろ?』って迷っている人に対して使うかどうかは、実際の村では少し微妙かなー って思った。 ま、でも、兎に角、攻撃しやすい発言だねー

男の子君へ

こんな感じで作ってみたけどどうかな? 落ち着いて書いた後付けの文章だから、いつもの村の文章よりはある程度質は高いと信じたいなー
実際の村ではまとまっている文章を書くのは難しいけれど、たまには、時間をかけて練られた文章で誘導合戦できたら楽しいかもねー
またよろしくねー

おわりに

ここまで読んでくれた人、ありがと!
動画村参加させてもらって楽しかったよ! ボク、今でも時々思い出すよ!
参加して思ったのは、ボクの力はまだまだ足りないなぁ…ってことだね。
だけど、人狼で一番大事なのは楽しむことだよね! また、楽しい村に参加することができたらいいなぁ。
また、一緒に遊ばせてもらう時があったらよろしくね! 一緒に楽しい村が作れるといいね!
暑い夏はまだまだ続くけど、体に気をつけようね! ボクも体に気をつけて残りの夏休み、楽しく過ごしたいな。

StudentS’s Afterwords.

感想

久しぶりにブログ用の文章を書いたーという感じでした。 書こうと思った理由は

こんな人狼ゲームのお話【13】-配役14D猫 by 禅乃蓮(ぜんのはす) ゲーム/動画 - ニコニコ動画

の編集技術に圧倒されたからですね… 自分も何かできるかなぁ? と思って書いてみた…という感じですねー

ファイルの管理にご注意を

現実世界の知り合いの方との共有フォルダに誤ってこの原稿の下書きを入れてしまって1週間立っていました。赤面ものです。どうか、見られていませんように。 …現実世界で「…んで、『男の子』はどう思うの?」とか言われたら、私はどうすればいいんでしょうか? 皆様も、重要な情報の管理にはご注意ください。

3-1進行をモチーフにした、確率計算の練習問題

どーてもいい話

こんにちは。StudentSです。
最近、書店に行き本を購入しました。
すると、おまけで 自由研究ノートというものを頂きました。
(タイトルが「せいしゅんのきろく」うーん、どう使えばいいのだろうなぁ?と思いながら。)
何かやらねばならんなーという感じがしたので、
そのノートを使って、ちょっとした頭の体操をしてみました。

導入

るる鯖12A猫、3-1展開はよく見られますね。
占い師吊りになる場合、初日の吊り先の決定要素として、確率論を使うことは多いみたいです。
問題を単純化した場合、議論で大切なのは「狼が初手囲いを採用する確率」です。

読みにくい文章ですが…

3-1○展開のグレーランダムと占い師吊りの均衡点について - 12A猫で学んだこと-Memoir-

でも考えたりしてみました。

霊能者狼だったり、占い真狼狼の確率を導入するともう少し複雑な問題になりますが、 その可能性を0として見なすのであれば、1パラメータで議論ができるでしょう。

今回は、「3人の占い師候補の内、2人が相互○を出していて、1人がグレーに○を出している」
という条件下で

  • 相互○が(真, 狂)
  • 相互○が(狂, 狼)

である事後条件確率を求めたいと思います。

問題設定・全視点で成立する前提と全てのPLで共通して持つ仮定

  • ルールは12A猫 (るる鯖準拠)
  • 3-1 真狂狼 - 真
  • 狼が初手囲いをする確率をmとする。
  • 占い/占い騙りのPLはABC, AとBは相互に○出し、Cは霊能者以外に○を出す…[ア]
    (例)

    • A: B○
    • B: A○
    • C: (霊能者以外のグレー)○
  • [ア]の状況が観測された条件下で、

    • Case1. Cが狼である事後条件確率
    • Case2. Cが真である事後条件確率

を求める。

結果

  • Case1の事後条件確率: (3m+5) / (10-2m)
  • Case2の事後条件確率: (5-5m) / (10-2m)

従って、Cが真である確率が1/3以上になる条件は、
mが 5/13 よりも小さいことであると言える。

導出の詳細

  • 狂人は○打ちの戦略を選択したとして良い。

Case1. の条件下で[ア]が観測されるケース

  • 1/10 * 1/10 * (m * 1 + (1-m) * 5/8)
    • 狂人・占いが相互に○打ちをする。
    • 狼が初手囲いするとしたか、初手囲いをしない戦略を採用し、(11 - 3 - 2 - 1 = 5)人のなかの誰かに○を出す。

Case2. の条件下で[ア]が観測されるケース

  • 1/10 * ((1-m) * 1/8) * 5/10

    • 狂は占い騙りの狼に○を出す。
    • 狼は、初手囲いをしない戦略を採用し、狂人に○を出す。
    • 真は10人の中から、グレーの中の5人の誰かに○を出す。

この2つの確率より、結果を導出できる。

3-1○展開のグレーランダムと占い師吊りの均衡点について

はじめに

12A猫の進行をみさせていただいて、初日3-1進行の時、
占い師吊りかグレーランダムで意見が別れるということを見せていただきました。
個人的には、どっちの進行でもいいと思います。
占い師に頼る進行もあれば、狩人や猫に頼る進行もあるでしょう。

単純にロジックのパズルとして考えた時、どちらの進行がいいのでしょうか?
このエントリではそれを考えてみたいと思います。

サマリー

(詳細な様々な仮定は必要ですが)
初日3-1○展開で霊能以外の3人に○が出ている際、
狼の初手囲い確率20%が、
狼を吊るという目的に照らし合わせた時の
占い師吊りとグレーランダムのどちらがいいかの分岐点です。

解析の詳細

最初に言わなければならないことは、
「村/狼陣営の勝率」という形で厳密に解析しようとすると、この問題は極めて難しくなります。
グレランで猫/狼/狩人が吊れた場合の村勝率を計算しなければならないからです。
4人最終日/3人最終日から逆算して、算出していくことが出来れば理論的にはできるはずですが、
非常に重い。だから、それは止めましょう。

評価規範を

  • 初日に狼を連れる確率が高い方が良い

という1点に絞って議論をします。
さらに、簡単のため、以下のような前提をおきます。

解析の前提

  • 3-1 (占い師CO3-霊能CO1) 霊能者は真、占い師は真狂狼とする。
  • 占い師候補は霊能者以外のそれぞれ別の場所に○結果を出している。
  • 狩人/猫又COを考慮しない。
  • 狼の占い騙りが仲間に○を出す戦術を取る確率をm, ○を出さない戦術を取る確率を(1-m)とする。
  • 組織票を考慮しない為に、グレランの時も占い師候補つりの時もダイスで吊り先決定する。

さて、mの値によって、初日、占い師候補吊りがいいのか、グレーランダムがいいのか異なります。
占い師吊りとグレーランダム吊りで狼が吊れる確率が一致するmの値を求めてみたいと思います。

「厳密には間違えている」大雑把な解析

さて、まずは軽くどの程度の値になるかをざっくりと算出しましょう。

  • 狂人の○は、適当に出されているだけなので無視してよい
  • 残りの真占いと狼の2○のうち、狼の期待値はm

つまり、ざっくりと、11 - 3 - 1 - (3 - 1) = 5 の中に、2-m匹の狼が潜んでいると考えていいでしょう。
「適当にダイスを振って、ダイスの通りに投票する」という乱択戦略を採用することで
吊ることのできる狼の期待値は (2-m) / 5.
m = 0 (狼が初手囲いをしない場合) であれば、40%で狼が吊れることになりますし、
m = 1 (狼が必ず初手囲いをする場合)であれば、20%で狼が吊れることになります。

占い師候補吊りの時に狼が吊れる確率は 1 / 3 なので、
m = 1 / 3 の時に、2つの確率は一致する。

つまり、

  • 狼が初手囲いを行う確率が大体1/3よりも大きいと思うのであれば、占い師吊りをするのが良い。
  • 狼が初手囲いを行う確率が大体1/3よりも小さいと思うのであれば、グレーランダムをするのが良い。

というのが大雑把な解析から言えることです。

この計算は間違っていますが、検討はずれの値にはならないでしょう。
近似的に感じをつかむには悪くない考え方だと思っています。

厳密な解析

上記の解析が誤りである理由は狼騙りが

  • 初手囲いを選んだ場合
  • 初手囲いを選ばなかった場合

2つの場合について

  • 3-1 で別々の場所に○がでる。

確率が異なるからです。
なので、厳密に確率を調べるにはそれを考慮して事後確率分布を計算する必要があります。
ちょっとだけ大変です。

  • 真占い師が○引きという前提 ・ 狂人が○を出すという前提で考えてよい。
  • 村人に○が出される時、狂人/狼が真占いとは別の場所に○を出す時の確率を考える。

上記の方針で計算していきます。

計算…

真占い師の○先以外に、狼/狂人が別々の場所に○を出す場合で以下の事象が起こる確率を計算していく。

  • 狼が初手囲いをしない場合: 8人のうちからランダムに1人
  • 狼が初手囲いをする場合: 2人のうちからランダムに1人
  • 狂人が○を出す先: 10人のうちからランダムに1人

に結果を出すこと、そして

  • 占いの○先が重複しない場合

のみを扱うので…

  • 狂人の○が村に、狼の○が狼にでる確率 (グレラン対象1W): 4 / 10 * m
  • 狂人の○が村に、狼の○が村にでる確率 (グレラン対象2W): 4 / 10 * (1 - m) * 3 / 8
  • 狂人の○が狼に、狼の○が村にでる確率 (グレラン対象1W): 2 / 10 * (1 - m) * 4 / 8
  • 狂人の○が狼に、狼の○が狼にでる確率 (グレラン対象0W): 2/10 * 1 / 2 * m

以上の確率となります。

  • グレラン対象0Wになる確率: 2m / (5+5m)
  • グレラン対象1Wになる確率: (2+6m)/(5+5m)
  • グレラン対象2Wになる確率: (3-3m)/(5+5m)

となります。
したがって、

狼がグレランで吊れる確率は

  • 1 / 4 * (2+6m)/(5+5m) + 2 / 4 * (3-3m) / (5+5m) = 2 / (5+5m)

となります。

  • m = 0の時の結果
  • m = 1の時の結果

は前述のざっくり計算と同じ結果になりますね。 したがって、

「狼が初手囲いの戦略を取る可能性が1/5よりも大きい時に、占い師3択吊りを行った方が狼が吊れる可能性が高く、 狼が初手囲いの戦略を取る可能性が1/5よりも小さい時に、グレランを行った方が狼を連れる可能性が高い。」

という結論になります。

ざっくり計算とは10%ほど結果が異なりましたね。

終わりに

  • 狂人は必ず○結果の占いCOをする。
  • 狼2騙りは考えない
  • グレーや○もらいの猫又/狩人COを考慮しない。

など、多くの仮定を必要としますが、上記が単純化した状況におけるロジックからの結論です。

1人の人狼の観戦者として主張したいことは

  • 「狼の戦略によって、村視点の良い進行が異なる」

ということですね。 様々な戦術論があると思うのですが、 「勝利を追求する」という姿勢からみれば、それは「じゃんけんでグー/チョキ/パーのどれを出すのがいいかを議論している」のと同じです。
人狼ゲームは複雑なルールのじゃんけんでしょうね。
人狼ゲームが強い方は、対戦相手の癖…対戦相手の出すじゃんけんの手を意識的/無意識的にうまく活用しています。
ただ、人狼ゲームがじゃんけんとは違うのは、ゲーム中のストーリーの面白さだと思いますね。

人狼が強い参加者の方は、じゃんけんが強い方です。
人狼のゲームを舞台に人を楽しませられる参加者やGMさんは、エンターテイナーです。

人狼はゲームだから、楽しむことが第一でいいんじゃないかなぁ。と思うのです。
「弱い」と言われても仕方はないけど、「面白くない」というのは悲しいですよね。

つぶやき

自分は人狼ゲームでの勝利や、GM業にあんまり適性がないなぁ…と思っています。
それでも、刺激を得られるから、参加させていただいているのかなぁ…
あと、村での振る舞いや発言が面白かったといっていただけると嬉しいですねー

初日占い文を作ろう -ちょっと工夫してみる-

最初に

ちょっと、力不足だなぁ…と思う所が多いですが、 多分、ためていても駄目なものだと思うし、メモ程度のものとして、 占い文の自動生成のコードをおいておこうと思いました。

初日占い文の自動生成を考えた話の続き。

初日占い文を作ってみる。 -位置情報の自動生成- - 12A猫で学んだこと-Memoir-

考えたこと

初日占い文を上記のエントリで作成しましたが、最低限の機能しかなかったです。 使うことができるようになるには、工夫がまだまだ必要だと思います。 少し考えてみた結果、自分は最低でも以下の点は欲しいと思いました。

  • 第一犠牲者からの位置情報も欲しい。
  • 位置を書く時に自分のCharacterNameをそのまま書かない。 自分自身のCNは「自分」のように置き換えよう。
  • 挨拶があまりにも単調。 バリエーションを持たせたい。
  • 全ての位置を記載するPlayerはかなり不自然。書く位置のPlayerの数を制限しよう。
  • 感嘆詞・Fillerを活用したい。

実装方針

第一犠牲者からの位置情報

これは合った方がいいですね。バグの修正レベルの内容でしたね。

自分自身のCNの書き換え

凄く簡単。1-2行追加するだけ。

挨拶のバリエーション増加

  • 時間帯に合せた挨拶をする
  • 挨拶を入れるかどうかをランダムにする

上記2点ぐらいを入れたら、少しは単調さがなくなるでしょうか、

書く位置のPlayer数の制限 / 感嘆詞・Filler・接続詞の活用

「位置情報をどのPlayerから記述するか」という問題と絡んで、 少し難しいですね。とりあえず、"よさそうな"例を1つ作ってみて、 細かい所は調整ということにしましょう。

上記の考え方に基づいて作ってみたのが下のスクリプトになります。 うーん、エンターテイメント性に欠けているなぁ…

ソースコード

import os
import sys
import re
import datetime
import math  
import random
import codecs
from collections import defaultdict
from operator import sub, add, mul

import lxml.html

def _get_partition_maplist(target_list, function):
    """ Return the partitions of list 
            function: element -> key of maplist
    """
    ## Not sophisticated code...
    maplist = dict()
    for elem in target_list:
        key = function(elem)
        tmp = maplist.get(key, list()); tmp.append(elem); maplist[key] = tmp
    return maplist

def get_myname(root):
    """ Return my name.
    
    """
    nodes = root.xpath('//td[@class="occupation"]//span[@class="name"][position()=1]')
    assert len(nodes) == 1
    node = nodes[0]
    return node.text

def get_position_map(root):
    """ Return the position map: position -> name. 
           position: 2D tuple.
           name: participant's name.
    
    " Left upper is (0, 0), and the format is (vertical_index, horizontal_index).   
    """
    table_nodes = root.xpath('//table[@class="iconsmall"]')
    assert len(table_nodes) == 1
    table_node = table_nodes[0]
    name_nodes = table_node.xpath('//td[@class="name"]')
    position_map = dict()
    for index, name_node in enumerate(name_nodes):
        horizontal_index = index // 2
        vertical_index  = index % 2
        position_map[(horizontal_index, vertical_index)] = name_node.text_content()
    return position_map

def create_document(myname, target_name, position_map):
    """ Create the sentence of foreseener. 
     @param str myname: your name.
     @param str target_name :  the target of foreseeing.
     @param dict position_map :  position -> name.
    """
    def create_header(target_name):
        return "占いCO {name} ○".format(name=target_name)

    def create_greeting(myname):
        def _select_greeting_with_time():
            greeting = ""
            hour  = datetime.datetime.now().hour
            if 0 <= hour  <= 3:
                greeting =  "深夜の人狼、楽しみたいと思います。\n"
            elif 4 <= hour <= 11:
                greeting =  "おはようございます。"
            elif 12 <= hour <= 16:
                greeting = "こんにちは!"
            elif 17 <= hour <= 23:
                greeting = "こんばんは。"
            return random.choice([greeting, ""])
        greeting = ""
        greeting += _select_greeting_with_time()
        greeting +=  "占い師の{name}です。".format(name=myname)
        return greeting

    def explain_act(target_name):
        return "気になった{name}さんを占います。".format(name=target_name)

    def explain_result(target_name):
        return "○結果。人狼ではないです。".format(name=target_name)

    def explain_closing(my_name, target_name):
        text = "久しぶりの占い師、楽しませていただきたいと思います。\n"
        text += "特に大人数村の占い師はあまりやったことがないので、ドキドキです。\n"
        text += "配役に狐がいると、同じ人外でも狙う対象が変わったりして、考える幅が広くて面白そうです。\n"
        text += "\nあ...{target_name}さん、霊界観戦楽しんでねー".format(target_name=target_name)
        return text

    def create_position_information(myname, target_name, name_to_pos):
        root2 = 2**0.5
        _basis_map = {(1, 0): "下", (-1, 0): "上", (0, 1):"右", (0, -1):"左"}
        _basis_map.update({(1/root2, 1/root2):"右下", (1/root2, -1/root2): "右上", (-1/root2, 1/root2):"左上", (-1/root2, -1/root2): "左下"})

        def _is_display_position(diff_vector):
            max_norm = max(map(abs, diff_vector))
            return  max_norm <= 2
        
        def _calc_dot(vec1, vec2):
            assert len(vec1) == len(vec2)
            dot = sum(map(mul, vec1, vec2))
            return dot

        def _convert_to_string(target_name, diff_vector, basis_map):
            def get_vector_array(vector, ref_vectors):
                square_norm2 = sum(map(mul, vector, vector)) 
                if square_norm2 < 1:
                    return []
                result = list()
                best_basis = max(ref_vectors, key=lambda ref_vec: _calc_dot(ref_vec, vector))
                square_norm_best_basis = sum(map(mul, best_basis, best_basis)) 
                best_coef = _calc_dot(vector, best_basis)  / square_norm_best_basis
                best_pair = (best_basis, best_coef)
                best_vector = list(map(lambda elem: best_coef * elem, best_basis))
                residual = list(map(sub, vector, best_vector))
                return [best_pair] + get_vector_array(residual, ref_vectors)

            def to_position_string(vector_arrays, vector_map):
                def _to_str(char, number):
                    if number == 1:
                        return char
                    return "{number}つ{char}".format(number=number, char=char)
                position_str = ""
                pair_list = sorted(vector_arrays, key=lambda pair: pair[1])
                string_list = [_to_str(char=vector_map[pair[0]],number=int(pair[1])) for pair in pair_list]
                position_str = "の".join(string_list)
                return position_str
            
            def _add_honorific(name):
                if name != "自分" and name != "第一犠牲者":
                    return name + "さん"
                return name

            ref_basis = list(basis_map.keys())
            pairs = get_vector_array(diff_vector, ref_basis)
            position_str = to_position_string(pairs, basis_map)
            return "{name}の{p_str}".format(name=_add_honorific(target_name) , p_str=position_str)

        def _difflist_to_text(target_name, diff_list, diff_to_name, dist):
            text_list = list()
            for index, diff_vector in enumerate(diff_list):
                name = diff_to_name[diff_vector]
                if name == myname:
                    name = "自分"
                if name != target_name:
                    text_list.append(_convert_to_string(name, diff_vector, _basis_map)) 
            return "、".join(text_list) 

        result_string = ""
        text_lines = list()
        result_string += "\n{target_name}さんの位置は、\n".format(target_name=target_name)
        name_to_pos = {value:key for key, value in position_map.items()}
        target_pos = name_to_pos[target_name]

        diff_to_name = {tuple(map(sub, target_pos, pos)):name for pos, name in position_map.items()}
        diff_list = sorted(diff_to_name.keys()) 

        def _square_norm2(diff_vector):
            return sum([elem**2 for elem in diff_vector]) 
        dist_to_difflist = _get_partition_maplist(diff_list, _square_norm2)
        dist_list = sorted(list(dist_to_difflist.keys()))
        dist_list = list(filter(lambda dist: 0 < dist <= 2**2, dist_list))
        

        for index, dist in enumerate(dist_list):
            diff_list = dist_to_difflist[dist]
            result_string += _difflist_to_text(target_name, diff_list, diff_to_name, dist)
            if index != len(dist_list)-1:
                result_string += "。\n"
            else:
                result_string += "ですね。\n"

        return result_string


    lines = list()
    name_to_pos = {value:key for key, value in position_map.items()}
    target_pos = name_to_pos[target_name]
    lines.append(create_header(target_name))
    lines.append(create_greeting(myname))
    lines.append(explain_act(target_name))
    lines.append(explain_result(target_name))
    lines.append(create_position_information(myname, target_name, name_to_pos))
    lines.append(explain_closing(myname, target_name))
    lines = [line + '\n' for line in lines]

    return lines

def execute(input_file_name, output_file_name):
    """ Created documents from input_file_name and output.
    "@param str input_file_name: the path to .html file.
    "@param str output_file_name: the path to output_file.
    """
    # Acquire the information by interpreting .html file. 
    html  = codecs.open(input_file_name, 'r','utf-8').read()
    root = lxml.html.fromstring(html)

    myname = get_myname(root)
    position_map = get_position_map(root)

    # Create documents for each player other than myself and the first victim. 
    output_lines = list()
    pos_list = sorted(position_map.keys())
    for pos in pos_list:
        name = position_map[pos]
        if name == myname or name == "第一犠牲者":
            continue
        output_lines += create_document(myname, name, position_map)
        output_lines += ["\n\n"]

    with open(output_file_name, "wt") as fp:
        fp.writelines(output_lines)
        

if __name__ == "__main__":
    input_file_name = "./example.html" # This is the path for saving html.
    output_file_name = "./output.txt"
    execute(input_file_name, output_file_name)

実例

占いCO アイドルアトリ ○
こんばんは。占い師の境界人レヴァティです。
気になったアイドルアトリさんを占います。
○結果。人狼ではないです。

アイドルアトリさんの位置は、
東天青騎士オルグさんの上、人形アケミさんの左。
ジュリエッタさんの左下。
エニサーモンさんの2つ上ですね。

久しぶりの占い師、楽しませていただきたいと思います。
特に大人数村の占い師はあまりやったことがないので、ドキドキです。
配役に狐がいると、同じ人外でも狙う対象が変わったりして、考える幅が広くて面白そうです。

あ…アイドルアトリさん、霊界観戦楽しんでねー



占いCO 人形アケミ ○
占い師の境界人レヴァティです。
気になった人形アケミさんを占います。
○結果。人狼ではないです。

人形アケミさんの位置は、
ジュリエッタさんの上、アイドルアトリさんの右。
東天青騎士オルグさんの左上。
自分の2つ上ですね。

久しぶりの占い師、楽しませていただきたいと思います。
特に大人数村の占い師はあまりやったことがないので、ドキドキです。
配役に狐がいると、同じ人外でも狙う対象が変わったりして、考える幅が広くて面白そうです。
… …

感想

  • 「プログラムの練習に書いてみましたー」 というような感じになってしまっているなぁ…
  • ソースコードを綺麗にできていないなぁ…
  • PEP8とか守れていないんだろうなぁ…
  • コメントの書き方これでいいのかなぁ…

初日占い文を作ってみる。 -位置情報の自動生成-

はじめに

12A猫の初日の占い文は、参加者の方の個性があって面白いですよね。
12A猫とは違って、狐入りの村の初日の占い文は、真偽判定に使われることが多いですね。EXCELプログラミング言語で占い文の自動生成をされている方は結構いらっしゃるみたいです。 最近、面白い自動生成を見せていただきました。

作成された方に聞いた所、JAVAで作成されたようです。 このエントリでは、るる鯖のゲームシステムに適合するように、 初日の占い文の生成をpythonを使ってやってみたいと思います。

目的

初日占い文を python + lxml で作成する。

運用手法

  1. .html ファイルを保存
  2. .html ファイルを読み込み、占い文を .txt に保存する
  3. .txt の中から、Copy & Pasteで対象の人の占い文を貼付ける

道具

機能

  • 自分の名前を自動抽出
  • 他プレイヤーの名前を自動抽出
  • 位置情報自動出力

ソースコード

とりあえず、最低限のものを作ろうとしたら以下のようなソースコードでしょうか。

import os
import sys
import re
import math  
import codecs
from operator import sub, add, mul

import lxml.html

def get_myname(root):
    """ Return my name.
    """
    nodes = root.xpath('//td[@class="occupation"]//span[@class="name"][position()=1]')
    assert len(nodes) == 1
    node = nodes[0]
    return node.text

def get_position_map(root):
    """ Return the position map: position -> name.
    "       position: 2D tuple.
    "       name: participant's name.
    "
    " Left upper is (0, 0), and the format is (vertical_index, horizontal_index).   
    """
    table_nodes = root.xpath('//table[@class="iconsmall"]')
    assert len(table_nodes) == 1
    table_node = table_nodes[0]
    name_nodes = table_node.xpath('//td[@class="name"]')
    position_map = dict()
    for index, name_node in enumerate(name_nodes):
        horizontal_index = index // 2
        vertical_index  = index % 2
        position_map[(horizontal_index, vertical_index)] = name_node.text_content()
    return position_map

def create_document(myname, target_name, position_map):
    """ Create the sentence of foreseener.
    " @param str myname: your name.
    " @param str target_name :  the target of foreseeing.
    " @param dict position_map :  position -> name.
    """
    def create_header(target_name):
        return "占いCO {name} ○".format(name=target_name)

    def create_greeting(myname):
        return "占い師の{name}です。".format(name=myname)

    def explain_act(target_name):
        return "初日なので適当に{name}を占います。".format(name=target_name)

    def explain_result(target_name):
        return "結果は○。{name}は人狼ではありませんでした。".format(name=target_name)

    def explain_closing(my_name, target_name):
        return "{target_name}...溶けましたね。".format(target_name=target_name)

    def create_position_information(myname, target_name, name_to_pos):
        _basis_map = {(1, 0): "下", (-1, 0): "上", (0, 1):"右", (0, -1):"左"}

        def _calc_dot(vec1, vec2):
            assert len(vec1) == len(vec2)
            dot = sum(map(mul, vec1, vec2))
            return dot

        def _dist(vector1, vector2):
            diff_vec = list(map(sub, vector1, vector2))
            norm1 = sum(map(abs, diff_vec))
            angle = math.atan2(diff_vec[1], diff_vec[0])
            return (norm1, angle)

        def _convert_to_string(target_name, diff_vector, basis_map):

            def get_vector_array(vector, ref_vectors):
                square_norm2 = sum(map(mul, vector, vector))
                if square_norm2 < 1:
                    return []
                result = list()
                best_basis = max(ref_vectors, key=lambda ref_vec: _calc_dot(ref_vec, vector))
                square_norm_best_basis = sum(map(mul, best_basis, best_basis))
                best_coef = _calc_dot(vector, best_basis)  / square_norm_best_basis
                best_pair = (best_basis, best_coef)
                best_vector = list(map(lambda elem: best_coef * elem, best_basis))
                residual = list(map(sub, vector, best_vector))
                return [best_pair] + get_vector_array(residual, ref_vectors)

            def to_position_string(vector_arrays, vector_map):
                position_str = ""
                pair_list = sorted(vector_arrays, key=lambda pair: pair[1])
                string_list = ["{char}に{number}つ".format(char=vector_map[pair[0]],number=int(pair[1])) for pair in pair_list]
                position_str = "、".join(string_list)
                position_str += "移動した位置"
                return position_str


            ref_basis = list(basis_map.keys())
            pairs = get_vector_array(diff_vector, ref_basis)
            position_str = to_position_string(pairs, basis_map)
            return "{name}から、{p_str}。".format(name=target_name , p_str=position_str)

        text_lines = list()
        text_lines.append("○結果なので位置情報を書きます。\n")
        text_lines.append("{target_name}の位置は、".format(target_name=target_name))
        name_to_pos = {value:key for key, value in position_map.items()}
        target_pos = name_to_pos[target_name]
        position_list = sorted(position_map.keys(), key=lambda pos: _dist(pos, target_pos))
        for position in position_list:
            name = position_map[position]
            diff_vector = list(map(sub, target_pos, position))
            if name != target_name and name != "第一犠牲者":
                text_lines.append(_convert_to_string(name, diff_vector, _basis_map))
        return "\n".join(text_lines)

    lines = list()
    name_to_pos = {value:key for key, value in position_map.items()}
    target_pos = name_to_pos[target_name]
    lines.append(create_header(target_name))
    lines.append(create_greeting(myname))
    lines.append(explain_act(target_name))
    lines.append(explain_result(target_name))
    lines.append(create_position_information(myname, target_name, name_to_pos))
    lines.append(explain_closing(myname, target_name))
    lines = [line + '\n' for line in lines]

    return lines

def execute(input_file_name, output_file_name):
    """ Created documents from input_file_name and output.
    "@param str input_file_name: the path to .html file.
    "@param str output_file_name: the path to output_file.
    """
    # Acquire the information by interpreting .html file.
    html  = codecs.open(input_file_name, 'r','utf-8').read()
    root = lxml.html.fromstring(html)

    myname = get_myname(root)
    position_map = get_position_map(root)

    # Create documents for each player other than myself and the first victim.
    output_lines = list()
    pos_list = sorted(position_map.keys())
    for pos in pos_list:
        name = position_map[pos]
        if name == myname or name == "第一犠牲者":
            continue
        output_lines += create_document(myname, name, position_map)
        output_lines += ["\n\n"]

    with open(output_file_name, "wt") as fp:
        fp.writelines(output_lines)


if __name__ == "__main__":
    input_file_name = "./test.html" # This is the path for saving html.
    output_file_name = "./output.txt"
    execute(input_file_name, output_file_name)



使用例

f:id:StudentS:20170423200950p:plain

上記のような.htmlファイルを保存して、 input_file_name に指定して、 プログラムを実行します。

占いCO アイドルアトリ ○
占い師の境界人レヴァティです。
初日なので適当にアイドルアトリを占います。
結果は○。アイドルアトリは人狼ではありませんでした。
○結果なので位置情報を書きます。


アイドルアトリの位置は、
東天青騎士オルグから、上に1つ移動した位置。
人形アケミから、左に1つ移動した位置。
エニサーモンから、上に2つ移動した位置。
ジュリエッタから、左に1つ、上に1つ移動した位置。
新米ワカバから、上に3つ移動した位置。
境界人レヴァティから、左に1つ、上に2つ移動した位置。
留守番シィから、上に4つ移動した位置。
夢遊病フェネから、上に5つ移動した位置。
漫画家ミモザから、左に1つ、上に4つ移動した位置。 魔女マーヤから、左に1つ、上に5つ移動した位置。
アイドルアトリ…溶けましたね。


占いCO 人形アケミ ○
占い師の境界人レヴァティです。
初日なので適当に人形アケミを占います。
結果は○。人形アケミは人狼ではありませんでした。
○結果なので位置情報を書きます。

人形アケミの位置は、
アイドルアトリから、右に1つ移動した位置。
ジュリエッタから、上に1つ移動した位置。
東天青騎士オルグから、右に1つ、上に1つ移動した位置。
境界人レヴァティから、上に2つ移動した位置。
エニサーモンから、右に1つ、上に2つ移動した位置。
新米ワカバから、右に1つ、上に3つ移動した位置。
漫画家ミモザから、上に4つ移動した位置。
留守番シィから、右に1つ、上に4つ移動した位置。
魔女マーヤから、上に5つ移動した位置。
夢遊病フェネから、右に1つ、上に5つ移動した位置。
人形アケミ…溶けましたね。

注意

  • ブラウザによって、保存内容 / 形式が異なります。

ブラウザによって、 参加者の情報や自分の情報を.htmlファイルを保存することができるか が異なるみたいです。 自分はGoogle Chromeを使って、保存を行いました。

  • ソースコードは utf8形式での保存が必要だと思います。

  • lxml をインストールしないと上記のスクリプトは作動しません。

    • 基本的には pip install lxml ただ環境によっては駄目かも…
  • いいソースコードとは思えないけれど、許してください。

さて、今回の生成文はいかにも「自動生成しました!」という感じが 出ていますね。これを改造すると、それなりに人間が書いたような文章に近づけることができると思っています。
ちょっと考えてみたいなー と思っています。

4人/狂人残り。確定○の数と村陣営の勝率について -単調性が崩れる時-

「Q. 確定○がいない方が村有利になる状況を提示してください。」
この問題の回答は簡単ですね。3人残りの狼村狂の時、村人が確定○であれば、 狼陣営側は確実にPPを決めることができます。
逆に確定○がいなければ、村人陣営側は、狼騙りで勝負をすることができます。

このように吊り数よりも狼陣営の数が多くなると、確定○が少ない方が村人陣営にとって有利になることがあります。 その時、確定○の数と村人の勝率の関係について単調性がない場合があります。

今回は以下の設定で、確定○と村人の勝率との関係についてみます。

問題設定

  • 昼: 狐無し4人残り村、確定狂人が1人生存している。狼狂村村。
  • 再投票引き分けは無し。票数が同数の場合は、ランダムに同票の人が吊られる。
  • 狼が確定した時、狼と狂人は票を合わせることができる。村人は狼に確率1で投票することができる。
  • 以上の仮定の下、シンプルな確率論(Xグレーから狼に投票できる(またはしてしまう)確率は1/Xとする)に従って、狼が吊れる確率を算出する。

結果

狼が吊れる確率は、狂人以外の確定○の数によって、以下のようになる。
- 確定○0: 1 / 3
- 確定○1: 1 / 4
- 確定○2: 1 / 2

確定○が0人の時は1/3。 1人増えると1/4。しかし、もう1人確定○が増えると1/2に村の勝率が上がる。

現実の村への示唆

4人狂生存を考慮しなければいけない状況では「最善の行動」が極めて難しいことを示唆しています。
「確定○のように振る舞う村人が1人いるが、その村人にとって、狼を当てる2択が難しい」
状況が村人勝率1/4の状況 (確定○1の状況) に近い状況になります。

村人のプレイヤーにとって、操作できるのは自分自身のみであるため、
「あやしい行動をとり、自分自身の狼目を向上させ、確定○0の状況に近づける」
という行動が村視点の利益になると、上記の結果から正当化できることを示唆します。
様々な仮定の前提の下で「一見利敵行為になる行動が、村の勝率向上に寄与すると正当化できる」一例となっています。

「良い」/「悪い」の行動について、単調性が保持されない状況では、最適解を目指すプレイヤーに求められる情報処理能力/判断能力が高くなるということでしょう。

計算結果の詳細

確定○2 の時

狼は確定。確定○に2票/狼に2票で、ランダムでどちらが吊れるか。村人勝率1/2。

確定○1 の時

狼 / 狂の票が、確定○1に2票。確定○1の票が 1. 狼を当てることができれば、 村人勝率 1/2。
2. 狼を当てることができなければ、狼勝利。
ということで、まとめて 村人勝率 1/4。

確定○0 の時

少しややこしい。 狂人は3グレーの誰かに投票する。狼/村人は自分以外のグレーに投票する。

  1. 得票数が 3-1-0-0のパターン 1 / 4

    • 狼が吊れる確率 1/12
  2. 得票数が 2-2-0-0のパターン 1 / 4

    • 村2票 - 狼2票 の確率 2/12。 狼が吊れる確率 1/12。
  3. 得票数が 2-1-1-0のパターン 1 / 2

    • 狼が2票の確率 1/6

1-3より。 狼が吊れる確率 1/3。

(計算間違っていたらごめんなさい…)

Memoir -Sillteの世界-Chapter2-2 投票して、占って、護衛して。

サマリー

  • Sillteさんが最も投票した人は「goburei」さん。(20回)
  • Sillteさんに最も投票した人は「ハルク」さん。(23回)
  • Sillteさんが最も占った人は「ルール」さん。(3回)
  • Sillteさんを最も占った人は「goburei」さん。(4回)
  • Sillteさんが最も護衛した人は「ふじた」さん。(4回)
  • Sillteさんが護衛した回数は31回 。護衛成功回数は3回。
  • Sillteさんを最も護衛した人は「t.n」さん, 「人狼」さん, 「モトラド」さん。(4回)
  • Sillteさんが護衛された回数は57回 。成功回数は14回。

投票情報@Sillteの世界

Sillteが投票した人

HN#0 投票数#0 HN#1 投票数#1 HN#2 投票数#2
goburei 20 ウィキッド 9 VAPE 7
モトラド 16 ひげ男爵 8 うな 7
るなちー 16 ふじた 8 ととねをぃ 6
ハルク 15 ぷと 7 人狼 6
役職野郎 12 tonnma 7 無鉄砲君 6
one shot one kill 12 zunko 7 こころ 6
誉れ 11 マークポーク 7 sasakama 6
殺意の波動に目覚めたリュウ 11 通行人A(仮) 7 姉ヶ崎 5
t.n 10 いぬ 7 ヴァラ 5
nttw 10 アポロ 7 いつき葉show 5

gobureiに投票した村一覧

「初心者大歓迎12A猫」村, goburei(エイジ):猫又, Sillte(カンザキ):狂人 6回
「初心者大歓迎12A猫」村, goburei(ニコライ):狂人, Sillte(アナスタシア):猫又
「この先生きのこるための12A猫」村, goburei(おにのこ):猫又, Sillte(そらまめ):人狼
「初心者歓迎12A猫」村, goburei(ふくがん):人狼, Sillte(むくろ):猫又
「深夜12A猫」村, goburei(夜重):人狼, Sillte(シャロン):霊能
「深夜の初心者歓迎12A猫」村, goburei(パーヴェル):占い師, Sillte(グレゴリー):人狼 2回
「初心者歓迎12A猫」村, goburei(スコル):村人, Sillte(ゼノン):村人
「初心者歓迎12A猫」村, goburei(イグナチウス):人狼, Sillte(ニコライ):人狼
「初心者歓迎12A猫」村, goburei(トルニー):人狼, Sillte(迷子アヘル):村人
「初心者歓迎12A猫」村, goburei(学生ニーナ):人狼, Sillte(嘘つきメアリー):村人
「※12A 希望あり」村, goburei(ダンテ):狂人, Sillte(フェイト):霊能 4回

Sillteに投票した人

HN#0 投票数#0 HN#1 投票数#1 HN#2 投票数#2
ハルク 23 ふじた 9 ふろー 6
ととねをぃ 17 ヴァラ 8 殺意の波動に目覚めたリュウ 6
nttw 16 黄マリン 8 ウィキッド 5
モトラド 15 アポロ 8 りんこ 5
goburei 13 役職野郎 7 はる 5
one shot one kill 13 おっさん 7 sasakama 5
t.n 11 るなちー 7 お人形 5
AKO 10 ひげ男爵 6 フナムシ 5
みたらし 9 こころ 6 kouichi 5
誉れ 9 シャドウ 6 抹茶 5

ハルクが投票した村一覧

「初心者大歓迎12A猫」村, ハルク(ジャック):村人, Sillte(エイミー):猫又
「初心者大歓迎12A猫」村, ハルク(マキ):占い師, Sillte(グンジ):人狼 2回
「初心者大歓迎12A猫」村, ハルク(天狗):人狼, Sillte(ファラオ):人狼
「初心者大歓迎12A猫」村, ハルク(ようせいさん):村人, Sillte(うろこうま):霊能 2回
「初心者歓迎12A猫」村, ハルク(はやて):人狼, Sillte(えがお):人狼
「初心者歓迎12A猫」村, ハルク(キング):村人, Sillte(イル):占い師
「初心者大歓迎12A猫ラスト」村, ハルク(メロン):霊能, Sillte(ペッパー):人狼
「初心者歓迎12A猫」村, ハルク(響子):村人, Sillte(グレイヴ):占い師
「初心者歓迎12A猫」村, ハルク(朱璃):村人, Sillte(稔):人狼 2回
「初心者歓迎12A猫」村, ハルク(くものあし):狩人, Sillte(うまあし):人狼
「初心者歓迎12A猫」村, ハルク(ダディクール):村人, Sillte(妹者):人狼
「初心者歓迎12A猫」村, ハルク(桃):村人, Sillte(ムスリカ):村人
「12A猫」村, ハルク(園児モエミ):村人, Sillte(道化師レミー):狂人
「初心者歓迎-12A猫」村, ハルク(研究者シルビア):人狼, Sillte(性別不明オペラ):村人
「初心者歓迎-12A猫」村, ハルク(軍人ミーシャ):猫又, Sillte(士官ルスラン):霊能 2回
「親子丼GMの12A猫」村, ハルク(クレマチス):占い師, Sillte(リンドウ):人狼
「11A(`・ω・´)」村, ハルク(エレオノーラ):占い師, Sillte(ミハイル):人狼
「12A猫エクストリーム」村, ハルク(クロッカス):人狼, Sillte(スターチス):村人
「予測転換をして誤字を誤字をする」村, ハルク(星拾いネーロ):人狼, Sillte(星追いビアンカ):村人

占い情報@Sillteの世界

Sillteが占った人

HN#0 占い数#0 HN#1 占い数#1 HN#2 占い数#2
ルール 3 ゆうる 1 クマー 1
霊能はCOが9割 2 誉れ 1 poi 1
m_hr 2 ダンバン 1 マークポーク 1
とうだいもと 2 れいん 1 Tokugawa 1
bayashi 1 ハルク 1 のなめ 1
小ライス 1 みたらし 1 ウラジーミル 1
揚餅(小) 1 ありしあ 1 柳沢 1
しる 1 umus 1 暇人 1
サイモン 1 loco 1 1
無能 1 もも 1 私が狼だと思ったか!馬鹿め、ただの可愛いわんこだ! 1

ルールを占った村一覧

「今宵も楽しく12A猫」村, ルール(天狗):猫又, Sillte(ガキ):占い師
「建てたいから建てた12A猫」村, ルール(サトリ):村人, Sillte(フミノエ):占い師
「初心者歓迎12A猫希望の」村, ルール(ミリィ):猫又, Sillte(ベッティ):占い師

Sillteを占った人

HN#0 占い数#0 HN#1 占い数#1 HN#2 占い数#2
goburei 4 もりきゅー 1 マカ 1
モトラド 3 ren 1 ごるびー 1
ハルク 2 隊長 1 モール 1
らるすッス 2 みたらし 1 mimi 1
ふじた 2 majan 1 1
るなちー 2 calia 1 ゆぴ  1
こころ 1 めのう 1 脱ぐぞ 1
役職野郎 1 人狼 1 リンベル 1
hacchiii 1 赤鯉 1 nttw 1
C7 1 黒太郎 1 ふく 1

gobureiに占われた村一覧

「深夜の初心者歓迎12A猫」村, goburei(パーヴェル):占い師, Sillte(グレゴリー):人狼
「【酉3↑】12A猫」村, goburei(ヨハナ):占い師, Sillte(ベアトリーチェ):人狼
「12A猫(=^・^=)」村, goburei(フミノエ):占い師, Sillte(パルル):人狼
「♪12A猫」村, goburei(ドラガノフ):占い師, Sillte(ゼノビア):村人

護衛情報@Sillteの世界

Sillteが護衛した人

HN#0 護衛数#0 HN#1 護衛数#1
ふじた 4 ウィキッド 1
すいっちな 3 kiyoken 1
kariko 3 てんてん 1
yatuha 2 東京湾の黒い弾丸 1
Nephrite 2 Nul 1
鳴海優菜 2 シオン 1
鳥紳士 1 花鳥風月 1
ほのぼの 1 ざわ 1
赤鯉 1 George 1
御苦労様 1 枝豆三昧 1

ふじたを護衛した村一覧

「今宵も初心者歓迎12A猫」村, ふじた(ぬこ次郎):占い師, Sillte(桔梗):狩人 3回
「12A猫むらムラ」村, ふじた(オクタヴィア):村人, Sillte(ヴィリー):狩人

Sillteが護衛を成功させた村一覧

「12A猫」村, Sillte(傭兵ダレン):狩人, ほのぼの(神父ナーシェス):占い師
「めんたるダメーシ」村, Sillte(少女ユーナ):狩人, 鳴海優菜(代打ちラシン):占い師
「にゃんだふる12猫」村, Sillte(ようせいさん):狩人, Nephrite(たうで):村人
護衛成功回数/護衛回数 :3回/31回

Sillteを護衛した人

HN#0 護衛数#0 HN#1 護衛数#1 HN#2 護衛数#2
t.n 4 zunko 2 ハルク 1
人狼 4 偽りの神に抗え 2 赤鯉 1
モトラド 4 りあす 2 jeanne 1
3 ふじた 2 アポロ 1
オフィーリア 3 るなちー 2 由良 1
リンク 3 hyperbola 2 yuu 1
役職野郎 2 しらさぎ 1 おっさん 1
honoka 2 暇人 1 はる 1
2 大根おろし醤油 1 nttw 1
ぱぱ 2 メラゾーマ 1 ぷと 1

t.nが護衛した村一覧

「初心者GMによる12A猫」村, t.n(まんたん):狩人, Sillte(ファラオ):霊能
「この先生きのこるための12A猫」村, t.n(アノニマス):狩人, Sillte(擬人化モララー):人狼
「初心者大歓迎12A猫ラスト」村, t.n(ショコラ):狩人, Sillte(マーシャ):人狼
「初心者歓迎12A猫」村, t.n(おくされ):狩人, Sillte(うるおい):村人

人狼が護衛した村一覧

「初心者歓迎12A猫」村, 人狼(マクシーム):狩人, Sillte(ニコライ):人狼 2回
「11A(`・ω・´)」村, 人狼(ヴァネッサ):狩人, Sillte(防毒フローレンツ):狂人 2回

モトラドが護衛した村一覧

「この先生きのこるための12A猫」村, モトラド(ジャックランタン):狩人, Sillte(ルタバガ):村人 3回
「初心者歓迎12A描」村, モトラド(アスティン):狩人, Sillte(ヴァレリー):人狼

Sillteへの護衛を成功させた村一覧

「11A(`・ω・´)」村, Sillte(防毒フローレンツ):狂人, 人狼(ヴァネッサ):狩人
「昼下がりの12A猫」村, Sillte(エレア):占い師, kari(リュミエール):人狼
「初心者歓迎系12A猫 」村, Sillte(金魚草):村人, しらさぎ(クレマチス):狩人
「初心者歓迎12A猫」村, Sillte(うるおい):村人, t.n(おくされ):狩人
「初心者大歓迎12A猫ラスト」村, Sillte(キリカ):霊能, 星(フクトミ):狩人
「12A猫」村, Sillte(サムス):霊能, honoka(サイフェス):狩人
「この先生きのこるための12A猫」村, Sillte(ルタバガ):村人, モトラド(ジャックランタン):狩人
「初心者歓迎12A猫始まりの」村, Sillte(刑事アナスタシア):霊能, 雀(殺人鬼コーヴィヤ):狩人
「(σ・∀・)σ12A猫」村, Sillte(眼鏡好きルージュ):村人, 大根おろし醤油(聖女シオン):狩人
「この先生きのこるための12A猫」村, Sillte(むくろ):村人, おっさん(ふくがん):狩人
「お気楽のんびり12A猫」村, Sillte(学生ヒナタ):霊能, リンク(用心棒ニーチェ):狩人
「初心者歓迎ー12A猫」村, Sillte(倉庫番カルドナ):占い師, ぱぱ(生存者スー):狩人
「初心者GMの12A猫初心者歓迎」村, Sillte(えがお):占い師, nttw(おくされ):狩人
「初心者歓迎12A猫」村, Sillte(むくろ):村人, メラゾーマ(からくり):狩人
被護衛成功回数/被護衛回数 :14回/57回