Retro
Retro

Reputation: 130

Python - creating a building map with a dictionary

I'd like to create a building map of sorts where each room has dictionary containing a north, south, east and west populated from rooms randomly picked from a list (think old school text adventures).

So as an example:

random_rooms = [class_room,hall,entrance]
room_A.directions = {"North":random.choice(random_rooms),"East":random.choice(random_rooms),"South":random.choice(random_rooms),"West":random.choice(random_rooms)}

However, I'd like to populate that so that it matches up as a building would. So if room_A is set first, and has room_B set to the north, then room_B has room_A placed south.

So:

room_A.directions = {"North":room_B,"East":None,"South":None,"West":None}
room_B.directions = {"North":None,"East":None,"South":room_A,"West":None}

I'm not sure what the best way to go about this. I'm not worried about what order things are placed, just as long as a room doesn't end up being both to the North AND South of another room.

Upvotes: 0

Views: 1520

Answers (3)

Nriuam
Nriuam

Reputation: 111

You might want to have a matrix encodes coordinates of roomA, roomB,...etc. In this way their relative location can be defined as-is so you don't need to worry about collisions. For example:

import numpy as np

rooms = np.arange(4)  # 0, 1, 2, 3 stands for 4 rooms/roometypes/whatever
room_arrangement = np.random.shuffle(tmp).reshape(2,2)  # reshape into a 2x2 grid

Rooms allocated into room_arrangement, use the numbers to refer to room objects or strings. If you need the rooms be arrange sparsely i.e. they can scatter to anywhere, plug some 0 into the rooms array, and change the next line to reshape(m, n) where m*n==np.sum(rooms.shape).

btw it's a good idea to check out how people model Go game as matrices. Basics are the same as above: 1) define the ground board you are going to work on, 2) plug labels into the ground board, 3)when necessary, link the labels to objects you are interested in (simple case: dictionary, dataframe entries; slight complicated case: define classes). Generally data are encoded in the matrices, and dictionary/class instances handle the metadata/special rules part.

Upvotes: 1

Westly White
Westly White

Reputation: 559

This seems like a great time to start using classes. With a class you will be able to handle whats connected to each room, and through which direction. Heres a simple example.

class Room(object):
    def __init__(self, name=None):
        self.name = str(name)
        self.matching_direction = { "N": "S", "S": "N", "W": "E", "E": "W"}
        self.open_walls = ["N", "S", "E", "W"]
        self.connected_rooms = {}

    def connect_room(self, room_obj=None, room_obj_exit=None):
        """
        Connect two rooms if able.
        Params:
            room_obj: Room(Object)
            room_obj_exit: Direction(String)
        Return: Bool
        """
        try:
            opposite_direction = self.matching_direction[room_obj_exit]

            if opposite_direction not in self.open_walls:
                print "{} door is occupied by {}".format(opposite_direction, self.connected_rooms[opposite_direction].name)
                return False

            if room_obj_exit not in room_obj.open_walls:
                print "{} is occupied by {}".format(room_obj_exit, room_obj.connected_rooms[room_obj_exit].name)
                return False

            self.connected_rooms[opposite_direction] = room_obj
            room_obj.connected_rooms[room_obj_exit] = self
            self.open_walls.remove(opposite_direction)
            room_obj.open_walls.remove(room_obj_exit)
            return True

        except Exception as e:
            print e
        return False

    def explore_door(self, direction=None):
        """
        Try to move to another Room
        Return : Room(Object)
        """
        try:
            if direction in self.connected_rooms:
                print "The {} Door is open to {}".format(direction, self.connected_rooms[direction].name)
                return self.connected_rooms[direction]
            else:
                print "The {} Door is locked".format(direction)
        except Exception as e:
            print e
        return False

Here some usage:

room_one = Room(name="Room One")
room_two = Room(name="Room Two")
room_three = Room(name="Room Three")

room_one.connect_room(room_obj=room_two, room_obj_exit="N")
room_two.connect_room(room_obj=room_three, room_obj_exit="E")
room_three.connect_room(room_obj=room_one, room_obj_exit="S")

room_one.explore_door(direction="N")
room_one.explore_door(direction="S")
room_one.explore_door(direction="E")
room_one.explore_door(direction="W")

Output:

S is occupied by Room Two
The N Door is locked
The S Door is open to Room Two
The E Door is locked
The W Door is locked

Upvotes: 0

Roy Folkker
Roy Folkker

Reputation: 427

It sounds like what you are actually looking for is more of a coordinate mapping system than a directional map. For this you want to create a grid array. Your array would then consist of your layout (e.g. a 4x4 grid area could either be a 4x4 matrix, or a simple 16 unit array).

Assuming an #x# matrix:

If room[0][3] = random.choice(random_rooms) your only concern would be to make sure that all rooms are connected (add a pass filter to go back over and if [0][0] for example == a valid room, than [0][1] must, or [1][0] must, which would fill in the gaps connecting all rooms.

Upvotes: 0

Related Questions