Can I win in gambling? Python Simulation

Published on April 01, 2018

Can I win in gambling? Python Simulation

    Hi, Geektimes.

    In the process of idle idleness, the idea arose to study various gambling games, at the same time to better understand how it works. The results turned out to be, albeit generally obvious, but interesting enough to be shared with the public.



    Who are interested in the details, please under the cat.

    Dice: Craps Game


    Most probably, an intuitively simple and understandable option - there is a cube with labels from 1 to 6, and the probability of a particular number falling out is 1/6. But to play in this way would be boring, so games with more complex rules are popular. Popular gambling game is craps , the figure above shows the image of the game table. As you can see, there is a lot there, but we will not go into deep subtleties.

    Each turn of the game consists of throwing two dice, accumulated points are summed up. As written in the article , “The rules of the game are straightforward: the player rolls two dice, and if the sum of points on them is 7 or 11, he wins, if 2, 3 or 12 loses. When another amount falls on the dice, the shooter throws them to winning or losing combinations. ”

    Let's see how much you can win in this way. To do this, it is not necessary to go to the casino, to simulate the game, we will use Python. Write the function for one throw:

    import random
    def shoot():
        return random.randint(1,6) + random.randint(1,6)
    

    We write the function of simulating one move according to the rules described above.

    def move():
        while True:
            val = shoot()
            print "Dice roll:", val
            if val == 7 or val == 11:
                return True
            if val == 2 or val == 3 or val == 12:
                return False
    

    Let's assign our virtual player the initial amount of $ 100, and start the game process. Let our player make 100 bets, 1u each time.

    money_total = 100
    win = 0
    loss = 0
    for p in range(100):
        bet = 1
        step = move()
        if step is True:
            money_total += bet
            win += 1
        else:
            money_total -= bet
            loss += 1
    print "Win", win, "Loss", loss, "Money", money_total
    

    We run the simulation of 100 games and wonder about the result, the player won , and with a noticeable margin wins from defeats: Win 63, Loss 37, Money 126. Increase the number of games to 1000 and run again, the player won again: Win 680, Loss 320, Money 460 .

    it is clear that something is wrong - the game in which the player would be always in the black, would hardly have been a popular casino, it would have just ruined. Let's try to figure it out.

    Intuitively, it seems that when you roll a die, the probability of any face falling out is equally probable. And this is true, but in the case of one die. If there are two cubes, then everything becomes more complicated. For example, the number 7 can fall as 3 + 4, 2 + 5, 1 + 6, but the number 12 can fall out only in the form of a combination of 6 + 6.

    Let's build in Jupyter notebook the schedule of loss of sums from 1 to 12 for 100 shots:

    from matplotlib import pyplot as plt
    %matplotlib inline
    y = [ shoot() for v in range(100) ]
    plt.hist(y)



    The assumption was confirmed, and the amount from the center really drops out more often. Thus, the numbers 7 and 11 really fall out more often than 2.3 or 12. And the probability to get the winning combination “7 or 11” is really higher.

    How can this be? Alas, the answer is simple - the author of the article cited above simply did not understand the rules of the game thoroughly. The text “the rules of the game are uncomplicated: the player throws two dice, and if the sum of points on them is 7 or 11, he wins, if 2, 3 or 12 loses ” is very far from the truth, and the rules in craps are not so simple as they seem .

    The real rules for the bet on the pass line turned out to be somewhat more difficult (there are other types of bets that anyone can figure out on their own).

    Turn 1: A throw is made. If 7 or 11 falls out, the player wins, if 2, 3 or 12, the player loses. If another number falls out, it is remembered under the name point.

    Move-2 : A throw is made. If 7 falls out, then the player lost. If the point falls out then the player won. If other numbers fall out, the move repeats (at this time, players can also bet on other numbers).

    Indeed, everything is a little more complicated than described in the original version. We add the simulation function with more accurate rules.

    def move():
        point = 0
        while True:
            val = shoot()
            if point == 0:
                # First move
                if val == 7 or val == 11:
                    return True
                if val == 2 or val == 3 or val == 12:
                    return False
                point = val
            else:
                # 2..N move
                if val == 7:
                    return False
                if val == point:
                    return True

    The result is now more similar to the truth: for 100 games, the player won 43 times, lost 57 times, the balance at the end of the game was 86 cu. from the original 100. It is also interesting that the number of winnings turned out to be quite large, and is only slightly less than 50%. This is a competent strategy from the point of view of the casino - it allows you to maintain the participant’s interest in the game (it would be uninteresting to lose all the time), but at the same time, the balance of profits of the casino remains positive, and the player’s money balance is accordingly negative.

    Let's see in more detail what is obtained for the simulation of 100 games.
    - The chance to win in the first step fell in about 20 cases.
    - The chance to lose immediately in the first step fell in 15 cases.
    - In the remaining 65 cases, the game continues, and everything is tricky here: the choice comes from two numbers, 7 and point, but as you can see from the graph above, the probability of a loss of the “losing” number 7 is maximum, which, in general, was required to prove.

    It is interesting to note that the 45% chance of winning is rather high. So is it possible to win? In the short term, yes, for example, in another simulation, the player was “lucky,” and in 100 games he increased his virtual capital from 100 to 112%.



    But the next simulation showed a negative balance: the player reduced his fortune from 100 to 88, having lost, by the way, the same 12, “won” the previous time.

    If you increase the number of iterations to 1000, you can see how a player’s cash balance can look like in the long run:



    It is clear that with the chance of winning each game less than 50%, the resulting amount of money in the player's account will gradually decrease, and the amount of casino profits will gradually increase. By the way, the graph shows ups and downs, and a reasonable question may arise - can they be predicted? Alas, no, because die rolls are events independent of each other, and previous results have no effect on the following. You can repeat the main thought once again - you can win one or even several times, but in the long term it is impossible to stay in the casino at a plus, the rules of the game are made so that the balance will not be in favor of the player.

    There are other types of bets in the game of craps, those who wish can analyze them themselves.

    American Roulette


    The next popular form of gambling is roulette, consider its American version.



    The roulette game board is divided into 38 cells: 36 zones with numbers + 2 zones “zero” and “double zero”. The ball thrown at the roulette wheel will obviously stop in one of the zones. The player can make a variety of bets, types of which are more than 10, consider some of them.

    Black-red (or even-odd)

    The player wins if the bet he called matches. Obviously, the probability of black or red would be 50/50, if not for the two fields of zero - if you hit them, the bet loses. As in the case of craps, this makes the probability of winning just a little less than 50% - but this “slightly” is enough to be in the red.

    Let us write the simulation function of a move using random numbers from 1 to 38, the last 2 digits will be considered as “zero”.

    def move_roulette1():
        val = random.randint(1,38)
        if val == 37 or val == 38: 
            return False
        return val % 2 != 0

    Run the simulation for 100 games, the code is the same as in the craps simulation, change only the function call.

    money_total = 100
    win = 0
    loss = 0
    for p in range(100):
        bet = 1
        step = move_roulette1()
        if step is True:
            money_total += bet
            win += 1
        else:
            money_total -= bet
            loss += 1
    print "Win", win, "Loss", loss, "Money", money_total

    Result: for 100 attempts, the player won 46 times and lost 54 times. The graph shows that the player had both “highs” and “lows”, but the final balance is still negative.



    The more we play, the deeper we go into a minus, and the casino accordingly, plus:



    There was a question from the reader, why I didn’t consider European roulette with one zero field - as you might guess, the chance of winning is really higher there, but the general principle does not change. In fact, the difference is only in the “loss rate”. Here is the joint schedule for the American and European versions of the game:


    Those who want to test the European version of the roulette with 37 slots can use the second option of the function:

    def move_roulette1():
        val = random.randint(1,37)
        if val == 37: 
            return False
        return val % 2 != 0

    The bet on a specific number

    The player can also bet on a certain number, the bet when winning is 35: 1. It seems great, but it is not hard to guess that the probability of a particular roulette number 1:38 falling out, i.e. again, a little less.

    Let's add the function of betting on a specific number:

    def move_roulette2(num):
        val = random.randint(1,38)
        return val == num

    Simulation, we will assume that the player puts on the number 10:

    money_total = 100
    win = 0
    loss = 0
    for p in range(100):
        bet = 1
        step = move_roulette2(10)
        if step is True:
            money_total += 35*bet
            win += 1
        else:
            money_total -= bet
            loss += 1
    print "Win", win, "Loss", loss, "Money", money_total

    As a result, the player won 2 times and lost 98 times, the final balance -28u.



    Bet on two numbers

    You can bet on two numbers - the chance of winning is higher, but the rate is less and amounts to 17: 1.

    Write the function:

    def move_roulette3(num1, num2):
        val = random.randint(1,38)
        return val == num1 or val == num2

    For 100 attempts at our simulation, the player won 3 times and lost 97 times, the balance was -46 u.

    There are other types of bets, for example, on 4 numbers with a 1: 8 ratio, those who wish can experiment on their own. As you might guess, all the coefficients are calculated so that the player is in the red. It seems tempting to put 1 number on the number to win as much as 35 a. But the amount of winnings is increased by 35 times, and the chance of winnings is reduced by 38 times - the final balance will still be in favor of the casino.

    Lotto 6 out of 45


    The next thing to check is lotto. The principle of the game is quite simple - there are 45 balls in the drum, 6 of them drop randomly. The price of a ticket according to the Gosloto website is 100 rubles, and the win depends on the number of guessed balls. The approximate order of the winning amounts is as follows: 2 guessed balls give a gain of 100r, 3 guessed balls give 300r, 4 balls - 3000r, 5 balls - 300.000r and 6 balls - a super prize of about 10.000.000r.

    To begin with, we will write a program for throwing balls and comparing the result:

    def lottery(values):
        balls = range(1, 45+1)
        b1 = balls.pop(random.randint(0, len(balls)-1))
        b2 = balls.pop(random.randint(0, len(balls)-1))
        b3 = balls.pop(random.randint(0, len(balls)-1))
        b4 = balls.pop(random.randint(0, len(balls)-1))
        b5 = balls.pop(random.randint(0, len(balls)-1))
        b6 = balls.pop(random.randint(0, len(balls)-1))
        s = [b1,b2,b3,b4,b5,b6]
        res = list(set(s) & set(values))
        return len(res)

    From the array of balls, a random ball “gets” 6 times, then the number of elements of intersections of two sets is determined. Now we will build a graph of the total winnings on the number of tickets purchased. For simplicity, we assume that the player puts on the same numbers.

    money = [] 
    money_total = 0
    ticket_price = 100
    for p in xrange(N):
        val = lottery([3,7,12,18,33,28])
        if val == 2:
            money_total += 100 
        if val == 3:
            money_total += 300 
        if val == 4:
            money_total += 3000 
        if val == 5:
            money_total += 300000 
        if val == 6:
            money_total += 10000000 
        money.append(money_total)
    x = range(0, N)
    price = map(lambda x: ticket_price*x, x)
    from matplotlib import pyplot as plt
    %matplotlib inline
    plt.plot(price, money)

    To understand the order of magnitude: if you buy 100 tickets (the total amount spent will be 10.000 rubles), then this gives 14 guessed “double” balls and one guessed “triple”. The total winnings are around 2000r with 10.000r spent.

    The winning schedule from the amount spent is almost linear:



    It turns out that if you buy tickets for a million, the gain will be 250 thousand. The “super prize” in the simulation has never once dropped out, although theoretically it is certainly possible. By the way, as written in the rules, the prize pool is 50% of the tickets sold, but the “super prize” does not always fall, so as is the case with the casino, the organizers, of course, always win.

    Slot machines


    They also work on the (pseudo) random principle, “pseudo” because The code in them has long been software and pure mechanics are almost there. The general principles described above for gaming machines also work, and the graphs most likely will not differ, anyone can add the simulation function on their own.

    Good article on a design of slot machines already was on Geektimes.

    Conclusion


    Probably this article did not open America for many, but on the charts it is in principle clearer. It was more interesting to compare a fundamentally different psychological approach to the game. In the lottery winnings are potentially large, but very rare. In the casino, the approach is reverse - the bets are set up so that the person will win as often as possible. Conditionally, having made 10 casino games, a person will win 4 times and lose 6 times. This allows the player to not lose interest in the game, but in any case, the overall balance remains negative - the person will win many times, but also lose a little more .

    This is probably obvious, but the article only deals with games based on chance, not poker, cards, chess, etc. Can there be a “winning strategy” in such random games? Obviously not, because neither the bone, nor the ball, nor the lottery tickets, have no memory, and their behavior does not depend on previous iterations. By the way, it is important to remember this moment - intuitively, having lost several times, a person can decide that now he will definitely win. Alas, no - the roulette or die has no memory, and “do not know” about the number of previous attempts, each game essentially starts from scratch.

    Answering the question of the title of the article - is it possible to win in gambling? As the simulation shows, in principle it is possible, the theory of probability allows. But not for long - you should start playing 2nd, 3rd, ... Ny time, as the balance goes down. In the long run, winning the casino is impossible.

    PS: For those who want to experiment, the source code in one file is laid out under the spoiler. It can be run online in the Python IDE, for example here . To test the European version of the roulette instead of the American one, it’s enough to change 38 to 37 in the code. This simulation is fairly basic, and does not take into account various additional factors, such as the amount of money a player has or the casino betting limit, those who want can add it all by themselves. Under the spoiler you can also watch the video version of this article.

    Video


    Source
    import random
    def craps():
        point = 0
        while True:
            val = shoot()
            # print "  Dice roll:", val
            if point == 0:
                # First move
                if val == 7 or val == 11:
                    return True
                if val == 2 or val == 3 or val == 12:
                    return False
                point = val
            else:
                # 2..N move
                if val == 7:
                    return False
                if val == point:
                    return True
    def move_roulette1():
        val = random.randint(1,38)
        if val == 37 or val == 38: 
            return False
        return val % 2 != 0
    def move_roulette2(num):
        val = random.randint(1,38)
        return val == num
    def move_roulette3(num1, num2):
        val = random.randint(1,38)
        return val == num1 or val == num2
    def lotto(values):
        balls = range(1,46)
        b1 = balls.pop(random.randint(0, len(balls)-1))
        b2 = balls.pop(random.randint(0, len(balls)-1))
        b3 = balls.pop(random.randint(0, len(balls)-1))
        b4 = balls.pop(random.randint(0, len(balls)-1))
        b5 = balls.pop(random.randint(0, len(balls)-1))
        b6 = balls.pop(random.randint(0, len(balls)-1))
        s = [b1,b2,b3,b4,b5,b6]
        res = list(set(s) & set(values))
        return len(res)
    money_total = 100
    steps = 100
    win = 0
    loss = 0
    for p in range(steps):
        bet = 1
        step = move_roulette1()
        if step is True:
            money_total += bet
            win += 1
        else:
            money_total -= bet
            loss += 1
        print "Step", p+1, "Bet", bet, "Result", step, "Win", win, "Loss", loss, "Money total", money_total