See also the [Mapbuilder](../Contribs/Contrib-Mapbuilder.md) and [XYZGrid](../Contribs/Contrib-XYZGrid.md) contribs, which offer alternative ways of both creating and displaying room maps. The [Beginner Tutorial lesson implementing Evadventure rooms](https://www.evennia.com/docs/latest/Howtos/Beginner-Tutorial/Part3/Beginner-Tutorial-Rooms.html#adding-a-room-map) also explains how to add a (simpler) auto-map.
1. The structure of your mud has to follow a logical layout. Evennia supports the layout of your world to be 'logically' impossible with rooms looping to themselves or exits leading to the other side of the map. Exits can also be named anything, from "jumping out the window" to "into the fifth dimension". This tutorial assumes you can only move in the cardinal directions (N, E, S and W).
2. Rooms must be connected and linked together for the map to be generated correctly. Vanilla Evennia comes with a admin command [tunnel](evennia.commands.default.building.CmdTunnel) that allows a user to create rooms in the cardinal directions, but additional work is needed to assure that rooms are connected. For example, if you `tunnel east` and then immediately do `tunnel west` you'll find that you have created two completely stand-alone rooms. So care is needed if you want to create a "logical" layout. In this tutorial we assume you have such a grid of rooms that we can generate the map from.
Before getting into the code, it is beneficial to understand and conceptualize how this is going to work. The idea is analogous to a worm that starts at your current position. It chooses a direction and 'walks' outward from it, mapping its route as it goes. Once it has traveled a pre-set distance it stops and starts over in another direction. An important note is that we want a system which is easily callable and not too complicated. Therefore we will wrap this entire code into a custom Python class (not a typeclass as this doesn't use any core objects from evennia itself). We are going to create something that displays like this when you type 'look':
First we must define the components for displaying the map. For the "worm" to know what symbol to draw on the map we will have it check an Attribute on the room it visits called `sector_type`. For this tutorial we understand two symbols - a normal room and the room with us in it. We also define a fallback symbol for rooms without said Attribute - that way the map will still work even if we didn't prepare the room correctly. Assuming your game folder is named `mygame`, we create this code in `mygame/world/map.py.`
-`self.max_width/length` determine the max width and length of the map that will be generated. Note that it's important that these variables are set to *odd* numbers to make sure the display area has a center point.
-` self.worm_has_mapped` is building off the worm analogy above. This dictionary will store all rooms the "worm" has mapped as well as its relative position within the grid. This is the most important variable as it acts as a 'checker' and 'address book' that is able to tell us where the worm has been and what it has mapped so far.
Before any sort of mapping can actually be done we need to create an empty display area and do some sanity checks on it by using the following methods.
Before we can set our worm on its way, we need to know some of the computer science behind all this called 'Graph Traversing'. In Pseudo code what we are trying to accomplish is this:
-`max_distance` is a variable indicating to our Worm how many rooms AWAY from your current location will it map. Obviously the larger the number the more time it will take if your current location has many many rooms around you.
The first hurdle here is what value to use for 'max_distance'. There is no reason for the worm to travel further than what is actually displayed to you. For example, if your current location is placed in the center of a display area of size `max_length = max_width = 9`, then the worm need only
The `max_distance` can be set dynamically based on the size of the display area. As your width/length changes it becomes a simple algebraic linear relationship which is simply `max_distance = (min(max_width, max_length) -1) / 2`.
Obviously this method of generating maps doesn't take into account of any doors or exits that are hidden.. etc.. but hopefully it serves as a good base to start with. Like previously mentioned, it is very important to have a solid foundation on rooms before implementing this. You can try this on vanilla evennia by using @tunnel and essentially you can just create a long straight/edgy non- looping rooms that will show on your in-game map.
The above example will display the map above the room description. You could also use an [EvTable](github:evennia.utils.evtable) to place description and map next to each other. Some other things you can do is to have a [Command](../Components/Commands.md) that displays with a larger radius, maybe with a legend and other features.
Below is the whole `map.py` for your reference. You need to update your `Room` typeclass (see above) to actually call it. Remember that to see different symbols for a location you also need to set the `sector_type` Attribute on the room to one of the keys in the `SYMBOLS` dictionary. So in this example, to make a room be mapped as `[.]` you would set the room's `sector_type` to `"SECT_INSIDE"`. Try it out with `@set here/sector_type = "SECT_INSIDE"`. If you wanted all new rooms to have a given sector symbol, you could change the default in the `SYMBOLS` dictionary below, or you could add the Attribute in the Room's `at_object_creation` method.