Levels are one of the most common things in roguelikes. Yet, there are different ways of representing them, each with their own advantages and disadvantages. This post shows how they are implemented in pyherc.
Floors and walls are implemented as lists of list (essentially modelling a two dimensional array). Each cell contains an ID of tile that should be displayed there. If a wall tile is None, then there is no wall there and creatures can move in that tile (unless something else prevents it, of course). It would be possible to combine these two things together, since the floor is not visible from below walls. However, that would require to somehow code where characters may move and where the walls would block them.
Ornamentation are all those little details and trinkets that don’t have any direct effect on the game play. Currently torches on the wall are the only example of this type of items, but in the future more will be added (dirt and stones on floors, cracks on walls, moss growing here and there and so on). They are stored in a similar data structure as walls and floors and handled in the same way. They are on a separate data structure, because most of them contain see through portions that reveal the tile (be it floor or wall) beneath of them.
Items and creatures are both stored in their respective lists and drawn on top of other tiles. The difference here is that while walls have a two dimensional data structure that has a reserved space for each location, items and creatures are simple lists. Amount of objects in each list is relatively small and each element can hold its own information about the location. Checking whether some specific location contains an item or a creature is a bit slower, but so is memory consumption too (not that either one of those really matter in a modern computer).
Last data structure contains portals (usually stairs) and it is handled in the similar manner than items and creatures. The biggest difference is that content of this list is never drawn on screen. The stairs shown on the image above are actually stored on the floor data structure. I made this choice, because it makes it much easier to place that small border around the stairs that is shown in the picture. The routine that does that is the same routine that handles the border that runs alongside of the walls.
Portals are used when player tries to descent stairs. The engine checks if there are an object in portals list that has the same location as the player. If such an portal is found, then player is moved to a new level and new location within that level (required data is stored in the Portal object).
Mostly Level objects in pyherc are just lists and more lists. Levels are then linked together via Portals and form a treelike graph. There is also a portal that has a special flag turned on. If player ascends these stairs, he leaves the dungeon and the game ends.