システムとモデリング

modelica, Julia, Design Structure Matrix, SysML, 他モデリング全般について。

『地雷グリコ』のシミュレーションJuliaプログラムを生成AIで作る。

お正月休みを利用して『地雷グリコ』を読みました。

漫画版もあります。

younganimal.com

小説版を読了したところ、作中で登場するゲーム「地雷グリコ」をシミュレーションしたくなりプログラムを作ろうとしましたが、その過程でChat GPTの力を思い知ることになりましたので紹介したいと思います。

 「グリコ」のシミュレーションプログラムを作る

「地雷グリコ」の前にまず通常の「グリコ」のシミュレーションプログラムを作ろうと思いました。言語はJuliaです。

じゃんけん「グリコ」のシミュレーションプログラムをJuliadeタイプミスして間違ってエンターをしてしまいましたが問題なくプログラムが生成されました。

説明書きも完備しています。以下がGPTの回答の全文です


以下は、Julia で「じゃんけんグリコ」のシミュレーションプログラムを実装した例です。このプログラムは、2人のプレイヤーがじゃんけんを行い、勝者が「グリコ」のルールに従って進むステップ数を決定します。

Juliaコード

# じゃんけんグリコ シミュレーションプログラム

# グリコのステップ数マッピング
const GLIKO_STEPS = Dict(
    "グー" => 3, # グリコ(3歩)
    "チョキ" => 6, # チョコレート(6歩)
    "パー" => 9  # パイナップル(9歩)
)

# じゃんけんの勝敗判定
function judge(player1, player2)
    if player1 == player2
        return "draw"
    elseif (player1 == "グー" && player2 == "チョキ") || 
           (player1 == "チョキ" && player2 == "パー") || 
           (player1 == "パー" && player2 == "グー")
        return "player1"
    else
        return "player2"
    end
end

# プレイヤーの手をランダムに選ぶ
function random_hand()
    hands = ["グー", "チョキ", "パー"]
    return hands[rand(1:3)]
end

# メインシミュレーション関数
function janken_gliko_simulation(steps_to_goal::Int)
    # 各プレイヤーの位置
    player1_position = 0
    player2_position = 0

    while player1_position < steps_to_goal && player2_position < steps_to_goal
        # 各プレイヤーの手
        player1_hand = random_hand()
        player2_hand = random_hand()

        println("Player 1: $player1_hand, Player 2: $player2_hand")

        # 勝敗を判定
        result = judge(player1_hand, player2_hand)

        if result == "draw"
            println("あいこ!")
        elseif result == "player1"
            steps = GLIKO_STEPS[player1_hand]
            player1_position += steps
            println("Player 1 勝ち! $steps 歩進む (位置: $player1_position)")
        elseif result == "player2"
            steps = GLIKO_STEPS[player2_hand]
            player2_position += steps
            println("Player 2 勝ち! $steps 歩進む (位置: $player2_position)")
        end
    end

    # 勝者を表示
    if player1_position >= steps_to_goal
        println("Player 1 がゴール!")
    else
        println("Player 2 がゴール!")
    end
end

# シミュレーション実行
janken_gliko_simulation(30)  # ゴールまでのステップ数を30に設定

プログラムの説明

  1. じゃんけんの勝敗判定:
    • プレイヤー1とプレイヤー2の手を比較し、勝敗を決定します。
  2. グリコのルール:
    • 勝者は選んだ手に応じたステップ数だけ進む(「グー」で3歩、「チョキ」で6歩、「パー」で9歩)。
  3. ゴール:
    • 先に指定されたステップ数(ここでは30)に到達したプレイヤーが勝利します。
  4. ランダム手選び:
    • 各プレイヤーの手はランダムに選ばれます。

実行結果の例

以下はサンプルの出力例です:

Player 1: グー, Player 2: チョキ
Player 1 勝ち! 3 歩進む (位置: 3)
Player 1: パー, Player 2: グー
Player 2 勝ち! 3 歩進む (位置: 3)
Player 1: チョキ, Player 2: チョキ
あいこ!
...
Player 1 がゴール!

このコードを実行して「じゃんけんグリコ」を楽しんでください!


この時点でGPTの成長に驚きました。私が過去に使用した際には生成されたJuliaプログラムは存在しない関数やライブラリを参照してエラーを吐いたものなのですが今回のプログラムは私の実行環境でも問題なく動作しました。プロンプトエンジニアリングのように要望を詳しく言語化した末に生成されたプログラムの品質が高いのはまだわかるのですが、今回はタイプミスで途中で送信された命令文でも高品質なプログラムを生成してくれました。「グリコ」だけでグリコのルールが伝わっているのも驚きです。

地雷グリコ(簡易)のプログラムを生成する

次に「地雷グリコ」のプログラムを生成しようとしました

「地雷グリコ」のルール説明を一切していないのですがプログラムを生成してくれました。もちろん内容はオリジナルの地雷グリコとは異なっている部分が多いのですが雰囲気は同じです。


「地雷グリコ」のシミュレーションプログラムを以下に示します。このルールでは、「地雷」を含む追加の要素が入ります。プレイヤーが特定の条件で「地雷」を踏むとペナルティを受けます。

ルールの変更点

  1. 地雷の設置: コース上にランダムで「地雷」が配置される。
  2. 地雷を踏む条件: プレイヤーが地雷が設置された位置に到達するとペナルティを受け、現在位置から一定のステップ数戻される。

Juliaコード

# 地雷グリコ シミュレーションプログラム

using Random

# グリコのステップ数マッピング
const GLIKO_STEPS = Dict(
    "グー" => 3, # グリコ(3歩)
    "チョキ" => 6, # チョコレート(6歩)
    "パー" => 9  # パイナップル(9歩)
)

