7
\$\begingroup\$

This is my code I wrote completely on my own. Its one of my first real programs that I have written using booleans, functions, and loops if anyone could give me some feedback about how its structured and how it runs when executed. Any feedback or constructive criticism would be greatly appreciated!

# Imports random function for computer choice
import random
win_cnt = 0
losses_cnt = 0
# creates game function
def game_main():
# Prompts user about game   
    print(user_name + " will face off against the computer!\nIn this duel you and the computer will face off  by taking turns battling the first to fall loses! ")
    print("Remember to use nearby cover and to reload BEFORE you attack!")
# Creates variables needed for tracking computer and users health, ammo, and damage.
    user_potion = 0
    com_potion = 0
    user_ammo = 0
    com_ammo = 0
    user_heal = 10
    com_heal = 10
    user_atk = 10
    com_atk = 10
    user_HP = 30
    com_HP = 30
# Battle loop that loops as long as both players health is above 0    
    while (user_HP > 0 and com_HP > 0):
# Prompts user to choose a move        
        user_move = int(input("What would you like to do? 1) Attack 2) Block 3) Reload 4) Heal? 5) Grab Bandage(potion)"))
        if user_move > 5: #or str:
            print("INVALID INPUT! MUST BE 1-5")
# Uses random to generate a random integer between 1 and 3
        com_move = random.randint(1,5)
        if com_HP > 50:
# Branching if elif else statements that compare users and computers choice and decide outcome    
# if user attacks and has at least 1 ammo
        if user_move == 1 and user_ammo > 0:
            user_ammo -= 1
            if random.randint(0,100) > 50:
                if com_move == 1 and com_ammo > 0:
                    if random.randint(0,100) > 50:
                        user_HP = user_HP - com_atk
                        com_HP = com_HP - user_atk
                        com_ammo -= 1
                        print(user_name + " and the enemy both attack! You now have " , user_HP , "HP and " , user_ammo , "ammo! The enemy has" , com_HP , "HP!")
                    else:
                        com_HP = com_HP - user_atk
                        com_ammo -= 1
                        print("You and the enemy both attack! The enemy misses but you hit him! He now has ", com_HP , "HP and " , " ammo!")
                elif com_move == 2:
                    print("The enemy blocked your attack! You now have " , user_ammo , " ammo and he still has " , com_HP , "HP!")
                elif com_move == 3:
                    com_HP = com_HP - user_atk
                    com_ammo += 1
                    print(user_name + " attacks as the enemy reloads! He now has " , com_HP , "HP!")
                elif com_move == 4:
                    com_HP = com_HP - user_atk
                    print("The enemy attempts to use a healing potion! But you hit him! He now has " , com_HP , "!")
                else:
                    com_HP = com_HP - user_atk
                    com_potion += 1
                    print("The enemy grabs a health potion as you fire! You hit him! He now has " , com_HP , "HP!")
            else:
                if com_move == 1 and random.randint(0,100) > 50:
                    user_HP = user_HP - com_atk
                    com_ammo -= 1
                    print("You missed and the enemy fires! You now have " , user_HP , "HP and " , user_ammo , "ammo!")
                elif com_move == 2:
                    print("You missed and the enemy took cover! You now have " , user_ammo , "ammo!")
                elif com_move == 3:
                    print("You missed and the enemy reloads!")
                elif com_move == 4:
                    com_HP = com_HP + com_heal
                    print("You missed! The enemy uses a healing potion! He now has " , com_HP , "HP!")
                else:
                    com_potion += 1
                    print("You missed! The enemy quickly grabs a healing potion! You now have " , user_ammo , " ammo!")
# If user attempts to attack with no ammo        
        elif user_move == 1 and user_ammo <= 0:
            if com_move == 1 and com_ammo > 0: 
                if random.randint(0,100) > 50:
                    user_HP = user_HP - com_atk
                    com_ammo -= 1
                    print("You must reload before attacking! The enemy fires! You now have" , user_HP , "HP!")
                else:
                    com_ammo -= 1
                    print("You must reload before attacking! The enemy fires but misses!")
            elif com_move == 2:
                print("You must reload before attacking! The enemy takes cover!")    
            elif com_move == 3:
                com_ammo += 1
                print("You must reload before attacking! The enemy reloads!")
            elif com_move == 4:
                com_HP = com_HP + com_heal
                com_potion -= 1
                print("You must reload before attacking! The enemy uses a health potion! He now has " , com_HP , "HP!")
            else:
                com_potion += 1
                print("You must reload before attacking! The enemy grabs a health potion!")
