Make a rare gacha simulator with Flask

Yesterday created a simple response system with the Python web framework Flask. This alone is too boring, so I'd like to use NumPy to make something that I can enjoy a little.

"Gacha" is a mechanism that allows you to randomly obtain items, etc. by paying once for social games and online games that are popular these days. 10 consecutive gachas is a mechanism to draw 10 rare gachas in one trial. In social games that claim to be free-to-play, it is a mechanism to make a profit by such item billing.

The purpose of the simulation is to check if the gacha can be provided, as the management side incites the gambling spirit that makes the player want to charge a lot. the side there is the aim, such as felt or to succeed in advance how much of probability before turning on the real money so-called real money (the result by cooling the head).

Until now, the population has been selected from some samples using Inference Statistics and Visualization. I've been guessing, but it's also worth trying out the parts that can't be imagined by theory alone.

Gacha specifications

The specifications of the gacha to be implemented are as follows.

Type and price

There are two types of gacha, "rare gacha" and "10 consecutive rare gacha". Rare gacha is 300 yen each time, and 10 consecutive rare gacha is 3,000 yen each time. You will get one card for each draw.

Rarity

Rarity is translated as rarity. The higher the rarity, the higher the value.

As an aside, the word rarity seems to be pronounced more accurately.

type Description
R Just rare. The least valuable.
SR Super rare. The value is high as it is.
UR Ultimate rare. It is the most valuable and it is the player's purpose to obtain it.

Winning probability

The winning probability of rare gacha is as follows.

R SR UR
94.85% 5.04% 0.12%

The winning probability of 10 consecutive rare gachas is as follows.

R SR UR
90.28% 9.29% 0.45%

However, in 10 consecutive rare gachas, SR will always win the last one as a bonus. At first glance this seems like a preferential treatment, but conversely it means that the UR will never win in the final round.

Also, the probability notation does not add up to 100 percent. This is because there is a third decimal place and it is "rounded up". The reason for assuming rounding up instead of rounding is that the total of 10 stations is 100.02%, but if it is assumed that the third decimal place of the three types of rarity is rounded off, such a total value cannot be obtained. Because there isn't.

Types of prizes

