Alloyでパズル (5) 人狼ゲーム

今回はパズルではなく、対人ゲームのモデル化に挑戦してみる。
wikipedia「[汝は人狼なりや？](https://ja.wikipedia.org/wiki/%E6%B1%9D%E3%81%AF%E4%BA%BA%E7%8B%BC%E3%81%AA%E3%82%8A%E3%82%84%3F)」を参考に、Loony Labs. 公式サイトにある [ルール](https://www.looneylabs.com/lit/rules/are-you-werewolf-rules) のもっとも基本的なものを採用する。
ルール説明は公式ルールもしくはリストのコメントを参照してほしい。

# リスト

ルールを表現しただけで、ゲームの戦略や面白さを全く表現できていないことを先に謝っておく。

実のところ、対人ゲームをモデル化する難しさはルールそのものではない。
プレイヤーがどう考えるかによって行動が変わり、ゲームの流れが変わることだ。
人狼ゲームで言えば、その時点で村人や人狼が知り得た情報（顔色なども含む）が選択に与える影響をどう定式化したらいいかわからない点である。
AI でなんとかしようという試みなどもあるが、今回は「知り得た情報は行動に全く影響しない」モデルとした。

そのため実は占い師の存在価値が全くない。
もしこう影響すべきという主張があれば、それをモデルに反映してみるとさらに面白いだろう。
（生き残りの中で「人狼は必ず村人から選び、占い師は人狼→正体不明者の順に選び、村人はランダムに選ぶ」「そして挙がった候補者の中からランダムに処刑者が選ばれる」という程度でもそれらしくなるかもしれない）
他にも数多いオプションルール、占い師が複数いる場合や狩人がいる場合など、拡張の余地はいくらでもある。

```alloy:werewolf.als
// 人狼ゲーム（Are You a Werewolf?）
// https://www.looneylabs.com/lit/rules/are-you-werewolf-rules
open util/ordering [Day]

abstract sig Player {}              // 7-16 players
one sig Moderator in Player {}      // 1 GM (非Playerになるオプションも記載あり)
sig Werewolf extends Player {}      // 2 人狼
sig Seer extends Player {}          // 1 占い師
sig Villager extends Player {}      // other 村人

enum Side {Werewolves, Villagers}
let werewolves[players] = (players & Werewolf)
let villagers[players] = players & (Seer+Villager)

sig Day {
    alive: set Player,                              // 朝の時点で生き残っている人々
    seerKnows: set Player,                          // 占い師が正体を知っている生き残り
    lynched: lone alive,                            // 昼間選ばれた被処刑者
    victim: set (alive-lynched) & (Villager+Seer),  // 夜の犠牲者
    winner: lone Side,                              // 勝利陣営
} {
    // 朝の判定
    (no alive.werewolves) => {
        // 人狼がいなければ村人側の勝利
        winner = Villagers
        no lynched
        no victim
    } else (#alive.werewolves) >= (#alive.villagers) => {
        // 人狼が村人以上いれば人狼側の勝利
        winner = Werewolves
        no lynched
        victim = alive.villagers
    } else {
        // 初日以外ならひとり処刑される
        this!=first => one lynched

        // 夕方の判定
        let eveningAlive = (alive - lynched) {     // 夕方の生き残り
            (no eveningAlive.werewolves) => {
                // 人狼がいなければ村人側の勝利
                winner = Villagers
                no victim
            } else (#eveningAlive.werewolves) >= (#eveningAlive.villagers) => {
                // 人狼が村人以上いれば人狼側の勝利
                winner = Werewolves
                victim = eveningAlive.villagers
            } else {
                // 未決着なら人狼の数だけ犠牲者が出る
                no winner
                #victim = #eveningAlive.werewolves
            }
        }
    }
}
fact {
    one Seer
    2 = #Werewolf

    first.alive = Player-Moderator          // 役柄不明なGMを外す
    first.seerKnows = (Seer & first.alive)  // (GMでなければ)占い師自身のことは知っている
    no first.lynched
    no first.winner
    // one last.winner

    all day:Day-last | let day'=day.next {
        day'.alive = day.alive - day.lynched - day.victim
        (no day'.winner) && (some Seer & day'.alive) => {
            // (未決着で)占い師がいるなら、生き残りのうちひとりの正体を知る
            one p:(day'.alive-day.seerKnows) |
                day'.seerKnows = (day'.alive & day.seerKnows) + p
        } else {
            no day'.seerKnows
        }
    }
}

run {} for 7 Day, exactly 10 Player
```

# 結果例

今回も Table ビューで見るが、縦に長いのでテキスト貼り付けとした。

```
┌────────┬─────────┬─────────┬─────────┬─────────┬───────────┐
│this/Day│alive    │seerKnows│lynched  │victim   │winner     │
├────────┼─────────┼─────────┼─────────┼─────────┼───────────┤
│Day⁰    │Seer⁰    │Seer⁰    │         │Villager²│           │
│        ├─────────┼─────────┤         ├─────────┤           │
│        │Villager⁰│         │         │Villager³│           │
│        ├─────────┤         │         ├─────────┤           │
│        │Villager²│         │         │         │           │
│        ├─────────┤         │         │         │           │
│        │Villager³│         │         │         │           │
│        ├─────────┤         │         │         │           │
│        │Villager⁴│         │         │         │           │
│        ├─────────┤         │         │         │           │
│        │Villager⁵│         │         │         │           │
│        ├─────────┤         │         │         │           │
│        │Villager⁶│         │         │         │           │
│        ├─────────┤         │         │         │           │
│        │Werewolf⁰│         │         │         │           │
│        ├─────────┤         │         │         │           │
│        │Werewolf¹│         │         │         │           │
├────────┼─────────┼─────────┼─────────┼─────────┼───────────┤
│Day¹    │Seer⁰    │Seer⁰    │Werewolf⁰│Villager⁵│           │
│        ├─────────┼─────────┼─────────┼─────────┤           │
│        │Villager⁰│Werewolf⁰│         │         │           │
│        ├─────────┼─────────┤         │         │           │
│        │Villager⁴│         │         │         │           │
│        ├─────────┤         │         │         │           │
│        │Villager⁵│         │         │         │           │
│        ├─────────┤         │         │         │           │
│        │Villager⁶│         │         │         │           │
│        ├─────────┤         │         │         │           │
│        │Werewolf⁰│         │         │         │           │
│        ├─────────┤         │         │         │           │
│        │Werewolf¹│         │         │         │           │
├────────┼─────────┼─────────┼─────────┼─────────┼───────────┤
│Day²    │Seer⁰    │Seer⁰    │Villager⁶│Seer⁰    │           │
│        ├─────────┼─────────┼─────────┼─────────┤           │
│        │Villager⁰│Villager⁰│         │         │           │
│        ├─────────┼─────────┤         │         │           │
│        │Villager⁴│         │         │         │           │
│        ├─────────┤         │         │         │           │
│        │Villager⁶│         │         │         │           │
│        ├─────────┤         │         │         │           │
│        │Werewolf¹│         │         │         │           │
├────────┼─────────┼─────────┼─────────┼─────────┼───────────┤
│Day³    │Villager⁰│         │Villager⁴│Villager⁰│Werewolves⁰│
│        ├─────────┤         ├─────────┼─────────┼───────────┤
│        │Villager⁴│         │         │         │           │
│        ├─────────┤         │         │         │           │
│        │Werewolf¹│         │         │         │           │
├────────┼─────────┼─────────┼─────────┼─────────┼───────────┤
│Day⁴    │Werewolf¹│         │         │         │Werewolves⁰│
├────────┼─────────┼─────────┼─────────┼─────────┼───────────┤
│Day⁵    │Werewolf¹│         │         │         │Werewolves⁰│
├────────┼─────────┼─────────┼─────────┼─────────┼───────────┤
│Day⁶    │Werewolf¹│         │         │         │Werewolves⁰│
└────────┴─────────┴─────────┴─────────┴─────────┴───────────┘
（他は省略）
```
先に述べたとおり各プレイヤーは何も考えていないので、「こういう展開になることもあるだろうな」くらいに見てもらいたい。

# 参考

- wikipedia：[汝は人狼なりや？](https://ja.wikipedia.org/wiki/%E6%B1%9D%E3%81%AF%E4%BA%BA%E7%8B%BC%E3%81%AA%E3%82%8A%E3%82%84%3F)
- Loony Labs. 公式サイト：HOW to PLAY - [ARE YOU A WEREWOLF?](https://www.looneylabs.com/lit/rules/are-you-werewolf-rules)