Gacha written in python-Addition of period setting function-

Contents

When the gacha service is actually operated, it is necessary to add new items on a regular basis. In the data structure up to Last time, it was necessary to rewrite the Gacha item information when it was time to add an item.

Therefore, let's consider a data structure that meets the following function requests.

――I want to set the implementation period of gacha --I want to automatically add lottery items when the gacha period changes.

Repair of setting information

Gacha information

gacha

id start_time end_time gacha_group gacha_lottery_id
1 2020-05-01 00:00:00 2020-05-31 23:59:59 A normal_1
2 2020-05-01 00:00:00 2020-05-31 23:59:59 A normal_11
3 2020-05-25 00:00:00 2020-05-31 23:59:59 B fighter_2
4 2020-06-01 00:00:00 2020-06-04 23:59:59 C omake_2_11
5 2020-05-20 00:00:00 2020-05-31 23:59:59 A omake_fighter_6
6 2020-06-01 00:00:00 2020-06-30 23:59:59 C normal_1
7 2020-06-01 00:00:00 2020-06-30 23:59:59 C normal_11

The blue (1 and 2) </ font> and red (6 and 7) </ font> IDs use the same gacha_lottery_id, respectively. , The lottery group target to be used differs as follows.

--Groups subject to lottery until May 31, 2020: ʻA --Groups subject to lottery from June 1, 2020:C`

If you set each period in this way, you can switch without updating the gacha item information at that time. The settings are summarized below.

--Start and end of gacha implementation period (start_time, end_time) --Lottery target group (gacha_group) within the period --Corresponding gacha method definition ID (gacha_lottery_id)

Gacha method definition information

gacha_lottery

id item_type times rarity omake_times omake_rarity cost
normal_1 0 1 0 0 0 10
normal_11 0 10 0 1 3 100
fighter_2 0 2 0 0 0 30
omake_2_11 0 9 2 2 3 150
omake_fighter_6 2 5 0 1 3 100

The management of the lottery target group (gacha_group) will be transferred to Gacha information, and the information will be linked to each other by gacha_lottery_id. The group prefix (A or B) has been removed from the ID because it no longer has a lottery control group (gacha_group) item

Implementation

gacha.py


import random
from datetime import datetime

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 information dictionary
def get_gacha_info(now_time: int) -> dict:
    gachas = {
        1: {"start_time": "2020-05-01 00:00:00", "end_time": "2020-05-31 23:59:59", "gacha_group": "A",
            "gacha_lottery_id": "normal_1"},
        2: {"start_time": "2020-05-01 00:00:00", "end_time": "2020-05-31 23:59:59", "gacha_group": "A",
            "gacha_lottery_id": "normal_11"},
        3: {"start_time": "2020-05-25 00:00:00", "end_time": "2020-05-31 23:59:59", "gacha_group": "B",
            "gacha_lottery_id": "fighter_2"},
        4: {"start_time": "2020-06-01 00:00:00", "end_time": "2020-06-04 23:59:59", "gacha_group": "C",
            "gacha_lottery_id": "omake_2_11"},
        5: {"start_time": "2020-05-20 00:00:00", "end_time": "2020-05-31 23:59:59", "gacha_group": "A",
            "gacha_lottery_id": "omake_fighter_6"},
        6: {"start_time": "2020-06-01 00:00:00", "end_time": "2020-06-30 23:59:59", "gacha_group": "C",
            "gacha_lottery_id": "normal_1"},
        7: {"start_time": "2020-06-01 00:00:00", "end_time": "2020-06-30 23:59:59", "gacha_group": "C",
            "gacha_lottery_id": "normal_11"}
    }

    results = {}
    for gacha_id, info in gachas.items():
        start_time = int(datetime.strptime(info["start_time"], '%Y-%m-%d %H:%M:%S').timestamp())
        end_time = int(datetime.strptime(info["end_time"], '%Y-%m-%d %H:%M:%S').timestamp())
        #Narrow down the target gacha information within the range of the date and time
        if start_time <= now_time <= end_time:
            results[gacha_id] = info

    return results

#Dictionary of gacha method definition information
def get_gacha_lottery_info(gacha_lottery_id: str) -> dict:
    # gacha_Transferred group
    gacha_lottery = {
        "normal_1":  {"item_type": 0, "times": 1, "rarity": 0, "omake_times": 0, "omake_rarity": 0, "cost":10},
        "normal_11":  {"item_type": 0, "times": 10, "rarity": 0, "omake_times": 1, "omake_rarity": 3, "cost":100},
        "fighter_2":  {"item_type": 0, "times": 2, "rarity": 0, "omake_times": 0, "omake_rarity": 0, "cost":30},
        "omake_2_11":  {"item_type": 0, "times": 9, "rarity": 2, "omake_times": 2, "omake_rarity": 3, "cost":150},
        "omake_fighter_6":  {"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, now_time: int=0) -> list:
        if not now_time: now_time = int(datetime.now().timestamp())
        #Get executable gacha information
        gachas = get_gacha_info(now_time)
        lottery_info = get_gacha_lottery_info(gacha_lottery_id)

        ids = []
        for gacha_id, gacha_info in gachas.items():
            if gacha_lottery_id == gacha_info["gacha_lottery_id"]:
                lottery_info["gacha_group"] = gacha_info["gacha_group"]
                print("==%s==:gacha_group:%s" % (gacha_lottery_id, lottery_info["gacha_group"]))
                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},
        #Added below
        4101: {"rarity": 4, "item_name": "SSR_Brave", "item_type": 1, "hp": 1000},
        5201: {"rarity": 5, "item_name": "UR_Warrior", "item_type": 2, "hp": 1300},
        5301: {"rarity": 5, "item_name": "UR_Wizard", "item_type": 3, "hp": 1000},
    }

    #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},
        #Added below
        14: {"gacha_group": "C", "weight": 1, "item_id": 5101},
        15: {"gacha_group": "C", "weight": 1, "item_id": 5201},
        16: {"gacha_group": "C", "weight": 1, "item_id": 5301},
        17: {"gacha_group": "C", "weight": 9, "item_id": 4101},
        18: {"gacha_group": "C", "weight": 6, "item_id": 4201},
        19: {"gacha_group": "C", "weight": 6, "item_id": 4301},
        20: {"gacha_group": "C", "weight": 6, "item_id": 4401},
        21: {"gacha_group": "C", "weight": 20, "item_id": 3201},
        22: {"gacha_group": "C", "weight": 20, "item_id": 3301},
        23: {"gacha_group": "C", "weight": 20, "item_id": 3401},
        24: {"gacha_group": "C", "weight": 40, "item_id": 2201},
        25: {"gacha_group": "C", "weight": 40, "item_id": 2301},
        26: {"gacha_group": "C", "weight": 40, "item_id": 2401},
    }

    #Gacha tuple to carry out
    gacha_lottery_ids = (
        "normal_1","normal_11","fighter_2","omake_2_11","omake_fighter_6"
    )

    #Specify the gacha execution date and time to check the operation
    now_time = int(datetime.strptime("2020-06-01 00:00:00", '%Y-%m-%d %H:%M:%S').timestamp())

    #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:
        ids = func_gacha(gacha_lottery_id,now_time)
        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()

Supplement

The program is written so that the gacha is executed by specifying gacha_lottery_id so that it is easy to understand that the target gacha group is switched depending on the execution date and time.

Execution result

==normal_1==:gacha_group:C
ID:26, R, R_Priest
==normal_11==:gacha_group:C
ID:25, R, R_Wizard
ID:22, SR, SR_Wizard
ID:26, R, R_Priest
ID:24, R, R_Warrior
ID:25, R, R_Wizard
ID:21, SR, SR_Warrior
ID:15, UR, UR_Warrior
ID:24, R, R_Warrior
ID:23, SR, SR_Priest
ID:24, R, R_Warrior
ID:21, SR, SR_Warrior
==omake_2_11==:gacha_group:C
ID:21, SR, SR_Warrior
ID:25, R, R_Wizard
ID:24, R, R_Warrior
ID:21, SR, SR_Warrior
ID:23, SR, SR_Priest
ID:25, R, R_Wizard
ID:23, SR, SR_Priest
ID:18, SSR, SSR_Warrior
ID:25, R, R_Wizard
ID:23, SR, SR_Priest
ID:17, SSR, SSR_Brave

Postscript

In the actual game, as shown in the flow below, the gacha will be executed by specifying gacha_id, so the program configuration will be slightly different.

  1. Request execution of gacha by specifying gacha_id from the game screen (app) side
  2. Determine that the specified gacha_id is within the expiration date
  3. Execute gacha using gacha information (information acquired by gacha_id)

Recommended Posts