# Adding room coordinates in your game
- An object can be in a location, that is, another object. Like an exit in a room.
- An object can access its content. A room can see what objects uses it as location (that would include exits, rooms, characters and so on).
Some additional searches¶
Having coordinates is useful for several reasons:
- It can help in shaping a truly logical world, in its geography, at least.
- It can allow to look for specific rooms at given coordinates.
- It can be good in order to quickly find the rooms around a location.
- It can even be great in path-finding (finding the shortest path between two rooms).
Roomtypeclass. These methods will just be search methods. Notice that they are
Finding one room¶
First, a simple one: how to find a room at a given coordinate? Say, what is the room at X=0, Y=0, Z=0?
class Room(DefaultRoom): # ... @classmethod def get_room_at(cls, x, y, z): """ Return the room at the given location or None if not found. Args: x (int): the X coord. y (int): the Y coord. z (int): the Z coord. Return: The room at this location (Room) or None if not found. """ rooms = cls.objects.filter( db_tags__db_key=str(x), db_tags__db_category="coordx").filter( db_tags__db_key=str(y), db_tags__db_category="coordy").filter( db_tags__db_key=str(z), db_tags__db_category="coordz") if rooms: return rooms return None
Room.get_room_at(5, 2, -3)
Notice that this is a class method: you will call it from
class), not an instance. Though you still can:
@py here.get_room_at(3, 8, 0)
Finding several rooms¶
from math import sqrt class Room(DefaultRoom): # ... @classmethod def get_rooms_around(cls, x, y, z, distance): """ Return the list of rooms around the given coordinates. This method returns a list of tuples (distance, room) that can easily be browsed. This list is sorted by distance (the closest room to the specified position is always at the top of the list). Args: x (int): the X coord. y (int): the Y coord. z (int): the Z coord. distance (int): the maximum distance to the specified position. Returns: A list of tuples containing the distance to the specified position and the room at this distance. Several rooms can be at equal distance from the position. """ # Performs a quick search to only get rooms in a square x_r = list(reversed([str(x - i) for i in range(0, distance + 1)])) x_r += [str(x + i) for i in range(1, distance + 1)] y_r = list(reversed([str(y - i) for i in range(0, distance + 1)])) y_r += [str(y + i) for i in range(1, distance + 1)] z_r = list(reversed([str(z - i) for i in range(0, distance + 1)])) z_r += [str(z + i) for i in range(1, distance + 1)] wide = cls.objects.filter( db_tags__db_key__in=x_r, db_tags__db_category="coordx").filter( db_tags__db_key__in=y_r, db_tags__db_category="coordy").filter( db_tags__db_key__in=z_r, db_tags__db_category="coordz") # We now need to filter down this list to find out whether # these rooms are really close enough, and at what distance # In short: we change the square to a circle. rooms =  for room in wide: x2 = int(room.tags.get(category="coordx")) y2 = int(room.tags.get(category="coordy")) z2 = int(room.tags.get(category="coordz")) distance_to_room = sqrt( (x2 - x) ** 2 + (y2 - y) ** 2 + (z2 - z) ** 2) if distance_to_room <= distance: rooms.append((distance_to_room, room)) # Finally sort the rooms by distance rooms.sort(key=lambda tup: tup) return rooms
This gets more serious.
- We have specified coordinates as parameters. We determine a broad range using the distance. That is, for each coordinate, we create a list of possible matches. See the example below.
- We then search for the rooms within this broader range. It gives us a square around our location. Some rooms are definitely outside the range. Again, see the example below to follow the logic.
- We filter down the list and sort it by distance from the specified coordinates.
An example might help. Consider this very simple map (a textual description follows):
4 A B C D 3 E F G H 2 I J K L 1 M N O P 1 2 3 4
The X coordinates are given below. The Y coordinates are given on the left. This is a simple square with 16 rooms: 4 on each line, 4 lines of them. All the rooms are identified by letters in this example: the first line at the top has rooms A to D, the second E to H, the third I to L and the fourth M to P. The bottom-left room, X=1 and Y=1, is M. The upper-right room X=4 and Y=4 is D.
So let’s say we want to find all the neighbors, distance 1, from the room J. J is at X=2, Y=2.
So we use:
Room.get_rooms_around(x=2, y=2, z=0, distance=1) # we'll assume a z coordinate of 0 for simplicity
- First, this method gets all the rooms in a square around J. So it gets E F G, I J K, M N O. If you want, draw the square around these coordinates to see what’s happening.
- Next, we browse over this list and check the real distance between J (X=2, Y=2) and the room. The four corners of the square are not in this circle. For instance, the distance between J and M is not 1. If you draw a circle of center J and radius 1, you’ll notice that the four corners of our square (E, G, M and O) are not in this circle. So we remove them.
- We sort by distance from J.
So in the end we might obtain something like this:
[ (0, J), # yes, J is part of this circle after all, with a distance of 0 (1, F), (1, I), (1, K), (1, N), ]
You can try with more examples if you want to see this in action.