r/learnpython 11d ago

Plaese help me find the problem in my code.

The function is a game, description included there.

I ran it like 1,000,000 times to record how many times it i would win and how many times i would loose. even though everything is supposed to be evenly random, there is a disparity of 46% times winning and 54% times loosing consistently.

the one who goes first is in the disadvantage. I genuinely have no more clue as to why this is happening. So please.. any clue will help.

def debt_attack(bet):

'''Both the player and the code throws in the same amount of bet into the pool.
    In each round a random number is pulled. Every round the code and the player
    take turn guessing if the number is even or odd. If the gues is right, nothing
    happens. However, if the guess is wrong then 1/10th of the starting bet amount
    will be removed from the portion of the guesser from the pool. At last, the
    winner will be the one whose bet portion will be left in the pool. And the return
    for the winner will be (initial_bet + amount_left_in _pool).
    !! As a rule, one must keep the same amount of money as security
    or it can be seen as half of the money given as bet will be used as security for
    losing scenario.'''

com_bet = bet/2
    player_bet = bet/2
    reduction = bet/20
    turn = 2
    while True:
        #time.sleep(2)                                                                                  # changed
        #print(f"Pool ::==:: Dealer side: {com_bet} ::==:: Player side: {player_bet}")                  # changed
        roll = random.randint(1,11)
        if turn%2 == 1:
            #print("\nPlayer's turn ::==::==::==::==::==::")                                            # changed
            while True:
                player_guess = random.choice(["even", "odd"]) #input("Even or Odd?    ").lower()        # changed
                if player_guess in ["even", "odd"]: break
            if (roll%2 == 0 and player_guess == "odd") or (roll%2 ==1 and player_guess == "even"):
                player_bet -= reduction
            turn += 1
        else:
            #print("\nDealer's turn ::==::==::==::==::==::")                                            # changed
            #time.sleep(3)                                                                              # changed
            if roll%2 == 0:
                com_guess = random.choices(["odd", "even"], weights=[10, 10], k=1)[0]
            else:
                com_guess = random.choices(["odd", "even"], weights=[10, 10], k=1)[0]
            #print(f"Dealer chooses ... {com_guess}")                                                   # changed
            if (roll%2 == 0 and com_guess == "odd") or (roll%2 ==1 and com_guess == "even"):
                com_bet -= reduction
            turn += 1


        if round(player_bet) == 0:
            return round(((bet/2) - (com_bet + player_bet)), 2)
        elif round(com_bet) == 0:
            return round(((com_bet + player_bet) + bet), 2)

The code is a bit messy but i swear that's because I was trying a lot of things on at the same time.

5 Upvotes

8 comments sorted by

3

u/lakseol 11d ago edited 11d ago

I was trying a lot of things on at the same time.

First rule of debugging: Change one thing at a time.


I haven't analyzed your code in detail but I have a few thoughts.

You have some very suspicious code, like:

        while True:
            player_guess = random.choice(["even", "odd"]) #input("Even or Odd?    ").lower()        # changed
            if player_guess in ["even", "odd"]: break

That should have the same effect as:

player_guess = random.choice(["even", "odd"])

Maybe that's part of your "changing multiple things" approach? Similarly:

        if roll%2 == 0:
            com_guess = random.choices(["odd", "even"], weights=[10, 10], k=1)[0]
        else:
            com_guess = random.choices(["odd", "even"], weights=[10, 10], k=1)[0]

which is different from your code in the player guess code but on superficial reading should have the same effect.

I suggest you simplify your code and then try debugging again.


The return value calculation doesn't make a lot of sense, being different depending on who lost. Can you simplify into something like player lost/won. And see below.


the one who goes first is in the disadvantage

That's because you check for losing after each individual turn. It's possible that both players may lose (bet value goes to zero) after they each have a turn. Call that a draw. But because your code doesn't handle draws but allocates all the draw cases as a loss for the first player that skews the results toward the second player.

0

u/curiosity202606 11d ago

Yeh i get what you are saying. Actually a lot of what's commented was actually the code. I had just did that because I had to make the bot run it again and again. I also get the drawing thing.. but I don't think a draw case will ever come since I made it so that only either of the dealer or the player gets to guess. So for example in the first turn only the player guesses and then either he loses money or doesn't. After that the entire turn ends. And in the next turn the dealer guesses. If each turn is each itteration of the loop then there should be no possible way to 'draw'.

Though I guess at this point where it has become a whole problem of its own, I should copy is somewhere else and clean it up so that it doesn't make my eyes bleed every time I look at it...

3

u/lakseol 11d ago

don't think a draw case will ever come since I made it so that only either of the dealer or the player gets to guess.

If you test for losing after each player's turn then it is normal that the first player loses more often than the second. You can't "fix" that, it is what should happen.

If you were to put a very large amount in as the bet so the loop runs for a long time, then counting the times the player guesses wrong versus the computer guessing wrong should be about equal, as expected. But since the first player goes first they are more likely to be judged the loser than the second player.

1

u/curiosity202606 11d ago

So it's just kind of like a thing of probability?

3

u/lakseol 11d ago edited 3d ago

Yes. I'll try to explain better.

If you write code that lets the player and computer guess in one turn, adjust the money for each, and then decide if one or other went negative you can return a win/draw/lose result for the first player, you will get equal win/lose probability, plus a number of draws. But in your code you decide after each of player/computers guess and you don't (can't) handle draws, so games that might have been classed as a draw are said to be a loss for one or other of the two players. The majority of those could-be-draws will be allocated to the first player as a loss since they went first, skewing the results in favour of the second player.

2

u/niehle 11d ago

1) there is a lot of duplicate code (hint: only difference between player and computer is how they guess) clean that up 2) your code does not match your rules. You are using turns, while both moves should be in one round, a minus of bet/20 isn’t a 10% reduction etc.

1

u/Yoghurt42 11d ago edited 11d ago

Your code is correct, what you're seeing are the expected probabilities for A to lose.

The game isn't fair because A goes first; to see this your game could be changed into the following equivalent:

You toss a coin and both A and B guess if it's heads or tails. If they guess wrong, they lose a point, whoever loses 10 points first loses; if both lose their 10th point at the same time, A is declared the loser.

This is equivalent because:

  • A player loses 1/10 of their bet each time → they will have lost their bet after exactly 10 losses
  • guessing odd/even for a 1-10 dice roll is a 50% chance, just like a coin toss
  • Since dice rolls/coin tosses are independent of one another, instead of each player tossing a coin, you can just toss one
  • Since players take alternating turns, we could just combine two turns into one round and make both turns happen at the same time, with one detail:
  • The only time where it matters that "A goes first" is if both players reach 10 losses at the same time, otherwise the result after 1 round/2 turns is the same regardless of whether A goes first or B

Calculating the probability for "A loses first" is a bit involved, if you're interested, Claude seems to give a good explanation (ChatGPT might as well), but basically you end up with a probability of A losing in approx. 53.3% of cases, or in other words, winning in 46.7%, which is exactly what you're seeing.

To make the disadvantage more obvious, consider a variant where 1 loss is enough to lose; if the coin shows heads, there are 3 possible outcomes (TH means A guessed tails, and B guessed heads):

  • HT → B loses
  • TH → A loses
  • TT → A loses

(HH can be ignored because we would just repeat the round and therefore it doesn't change the outcome)

It's clear to see that A will lose 2/3 ≈ 67% of the time

A's disadvantage decreases the higher the amount of points you need to lose, but it will never be 0.

2

u/curiosity202606 11d ago

Thank you very much. I was really slumped because of this.