pythonでゲーム #4

pygame
今日の課題

・目指せガチャ?
・ステータスランダム生成
・ソフトマックス関数

キャラクター(基本モブ)を大量に生成することを考えて極力手間をかけず、すぐに増やせる環境を作る

まずは自然に簡単に作成できるよう、ランダム生成系に取り組む

はじめに

前回、きづいた人がいたらうれしいのですが、前回投稿したキャラメイク画面(GUI)に「ランダム生成」っていうボタンがあったんですね。

今回はこのボタンを作っていきたいと思います。

(´・ω・)<登録はどうしたn

さて、ボタンの用途ですが、
キャラクターのgene(遺伝子)をランダムで決定するボタンです。

ポケ〇ンの個体値って基本的にランダムですよね?
ざっくりいうとそれを表現したかったのです。

そもそも作りたいゲームはシミュレーションゲーム
世界があって国があって人がいます。

住んでいる人たちにはレベルがあって、才能も人それぞれ。
男女差があり、年齢があり、それぞれに名前があって、個性があります。

彼らを一人一人練りながら、設定を考えるのはRPGになってしまいますので
今回の趣旨には合いません。

極力、リアルに近い世界観に近づけていきたいと思います。

それでは具体的に何の数値をランダムで決めるのかを見ていきましょう。

ランダムで表現する項目

レベル
 1~100レベルまで
才能(遺伝子)
 HP、攻撃などステータス全般(1~100)
種族
 コンボボックスからランダム、今回は対象外
キャラ名
 これが一番悩ましい。スクレイピングで実装したい、今回は対象外
キャラクターデータ
 出身、生年月日、年齢など。今回は対象外

(;´・ω・)<いや、対象外多くね?

レベルと才能、これらは1~100までの数字から、ランダムで取得しましょう。

例えば以下のような簡単な方法で取得できます。

import random
r_num = random.randint(1,100)
print(r_num)

実行するとr_numに1~100がランダムで取れてきます。

ただこれだと均一の割合で生成されてしまいます

強キャラと弱キャラが平等に生まれてしまうのでゲームバランスが壊れてしまうでしょう

ガチャでいえば、レアがモブと同じ割合で出てくるようなものです

今回はちゃんと弱キャラが生きていけるよう、強い人を少なくしてあげましょう

まず確率を少しいじれるようにしたいと思います。

確率をいじるといっても、極端に40%→80%に変更するなどというわけではありません

テストの難易度によって標準偏差が変わるイメージです

今回はソフトマックス関数というものを使います

ソフトマックス関数

[latex]y_{i}= \frac{\exp(x_{i})} {\sum\limits_{i=1}^{n}\exp(x_{i})}[/latex]

はい、こんなのです。ちなみに[latex]exp(x_{i})[/latex]というのは自然対数の[latex]e^{x_{i}}[/latex]のことです

少しわかりずらいので順番に行きましょう

[latex]x=[x_{1}, x_{2}, x_{3}][/latex]

というのがあったらyは

[latex]y=[\frac{e^{x_{1}}}{ e^{x_{1}}+e^{x_{2}}+e^{x_{3}}},\frac{e^{x_{2}}}{ e^{x_{1}}+e^{x_{2}}+e^{x_{3}}},\frac{e^{x_{3}}}{ e^{x_{1}}+e^{x_{2}}+e^{x_{3}}}][/latex]

という風になります

・xの値の大小
・xの値の数
によって2通りのアプローチでyの要素を操作することができそうです

それではどんな値が取れるのか見てみましょう

pythonで数式を扱うときはnumpyモジュールが有効です

numpyを使ってみる

import numpy as np
import matplotlib.pyplot as plt
weight= 3
x = np.arange(0,weight,0.1)         # 0から3まで0.1刻みで表示
exp_x = np.exp(x)
sum_exp_x = np.sum(exp_x)
y = exp_x / sum_exp_x      # ソフトマックス関数
plt.plot(x,y)
plt.show()                                  # 関数を描写

こちらを実行してみます。

こんなグラフが取れました。

weight=3は重み付けの役割を果たします。テストでいうところの難易度のようなものと考えてください

では次にweight= 8にして実行してみましょう

(´・ω・)<num = 8にしたら反りが深くなったね

weight = 3の時は緩やかでしたねテストの難易度が低いので、みんなそれほど差がないようです

weight = 8の時は急に上昇していきました。テストの難易度が高いので、できる人にしか高得点は取れません

ひとまずこんなイメージでよいです

では最後に実装してみます。

こんなモジュールを作って実際のGUIを実行します。

def rand_num(self, num, weight):
        import numpy as np
        import matplotlib.pyplot as plt
        # weight=3:強者が出やすくなる
        # weight=8:強者が出にくくなる
        a = np.arange(0,weight,0.1)
        exp_a = np.exp(a)
        sum_exp_a = np.sum(exp_a)
        y = exp_a / sum_exp_a
        rn_int = int(random.choice(y)*10**num)
        if rn_int > 10**(num-1):
            rn_int = 10**(num-1)
        return rn_int

まずはweight = 3

次にweight = 8です

テキストボックスのtotal_sense、totalに注目してみてください

ステータスの合計値がweight = 3の時の方がweight = 8の時よりも若干強めに設定されているかと思います

まとめ

・ランダムで確率を取得する場合にソフトマックス関数を使ってみる
・数式を扱うpythonのモジュールはnumpy
・weightを設定して確率を操作する

今日はランダム生成ボタンの作成でした

これでキャラの生成のハードルが一つ下がったと思います
次回は名前をランダムで決定できるように頑張ります

できればクローリングスクレイピングで取得します。

]]>

コメント

タイトルとURLをコピーしました