Junior
Junior

Reputation: 71

How do I reset the value of variables in a loop? (Python 3.1.1)

When I run my code and get to the battle part of my game, I get random values assigned to my characters attack, defense, damage and health. However, after their first turn, they keep getting the same values and they can't reset.

For example, the user's attack is a random number from 4 to 11. The program "rolls" 5 and assigns it to the variable userAtk

userAtk = random.randint(4,11)

I assumed that everytime the loop ran, it would generate a new value. But its not, and every time I print the variable its the same value it was first assigned. Am I missing something?

Below is my code

import random

# VARIABLES
#
#
# This variable is the user's character name
userName = input("Brave warrior, what is your name? ")

# This variable is used in the input function to pause the game
enterNext = ("Press enter to continue...")

# This variable is used to format the user input prompt
# as well as the battle text
prompt = ">>>>>  "

# This variable is used to add a new line to a string
newLine = "\n"

# This variable is used to display a message when the hero dies
heroDeadmsg = userName + " has fallen!"

# These variables represent the dragon's stats (HP, ATK & DEF)
dragonHp = 100
dragonAtk = random.randint(5,10)
dragonDef = random.randrange(8)

# These variables represent the user's stats (HP, ATK & DEF)
userHp = 90
userAtk = random.randint(4,11)
userDef = random.randrange(8)

# These variables calculate battle damage and HP
dragonDmg = (userAtk - dragonDef)
dragonHp -= dragonDmg
userDmg = (dragonAtk - userDef)
userHp -= userDmg

# This variable prints the options in the battle menu
battleMenu = """Attack (a) - Magic (m) - Item (i) - Run (r)""" 

# This variable determines who goes first
cointoss = random.randint(0, 1)

# These variables print the actions in each turn
dragonAttack = \
    prompt + "Crimson Dragon attacks you with " + str(dragonAtk) + " ATK!"\
    + newLine + prompt + "You defend with " + str(userDef) + " DEF!"\
    + newLine + prompt

userAttack = \
    prompt + "You attacked with " + str(userAtk) + " ATK!"\
    + newLine + prompt + "Crimson Dragon defends with " + str(dragonDef) + " DEF!"\
    + newLine + prompt

userMagic = \
    prompt + userName + " tried to use Magic!"\
    + newLine + prompt + userName + " has no magic!"\
    + newLine + prompt

userItem = \
    prompt + userName + " tried use an Item!"\
    + newLine + prompt + userName + " has no Items!"\
    + newLine + prompt

userRetreat = \
    prompt + userName + " tries to retreat!"\
    + newLine + prompt + "The enemy won't let you escape!"\
    + newLine + prompt


# These variables show health during battle 
printDragonhp = "Crismon Dragon has " + str(dragonHp) + " HP remaining!"
printUserhp = userName + " has " + str(userHp) + " HP remaining!"

# This variable simulates the results of a coin toss
coinToss = random.randint(0, 1)


#
#
# CONDTITIONS
#
#
# These conditions determines who attacks first
if coinToss == 0:
    currentTurn = "dragon"
elif coinToss == 1:
    currentTurn = "user"
else:
    print("The Coin Toss Failed!")    

#
#
# BATTLE MECHANICS
#
#

while currentTurn:
# Mechanics for the Crimson Dragon's Turn
if currentTurn == "dragon":

    # Prints the Crimson Dragon's Attack and ends the turn
    print(newLine + prompt + "Crimson Dragon moves!"\
          + newLine + prompt + newLine + dragonAttack\
          + newLine + prompt + userName + " takes " + str(userDmg) + " DMG!"\
          + newLine + prompt + printUserhp)
    currentTurn = "user"
    input(prompt)

    # Need to implent a way to reset ATK and DEF

# Mechanics for the User's Turn    
if currentTurn == "user":

    # Prints the Battle Menu and asks for the User's choice
    print(newLine + prompt + battleMenu\
          + newLine + prompt)
    userChoice = input(prompt)

    # Prints the User's Attack and ends the turn
    if userChoice == "a":
        print(userAttack)
        if userHp < 1:
            print(heroDeadmsg)
            break

        input (prompt)
        currentTurn = "dragon"
    # Prints the User's Magic and ends the turn
    elif userChoice == "m":
        print(userMagic)
        input (prompt)
        currentTurn = "dragon"
    # Prints the User's Item and ends the turn   
    elif userChoice == "i":
        print(userItem)
        input (prompt)
        currentTurn = "dragon"
    # Prints the User's Retreat and ends the turn    
    elif userChoice == "r":
        print(userRetreat)
        input (prompt)
        currentTurn = "dragon"
    # Prints an error message for invalid entries
    else:
        print(newLine + prompt + "That is not a valid menu item."\
              + newLine + prompt + "Please try again.")

Upvotes: 0

Views: 8802

Answers (3)

abarnert
abarnert

Reputation: 365747

random.randint(4,11) just chooses an integer in range [4, 11] and returns you that number. So, when you do userAtk = random.randint(4,11), you're just getting a number and storing it as userAtk, and every time you access userAtk you'll get the same number back.

If you were hoping for userAtk to be a magic kind of thing that acts like a different number in the range [4, 11] each time you access it… well, that's not impossible (see here for a quick & dirty stab at it)… but it will almost certainly lead to more confusion than benefit.

For example, you have code that tries to print out str(userAtk)… but if the value is different each time you access it, what gets printed out will be different from what's used to calculate the damage! Imagine if you were playing tabletop D&D, and the dungeon master rolled a die to tell you your roll, and then immediately forgot the result and rolled again to figure out whether you hit. So he might say, "You rolled a 20. You missed." That's no good.

What might be useful is to make userAtk actually be a function:

def userAtk():
    return random.randint(4, 11)

And similarly for all of your similar variables. Then, everywhere you were just accessing a number, you'll instead call the function:

def dragonDmg():
    return userAtk() - dragonDef()

Then somewhere, you're going to want to store the results of calling those functions in some local variables within each loop.

But the key is that, however you do it, you have to have variables that you re-calculate each time through the loop.

Upvotes: 3

jeremy04
jeremy04

Reputation: 314

I believe even if you call randint() a million times, you will still get repeats (I'm sure you know this). I used to use a dictionary to keep track of the used / unused random numbers, and simply check the dictionary if it's already been used. Might have misunderstood the question.

Upvotes: 0

Jesse Jashinsky
Jesse Jashinsky

Reputation: 10663

Because userAtk isn't within a loop, as far as I can see. If you want it to be reset within a loop, call random.randint(4,11) within a loop.

Upvotes: 2

Related Questions