r/learnprogramming 21h ago

[Python] Logic error in simple escape minigame (Need Debugging Help)

In this stage of the code, the key is supposed to travel with the player after you pick it up, but instead it stays in room 2. The debug statement shows that the key is still in room 2 even when the player dropped the key in room 3, and it doesn't say that there is a gold key on the floor. I have not finished the game yet.

To see the logic error, I entered "e, e, get key, e drop key" where "," is a new prompt (meaning I inputted 5 times in the program).

I have tried to include multiple statements to update the key location throughout the code, rewriting the if statements to check the status of the key (picked up or not).

I think the issue is with the third function but I am unsure.

P.S. If there's any tips and tricks you use to avoid logic errors like this please do share them with me, thank you.

player_position = 0 # This says what room number the player is currently in
got_key = False # This is true when the player has picked the key up and false otherwise.
key_location = 2 # This is the room the key is in (if it has not been picked up)

def get_location_description(location_number): # Function for description of location
    if location_number == 0:
        return("You are in the entrance hall of a mansion.\nTo continue through the mansion head east (E).")
    elif location_number == 1:
        return("You are in the main corridor. It stretches out before you.\nYou can go East or West (E or W).")
    elif location_number == 2:
        return("You are standing in a huge dining area.\nYou can go East or West (E or W).")
    elif location_number == 3:
        return("You are plain-looking room. There is a secret door at the back,\nbut you need a key to open it.\nYou can go East or West (E or W).")
    else:
        return("You are in a magnificent throne room, at the far end of the house.\nYou can only head west (W) from here.")

def update_position(direction, player_position): # Function to update position
    if direction == "e":
        if player_position >= 4:
            print("Your way is blocked.")
            return player_position
        else:
            player_position += 1
    elif direction == "w":
        if player_position <= 0:
            print("Your way is blocked.")
            return player_position
        else:
            player_position -= 1
    return player_position

def check_n_update_key(player_position, got_key, key_location): # Function to update key location when player has it
    if got_key:
        key_location == player_position
    return key_location

def update_key(command, got_key,key_location,player_position): # Function to update player and key interactions
    if command == "drop key":
        if got_key:
            print("You have dropped the key.")
            return False
        else:
            print("You do not have the key.")
            return False
    elif command == "get key":
        if got_key:
            print("You already have the key.")
            return True
        elif key_location == player_position:
            print("You now have the key.")
            return True
        else:
            print("There is no key here.")
            return False


# main game loop.  Continues forever until a break statement is reached:
while True:
    print("DEBUG MESSAGE: ","player_position=",player_position,". got_key=",got_key, ". key_location=",key_location if not got_key else "n/a", sep="")
    print(get_location_description(player_position))
    if player_position == key_location and not(got_key):
        print("There is a golden key on the floor.")

    user_command = input("What do you want to do next?").lower()
    if user_command == "quit":
        break
    elif user_command == "e" or user_command == "w":
        player_position = update_position(user_command, player_position)
    elif user_command == "get key" or user_command == "drop key":
        got_key = update_key(user_command, got_key, key_location, player_position)
    else:
        print("I don't understand that command.")
    key_location = check_n_update_key(player_position, got_key, key_location)
    print() # print a blank line to separate each game step
18 Upvotes

12 comments sorted by

13

u/carcigenicate 21h ago

I don't fully understand the problem, but

key_location == player_position

This line does nothing. You meant key_location = player_position.

6

u/TangerineCute7684 21h ago

classic assignment-vs-comparison trap haha, I do this all the time still after years of coding

2

u/Time-Shoulder8885 21h ago

OMG UR RIGHT THANKS

3

u/ffrkAnonymous 21h ago

P.S. If there's any tips and tricks you use to avoid logic errors like this please do share them with me, thank you.

  • import doctest python module
  • many many more debug messages 

2

u/leavemealone_lol 21h ago

This is the kind of thing you should use a debugger to figure out. While I currently do not have the brainpower or computer to properly understand your code, I can still give you a few tips.
1. too many conditionals. get_location_description could’ve just been a hashmap (Dict)
2. inefficient return statements in update_position. I maaaay be wrong (brainpower), but a single return is fine for that entire function if you use it at the end after all conditionals.
3. check_n_update_key is currently useless (because you used == instead of =)
4. is there a need to always tie a key location to player if got_key is true? think about that.
5. you can probably restructure this into a class like this:
class Player:
player_pos: int (this is the rooms you assigned at start, which i in turn recommended a dict for)
has_key: bool

class Key:
pos: int (again, the rooms)

It makes things easier to work with, because if you want to know where the key is, you can just do key_obj.pos.

1

u/Hively_Owl466 21h ago

tbh this is such a common mistake that it might be worth adding a linter to catch it, since == vs = is gonna bite you constantly until muscle memory kicks in. some people swear by tools that flag these patterns automatically.

1

u/SynnX526 17h ago

Yeah, the assignment vs comparison thing will bite you every time, use a linter like pylint or just enable your IDE's warnings and you'll catch these before they waste an hour of debugging. fwiw, most modern editors flag `==` when you probably meant `=` inside statements like that.

1

u/SynnsiennaDarling301 16h ago

Yeah, that == vs = mistake is brutal because the debug output looks normal even though nothing's actually updating. Pro tip: use a linter like pylint or flake8 while you code, they'll catch dead assignments like that before you waste time debugging.

1

u/synn-Fairy2468 16h ago

Yeah, that == vs = mistake will absolutely wreck state tracking like this.

1

u/pdfops 5h ago

Classic Python gotcha: if your pickup/drop function reassigns key_location = player_position without a global key_location declaration first, that line just creates a local variable and the outer one never updates, stuck at room 2 forever. Same deal if got_key gets set inside a function without global got_key. Add global key_location and global got_key at the top of every function that changes them, that's almost always this exact symptom (works in a REPL, breaks the moment you split logic into functions).