# If user blocks    
        if user_move == 2:
            if com_move == 1 and com_ammo > 0:
                if random.randint(0,100) > 50:
                    com_ammo -= 1
                    print(user_name + " blocked the enemys attack! You still have " , user_HP , "HP!")
                else:
                    print("The enemy fires as you run for cover! His attack misses!")
            elif com_move == 2:
                print(user_name + " and the enemy both block!")
            elif com_move == 3:
                com_ammo += 1
                print(user_name + " finds cover as the enemy reloads!")
            elif com_move == 4:
                com_HP = com_HP + com_heal
                com_potion -= 1
                print(user_name + " runs for cover as the enemy uses a health potion! He now has " , com_HP , "HP!")
            else:
                com_potion += 1
                print("You run for cover as the enemy grabs a potion!")
# If user reloads                
        if user_move == 3:
            user_ammo += 1
            if com_move == 1 and com_ammo > 0:
                if random.randint(0,100) > 50:
                    user_HP = user_HP - com_atk
                    com_ammo -= 1
                    print(user_name + " reloads as the enemy attacks! You now have " , user_HP, "HP and " , user_ammo , " ammo!")
                else:
                    print("You reload as the enemy attacks! His attack misses! You know have" , user_ammo , " ammo!")
            elif com_move == 2:
                print(user_name + " reloads as the enemy finds cover! You now have " , user_ammo , " ammo!")
            elif com_move == 3:
                com_ammo += 1
                print(user_name + " and the enemy both reload! You now have " , user_ammo , " ammo!")
            elif com_move == 4:
                com_HP = com_HP + com_heal
                com_potion -= 1
                print("You reload as the enemy uses a health potion! He now has " , com_HP , "HP! You have " , user_ammo , " ammo!")
            else:
                com_potion += 1
                print("You reload as the enemy grabs a potion! You now have " , user_ammo , " ammo!")
# If user uses health potion and has at least one
        if user_move == 4 and user_potion > 0:
            user_potion -= 1
            if com_move == 1 and com_ammo > 0:
                if random.randint(0,100) > 50:
                    com_ammo -= 1
                    print("You use a health potion as the enemy fires and hits! You have " , user_HP , "HP!")
                else:
                    user_HP = user_HP + user_heal
                    com_ammo -=1
                    print("You use a health potion as the enemy fires! They miss and you gain +10HP! You now have " , user_HP , "HP!")
            elif com_move == 2:
                user_HP = user_HP + user_heal
                print("The enemy runs for cover as you quickly drink a healing potion! You gain +10HP! You now have " , user_HP , "HP!")
            elif com_move == 3:
                user_HP = user_HP + user_heal
                com_ammo += 1
                print("The enemy reloads as you drink a healing potion! You now have" , user_HP , "HP!")
            elif com_move == 4:
                user_HP = user_HP + user_heal
                com_HP = com_HP + com_heal
                com_potion -= 1
                print("You and the enemy both drink healing potions! You now have " , user_HP , "HP!")
            else:
                user_HP = user_HP + user_heal
                print("You drink a healing potion and gain +10HP! You now have " , user_HP , "HP and" , user_potion , " potions! The enemy grabs a healing potion!")
# If user tries to use potion but has none
        elif user_move == 4 and user_potion <= 0:
          if com_move == 1 and com_ammo > 0:
                if random.randint(0,100) > 50:
                    com_ammo -= 1
                    user_HP = user_HP - com_atk
                    print("You attempt to use a health potion but have none! The enemy fires and hits! You now have " , user_HP , "HP!")
                else:
                    com_ammo -=1
                    print("You attempt to use a health potion as the enemy fires! You have no more potions but their attack miss!")
          elif com_move == 2:
            print("The enemy runs for cover as you attempt to drink a healing potion! You have no potions!")
          elif com_move == 3:
            com_ammo += 1
            print("The enemy reloads as you reach for a healing potion! You have none!")
          elif com_move == 4:
            com_HP = com_HP + com_heal
            com_potion -= 1
            print("You are out of potions! The enemy quickly drinks a healing potion!")
          else:
            print("You attempt to drink a healing potion but have none! The enemy grabs a healing potion!")
        if user_move == 5:
            user_potion += 1
            if com_move == 1 and com_ammo > 0:
                com_ammo -= 1
                if random.randint(0,100) > 50:
                    user_HP = user_HP - com_atk
                    print("You grab a potion as the enemy fires! He hits! You now have " , user_HP , "HP and " , user_potion , " potions!")
                else:
                    print("You grab a potion as the enemy fires! He misses! You now have " , user_potion , " potions!")
            elif com_move == 2:
                print("You grab a potion as the enemy runs for cover! You now have " , user_potion , " potions!")
            elif com_move == 3:
                com_ammo += 1
                print("You grab a healing potion as the enemy reloads!")
            elif com_move == 4:
                com_HP =  com_HP + com_heal
                com_potion -= 1
                print("You grab a potion a the enemy uses a potion! You now have " , user_potion , " potions and he has " , com_HP , "HP!")
            else:
                com_potion += 1
                print("You and the enemy both grab a potion! You now have " , user_potion , " potions!")
