今回は水曜日のダウンタウン企画
電気椅子ゲームのシミュレーションです。


解説動画はこちら

 

電気椅子ゲームとは

水曜日のダウンタウンのネタ
結構色々やっていますが
今回は電気椅子ゲームの
シミュレーションです。

ゲームのルールはこうです。


1~12などの番号が書かれたイス
プレイヤー二人は交互に以下を行う
相手が座るイスを予想し、電流を仕掛ける
電気イスでなければ得点獲得し、イスは撤去される
電流イスに座ると得点没収され、イスはそのまま

最終的にポイントが高い方が勝利
3回電流を喰らうか、40点先取されたら負け

このルールでシミュレーション用の
コードを作ってみました。
import random

headers = ["ターン数", "選択プレイヤー", "選択数字", "電気プレイヤー", "仕掛数字", "結果", "P1得点", "P2得点", "P1電気回数", "P2電気回数", "残り椅子"]

class ElectricChairGame:
    def __init__(self):
        self.chairs = {i: i for i in range(1, 13)}
        self.player_scores = [0, 0]
        self.electric_fails = [0, 0]
        self.current_player = 0
        self.electrified_chair = None

    def choose_chair(self, chair_number):
        # 選択した数字と電気椅子の数字が一致する場合のみ電気椅子確定
        if chair_number == self.electrified_chair:
            self.electric_fails[self.current_player] += 1
            self.player_scores[self.current_player] = 0
            return "電気椅子"
        else:
            points = self.chairs[chair_number]
            self.player_scores[self.current_player] += points
            del self.chairs[chair_number]
            return "得点獲得"

    def set_electric(self, chair_number):
        self.electrified_chair = chair_number
        return True

    def check_game_end(self):
        message = ["", ""]
        for player in range(2):
            if self.electric_fails[player] >= 3:
                winner = 2 if player == 0 else 1
                message = [winner, "電気椅子3回"]
                return True, message
            if self.player_scores[player] >= 40:
                winner = player + 1
                message = [winner, "スコア40"]
                return True, message

        if len(self.chairs) == 1:
            winner = 1 if self.player_scores[0] > self.player_scores[1] else 2
            message = [winner, "スコア差"]
            return True, message

        return False, message

def simulate_game(echo=False):
    game = ElectricChairGame()
    turn,selecting_player = 1,1
    results = []
    while True:
        # 電気椅子設置
        electric_player = 2 if selecting_player == 1 else 1
        electric_choice = random.choice(list(game.chairs.keys()))
        game.set_electric(electric_choice)

        # 椅子選択
        chair_choice = random.choice(list(game.chairs.keys()))
        game.current_player = selecting_player - 1
        result = game.choose_chair(chair_choice)

        # ログ出力
        log_line = [
            turn,
            selecting_player,
            chair_choice,
            electric_player,
            electric_choice,
            result,
            game.player_scores[0],
            game.player_scores[1],
            game.electric_fails[0],
            game.electric_fails[1],
            sorted(list(game.chairs.keys()))
        ]
        results.append(log_line)
        # ゲーム終了判定
        game_end, message = game.check_game_end()
        if game_end:
          if message[0]==1:
              win_score = game.player_scores[0]
          else:
              win_score = game.player_scores[1]
          message+=[turn ,
            win_score,
            game.player_scores[0],
            game.player_scores[1],
            game.electric_fails[0],
            game.electric_fails[1],
            len(list(game.chairs.keys()))]
          if echo:
            print(", ".join(headers))
            for log_line in results:
              print(log_line)
            print(f"ゲーム終了: 勝利プレイヤー : {message[0]}, 勝因 : {message[1]}")
          return message, results

        # プレイヤー交代
        selecting_player = 2 if selecting_player == 1 else 1
        turn += 1

ゲームを実行する場合はこうです
message, log_line = simulate_game(True)
ターン数, 選択プレイヤー, 選択数字, 電気プレイヤー,
仕掛数字, 結果, P1得点, P2得点, P1電気回数, P2電気回数, 残り椅子
[1, 1, 2, 2, 3, '得点獲得', 2, 0, 0, 0, [1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]
[2, 2, 11, 1, 5, '得点獲得', 2, 11, 0, 0, [1, 3, 4, 5, 6, 7, 8, 9, 10, 12]]
[3, 1, 6, 2, 7, '得点獲得', 8, 11, 0, 0, [1, 3, 4, 5, 7, 8, 9, 10, 12]]
[4, 2, 1, 1, 8, '得点獲得', 8, 12, 0, 0, [3, 4, 5, 7, 8, 9, 10, 12]]
[5, 1, 3, 2, 10, '得点獲得', 11, 12, 0, 0, [4, 5, 7, 8, 9, 10, 12]]
[6, 2, 12, 1, 7, '得点獲得', 11, 24, 0, 0, [4, 5, 7, 8, 9, 10]]
[7, 1, 8, 2, 4, '得点獲得', 19, 24, 0, 0, [4, 5, 7, 9, 10]]
[8, 2, 9, 1, 7, '得点獲得', 19, 33, 0, 0, [4, 5, 7, 10]]
[9, 1, 10, 2, 7, '得点獲得', 29, 33, 0, 0, [4, 5, 7]]
[10, 2, 7, 1, 5, '得点獲得', 29, 40, 0, 0, [4, 5]]
ゲーム終了: 勝利プレイヤー : 2, 勝因 : スコア40





これで1万回やる場合は
こんな感じのコードで
データフレームにできます。
game_result, game_los = [], []
for i in range(10000):
  message, log_line = simulate_game()
  game_result.append([i+1] + message)
  for log in log_line:
    game_los.append([i+1] + log)

import pandas as pd
cols = ["ゲーム数", "勝利プレイヤー", "勝因","ターン数","獲得点数","P1得点", "P2得点", "P1電気回数", "P2電気回数", "残椅子個数"]
game_result_df = pd.DataFrame(game_result, columns=cols)
game_log_df = pd.DataFrame(game_los, columns=["ゲーム数"] + headers)

game_result_df.head()


シミュレーションの結果は
ぜひ動画を見てみてくださいませ


今回は電気椅子ゲームのシミュレーションコードについてでした
それでは!!