Ex36 Code review

Oh my God… So, I am finally done with ex36 after a week and a half :partying_face: and wanted to see what I got right and what stuff I totally butchered. My code is definitely very weird and a lot of things I did can be considered bad practice, I guess :sweat_smile: I don’t know, I did what my limited knowledge allowed me to do. Here’s my code:

from sys import exit

HP = 100

print("A super AI who calls itself Hades has gone rogue and wrecked havoc across the world.")
print("You are a cyborg and it is upto you to infiltrate its HQ, find the stolen quantum module, install it into Hades and destroy it.")


class Character:
    def __init__(self, defense, strength, stamina, agility, intelligence):
        self.defns = defense
        self.strng = strength
        self.stam = stamina
        self.agl = agility
        self.intl = intelligence


def damage(enemy, player):
    global HP
    enemy_hp = 100
    dmg_player = (enemy.strng * enemy.stam) - (player.defns * 2)
    dmg_enemy = (player.strng * player.stam * 2) - (enemy.defns * 0.5)

    while enemy_hp > 0:
        HP -= dmg_player
        enemy_hp -= dmg_enemy

    if HP < 0:
        dead("The enemies were stronger and killed you...")


def hacker_puzzle(player, enemy):
    if player.intl >= enemy.intl:
        print("Breachinng firewall...")
        print("Firewall breached. System access acquired...\n")
        valid_inputs = ['A5', 'B8', 'N9', 'Z3', 'K7', 'Y6', 'H1', 'V2', 'T4']
        print(f"Valid inputs:-\n{valid_inputs[0]}\t{valid_inputs[1]}\t{valid_inputs[2]}\n{valid_inputs[3]}\t{valid_inputs[4]}\t{valid_inputs[5]}\n{valid_inputs[6]}\t{valid_inputs[7]}\t{valid_inputs[8]}\n\n")

        print('Codes needed: N9 Z3 H1\n 5 inputs available.')

        codes_in = []
        while len(codes_in) < 5:
            code = input('> ')
            avlbl_in = []
            if code not in valid_inputs and code not in avlbl_in:
                print('Wrong input')
            else:
                index = valid_inputs.index(code)
                codes_in.append(code)
                if (len(codes_in) % 2) == 1:
                    print(f"Available inputs:-\n{valid_inputs[index - 3]}\n{valid_inputs[index]}\n{valid_inputs[index - 6]}")
                    avlbl_in = [valid_inputs[index - 3], valid_inputs[index], valid_inputs[index - 6]]

                elif (len(codes_in) % 2) == 0:
                    print(f"Valid inputs:-\n{valid_inputs[index - 1]}\n{valid_inputs[index]}\n{valid_inputs[index -2]}")
                    avlbl_in = [valid_inputs[index - 1], valid_inputs[index], valid_inputs[index -2]]

        if 'N9' in codes_in and 'Z3' in codes_in and 'H1' in codes_in:
            print("Enemies have been hacked. Installing malware...")
            print("Enemies have been destroyed.")
        else:
            dead("You were wrong and the bots killed you.")
    else:
        dead("The enemy AI was more intelligent and the bots killed you.")


def character_creator():
    print("This is your only chance to customize your abilities. There is no way to change stats later, so take your decisions carefully. And a little tip, neither being a generalist nor being too niche will get you anywhere. Be wise...\n\n\n")

    print("Total stat points = 20")

    while True:
        stat1 = input('Defense: ')
        stat2 = input('Strength: ')
        stat3 = input('Stamina: ')
        stat4 = input('Agility: ')
        stat5 = input('Intelligence: ')

        try:
            defense = int(stat1)
            strength = int(stat2)
            stamina = int(stat3)
            agility = int(stat4)
            intelligence = int(stat5)

            total_stats = defense + strength + stamina + agility + intelligence

            if total_stats == 20:
                start(defense, strength, stamina, agility, intelligence)
            elif total_stats < 20:
                print("You have remaining stat points, you must use them all.")
            else:
                print("You used more stats points than available. You can't have more than 20.")

        except ValueError:
            print("That is an invalid input. Try again!")


def start(*stats):
    defense, strength, stamina, agility, intelligence = stats
    main = Character(defense, strength, stamina, agility, intelligence)

    print("You are in front of the main compound.")
    print("You can either go to the old robot facility or the defense systems room.")

    while True:
        room = input('> ')

        if 'robot' in room:
            bot_room(main)
        elif 'defense' in room:
            turret_room(main)
        else:
            print("You can only go to these 2 locations")