# If user or computers health falls to 0 than game ends and prompts user to play again
    else:
        print("GAME OVER!")
        if com_HP <= 0 and user_HP <= 0:
            print("You killed eachother...")
            replay_game()

        elif com_HP <= 0:
            win()
            replay_game()

        elif user_HP <= 0:
            losses()
            replay_game()
# Declaration for replay_game function
def replay_game():
# Prompts user to play again and saves value in variable game_loop    
    game_loop = input("Would you like to play again? (Y/N)")
# If game_loop variable is equal to Y then replay     
    if game_loop == "Y" or "y":
        game_main()
# If game_loop is anything else then exit    
    else:
        return
# Declaration for the win function    
def win():
# Declares variable win_cnt as global and increments value by +1
    global win_cnt
    win_cnt += 1
    print("You won! You have " , win_cnt , " wins and " , losses_cnt , " losses!") 
# Declaration of the the losses function
def losses():
# Declares variable losses_cnt as global and increments its value by +1
    global losses_cnt 
    losses_cnt += 1
    print("You lost and now have " , losses_cnt , " losses and " , win_cnt , " wins!")
# Welcome user and prompt for their name
print("Welcome to the duel!")
user_name = input("What is your name? ")
# Begin game function
game_main()
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Hey, welcome to Code Review! I edited your title to include only what your code achieves and not so much what you want out of a review (we all want constructive criticism and feedback here). \$\endgroup\$
    – Graipher
    Apr 15, 2020 at 15:01

2 Answers 2

4
\$\begingroup\$

First of all, there is a syntax error:

if com_HP > 50:  # <-- if statement without body leads to indentation error
# some comment
if user_move == 1 and user_ammo > 0:
    # some more code

Moreover there are a few style issues with your code:

Comments

Always indent your comments on the same level as the code you are referring to, otherwise it is very confusing.

# Declaration for replay_game function
def replay_game():
# Prompts user to play again and saves value in variable game_loop    
    game_loop = input("Would you like to play again? (Y/N)")
# If game_loop variable is equal to Y then replay     
    if game_loop == "Y" or "y":
        game_main()

Indent your comments like this:

# Declaration for replay_game function
def replay_game():
    # Prompts user to play again and saves value in variable game_loop    
    game_loop = input("Would you like to play again? (Y/N)")
    # If game_loop variable is equal to Y then replay     
    if game_loop == "Y" or "y":
        game_main()

Paragraphs

Please use paragraphs between functions, also when there is a comment in between. The official python style guide states:

Surround top-level function and class definitions with two blank lines.

Avoid top level code

Top level code is executed every time this module is loaded, which is probably not what you want when importing this module from another script. That's why you should surround your top level code with:

if __name__ == '__main__':
    # Welcome user and prompt for their name
    print("Welcome to the duel!")
    user_name = input("What is your name? ")
    # Begin game function
    game_main()

User input

You don't handle the case of invalid user input, e.g. a user enters a name instead of a number. This can be handled with an extra function to get proper user input.

def get_user_move():
    try:        
        user_move = int(input("..."))
    except ValueError:
        print("Invalid Input: Not a number!")        
    # validate input
    if user_move < 0 or user_move > 5:
        print("Invalid Input: Must be 1-5")
        # ask the player again
        return get_user_move()
    else:
        return user_move

Structure

Structure your game as a class e.g.