The purpose of the user is to obtain the UR. There are 12 types of cards for this UR, from giveaway 1 to giveaway 12. If the UR wins, one of these prizes will be [equal probability](http://en.wikipedia.org/wiki/%E7%AD%89%E7%A2%BA%E7%8E%87% It shall be available at E3% 81% AE% E5% 8E% 9F% E7% 90% 86).

Gacha implementation

Random number generation

NumPy generates random numbers by Mersenne Twister. Random number generation with NumPy is here And here has an article in Japanese.

For the time being, create an extraction function for each rarity. Implement the weighted extractor as follows.

Card ejection process by weighting

def turn_rare():
    """Turn the rare gacha"""
    result = []
    #Round up to the third decimal place 94.85%, 5.04%, 0.12%
    weight = [0.94849, 0.0504, 0.00111]
    result.append(pickup_rare(weight))
    return result

def turn_10rare():
    """Turn 10 consecutive rare gachas"""
    result = []
    #Round up the third decimal place to 90.28%, 9.29%, 0.45%
    weight = [0.90278, 0.09281, 0.00441]
    #9 lottery
    for v in range(0, 9):
        result.append(pickup_rare(weight))
    #SR always wins the last one
    result.append("SR")
    return result

The above assumes the value that is most advantageous to the management side among the values rounded up to the third decimal place.

After that, describe the process of ejecting the card according to the given weight.

def pickup_rare(weight):
    """Eject rare gacha according to weight"""
    rarities = ["R", "SR", "UR"]
    picked_rarity = np.random.choice(rarities, p=weight)

    #If the UR wins, decide which prize to give
    if picked_rarity == "UR":
        picked_rarity = "".join((picked_rarity, "(", pickup_premium(), ")"))

    return picked_rarity

def pickup_premium():
    """Discharge UR prizes assuming equal probability"""
    ur = ["Freebie 1", "Freebie 2", "Freebie 3", "Freebie 4", "Freebie 5", "Freebie 6", "Freebie 7",
          "Freebie 8", "Freebie 9", "Freebie 10", "Freebie 11", "Freebie 12"]
    return np.random.choice(ur)

A value object that holds the price and number of times

A value object is an object that holds a value.

This time, we will keep the number of times the gacha was turned and the amount charged. It's a hassle, so combine them into one object.

class VO(object):
    def __init__(self):
        self._count = 0 #Number of times
        self._price = 0 #Billing amount

    def getcount(self):
        return self._count

    def setcount(self, count):
        self._count = count

    def getprice(self):
        return self._price

    def setprice(self, price):
        self._price = price

    count = property(getcount, setcount)
    price = property(getprice, setprice)

Routing of the process of turning the gacha

Now we'll implement Flask's routing.

@app.route('/')
def index():
    title = "Welcome"
    message = "Click the button to turn the gacha"
    return render_template('index.html',
                           message=message, title=title)

@app.route('/post', methods=['POST', 'GET'])
def post():
    time = datetime.datetime.today().strftime("%H:%M:%S")
    message = ""
    if request.method == 'POST':
        result = []
        if 'rare' in request.form:
            title = "I turned the gacha!"
            vo.price = vo.price + 300
            vo.count = vo.count + 1
            result = turn_rare()
        if '10rare' in request.form:
            title = "I turned the gacha!"
            vo.price = vo.price + 3000
            vo.count = vo.count + 1
            result = turn_10rare()
        if 'reset' in request.form:
            title = "Reset"
            vo.price = 0
            vo.count = 0
            result = ""
            message = "Reset"
        return render_template('index.html',
                               result=result, title=title,
                               time=time, vo=vo,
                               message=message)
    else:
        return redirect(url_for('index'))

View

Finally, prepare the screen.

<div class="form">
  <div class="container">
    <div class="row">
      <div class="col-md-12">
        <p class="lead">
          {% if result %}
            {{ time }}I turned the gacha!<br>
            {{ vo.count }}Total amount of money{{ vo.price }}Circle<br>
Result is
            {% for v in result %}
              {{ v }}
            {% endfor %}
was!
          {% else %}
            {{ message }}
          {% endif %}
        </p>
        <form action="/post" method="post" name="rare" class="form-inline">
          <button type="submit" name="rare" class="btn btn-default">Turn rare gacha</button>
        </form>
        <form action="/post" method="post" name="10rare" class="form-inline">
          <button type="submit" name="10rare" class="btn btn-default">Turn 10 consecutive rare gachas</button>
        </form>
        <form action="/post" method="post" name="reset" class="form-inline">
          <button type="submit" name="reset" class="btn btn-default">Reset</button>
        </form>
      </div>
    </div>
  </div>
</div>

That's all there is to it.

Try turning the gacha

Start the application as python app.py as in Last time.

Access port 5000 on localhost in your browser.

1.png

In this state, if you press the rare gacha, you can pay 300 yen, and if you press the 10-series rare gacha, you can pay 3,000 yen to spin the gacha. When I pressed 10 stations as a trial, I got 2 SRs as shown below.

2.png

How many trials can you get the UR? Please give it a try.

By the way, in this simulation, I was able to obtain UR for 10 consecutive rare gachas 16 times for a total charge of 48,000 yen.

3.png

It's a good idea to reconsider whether this charge is really worth the prize.

Previously [Comp Gacha](http://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%B3%E3%83%97%E3%83%AA%E3%83%BC%E3 % 83% 88% E3% 82% AC% E3% 83% 81% E3% 83% A3) was a problem, but for example, in order to use this simulation to prepare all 12 types of Gacha URs. It may be interesting to try how much it will cost.

The probability of gacha posted this time is a value set arbitrarily and has nothing to do with the actual service.

Summary

This time, I used the social game gacha as a theme, but it is very meaningful to be able to easily verify the calculation based on ** economic theory ** in this way.

Economic theory, for example, in microeconomic theory, is hypothetically derived about human behavior. To objectively verify that the theory explains the real economy well, use mathematical formulas to build a ** economic model **.

The quantified model is called the ** econometric model ** and is subject to empirical analysis.

The combination of Python + Flask, which makes it easy and highly functional to implement a simulation system, will be a powerful help in advancing empirical analysis.

The source code of this article is available at here.

Recommended Posts

Make a rare gacha simulator with Flask
Make a simple pixel art generator with Flask
Make a morphological analysis bot loosely with LINE + Flask
Make a fortune with Python
Make a fire with kdeplot
How to make a Cisco Webex Teams BOT with Flask
Make a sound with Jupyter notebook
Creating a Flask server with Docker
Let's make a breakout with wxPython
Creating a simple app with flask
Make a recommender system with python
Make Flask a Cloud Native application
Make a filter with a django template
Let's make a graph with python! !!
Let's make a supercomputer with xCAT
Make a model iterator with PySide
Make a nice graph with plotly
Let's make a WEB application for phone book with flask Part 1
Let's make a WEB application for phone book with flask Part 2
Let's make a WEB application for phone book with flask Part 3
Let's make a WEB application for phone book with flask Part 4
Let's make a shiritori game with Python
Make a video player with PySimpleGUI + OpenCV
Make a Notebook Pipeline with Kedro + Papermill
Make a partially zoomed figure with matplotlib
Make a drawing quiz with kivy + PyTorch
Let's make a voice slowly with Python
Make a cascade classifier with google colaboratory
Let's make a simple language with PLY 1
Create a simple web app with flask
Make a logic circuit with a perceptron (multilayer perceptron)
Make a Yes No Popup with Kivy
Make a wash-drying timer with a Raspberry Pi
Make a GIF animation with folder monitoring
Let's make a web framework with Python! (1)
Create a web service with Docker + Flask
Let's make a tic-tac-toe AI with Pylearn 2
Make a desktop app with Python with Electron
Let's make a Twitter Bot with Python!
Let's make a web framework with Python! (2)
I made a neuron simulator with Python
Let's make an A to B conversion web application with Flask! From scratch ...
Investment quest: Make a system trade with pyhton (2)
Make a Twitter trend bot with heroku + Python
[Python] Make a game with Pyxel-Use an editor-
Make a monitoring device with an infrared sensor
Investment quest: Make a system trade with pyhton (1)
How to make a dictionary with a hierarchical structure.
I want to make a game with Python
Try to make a "cryptanalysis" cipher with Python
Create a bulletin board with Heroku, Flask, SQLAlchemy
[Python] Make a simple maze game with Pyxel
Launch a web server with Python and Flask
Let's replace UWSC with Python (5) Let's make a Robot
Try to make a dihedral group with Python
[Chat De Tornado] Make a chat using WebSocket with Tornado
Make holiday data into a data frame with pandas
Make a LINE WORKS bot with Amazon Lex
(Memorandum) Make a 3D scatter plot with matplodlib
I made a Mattermost bot with Python (+ Flask)
Make one repeating string with a Python regular expression.