def bot_room(player):
    global HP

    print("You entered room #627, the old robot facility.")
    print("These robots had been made for construction and not battle.")
    print("But Hades has hacked them and they will kill anyone on sight.")
    print("You see an EMP charge on the far end of the room.")
    print(f"Do you battle the bots, try to hack the bots, or try to obtain the EMP charge?\nCurrent HP: {HP}")

    bots = Character(5, 4, 4, 4, 5)

    while True:

        choice_loop = True
        while choice_loop == True:
            choice = input('> ')

            if 'battle' in choice:
                damage(bots, player)
                print("You have destroyed the bots.")
                print(f"Remaining HP: {HP}\n")
                choice_loop = False
            elif 'hack' in choice:
                hacker_puzzle(player, bots)
                choice_loop = False
            elif 'EMP' in choice or 'emp' in choice:
                dmg = HP - (player.agl * 3)
                print("You outran the bots and detonated the EMP.")
                print("All robots destroyed.")
                print("You took some self damage due to overheating caused by agility override.")
                print(f"Remaining HP: {HP}\n")
                choice_loop = False
            else:
                print("I don't know what that means.")

        print("You can either take the battle exoskeleton or the shield weaver armor.")
        print("BATTLE EXOSKELETON:\nStrength +2\nStamina -1\n\nSHIELD WEAVER\nDefense +2\nAgility -1")

        armor_loop = True
        while armor_loop == True:
            armor = input("Which one do you take?\n>")
            if 'battle' in armor or 'exoskeleton' in armor:
                player.strng += 2
                player.stam -= 1
                armor = 'BATTLE EXOSKELETON'
                armor_loop = False
            elif 'shield' in armor or 'weaver' in armor:
                player.defns += 2
                player.agl -= 1
                armor = 'SHIELD WEAVER'
                armor_loop = False
            else:
                print("You only have 2 choices.")

        print("You suddenly hear cries from down the hallway.")
        print("Do you investigate or go to the HQ?")

        while True:
            decision = input('> ')
            if 'investigate' in decision:
                hostage_room(player)
            elif 'hq' in decision or 'HQ' in decision:
                hq_room(False, player)
            else:
                print("You have only two choices.")


def turret_room(player):
    global HP

    print("You entered room #572, the defense system management center.")
    print("The defense systems have been taken over and the turrets shoot on sight.")
    print("The turrets can fire .50 cal rounds but overheat in a while.")
    print("The turrets never miss their mark, but can be fooled into firing at each other if one is fast enough.\nAlternatively, they can be hacked or destroyed.")
    print("Do you destroy the defense system, hack it, or use override?")

    turret = Character(5, 4, 4, 0, 4)

    while True:
        choice = input('> ')
        choice_loop = True

        while choice_loop == True:
            if 'battle' in choice or 'destroy' in choice:
                print(f"Current HP: {HP}")
                damage(turret, player)
                print("You have destroyed the turrets.")
                print(f"Remaining HP: {HP}")
                choice_loop = False
            elif 'hack' in choice:
                hacker_puzzle(player, turret)
                choice_loop = False
            elif 'override' in choice:
                HP = player.agl * 5
                print("You fooled the turrets to fire at each other with your speed.")
                print("Turrets destroyed.")
                print("You took some damage due to overheating.")
                print(f"Remaining HP: {HP}")
                choice_loop = False
            else:
                print("I don't understand that.")


        print("You can either take the plasma blade or the smart gun.")
        print("PLASMA BLADE:\nAgility +2\nStrength -1\n\nSMART GUN\nIntelligence +2\nDefense -1")

        weapon_loop = True
        while weapon_loop == True:
            weapon = input("Which one do you take?\n>")
            if 'plasma' in weapon or 'blade' in weapon:
                player.agl += 2
                player.strng -= 1
                weapon = 'PLASMA BLADE'
                weapon_loop = False
            elif 'smart' in weapon or 'gun' in weapon:
                player.intl += 2
                player.defns -= 1
                weapon = 'SHIELD WEAVER'
                weapon_loop = False
            else:
                print("You only have 2 choices.")

        print(f"You chose {weapon}. Stats:-\nDefense: {player.defns}\nStrength: {player.strng}\nStamnina: {player.stam}\nAgility: {player.agl}\nIntelligence: {player.intl}")

        print("You suddenly hear cries from down the hallway.")
        print("Do you investigate or go to the HQ?")

        while True:
            decision = input('> ')
            if 'investigate' in decision:
                hostage_room(player)
            elif 'hq' in decision or 'HQ' in decision:
                hq_room(False, player)
            else:
                print("You have only two choices.")