class Game:
    def __init__(self, username):
        self.username = username
        self.user_potion = 0
        self.com_potion = 0
        # etc.

    def start(self):
        # prompt user to choose a move
        user_move = get_user_move()
        # Uses random to generate a random integer between 1 and 5
        com_move = random.randint(1,5)
        if user_move == 1:
            user_attack(com_move)
        if user_move == 2:
            user_block(com_move)
        # etc.

    def user_attack(com_move):
        # handle user attack

    # etc.    

In your main part you can now instantiate your game as an object and run the start method, e.g.

if __name__ == '__main__':
    # Welcome user and prompt for their name
    print("Welcome to the duel!")
    user_name = input("What is your name? ")
    game = Game(user_name)
    game.start()
\$\endgroup\$
1
  • \$\begingroup\$ Thank you this I exactly the feedback I needed thank you so much for taking the time! I will defiantly work through everything you mentioned and practice implementing them! I will be posting an updated program once I have a cleaner and still working copy! \$\endgroup\$ Apr 15, 2020 at 16:51
3
\$\begingroup\$

Welcome to Code Review. Great first question!

Things to maintain

You have some good habits already; keep them up:

  • Commenting code
  • Reasonable variable and function names

There are some other things to improve:

Whitespace

Programmers (sometimes snobbishly) think of code as poetry that should be broken up into stanzas, basically paragraphs of related statements. This helps break up the code for it to be more legible for humans without having any effect on Python's interpretation of the code. For example, the first few lines of your program could be

# Imports random function for computer choice
import random


win_cnt = 0
losses_cnt = 0


def game_main():
    """
    Game function
    """

    # Prompts user about game   
    print(user_name + " will face off against the computer!\nIn this duel you and the computer will face off  by taking turns battling the first to fall loses! ")
    print("Remember to use nearby cover and to reload BEFORE you attack!")

    # Variables needed for tracking computer and users health, ammo, and damage.
    user_potion = 0
    com_potion = 0
    user_ammo = 0
    com_ammo = 0
    user_heal = 10
    com_heal = 10
    user_atk = 10
    com_atk = 10
    user_HP = 30
    com_HP = 30

    # Battle loop that loops as long as both players health is above 0   
    # ...

Note the use of triple-quotes for a standard function docstring, and standard indentation of comments at the same level as the corresponding code.

Have a read through PEP8, and/or use pretty much any modern Python IDE that has auto-linting (PyCharm is my usual go-to); you will find many other suggestions there about whitespace in your code.

String interpolation

print(user_name + " will face off against the computer!\nIn this duel you and the computer will face off  by taking turns battling the first to fall loses! ")

can be more easily coded as

print(
    f'{user_name} will face off against the computer!\n'
    'In this duel you and the computer will face off '
    'by taking turns battling the first to fall loses! '
    'Remember to use nearby cover and to reload BEFORE '
    'you attack!'
)

The f does the interpolation to allow for the {} field insertion, and the consecutive strings use implicit string literal concatenation to keep the line length down.

Parentheses

This is not C/Java/C#/etc., so this:

while (user_HP > 0 and com_HP > 0):

does not need parentheses.

Input validation

    user_move = int(input("What would you like to do? 1) Attack 2) Block 3) Reload 4) Heal? 5) Grab Bandage(potion)"))
    if user_move > 5: #or str:
        print("INVALID INPUT! MUST BE 1-5")

What if someone inputs 0? Or "banana"? You will want to change this to (a) catch a ValueError, and also if not (1 <= input <= 5).

That aside, you should also consider making an enum.Enum to represent these choices, for many reasons - symbolic references to the numbers will make your code more legible; validation will be easier; etc.

Random

This:

random.randint(0,100) > 50

technically does not need to have a range of 100. You could use an upper limit of 2, or even

random.choice((True, False))

Functions

game_main is very long. Consider pulling out chunks of it into subroutines - perhaps one for every different possible type of user move.

No-op return

This:

else:
    return

does not do anything and can be removed.

Procedure

I encourage you to work on your code based on the feedback you get, ensure that your code is still working, and then post another question with your new, proposed code once you are satisfied that you have received enough responses on this question. Given that you are a beginner, there are many things that you can do to this code to improve it, and it wouldn't be very feasible to tackle it all at once.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you this I exactly the feedback I needed, thank you so much for taking the time! I will defiantly work through everything you mentioned and practice implementing them! I will be posting an updated program once I have a cleaner and still working copy! \$\endgroup\$ Apr 15, 2020 at 16:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.