5
\$\begingroup\$

I have began to practice Python after a couple of years and for my first Project, i decided to make a fighting/rpg-like game with different characters. So far, I am only familiar with loops and functions, not classes or OOP. Please give me any feedback on how I could improve my code, through debugging, optimization, or adding more content (In case the game doesn't start due to the absence of highscore.txt, please make a text file called highscore, and of the first line insert an interger, and on the second put any name. This should not happen, but just in case :P).

import random as r

######Getting High Score#####

try:
    hs = open("highscore.txt","r+")
except:

    hs = open("highscore.txt","x")
    hs = open("highscore.txt","r+")

try:
    score = hs.readlines(1)
    score = int(score[0])

    leader = hs.readlines(2)
    leader = str(leader[0])
except:
    hs = open("highscore.txt","w")
    hs.write("0\n")
    hs.write("null")
    hs = open("highscore.txt","r")
    score = hs.readlines(1)
    score = int(score[0])
    leader = hs.readlines(2)
    leader = str(leader[0])

#####Introduction, Initializing player#####

print("\nWELCOME TO WONDERLANDS RPG!")
print("The High Score is:",score,"by",leader)
points = 0
player_name = input("\nEnter your hero's name: ")

#####Classes [health, attack 1 (only does set damage), attack 2 min, attack 2 max, attack 3 min, attack 3 max, heal min, heal max], Getting player's Class#####

knight = [100,10,5,15,0,25,5,10] #health: 100, attack 1: 10, attack 2: 5-15, attack 3: 5-25, heal: 5-10
mage = [50,15,10,20,-5,25,10,15] #health: 50, attack 1: 15, attack 2: 10-20, attack 3: -5-25, heal: 10-15
healer = [150,5,5,10,5,15,10,20] #health: 150, attack 1: 5, attack 2: 5-10, attack 3: 5-15, heal: 10-20

while True:
    print("\n1. Knight: Health: ",knight[0],"; Attack 1:",knight[1],"; Attack 2:",knight[2],"-",knight[3],"; Attack 3:",knight[4],"-",knight[5],"; Heal:",knight[6],"-",knight[7])
    print("2. Mage: Health: ",mage[0],"; Attack 1:",mage[1],"; Attack 2:",mage[2],"-",mage[3],"; Attack 3:",mage[4],"-",mage[5],"; Heal:",mage[6],"-",mage[7])
    print("3. Healer: Health: ",healer[0],"; Attack 1:",healer[1],"; Attack 2:",healer[2],"-",healer[3],"; Attack 3:",healer[4],"-",healer[5],"; Heal:",healer[6],"-",healer[7])
    player_class = input("\nSelect your class: 1, 2, or 3: ")
    if player_class == "1":
        player_class = knight
        print("You have selected the Knight")
        break
    if player_class == "2":
        player_class = mage
        print("You have selected the Mage")
        break
    if player_class == "3":
        player_class = healer
        print("You have selected the Healer")
        break
    else:
        print("Please select a valid class.")
        continue

player_heal_max = player_class[0]

#####Difficulty/Upgrade Functions#####

def level_up(player,health_max):
    while True:
        lv_choice = input("\nWould you like to:\n Increase max health by 20 (1)\n Increase Healing Factor by 5 (2)\n increase your damage by 5 (3) ")
        if lv_choice == "1":
            health_max += 20
            player[0] = health_max
            return player,health_max
        elif lv_choice == "2":
            player[6] +=5
            player[7] +=5
            player[0] = health_max
            return player, health_max
        elif lv_choice == "3":
            player[1] +=5
            player[2] +=5
            player[3] +=5
            player[4] +=5
            player[5] +=5
            player[0] = health_max
            return player, health_max
        else:
            print("Please enter in a valid number")
            continue

def difficulty(ai,health_max,level):
    if level == 1:
        return ai
    else:
        ai[0] = health_max+15*round(0.5*level+0.5)
        ai[1] +=5*round(0.5*level+0.5)
        ai[2] +=5*round(0.5*level+0.5)
        ai[3] +=5*round(0.5*level+0.5)
        ai[4] +=5*round(0.5*level+0.5)
        ai[5] +=5*round(0.5*level+0.5)
        ai[6] +=5*round(0.5*level+0.5)
        ai[7] +=5*round(0.5*level+0.5)
        return ai

def ai_stats(s):
    s[0] += r.randint(-20,20)
    s[1] += r.randint(-3,3)
    s[2] += r.randint(-3,3)
    s[3] += r.randint(-3,3)
    s[4] += r.randint(-3,3)
    s[5] += r.randint(-3,3)
    s[6] += r.randint(-3,3)
    s[7] += r.randint(-3,3)
    return s

#####Game Loop#####

level = 1
print("\n----------------------- GAME START -----------------------")

while True:
    #####Determining AI Class/Stats#####
    #####(AI classes must be in the Game loop otherwise if an enemy chooses the same class twice, it would have <=0 HP, thus being an instant win)#####
    ai_knight = [100,10,5,15,0,25,5,10] #health: 100, attack 1: 10, attack 2: 5-15, attack 3: 5-25, heal: 5-10
    ai_mage = [50,15,10,20,-5,25,10,15] #health: 50, attack 1: 15, attack 2: 10-20, attack 3: -5-25, heal: 10-15
    ai_healer = [150,5,5,10,5,15,10,20] #health: 150, attack 1: 5, attack 2: 5-10, attack 3: 5-15, heal: 10-20

    ai = r.randint(1,3)
    if ai == 1:
        ai = ai_stats(ai_knight)
        print("\nYou are fighiting a knight with",ai[0],"HP!")
    if ai == 2:
        ai = ai_stats(ai_mage)
        print("\nYou are fighiting a mage with",ai[0],"HP!")
    if ai == 3:
        ai = ai_stats(ai_healer)
        print("\nYou are fighiting a healer with",ai[0],"HP!")

    ai_heal_max = ai[0]
    ai = difficulty(ai,ai_heal_max,level)
    #####Gameplay Loop#####
    while True:
        #####Player Attack#####
        player_move = input("\nWould you like to use attack (1), attack (2), attack (3), or heal (4)? ")
        print("")
        if player_move == "1":
            player_damage = player_class[1]
            ai[0] = ai[0]- player_damage
            print(player_name," did",player_damage,"damage!")
        elif player_move == "2":
            player_damage = r.randint(player_class[2],player_class[3])
            ai[0] = ai[0]- player_damage
            print(player_name," did",player_damage,"damage!")
        elif player_move == "3":
            player_damage = r.randint(player_class[4],player_class[5])
            if player_damage<0:
                player_class[0] = player_class[0]+player_damage
                print(player_name," damaged themselves for",player_damage,"HP!")
            else:
                ai[0] = ai[0]- player_damage
                print(player_name," did",player_damage,"damage!")
        elif player_move == "4":
            player_heal = r.randint(player_class[6],player_class[7])
            if player_class[0] + player_heal > player_heal_max:
                player_class[0] = player_heal_max
            else:
                player_class[0] = player_class[0] + player_heal
            print(player_name," healed for",player_heal,"HP")
        else:
            print("Please enter in a valid move.")
            continue
        #####Detecting Death#####
        if player_class[0]<=0:
            break
        elif ai[0]<=0:
            points += player_class[0]*level
            level +=1
            print("You have bested your opponent! You Have",points,"points. \nNow starting level",level)
            player_class,player_heal_max = level_up(player_class,player_heal_max)
            break
        #####AI Turn#####
        if ai[0] <= (ai_heal_max/5):
            ai_move = r.sample(set([1,2,3,4,4,4]), 1)[0]
        elif ai[0] >= (ai_heal_max*.8):
            ai_move = r.sample(set([1,2,3,1,2,3,4]), 1)[0]
        elif ai[0] == ai_heal_max:
            ai_move = r.randint(1,3)
        else:
            ai_move = r.randint(1,4)

        if ai_move == 1:
            ai_damage = ai[1]
            player_class[0] = player_class[0]- ai_damage
            print("Your opponent did",ai_damage,"damage!")
        elif ai_move == 2:
            ai_damage = r.randint(ai[2],ai[3])
            player_class[0] = player_class[0]- ai_damage
            print("Your opponent did",ai_damage,"damage!")
        elif ai_move == 3:
            ai_damage = r.randint(ai[4],ai[5])
            if ai_damage<0:
                ai[0] = ai[0]+ai_damage
                print("Your opponent damaged themselves for",ai_damage,"HP!")
            else:
                player_class[0] = player_class[0]- ai_damage
                print("Your opponent did",ai_damage,"damage!")
        elif ai_move == 4:
            ai_heal = r.randint(ai[6],ai[7])
            if ai[0] + ai_heal > ai_heal_max:
                ai[0] = ai_heal_max
            else:
                ai[0] = ai[0] + ai_heal
            print("Your opponent healed for",ai_heal,"HP")
        #####Displaying HP#####   
        print("\nYour health is:",player_class[0],"HP")
        print("Your opponent's health is",ai[0],"HP")
        #####Detecting Loss#####
        if player_class[0]<=0:
            break
        elif ai[0]<=0:
            points += player_class[0]*level
            level +=1
            print("You have bested your opponent! You Have",points,"points. \nNow starting level",level)
            player_class,player_heal_max = level_up(player_class,player_heal_max)
            break
        else:
            continue
    #####Finishing Game, Checking/Updating High Score#####
    if player_class[0]<=0:
        print("\nYou Died! :(")
        if points>score:
            hs = open("highscore.txt","w")
            hs.write(str(points))
            hs.write("\n")
            print("You have the new high score of",points,"!")
            hs.write(player_name)
        else:
            print("\nYou finished with",points,"points.")
            print("The high score is:",score,"by",leader)
        input("")
        hs.close()
        break
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Really cool game here. Thanks for sharing. Expect an answer soon. \$\endgroup\$ Jul 12, 2019 at 0:13

1 Answer 1

2
\$\begingroup\$

In your game, which I've played, you have 3 main warriors: knight, mage, and healer. These warriors all have similar behaviors, health, attacks, and heals - they are essentially objects of a class, Warrior.

Tip 1: Let's create a Warrior class:

  • You will be able to create new Warriors (ie Archers, Brutes, Zombies) later with ease.
  • You can interface your AI player as a Warrior.
  • You can simply control all of your Warrior objects.
class Warrior:
    def __init__(self, health, attack_1, attack_2, attack_3, heal):
        self.health = health
        self.attack_1 = attack_1
        self.attack_2 = attack_2 # tuple ie (5,25) representing range for attack value
        self.attack_3 = attack_3 # tuple ie (10,20) representing range for attack value
        self.heal = heal # tuple ie (10,20) representing range for health value

    def attributes(self):
        # string containing the attributes of the character
        string = "Health: "+ str(self.health) + " Attack 1: "+ str(self.attack_1) + " Attack 2: "+ str(self.attack_2[0]) + "-"+ str(self.attack_2[1])+ " Attack 3: "+ str(self.attack_3[0]) + "-"+ str(self.attack_3[1]) + " Heal:"+ str(self.heal[0]) + "-" + str(self.heal[0])
        return string

    def is_dead(self):
        return self.health <= 0

You may want to add other functions later. For instance, def attack_3(self), which would return the value of an attack. We then initialize the knight, mage, healer, and ai as so:

knight = Warrior(100, 10, (5,15),  (5,25),  (5,10))
mage   = Warrior(50,  15, (10,20), (-5,25), (10,15))
healer = Warrior(150, 5,  (5,10),  (5,15),  (10,20))

while True:
    # Determining AI Class/Stats
    ai_knight = Warrior(100, 10, (5,15),  (5,25),  (5,10))
    ai_mage   = Warrior(50,  15, (10,20), (-5,25), (10,15))
    ai_healer = Warrior(150, 5,  (5,10),  (5,15),  (10,20))
    ai_classes = [ai_knight, ai_mage, ai_healer]

    ai = ai_classes[r.randint(0,2)]
    randomize_ai(ai)
    if ai == ai_knight:
        print("\nYou are fighting a knight with ", ai.health,"HP!")
    elif ai == ai_mage:
        print("\nYou are fighting a mage with ", ai.health,"HP!")
    elif ai == ai_healer:
        print("\nYou are fighting a healer with ", ai.health,"HP!")

Tip 2: elif is your best friend. If your if statements are mutually exclusive, you can cut down on the complexity of your program, by using elif(which you used successfully in your program, just not always):

if ai == 1:
    #code
if ai == 2:
    #code
if ai == 3:
   #code

# should instead be...
# because ai can't be three values at once

if ai == 1:
    #code
elif ai == 2:
    #code
elif ai == 3:
   #code

Tip 3: The style in which you program is critical to your actual program. A few basic things you should know about coding styles:

  • Do not use too many # when you are commenting. Instead of ######Displaying HP####### try # Display HP. The latter is more readable for someone else or yourself reading/reviewing your code.
  • If you have a section header comment, you can try a special commenting style such as:
###########
# CLASSES #
###########
  • Do not add extra spaces to your code -- this makes your code longer than it needs to and should be. Make your code shorter if it doesn't reduce readability.
  • To improve the user experience, avoid typos when possible
  • And whatever you do, be consistent. It's easiest to read, review, and edit code that is consistent in style.
  • Style is one of those things that just takes experience and practice. You will get better over time.

With these three tips in mind, your final code should look more like:

import random as r

try:
    hs = open("highscore.txt","r+")
except:
    hs = open("highscore.txt","x")
    hs = open("highscore.txt","r+")

try:
    score = int(hs.readlines(1)[0])
    score = int(score[0])
    leader = hs.readlines(2)
    leader =  str(hs.readlines(2)[0])
except:
    hs = open("highscore.txt","w")
    hs.write("0\nnull")
    hs = open("highscore.txt","r")
    score = int(hs.readlines(1)[0])
    leader = str(hs.readlines(2)[0])

# Introduce and name the player
print ("\nWELCOME TO WONDERLANDS RPG!")
print ("The High Score is:", score, "by", leader)
points = 0
player_name = input ("\nEnter your hero's name: ")


###########
# CLASSES #
###########

class Warrior:
    def __init__(self, health, attack_1, attack_2, attack_3, heal):
        self.health = health
        self.attack_1 = attack_1
        self.attack_2 = attack_2 # tuple ie (5,25) representing range for attack value
        self.attack_3 = attack_3 # tuple ie (10,20) representing range for attack value
        self.heal = heal # tuple ie (10,20) representing range for health value

    def attributes(self):
        # string containing the attributes of the character
        string = "Health: "+ str(self.health) + " Attack 1: "+ str(self.attack_1) + " Attack 2: "+ str(self.attack_2[0]) + "-"+ str(self.attack_2[1])+ " Attack 3: "+ str(self.attack_3[0]) + "-"+ str(self.attack_3[1]) + " Heal:"+ str(self.heal[0]) + "-" + str(self.heal[0])
        return string

    def is_dead(self):
        return self.health <= 0

knight = Warrior(100, 10, (5,15),  (5,25),  (5,10))
mage   = Warrior(50,  15, (10,20), (-5,25), (10,15))
healer = Warrior(150, 5,  (5,10),  (5,15),  (10,20))

while True:
    print("\n1. Knight: ", knight.attributes())
    print("\n2. Mage:   ", mage.attributes())
    print("\n3. Healer: ", healer.attributes())
    player_class = input("\nSelect your class: 1, 2, or 3: ")
    if player_class == "1":
        player_class = knight
        print("You have selected the Knight class.")
        break
    elif player_class == "2":
        player_class = mage
        print("You have selected the Mage")
        break
    elif player_class == "3":
        player_class = healer
        print("You have selected the Healer")
        break
    else:
        print("Please select a valid class.")
        continue

player_heal_max = player_class.health


################################
# Difficulty/Upgrade Functions #
################################

def level_up(player,health_max):
    while True:
        lv_choice = input("\nWould you like to:\n 1. Increase max health by 20 \n 2. Increase Healing Factor by 5 \n 3. increase your damage by 5\n")
        if lv_choice == "1":
            health_max += 20
            player.health = health_max
            return player, health_max
        elif lv_choice == "2":
            player.heal += (5,5)
            player.health = health_max
            return player, health_max
        elif lv_choice == "3":
            player.attack_1 += 5
            player.attack_2 += (5,5)
            player.attack_3 += (5,5)
            player.health = health_max
            return player, health_max
        else:
            print("Please enter in a valid number")
            continue

def difficulty(ai,health_max,level):
    if level == 1:
        return ai
    else:
        ai.health = health_max + 15 * round(0.5 * level + 0.5)
        ai.attack_1 += 5 * round(0.5 * level + 0.5)
        ai.attack_2 += (5 * round(0.5 * level + 0.5),5 * round(0.5 * level + 0.5))
        ai.attack_3 += (5 * round(0.5 * level + 0.5),5 * round(0.5 * level + 0.5))
        ai.heal += (5 * round(0.5 * level + 0.5),5 * round(0.5 * level + 0.5))
        return ai

def randomize_ai(ai):
    ai.health += r.randint(-20,20)
    ai.attack_1 += r.randint(-3,3)
    ai.attack_2 += (r.randint(-3,3),r.randint(-3,3))
    ai.attack_3 += (r.randint(-3,3),r.randint(-3,3))
    ai.heal += (r.randint(-3,3),r.randint(-3,3))
    return ai

#############
# Game Loop #
#############

level = 1
print("\n----------------------- GAME START -----------------------")

while True:
    # Determining AI Class/Stats
    ai_knight = Warrior(100, 10, (5,15),  (5,25),  (5,10))
    ai_mage   = Warrior(50,  15, (10,20), (-5,25), (10,15))
    ai_healer = Warrior(150, 5,  (5,10),  (5,15),  (10,20))
    ai_classes = [ai_knight, ai_mage, ai_healer]

    ai = ai_classes[r.randint(0,2)]
    randomize_ai(ai)
    if ai == ai_knight:
        print("\nYou are fighting a knight with ", ai.health,"HP!")
    elif ai == ai_mage:
        print("\nYou are fighting a mage with ", ai.health,"HP!")
    elif ai == ai_healer:
        print("\nYou are fighting a healer with ", ai.health,"HP!")

    ai_heal_max = ai.health

    ai = difficulty(ai, ai_heal_max, level)

    # Gameplay Loop
    while True:
        # Player Attack
        player_move = input("\nWould you like to use attack (1), attack (2), attack (3), or heal (4)?  ")
        print("")
        if player_move == "1":
            player_damage = player_class.attack_1
            ai.health = ai.health - player_damage
            print(player_name," did",player_damage,"damage!")
        elif player_move == "2":
            player_damage = r.randint(player_class.attack_2[0],player_class.attack_2[1])
            ai.health = ai.health - player_damage
            print(player_name," did",player_damage,"damage!")
        elif player_move == "3":
            player_damage = r.randint(player_class.attack_3[0],player_class.attack_3[1])
            ai.health = ai.health - player_damage
            print(player_name," did", player_damage, " damage!")
        elif player_move == "4":
            player_heal = r.randint(player_class.heal[0],player_class.heal[1])
            if player_class.health + player_heal > player_heal_max:
                player_class.health = player_heal_max
            else:
                player_class.health = player_class.health + player_heal
            print(player_name," healed for",player_heal,"HP")
        else:
            print("Please enter in a valid move.")
            continue

        # Detecting Death
        if player_class.is_dead():
            break
        elif ai.is_dead():
            points += player_class.health * level
            level += 1
            print("You have bested your opponent! You Have",points,"points. \nNow starting level",level)
            player_class, player_heal_max = level_up(player_class,player_heal_max)
            break

        # AI Turn
        if ai.health <= (ai_heal_max/5):
            ai_move = r.sample(set([1,2,3,4,4,4]), 1)[0]
        elif ai.health >= (ai_heal_max*.8):
            ai_move = r.sample(set([1,2,3,1,2,3,4]), 1)[0]
        elif ai.health == ai_heal_max:
            ai_move = r.randint(1,3)
        else:
            ai_move = r.randint(1,4)

        if ai_move == 1:
            ai_damage = ai.attack_1
            player_class.health = player_class.health - ai_damage
            print("Your opponent did",ai_damage,"damage!")
        elif ai_move == 2:
            ai_damage = r.randint(ai.attack_2[0],ai.attack_2[1])
            player_class.health = player_class.health- ai_damage
            print("Your opponent did ",ai_damage," damage!")
        elif ai_move == 3:
            ai_damage = r.randint(ai.attack_3[0],ai.attack_3[1])
            player_class.health = player_class.health - ai_damage
            print("Your opponent did ", ai_damage," damage!")
        elif ai_move == 4:
            ai_heal = r.randint(ai.heal[0],ai.heal[1])
            if ai.health + ai_heal > ai_heal_max:
                ai.health = ai_heal_max
            else:
                ai.health = ai.health + ai_heal
            print("Your opponent healed for ", ai_heal," HP")

        # Displaying HP  
        print("\nYour health is:", player_class.health,"HP")
        print("Your opponent's health is ", ai.health," HP ")

        # Detecting Death
        if player_class.is_dead():
            break
        elif ai.health <= 0:
            points += player_class.health * level
            level += 1
            print("You have bested your opponent! You Have",points,"points. \nNow starting level",level)
            player_class, player_heal_max = level_up(player_class,player_heal_max)
            break

    # Finishing Game, Checking/Updating High Score
    if player_class.health<=0:
        print(" \ nYou Died !: (")
        if points > score:
            hs = open(" highscore.txt "," w ")
            hs.write(str(points))
            hs.write(" \ n ")
            print(" You have the new high score of ",points," !")
            hs.write(player_name)
        else:
            print(" \ nYou finished with ",points," points.")
            print(" The high score is:",score," by ",leader)
        input(" ")
        hs.close()
        break
```
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I made lots of other small edits. If you're curious about one of them, leave a comment and I'll be sure to respond. \$\endgroup\$ Jul 12, 2019 at 17:30

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.