Let's create a BOX gacha. The following sources will be used. (Gacha written in Python-Data design-)
There are a fixed number of lottery tickets in the lottery box (BOX), and the gacha ends when ** all are drawn **. (Please note that the BOX gacha that automatically replenishes the lottery of the lower rarity is a fake. It will burn big)
There is no weight setting for each item in the lottery. The probability of drawing one item is the probability of using the total number (n) in the BOX as a parameter.
p = \frac{1}{n}
The probability after drawing one is as follows
p = \frac{1}{n-1}
gacha_box.py
import random
#Use closures to keep the BOX state
def gacha_box(gacha_items: dict):
#Extract ID
#weight is not used
items = [key for key in gacha_items.keys()]
def lottery(times: int=1):
#If the number of lottery is larger than the remaining number, match the remaining number
if len(items) < times:
times = len(items)
#Non-overlapping lottery
ids = random.sample(items, k=times)
#Delete the ID drawn from the item
for key in ids:
items.remove(key)
return ids
return lottery
def gacha(gacha_items: dict, times: int=1) -> list:
#Create a dictionary of IDs and weights required for lottery
lots = {key: info["weight"] for key, info in gacha_items.items()}
return random.choices(tuple(lots), weights=lots.values(), k=times)
def main():
#Gacha item information
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 name
rarity_names = {5: "UR", 4: "SSR", 3: "SR", 2: "R", 1: "N"}
#Number of lottery
times = 10
#Get a list of ids by lottery
ids = gacha(gacha_items, times)
#Result output
print("Normal gacha")
for id in ids:
print("ID:%d, %s, %s" % (id, rarity_names[gacha_items[id]["rarity"]], gacha_items[id]["item_name"]))
print("=======")
#Store lottery function in func
func = gacha_box(gacha_items)
times = 3
box_ids = func(times)
print("BOX Gacha: 1st time,Number of lottery settings:%d,Number of lottery results:%d" %(times,len(box_ids)))
for id in box_ids:
print("ID:%d, %s, %s" % (id, rarity_names[gacha_items[id]["rarity"]], gacha_items[id]["item_name"]))
times = 8
box_ids = func(times)
print("BOX Gacha: Second time,Number of lottery settings:%d,Number of lottery results:%d" %(times,len(box_ids)))
for id in box_ids:
print("ID:%d, %s, %s" % (id, rarity_names[gacha_items[id]["rarity"]], gacha_items[id]["item_name"]))
if __name__ == '__main__':
main()
Normal gacha
ID:9, N, N_HOGE
ID:4, SSR, SSR_FUGA
ID:3, SSR, SSR_HOGE
ID:10, N, N_FUGA
ID:9, N, N_HOGE
ID:4, SSR, SSR_FUGA
ID:7, R, R_HOGE
ID:5, SR, SR_HOGE
ID:9, N, N_HOGE
ID:9, N, N_HOGE
=======
BOX Gacha: 1st time,Number of lottery settings:3,Number of lottery results:3
ID:2, UR, UR_FUGA
ID:8, R, R_FUGA
ID:4, SSR, SSR_FUGA
BOX Gacha: Second time,Number of lottery settings:8,Number of lottery results:7
ID:6, SR, SR_FUGA
ID:1, UR, UR_HOGE
ID:5, SR, SR_HOGE
ID:9, N, N_HOGE
ID:10, N, N_FUGA
ID:3, SSR, SSR_HOGE
ID:7, R, R_HOGE
The execution result of BOX gacha is different from normal gacha, and there is no duplication of ID throughout the first and second times. Also, in the second time, control is performed when the number of lottery settings and the number of lottery results are different, and you can see that the lottery is done within the remaining number in the BOX. Actually, the correct method is to check the remaining number in the BOX before executing the gacha and control it so that more gachas cannot be executed. It is a good idea to add a function to get the remaining number in BOX to the return value of gacha_box function.
#Use closures to keep the BOX state
def gacha_box(gacha_items: dict):
#Extract ID
#weight is not used
items = [key for key in gacha_items.keys()]
def lottery(times: int=1):
#If the number of lottery is larger than the remaining number, match the remaining number
if len(items) < times:
times = len(items)
#Non-overlapping lottery
ids = random.sample(items, k=times)
#Delete the ID drawn from the item
for key in ids:
items.remove(key)
return ids
#Get the remaining number in the BOX
def remain():
return len(items)
return lottery, remain
func, remain = gacha_box(gacha_items)
times = 10
if remain() < times:
print("BOX remaining number error")
return False
box_ids = func(times)
Recommended Posts