# ペナルティのステップ数
const MINE_PENALTY = 5

# じゃんけんの勝敗判定
function judge(player1, player2)
    if player1 == player2
        return "draw"
    elseif (player1 == "グー" && player2 == "チョキ") || 
           (player1 == "チョキ" && player2 == "パー") || 
           (player1 == "パー" && player2 == "グー")
        return "player1"
    else
        return "player2"
    end
end

# プレイヤーの手をランダムに選ぶ
function random_hand()
    hands = ["グー", "チョキ", "パー"]
    return hands[rand(1:3)]
end

# 地雷を設置
function place_mines(course_length, num_mines)
    return sort(rand(1:course_length, num_mines)) # 地雷の位置をランダムに選ぶ
end

# 地雷グリコ シミュレーション
function janken_gliko_with_mines(course_length::Int, num_mines::Int)
    # 各プレイヤーの位置
    player1_position = 0
    player2_position = 0

    # 地雷の配置
    mines = place_mines(course_length, num_mines)
    println("地雷の位置: $mines")

    while player1_position < course_length && player2_position < course_length
        # 各プレイヤーの手
        player1_hand = random_hand()
        player2_hand = random_hand()

        println("Player 1: $player1_hand, Player 2: $player2_hand")

        # 勝敗を判定
        result = judge(player1_hand, player2_hand)

        if result == "draw"
            println("あいこ!")
        elseif result == "player1"
            steps = GLIKO_STEPS[player1_hand]
            player1_position += steps
            println("Player 1 勝ち! $steps 歩進む (位置: $player1_position)")

            # 地雷判定
            if player1_position in mines
                println("Player 1 は地雷を踏んだ! $MINE_PENALTY 歩戻る")
                player1_position = max(player1_position - MINE_PENALTY, 0)
            end
        elseif result == "player2"
            steps = GLIKO_STEPS[player2_hand]
            player2_position += steps
            println("Player 2 勝ち! $steps 歩進む (位置: $player2_position)")

            # 地雷判定
            if player2_position in mines
                println("Player 2 は地雷を踏んだ! $MINE_PENALTY 歩戻る")
                player2_position = max(player2_position - MINE_PENALTY, 0)
            end
        end
    end

    # 勝者を表示
    if player1_position >= course_length
        println("Player 1 がゴール!")
    else
        println("Player 2 がゴール!")
    end
end

# シミュレーション実行
janken_gliko_with_mines(30, 5)  # コース長さ30, 地雷5個

プログラムの説明

  1. 地雷の設置:

    • コース上にランダムに地雷の位置を決定します (place_mines 関数)。
    • 地雷の位置はプレイヤーに見えませんが、出力でデバッグとして確認できます。
  2. 地雷判定:

    • 各プレイヤーが移動した後、その位置が地雷のリストに含まれている場合、地雷を踏んだとみなされ、ペナルティを受けます。
    • ペナルティとして、指定されたステップ数 (MINE_PENALTY) だけ戻ります。ただし、現在位置が0を下回らないように制御します。
  3. 実行例:

    • 以下はサンプルの出力例です。
地雷の位置: [5, 10, 15, 20, 25]
Player 1: グー, Player 2: チョキ
Player 1 勝ち! 3 歩進む (位置: 3)
Player 1: パー, Player 2: グー
Player 2 勝ち! 3 歩進む (位置: 3)
Player 1: グー, Player 2: グー
あいこ!
Player 1: チョキ, Player 2: グー
Player 2 勝ち! 3 歩進む (位置: 6)
Player 2 は地雷を踏んだ! 5 歩戻る
...
Player 2 がゴール!

地雷の位置や勝敗の結果により、ゲーム展開が毎回異なります。「地雷グリコ」のランダム性をぜひ楽しんでください!


こちらのプログラムも私の実行環境でエラーなく実行できました。 ※オリジナルの地雷グリコのルールは下記サイトにまとまっています

dic.nicovideo.jp

基本ルールは一般的な「グリコ」と同じ。「グーリーコ」の掛け声とともにジャンケンをし、グーで勝てば「グリコ」で3段、チョキで勝てば「チヨコレイト」で6段、パーで勝てば「パイナツプル」で6段、それぞれ階段を上がることができる。 階段の段数はゴールを含めて46段。 ゲーム開始前、参加者は階段内の3つの段に地雷を仕掛ける。設置できる時代は1段につき1つまで。スタート地点とゴール地点への設置は不可。どの段に地雷を仕掛けたかは審判にのみ伝える。希望が被った場合はその段数のみ公表して再設定。 対戦相手が、自分の設定した地雷の段で止まった場合、相手は10段下るペナルティを受ける。10段目以下で地雷を踏んだ場合はスタート地点に戻る。 自分が設定した地雷の段で止まった場合、「ミス」となり、下るペナルティは受けないが、その段に地雷があることが相手にバレる。 同じ手による「あいこ」が5回連続した場合、立っている位置がゴールに近いプレイヤーの勝ちとなり、3段か6段、好きな段数を選んで進むことができる。同じ段にいる場合は先にその段に到達した方が「ゴールに近い」と見なす。

こんな適当な命令文でもここまでのクオリティーのプログラムが生成されることにかなり驚きました。私自身が一からプログラムを書くより早く綺麗なものがAIで出来るのは嬉しくもあり、悲しくもありますね。これからは一からプログラムを書くよりもAIに書かせ、自分自身はチェックしていくようにしたほうが良いように思いました。 今回はここまでにしますが、引き続き地雷グリコのシミュレーションの生成は進めていきます。