Python Forum

Full Version: Using classes for room movement (text game)
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello again. This time, I'm using a class to define different rooms, but am having trouble moving between them whenever I run the program:
class Rooms:

    def __init__(self, name, desc, co_x, co_y, directions):
        self.name = name
        self.desc = desc
        self.co_x = co_x
        self.co_y = co_y
        self.loc = (self.co_x, self.co_y)
        self.directions = directions

    def __str__(self):
        return f' {self.name}, {self.desc}, {self.co_x}, {self.co_y}'


room1 = Rooms('Room1', 'the first room', 0, 0, ['north', 'east',])
room2 = Rooms('Room2', 'the second room', 0, 1, ['south',])

current_room = room1


while True:
    command = input('Enter a command: ')
    print(current_room)
    if current_room.loc == (0, 0):
        current_room = room1
    if current_room.loc == (0, 1):
        current_room = room2
    if command in current_room.directions:
        if command == 'north':
            current_room.co_y = current_room.co_y + 1
I was hoping that when I changed the current_room.co_y by adding 1, the program would check current_room.loc and see that it had changed to (0, 1), but that isn't the case. Is there an easier, or more efficient way to set this up? I've been searching around and found a text rpg tutorial but I don't want to copy the tutorial's code since I won't learn anything that way. I understand that the program is just adding one to the current room's y value every time the command is 'north'. However, I want it to change to a different room via the location each time the command is inputted, if there is a room in that direction.
One thing to do is store them by coordinate in a dictionary. You can even do this as a class attribute and automate it with __init__:

class Rooms:

    map = {}
 
    def __init__(self, name, desc, co_x, co_y, directions):
        self.name = name
        self.desc = desc
        self.co_x = co_x
        self.co_y = co_y
        self.loc = (self.co_x, self.co_y)
        Rooms.map[self.loc] = self
        self.directions = directions
 
    def __str__(self):
        return f' {self.name}, {self.desc}, {self.co_x}, {self.co_y}'
Now you get the current room from the dictionary, and move around based on that:

current_room = Rooms.map[(0, 0)]
while True:
    print(current_room.name)
    print(current_room.desc)
    command = input('Enter a command: ')
    if command in current_room.directions:
        loc = current_room.loc
        if command == 'north':
             current_room = Rooms.map[(loc[0], loc[1] + 1)]
        ...
If the tutorial you found isn't the one I wrote, I not so humbly suggest your read mine (link below in my signature).
Alright, so let me restructure your question, to make sure I understand it right.

Given this code:
class Room:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.loc = (x, y)

room_1 = Room(0, 0)
print(room_1.loc)
room_1.y += 1
print(room_1.loc)
...why is the same tuple printed twice? Or, why didn't the change to the y variable also change the loc variable?

The loc variable is created with copies of the x/y variables, not references to them. So changes to the x/y variables will not effect the loc.

The easy way to fix this, is to use a method to return the current location:
    def get_loc(self):
        return (self.x, self.y)
The other option would be to use objects to store positioning, instead of primitive types (like an int). That would look something like this:
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def get_loc(self):
        return (self.x, self.y)

    def __str__(self):
        return "Point: ({0}, {1})".format(self.x, self.y)

class Room:
    def __init__(self, x, y):
        self.loc = Point(x, y)

room_1 = Room(0, 0)
print(room_1.loc)
room_1.loc.y += 1
print(room_1.loc)
(Aug-19-2019, 07:02 PM)nilamo Wrote: [ -> ]Alright, so let me restructure your question, to make sure I understand it right.

Given this code:
class Room:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.loc = (x, y)

room_1 = Room(0, 0)
print(room_1.loc)
room_1.y += 1
print(room_1.loc)
...why is the same tuple printed twice? Or, why didn't the change to the y variable also change the loc variable?

The loc variable is created with copies of the x/y variables, not references to them. So changes to the x/y variables will not effect the loc.

The easy way to fix this, is to use a method to return the current location:
    def get_loc(self):
        return (self.x, self.y)
The other option would be to use objects to store positioning, instead of primitive types (like an int). That would look something like this:
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def get_loc(self):
        return (self.x, self.y)

    def __str__(self):
        return "Point: ({0}, {1})".format(self.x, self.y)

class Room:
    def __init__(self, x, y):
        self.loc = Point(x, y)

room_1 = Room(0, 0)
print(room_1.loc)
room_1.loc.y += 1
print(room_1.loc)

Thanks nilamo, you answered a few questions of mine. :) I hadn't taken into consideration that the loc variable just copied the x and y vars and left it at that. I'll probably use both your method and Ichabod's to make a more expanded piece of code, and then move on to more complicated practices for learning purposes ^^

(Aug-19-2019, 06:59 PM)ichabod801 Wrote: [ -> ]One thing to do is store them by coordinate in a dictionary. You can even do this as a class attribute and automate it with __init__:

class Rooms:

    map = {}
 
    def __init__(self, name, desc, co_x, co_y, directions):
        self.name = name
        self.desc = desc
        self.co_x = co_x
        self.co_y = co_y
        self.loc = (self.co_x, self.co_y)
        Rooms.map[self.loc] = self
        self.directions = directions
 
    def __str__(self):
        return f' {self.name}, {self.desc}, {self.co_x}, {self.co_y}'
Now you get the current room from the dictionary, and move around based on that:

current_room = Rooms.map[(0, 0)]
while True:
    print(current_room.name)
    print(current_room.desc)
    command = input('Enter a command: ')
    if command in current_room.directions:
        loc = current_room.loc
        if command == 'north':
             current_room = Rooms.map[(loc[0], loc[1] + 1)]
        ...
If the tutorial you found isn't the one I wrote, I not so humbly suggest your read mine (link below in my signature).

Your tutorial (and some old MUD's) was my inspiration to make a more complicated version of a text-based rpg, for learning purposes of course. Your response was very informative, I had no clue one could use a dictionary within a class object to automate some processes. I'll grind this information into memory, thanks again!!

p.s Your tutorial is VERY useful for newbie programmers like myself to learn the ropes to some basic python practices, excellent work!