Gacha written in python-Implementation in basic data structure-

Contents

Gacha data design (Basic structure 1, [Basic structure 2](https://qiita.com/saib-ryo/items/ Implement according to c1b7837fe04022b6864d)).

Improved the source code here

Gacha written in Python-Data design-

Setting information list

gacha_lottery

id gacha_group item_type times rarity omake_times omake_rarity cost
A_normal_1 A 0 1 0 0 0 10
A_normal_11 A 0 10 0 1 3 100
B_fighter_2 B 0 2 0 0 0 30
A_omake_2_11 A 0 9 2 2 3 200
A_omake_fighter_6 A 2 5 0 1 3 100

Since it will be positioned as the ID used when executing the gacha, make it a concrete and easy-to-understand character string ID.

gacha_items

id gacha_group weight item_id
1 A 3 5101
2 A 9 4201
3 A 9 4301
4 A 9 4301
5 A 20 3201
6 A 20 3301
7 A 20 3401
8 A 40 2201
9 A 40 2301
10 A 40 2401
11 B 15 4201
12 B 30 3201
13 B 55 2201

items

id rarity item_name item_type HP
5101 5 UR_Brave 1 1200
4201 4 SSR_Warrior 2 1000
4301 4 SSR_Wizard 3 800
4401 4 SSR_Priest 4 800
3201 3 SR_Warrior 2 600
3301 3 SR_Wizard 3 500
3401 3 SR_Priest 4 500
2201 2 R_Warrior 2 400
2301 2 R_Wizard 3 300
2401 2 R_Priest 4 300
3199 3 SR_Brave 1 600

rarity

id rarity_name
5 UR
4 SSR
3 SR
2 R
1 N

Viewpoint of renovation

Functional requirements

As a gacha mechanism that can be realized with the data structure of Basic structure 2, the following requirements will be satisfied.

--Set multiple gacha target items as a group (population) --Narrowing down attributes (item_type) when executing gacha --Narrow down (rarity) above the rarity of the normal lottery when executing gacha --Specify the number of times of normal lottery when executing gacha (times) --Narrow down more than the bonus rarity when executing gacha (omake_rarity) --Specify the number of extra lottery times (omake_times) when executing gacha

Data structure changes

** Gacha information ** and ** items as major differences from the data structure in the previous implementation (Gacha written in Python-Data design-) Information ** may be isolated. Therefore, it is necessary to link the information.

Implementation

gacha.py


import random

def gacha(lots, times: int=1) -> list:
    return random.choices(tuple(lots), weights=lots.values(), k=times)

def get_rarity_name(rarity: int) -> str:
    rarity_names = {5: "UR", 4: "SSR", 3: "SR", 2: "R", 1: "N"}
    return rarity_names[rarity]

#Gacha ID and settings dictionary
def get_gacha_lottery_info(gacha_lottery_id: str) -> dict:
    gacha_lottery = {
        "A_normal_1":  {"gacha_group": "A", "item_type": 0, "times": 1, "rarity": 0, "omake_times": 0, "omake_rarity": 0, "cost":10},
        "A_normal_11":  {"gacha_group": "A", "item_type": 0, "times": 10, "rarity": 0, "omake_times": 1, "omake_rarity": 3, "cost":100},
        "B_fighter_2":  {"gacha_group": "B", "item_type": 0, "times": 2, "rarity": 0, "omake_times": 0, "omake_rarity": 0, "cost":30},
        "A_omake_2_11":  {"gacha_group": "A", "item_type": 0, "times": 9, "rarity": 2, "omake_times": 2, "omake_rarity": 3, "cost":200},
        "A_omake_fighter_6":  {"gacha_group": "A", "item_type": 2, "times": 5, "rarity": 0, "omake_times": 1, "omake_rarity": 3, "cost":100}
    }
    return gacha_lottery[gacha_lottery_id]

def set_gacha(items: dict, gacha_items: dict):
    #Include the item information required for gacha settings in the gacha item information
    dic_gacha_items = {}
    for gacha_item_id, info in gacha_items.items():
        info["item_info"] = items[info["item_id"]]
        dic_gacha_items[gacha_item_id] = info

    #Extract the lottery target list
    def get_lots(lottery_info: dict):
        lots = {}
        omake_lots = {}
        for id, info in dic_gacha_items.items():
            if lottery_info["gacha_group"] != info["gacha_group"]:
                continue
            if lottery_info["item_type"] and lottery_info["item_type"] != info["item_info"]["item_type"]:
                continue

            if not(lottery_info["rarity"]) or lottery_info["rarity"] <= info["item_info"]["rarity"]:
                lots[id] = info["weight"]

            if lottery_info["omake_times"]:
                if not(lottery_info["omake_rarity"]) or lottery_info["omake_rarity"] <= info["item_info"]["rarity"]:
                    omake_lots[id] = info["weight"]

        return lots, omake_lots

    #Gacha execution
    def exec(gacha_lottery_id: str) -> list:
        lottery_info = get_gacha_lottery_info(gacha_lottery_id)
        lots, omake_lots =get_lots(lottery_info)
        ids = gacha(lots, lottery_info["times"])
        if len(omake_lots) > 0:
            ids.extend(gacha(omake_lots, lottery_info["omake_times"]))
        return ids

    return exec

def main():
    #Item information
    items = {
        5101: {"rarity": 5, "item_name": "UR_Brave", "item_type": 1, "hp": 1200},
        4201: {"rarity": 4, "item_name": "SSR_Warrior", "item_type": 2, "hp": 1000},
        4301: {"rarity": 4, "item_name": "SSR_Wizard", "item_type": 3, "hp": 800},
        4401: {"rarity": 4, "item_name": "SSR_Priest", "item_type": 4, "hp": 800},
        3201: {"rarity": 3, "item_name": "SR_Warrior", "item_type": 2, "hp": 600},
        3301: {"rarity": 3, "item_name": "SR_Wizard", "item_type": 3, "hp": 500},
        3401: {"rarity": 3, "item_name": "SR_Priest", "item_type": 4, "hp": 500},
        2201: {"rarity": 2, "item_name": "R_Warrior", "item_type": 2, "hp": 400},
        2301: {"rarity": 2, "item_name": "R_Wizard", "item_type": 3, "hp": 300},
        2401: {"rarity": 2, "item_name": "R_Priest", "item_type": 4, "hp": 300},
        3199: {"rarity": 3, "item_name": "SR_Brave", "item_type": 1, "hp": 600}
    }

    #Gacha item information
    gacha_items = {
        1:  {"gacha_group": "A", "weight": 3, "item_id": 5101},
        2:  {"gacha_group": "A", "weight": 9, "item_id": 4201},
        3:  {"gacha_group": "A", "weight": 9, "item_id": 4301},
        4:  {"gacha_group": "A", "weight": 9, "item_id": 4401},
        5:  {"gacha_group": "A", "weight": 20, "item_id": 3201},
        6:  {"gacha_group": "A", "weight": 20, "item_id": 3301},
        7:  {"gacha_group": "A", "weight": 20, "item_id": 3401},
        8:  {"gacha_group": "A", "weight": 40, "item_id": 2201},
        9:  {"gacha_group": "A", "weight": 40, "item_id": 2301},
        10: {"gacha_group": "A", "weight": 40, "item_id": 2401},
        11: {"gacha_group": "B", "weight": 15, "item_id": 4201},
        12: {"gacha_group": "B", "weight": 30, "item_id": 3201},
        13: {"gacha_group": "B", "weight": 55, "item_id": 2201}
    }

    #Gacha tuple to carry out
    gacha_lottery_ids = (
        "A_normal_1","A_normal_11","B_fighter_2","A_omake_2_11","A_omake_fighter_6"
    )

    #Set items etc.
    func_gacha = set_gacha(items, gacha_items)

    # gacha_lottery_Execute gacha with id setting
    for gacha_lottery_id in gacha_lottery_ids:
        print("==%s==" % gacha_lottery_id)
        ids = func_gacha(gacha_lottery_id)
        for id in ids:
            item_info = items[gacha_items[id]["item_id"]]
            print("ID:%d, %s, %s" % (id, get_rarity_name(item_info["rarity"]), item_info["item_name"]))


if __name__ == '__main__':
    main()

Execution result

Execute the gacha for the ID of ** gacha_lottery ** and check the behavior

==A_normal_1==
ID:10, R, R_Priest
==A_normal_11==
ID:8, R, R_Warrior
ID:10, R, R_Priest
ID:10, R, R_Priest
ID:6, SR, SR_Wizard
ID:5, SR, SR_Warrior
ID:8, R, R_Warrior
ID:5, SR, SR_Warrior
ID:8, R, R_Warrior
ID:10, R, R_Priest
ID:5, SR, SR_Warrior
ID:7, SR, SR_Priest
==B_fighter_2==
ID:13, R, R_Warrior
ID:13, R, R_Warrior
==A_omake_2_11==
ID:7, SR, SR_Priest
ID:10, R, R_Priest
ID:10, R, R_Priest
ID:6, SR, SR_Wizard
ID:8, R, R_Warrior
ID:7, SR, SR_Priest
ID:9, R, R_Wizard
ID:9, R, R_Wizard
ID:6, SR, SR_Wizard
ID:4, SSR, SSR_Priest
ID:1, UR, UR_Brave
==A_omake_fighter_6==
ID:8, R, R_Warrior
ID:5, SR, SR_Warrior
ID:5, SR, SR_Warrior
ID:8, R, R_Warrior
ID:5, SR, SR_Warrior
ID:2, SSR, SSR_Warrior

Consideration

The functional requirements were met. There are some inadequate parts as a mechanism that can withstand actual operation, First of all, this configuration is the basic form. In the future, in order to meet ** operational requirements **, we will change the data structure such as adding new information and rearranging information, and modify the implementation accordingly.

In this implementation, we have not introduced any technical difficulties. Simply put, it's just ** revisiting the data structure and modifying the implementation *. At the actual development site, the service designer is asked to review the composition of the text and rewrite the story ** in order to express the planner's ** draft ** (functional requirements) ** screenwriter ** Such ability is required. ( It's important, but there is a reality that is not understood *)

Postscript

Since the amount of information (master) will increase and the gacha will be performed in consideration of the user's state, we will implement it using DB from the next time onwards.

Recommended Posts

Gacha written in python-Implementation in basic data structure-
Gacha written in python-Practice 1-
Gacha written in Python-Data design-
Gacha written in Python -BOX gacha-
Simple gacha logic written in Python
Gacha written in python-Rarity confirmed with bonus-
Gacha written in python-Practice 2 ・ Basics of step-up gacha-
Gacha written in python-Practice 3 ・ Addition of step-up gacha functions-
Gacha written in python-Addition of period setting function-
Basic data frame operations written by beginners in a week of learning Python
Basic sorting in Python
Sampling in imbalanced data
C-like structure in Python
[Python tutorial] Data structure