def hostage_room(player):
    global HP

    print("You investigate and find hostages.")
    print("Hades has captured the researchers working in THE FACILITY and used nano bots to take over the minds of the guards.")
    print("You are running out of time. You try saving the hostages or go to the HQ.")
    print("Do you save the hostages or leave them?")
    print(f"Current HP: {HP}")

    guards = Character(3, 4, 5, 3, 2)

    while True:
        choice = input('> ')

        if 'save' in choice:
            damage(guards, player)

            print(f"Remaining HP: {HP}")
            print(f"You have knocked out all the guards.")
            print("You have secured the hostage researchers.")
            print("One of them tells you where Hades hid the quantum module.")
            print("You thank him and go to the module's location.\nYou have obtained the quantum module.")
            print("You receive +3 intelligence.")

            player.intl += 3

            hq_room(True, player)
        elif 'leave' in choice:
            print("You let the hostages die...")
            print("You leave and were tricked by Hades. You are now in the HQ.")

            hq_room(False, player)
        else:
            print("I don't understand that")


def hq_room(quantum_module, player):
    print("You have reached the HQ.")

    if quantum_module == True:
        ending(player)
    elif quantum_module == False:
        print("You could not find the quantum module.")
        dead("Hades hacked your systems and fried your brains...")


def dead(reason):
    print(f'{reason} Mission failed.')
    exit(0)


def ending(player):
    print("You connected the module.")
    print("INSTALLING MODULE..... MODULE INSTALLED")
    print("Hades is trying to destroy the module. You must stop him.")
    print("1011010----101101000----1111000----100101100----10110100")
    print("5 circles appeared before you. The numbers and the circles have a connection, you must figure it out!")

    end_loop = True
    while end_loop == True:
        op1 = input('> ')
        op2 = input('> ')
        op3 = input('> ')
        op4 = input('> ')
        op5 = input('> ')

        solution = [op1, op2, op3, op4, op5]

        if solution == ['90', '360', '120', '300', '180']:
            print("You are almost there, just a bit more.")
            end_loop = False
            if player.intl > 7:
                print("Analysis complete. Your high intelligence has helped you deduce a clue to solve the code.")
                print("Those are all angles. Picture a clock with 3 o'clock as 0 degrees.")
            else:
                pass
        elif solution == ['12', '3', '11', '5', '9']:
            print("You did it! Hades has been stopped. You saved the world. Great job. Mission accomplished.")
            print("You will always be remembered as a hero.")
            exit(0)
        else:
            dead("You got it wrong.")

    end_loop = True
    while end_loop == False:
        op1 = input('> ')
        op2 = input('> ')
        op3 = input('> ')
        op4 = input('> ')
        op5 = input('> ')

        solution = [op1, op2, op3, op4, op5]

        if solution == ['12', '3', '11', '5', '9']:
            print("You did it! Hades has been stopped. You saved the world. Great job. Mission accomplished.")
            print("You will always be remembered as a hero.")
        else:
            dead("You got it wrong.")
            
character_creator()

I am sorry for the length. :sweat: I tested it, it all works. I was looking for some code reviews. Won’t make any further changes to it but want to improve my skills. Thanks!

Edit: I apologize for the weirdness of hacker_puzzle() function. :pray:

1 Like

Okay, to anyone that ever happens to come across this thread, I found a few bugs and fixed them. However, I couldn’t update the post above cause it is too old. I am not including any code cause the fixes are too minor to be noticeable. It is just a fix for a problem with the loops in the same function where an invalid input in one loop would take you to the last loop. And after this, I promise I am never returning to this, just happened to spot it when I was playing around with the script.

Why not include a link to the git repo instead?

I don’t have one… :sweat:

Get one! It doesn’t have to be GitHub or anywhere public, but having some sort of version control system will become indispensable at some point.

Git is free, extremely powerful, and learning the few basic commands you use everyday is not much of a challenge.

1 Like

Totally agree. It can be a bit confusing to start with (merging, pull from master etc) but even in terms of having a backup of your projects folder, essential.

It’s also a behaviour that is expected in any serious coding environment.

1 Like

Hi @CodeNinja haven’t gone through all of your code, but one thing I recognized is that you can ease your life when defining instance variables (the variables under the __init__-function. It is common practice to call it the same as the arguments. So Instead of give them another name like self.defns = defense you can write self.defense = defense:

You’re __init__-funktion would look like that:

class Character: 
    def __init__(self, defense, strength, stamina, agility, intelligence): 
        self.defense = defense 
        self.strength = strength 
        self.stamina = stamina 
        self.agility = agility 
        self.intelligence = intelligence

See also here: https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables

1 Like

@florian and @gpkesley Alright, I will look into it. I have heard about it but never bothered to learn.
@DidierCH Okay, thanks! I will make the changes in the code!

Also, sorry for the month late reply, I was super busy with exams and stuff. Hopefully, I can complete this book by mid-October

1 Like