Kurt Ferrier
Kurt Ferrier

Reputation: 73

Better way to check every instance of a class?

So I have been trying to figure out how classes and instances work in python for a bit, and have been making a text based game to try and learn about it firsthand.

I know that having to repeat yourself usually means you're doing something wrong, but I just can't figure out what to do. My code looks like this:

win = False
class Rooms(object):

  walls = 4

  def __init__(self, command, desc, secret, x, y):
    self.command = command
    self.desc = desc
    self.secret = secret
    self.x = x
    self.y = y

desc is the description of the room, command is the word you use to access the room, secret is extra information about the room, and x and y is the rooms place on the xy axis

  def check(self):
    if action == self.command:
      player.move_x(self.x)
      player.move_y(self.y)
    if self.x == player.x and self.y == player.y:
      print(self.desc)

I've been struggling with this particularly, as I need it to check the command to see how much x and y spaces it needs to move, but if I also need to check if the players position matches the rooms position on the xy axis.

If I put them in together, then the rooms description only prints when you input the specific command, so an interaction would be: 'start of game text' '> north' 'north room description' '> north' '' 'south' ''

Even though logically you would be in the north room from where you started. By having it the way it is, it causes other problems though.

class Player(object):

  def __init__(self, x, y):
    self.x = x
    self.y = y

  def move_x(self, new_x):
    self.x = self.x + new_x

  def move_y(self, new_y):
    self.y = self.y + new_y

player = Player(0, 0)
default_room = Rooms('start', '...', '...', 0, 0)
north_room = Rooms('north', '...', '...', 0, 1)
south_room = Rooms('south', '...', '...', 0, -1)
west_room = Rooms('west', '...', '...', -1, 0)
east_room = Rooms('east', '...', '...', 1, 0)

print(default_room.desc)
action = input('> ')
while not win:
  north_room.check()
  south_room.check()
  west_room.check()
  east_room.check()
  default_room.check()
  print(player.x, player.y)
  action = input('> ')

As said earlier, with the way checking works, the program works like: 'start of game stuff' '> north' 'north room description' 'south' 'north room description' 'starting room description'

Because the program always checks.north before south, so it sees it is on the same place as the north room and puts out the north description, and then when checking south it actually moves it to the correct place.

A last thing, I know that using the rooms actual position as the basis for moving the player isn't going to work because once you get a room such as 0, -2, then leaving it would bring you back to the start.

Sorry if I asked too many questions it's just I don't know where to start.

My solution: I added all of the instances of Rooms (renamed to 'Room') to a list, and iterated over that list, checking if the instances x and y values matched the players, e.g:

for room in list_of_rooms:
   if room.x == player.x and room.y == player.y:
     print(room.description)

Upvotes: 1

Views: 132

Answers (1)

stovfl
stovfl

Reputation: 15513

Question: ... check every instance of a class?

Instead of checking all Rooms in the main Loop,
as a Player could only in one Room, hold a Reference off the actual Room in class Player.

Note: In this Example you could't leave a Room, as no Doors implemented.

Consider the following:

class Room(object):
    DIMENSION = (5, 5)

    def __init__(self, name):
        self.name = name
        self.pos = (0, 0)

    def __str__(self):
        return self.name

    def move(self, _move):
        _pos = (self.pos[0] + _move[0], self.pos[1] + _move[1])
        if abs(_pos[0]) == Room.DIMENSION[0] or abs(_pos[1]) == Room.DIMENSION[1]:
            return False
        self.pos = _pos
        return True

class House(object):
    def __init__(self, start_room=0):
        self.rooms = [Room('Hall'), 
                      Room('Room-1 North'), Room('Room-2 East'),
                      Room('Room-3 South'), Room('Room-4 West')]
        self.room = self.rooms[start_room]

    def move(self, _move):
        if not self.room.move(_move):
            print('Move imposible, you reached the wall!'.format())
        return self.room

class Player(object):
    def __init__(self, name, house):
        self.name = name
        self.house = house
        self.room = self.house.room()

    def move(self, _move):
        self.room = self.house.move(_move)

if __name__ == '__main__':
    player = Player('Player-1', House(start_room=0))
    while True:
        print('{}: You are in {} at Position:{}'.format(player.name, player.room, player.room.pos))
        action = input('Move to (north, east, south, west)> ')
        if action in ["north", "east", "south", "west"]:
            player.move({'north': (1, 0), 'east': (0, 1), 'south': (-1, 0), 'west': (0, -1)}[action])
        elif action == 'break':
            break
        else:
            print('Unknown Action? {}'.format(action))

Output:

Player-1: You are in Hall at Position:(4, 0)
Move to (north, east, south, west)> north
Move imposible, you reached the wall!
Player-1: You are in Hall at Position:(4, 0)
Move to (north, east, south, west)> south
Player-1: You are in Hall at Position:(3, 0)
Move to (north, east, south, west)> break

Upvotes: 1

Related Questions