user3931640
user3931640

Reputation: 55

Why is this variable not counting as intended?

As a starting project in Python 3.4, I am trying to write some code that emulates rolling some dice and applies some simple rules to the results, I however am having difficulty.

10 sided dice are rolled, in this example the function is passed the parameter of 6 10 sided dice to roll. The function is also passed a target number, in this case 6. The function also takes a boolean value.

For each individual die that is equal too, or greater than the target number, a success is scored.

If any 1's are rolled, they “remove” a success.

I found this fairly straight forward, however when applying the following rule I become unstuck;

If the boolean value of True is passed to the function, any 10's rolled count as a success but may be rolled again. 1's cancel 10's before any other “normal” success.

Initially the code I have written seemed to work, however the re-rolled 10's do not add to the successes properly.

I have been through the debugger on a number of occasions and I cannot see what I am doing wrong, although I am convinced that it must lie somewhere in where I am making my successes = successes + 1 statements.

Any help or advice is greatly appreciated.

import random

def rollDice(numberOfDice, difficulty = 6, specialism = False):
    diceRoll = []
    rolledOnes = 0
    rolledTens = 0
    successes = 0

    for i in range (numberOfDice):
        diceRoll.append(random.randint(1,10))

    rolledOnes = diceRoll.count(1)
    rolledTens = diceRoll.count(10)

    for i in range (numberOfDice):
        if diceRoll[i] >= difficulty:
            successes = successes +1

    if specialism == True:
        if rolledOnes > 0:
            successes = successes - rolledOnes
            rolledTens = rolledTens - rolledOnes
            if rolledTens > 0:
                for i in range (rolledTens):
                    reRoll = random.randint(1,10)
                    if reRoll <= difficulty < 10:
                        successes = successes + 1
                    while reRoll == 10:
                        if reRoll == 10:
                            successes = successes + 1
                        reRoll = random.randint(1,10)

        else:
            for i in range (rolledTens):
                reRoll = random.randint(1,10)

                while reRoll == 10:
                    if reRoll >= difficulty:
                        successes = successes + 1
                    reRoll = random.randint(1,10)


    elif specialism == False:
        if rolledOnes > 0:
            successes = successes - rolledOnes

    return successes

print ('You have', rollDice(6, 6, True), 'Successes!')

Upvotes: 2

Views: 71

Answers (2)

user3931640
user3931640

Reputation: 55

Thanks to the above answer and comments, the below now works as intended.

import random

def rollDice(numberOfDice, difficulty = 6, specialism = False):
    diceRoll = []
    rolledOnes = 0
    rolledTens = 0
    successes = 0

    for i in range (numberOfDice):
        diceRoll.append(random.randint(1,10))

    rolledOnes = diceRoll.count(1)
    rolledTens = diceRoll.count(10)

    for i in range (numberOfDice):
        if diceRoll[i] >= difficulty:
            successes = successes +1

    if specialism:
        if rolledOnes > 0:
            successes = successes - rolledOnes
            rolledTens = rolledTens - rolledOnes

        if rolledTens > 0:
            for i in range (rolledTens):
                reRoll = random.randint(1,10)
                while reRoll == 10:
                    successes = successes + 1
                    reRoll = random.randint(1,10)
                if reRoll >= difficulty < 10:
                    successes = successes + 1

    else:
        if rolledOnes > 0:
            successes = successes - rolledOnes
        else:
            return successes

#MAIN
print ('You have', rollDice(7), 'Successes!')

Upvotes: 1

abarnert
abarnert

Reputation: 366133

It's hard to be sure, but I think your problem is happening when there are 10s but no 1s, because you do this:

for i in range (rolledTens):
    reRoll = random.randint(1,10)

    while reRoll == 10:
        if reRoll >= difficulty:
            successes = successes + 1
        reRoll = random.randint(1,10)

So if you reroll, say, a 9, that's >= difficulty, but since it's not == 10, you're never going to get to that check, so you're never going to add to successes.

So, if the code for the previous case (where there were ones) is correct, this code—which is clearly supposed to be doing the same thing—is incorrect.

This is why you never want to write the same code twice. It's very easy to get it right in every place but one. Try to run the same code in all places if you want the same effect. For example, here, you could do:

if rolledOnes > 0:
    successes = successes - rolledOnes
    rolledTens = rolledTens - rolledOnes
# everything else should be the same whether there were any ones or not
if rolledTens > 0:
    for i in range (rolledTens):
        reRoll = random.randint(1,10)
        if reRoll <= difficulty < 10:
            successes = successes + 1
        while reRoll == 10:
            if reRoll == 10:
                successes = successes + 1
            reRoll = random.randint(1,10)

Meanwhile, you seem to be doing a ton of extra work that doesn't do anything. For example:

if rolledTens > 0:
    for i in range (rolledTens):

What's the test there for? If rolledTens is 0 or negative, what happens with for i in range(rolledTens)?

while reRoll == 10:
    if reRoll == 10:

How could reRoll == 10 not be true when we've just entered a loop controlled by while reRoll == 10?

while reRoll == 10:
    if reRoll >= difficulty:

Again, how could reRoll >= difficulty not be true at the top of this loop?

elif specialism == False:

This is an elif to if specialism == True. So, unless you want to allow some third value other than True or False to mean "1s don't do anything", what is this test for?

Since I don't know what your thought processes were, I can't say whether these tests are useless, or whether they're important but written wrong (possibly explaining part of your problem). But hopefully you understand what each of these tests is supposed to do.


Finally, as a side note: You usually don't want to compare anything to True or False. Just write if specialism: or if not specialism:. The one exception is when you explicitly want to treat True or False different from other truthy or falsey values (and that's pretty rare; more often you want to treat is None specially, then treat every other falsey value the same…)

Upvotes: 1

Related Questions