3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Pythonで書くガチャ-データ設計-

Last updated at Posted at 2020-05-08

#内容
ガチャのデータ設計を考えてみます。

##ガチャに必要なデータ要素
ここまでガチャのデータとして、ID重みの値のみで実践してきましたが、

# 抽選対象のアイテムIDと重みのdictionary
item_dic = {"id_1":1,"id_2":5,"id_3":14,"id_4":30,"id_5":50}

実際にガチャを作る場合に必要な要素を列挙してみます。

  • ID
  • 重み(weight)
  • レア度(rarity)
  • アイテム名(item_name)

表にすると以下のようになります
gacha_items

id weight rarity item_name
1 1 5 UR_HOGE
2 1 5 UR_FUGA
3 9 4 SSR_HOGE
4 9 4 SSR_FUGA
5 20 3 SR_HOGE
6 20 3 SR_FUGA
7 30 2 R_HOGE
8 30 2 R_FUGA
9 40 1 N_HOGE
10 40 1 N_FUGA
  • weightは小さい方が、当選確率が低い
  • rarityは高いほうが、希少度が高い意味付け

レア度と、その名称の対応表は以下のようになります。
ratiry_names

id rarity_name
5 UR
4 SSR
3 SR
2 R
1 N
gacha_items = {
    1: {"weight":1, "rarity":5, "item_name":"UR_HOGE"},
    2: {"weight":1, "rarity":5, "item_name":"UR_FUGA"},
    3: {"weight":9, "rarity":4, "item_name":"SSR_HOGE"},
    4: {"weight":9, "rarity":4, "item_name":"SSR_FUGA"},
    5: {"weight":20,"rarity":3, "item_name":"SR_HOGE"},
    6: {"weight":20,"rarity":3, "item_name":"SR_FUGA"},
    7: {"weight":30,"rarity":2, "item_name":"R_HOGE"},
    8: {"weight":30,"rarity":2, "item_name":"R_FUGA"},
    9: {"weight":40,"rarity":1, "item_name":"N_HOGE"},
    10:{"weight":40,"rarity":1, "item_name":"N_FUGA"}
}

rarity_names = {5: "UR", 4: "SSR", 3: "SR", 2: "R", 1: "N"}

各々のディクショナリの説明

  • gacha_itemsは、idをキーとして、重みなどの情報を保持
  • rarity_namesは、レア度(id)に対応したレア名を保持

おまけのレアリティを指定したガチャ

おまけについて、レアリティ以上の指定ができるガチャを作成してみます。
@shiracamusさんのソースを流用します)

gacha.py
import random

def gacha(gacha_items: dict, times: int=1) -> list:
    # 抽選に必要な、IDと重みの辞書を作成
    lots = {key: info["weight"] for key, info in gacha_items.items()}
    return random.choices(tuple(lots), weights=lots.values(), k=times)

def gacha_omake(gacha_items: dict, times: int, omake_rarity: int) -> list:
    # おまけの対象をレアリティ制限で辞書を作成
    omake = {key: info for key, info in gacha_items.items() if info["rarity"] >= omake_rarity}
    ids = gacha(gacha_items, times)
    omake and ids.extend(gacha(omake))
    return ids

def main():
    # ガチャアイテム情報
    gacha_items = {
        1: {"weight": 1, "rarity": 5, "item_name": "UR_HOGE"},
        2: {"weight": 1, "rarity": 5, "item_name": "UR_FUGA"},
        3: {"weight": 9, "rarity": 4, "item_name": "SSR_HOGE"},
        4: {"weight": 9, "rarity": 4, "item_name": "SSR_FUGA"},
        5: {"weight": 20, "rarity": 3, "item_name": "SR_HOGE"},
        6: {"weight": 20, "rarity": 3, "item_name": "SR_FUGA"},
        7: {"weight": 30, "rarity": 2, "item_name": "R_HOGE"},
        8: {"weight": 30, "rarity": 2, "item_name": "R_FUGA"},
        9: {"weight": 40, "rarity": 1, "item_name": "N_HOGE"},
        10: {"weight": 40, "rarity": 1, "item_name": "N_FUGA"}
    }

    # レアリティ名
    rarity_names = {5: "UR", 4: "SSR", 3: "SR", 2: "R", 1: "N"}

    # 抽選回数
    times = 10

    # おまけレアリティ(以上)
    omake_rarity = 3

    # 抽選してidのリストを取得
    ids = gacha_omake(gacha_items, times, omake_rarity)

    # 結果出力
    for id in ids:
        print("ID:%d, %s, %s" % (id, rarity_names[gacha_items[id]["rarity"]], gacha_items[id]["item_name"]))

if __name__ == '__main__':
    main()

実行結果

ID:8, R, R_FUGA
ID:7, R, R_HOGE
ID:5, SR, SR_HOGE
ID:5, SR, SR_HOGE
ID:5, SR, SR_HOGE
ID:3, SSR, SSR_HOGE
ID:5, SR, SR_HOGE
ID:10, N, N_FUGA
ID:5, SR, SR_HOGE
ID:9, N, N_HOGE
ID:5, SR, SR_HOGE

考察

前回との違いを考察してみます。
pythonで書くガチャ-おまけ付きレアリティ確定-

  • 結果表示用に情報が付加されている
  • おまけ対象をレアリティ値にて制御している

ガチャに必要最低限な情報は、IDと確率(重み)ですが、
その他に、これらの情報を付加したことにより、実際のガチャに近い挙動結果を得ることが出来ました。

重要な事は処理を実現するために**データの定義(データ設計)**を行い、それに応じたロジックを記述しているということです。

ガチャそのものはシンプルなロジックです。
しかし、実サービスにおいてはガチャ運用に対応できるデータ設計が必要となり、データ設計が全てと言っても過言ではありません。
(実際にはこれらのデータをDBに格納して運用することになります)

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?