はじめに
格ゲーマー人狼を遅まきながら視聴をはじめました。人狼のルールはなんとなく知っていましたが、格ゲーマー人狼視聴でルールを理解しました。それで、動画をより楽しむために、人狼のゲーム推移パターンは網羅しておきたいと思い表にまとめました。
推移パターン全38通り
狂人と人狼の合計人数が村人と同数になる、または人狼が0人になる、が終了条件にしています。厳密には狂人特定ミスる可能性がありますが、それはイレギュラー(スーパープレイ)ということで、考慮除外しています。また、騎士が守って、誰も噛まれないというパターンは考慮していません。それは適宜考察ということで。。
太字がアクションによって消えた(変わった)プレイヤー人数になります。
初期値は村人:6、人狼:2、狂人:1です。
思ったこと
村人の勝ちパターンは21通り、人狼の勝ちパターンは17通り、でパターンの数だと村人の方が多い。
アクションした後の推移で勝利陣営のパターンのどっちが多いか絞られてくる。初日に人狼ないし狂人を吊れないとかなり村人側はしんどくなるような感じがする。あと、村人*1, 狂人*(-1.5), 人狼*(-2)でスコア付すると、盤面がどっち有利かも定量化できそう。
おわりに
まだ、第三回目くらいまでしか追えてないので、もっと見ます。格ゲーマー人狼面白い!
【#格ゲーマー人狼 01】初戦なのに予想を裏切るめちゃくちゃいい試合!【1戦目】【ウメハラ率いる格ゲーマー】(2020/6/25)
おまけ
パターン網羅確認のためのソースコード
use std::io::*; use std::str::FromStr; //https://qiita.com/tubo28/items/e6076e9040da57368845 fn read<T: FromStr>() -> T { let stdin = stdin(); let stdin = stdin.lock(); let token: String = stdin .bytes() .map(|c| c.expect("failed to read char") as char) .skip_while(|c| c.is_whitespace()) .take_while(|c| !c.is_whitespace()) .collect(); token.parse().ok().expect("failed to parse token") } fn dfs(h: u32, w: u32, m: u32, hang: bool, days:u32) { //村の人数 println!("hang:{} h:\t{} w:{} m:{}", hang, h, w, m); /*for _ in 0..days as usize{ print!(" "); } println!("hang:{} {} {} {}", hang, h, w, m);*/ //終了条件 if w == 0 { println!("The game was over on the {} day. h win.",days); return; } if h <= m + w { println!("The game was over on the {} day. w win.",days); return; } //吊るし or 噛み if hang { dfs(h - 1, w, m, !hang,days+1); dfs(h, w - 1, m, !hang,days+1); if m > 0 { dfs(h, w, m - 1, !hang,days+1); } } else { dfs(h - 1, w, m, !hang,days); if m > 0 { dfs(h, w, m - 1, !hang,days); } } } fn main() { let h: u32 = read(); let w: u32 = read(); let m: u32 = read(); let hang: bool = true; dfs(h, w, m, hang,1); }