Temple of The Roguelike Forums

Development => Programming => Topic started by: Robson on September 17, 2007, 12:16:30 AM

Title: Messing with dungeon generation
Post by: Robson on September 17, 2007, 12:16:30 AM
I've been working on a dungeon generator, so I thought I'd share what I've done so far.

Here's a load of examples (http://iceyboard.no-ip.org/stuff/dungeons.html).
Here's a screenshot of the application (http://iceyboard.no-ip.org/stuff/dungenerator.png).

Most of the examples are intentionally far bigger than I would use in a real game, because it's easier for me to test with larger maps and more stuff can be seen.

It's written in Visual Basic 6 in about 1,500 lines of code. The steps go like this:

1. Generate a perfect maze, which is a maze where every square can reach every other, with no loops. (image (http://iceyboard.no-ip.org/stuff/dg1.png))
2. Depending on the size of the area, we may allocate some large spaces for mazes, caves or prisons. The bigger the area, the higher than chance of more being created. (image (http://iceyboard.no-ip.org/stuff/dg2.png))
3. Overlay lots of rooms. 10% are circular. 90% are rectangular. Rectangular rooms may have additional bits carved out of the corners of them to make them less boring. (image (http://iceyboard.no-ip.org/stuff/dg3.png))
4. All dead ends are removed. (image (http://iceyboard.no-ip.org/stuff/dg4.png))
5. Doors are added everywhere that a corridor meets a room. (image (http://iceyboard.no-ip.org/stuff/dg5.png))
6. Any corridors that loop back to the room they exited from are removed. (image (http://iceyboard.no-ip.org/stuff/dg6.png))
7. If two rooms have multiple non-intersecting corridors between them, all but one is removed. (image (http://iceyboard.no-ip.org/stuff/dg7.png))
8. The contents of the special rooms is created. (image (http://iceyboard.no-ip.org/stuff/dg8.png))
9. Corridors are shortened. (image (http://iceyboard.no-ip.org/stuff/dg9.png))

The basic code is almost complete, except for two things. The first is that only some corridors get shortened. Intersection-to-intersection and intersection-to-cave corridors aren't shortened yet, because the shortening code uses doors to find the corridors. The second is that the flood fill code needs to be rewritten from the first method here (http://en.wikipedia.org/wiki/Flood_fill) to one of the others.

Once the dungeon generator is done and optimised, I can work out the purpose of each room (wizards lab, barracks, food store, shop, creature lair, etc). Then I just need to make the creatures, magic, items, combat, high scores, inventory, gods, interface, minimap, quickbar, skills, conducts, ai, difficulty levels, harvesting, story...
Title: Re: Messing with dungeon generation
Post by: edexter on September 17, 2007, 04:42:05 AM
that could be realy intresting as a command like tool to make it program independent...  I am writing something to take a maze from disk and load it into a 2d array...  checking for varous items like # exc... when I place monsters exc..
Title: Re: Messing with dungeon generation
Post by: Slash on September 20, 2007, 02:30:57 PM
That dungeon generator looks pretty cool! results are neither completely organic nor blocky... how are you generating cave rooms? are they templates, CA or L jumps? also, I didnt see the circular rooms in the example image?

My current approach to dungeon generation is completely different, classic room carving, which has many problems including tree-like levels without loops, no branches in corridors for now... a start is a start though.. Up to now I have done mostly cave-like levels and overworlds, which generation follows very different principles than dungeon carving :D

Is this for Paprika? English gentlemen seem to be pretty profficient on dungeon generation ;)
Title: Re: Messing with dungeon generation
Post by: Robson on September 20, 2007, 07:30:52 PM
That dungeon generator looks pretty cool!
Thanks Slash!

Quote from: Slash
results are neither completely organic nor blocky... how are you generating cave rooms? are they templates, CA or L jumps?
I used this excellent cellular automata tutorial: http://www.pixelenvy.ca/wa/ca_cave.html I haven't tried L jumps, I'll have to give that a try to see what it looks like.

Quote from: Slash
also, I didnt see the circular rooms in the example image?
Ha! "Circular" is a bit of an exaggeration! They are sort of circles made of squares. Like this:


    #####
    #...#
  ###...###
  #.......#
###.......###
+...........#
#...........#
#...........#
###.......###
  #.......#
  ###...#+#
    #...#
    #####   


I'll make them a bit rounder at some point :)

Quote from: Slash
My current approach to dungeon generation is completely different, classic room carving, which has many problems including tree-like levels without loops, no branches in corridors for now... a start is a start though.. Up to now I have done mostly cave-like levels and overworlds, which generation follows very different principles than dungeon carving :D

I really like your map/overworld generator (http://www.roguetemple.com/forums/index.php?topic=29.msg160#msg160). Very cool.

Quote from: Slash
Is this for Paprika?
I've been planning a new roguelike to replace Paprika. I learnt a lot from writing Paprika, so I feel with that knowledge I can create a better roguelike. I really want to change a lot of fundamental things, so a new project seems to be the best way to go. I'm not calling it a rewrite, because I want to change a lot of ways that the game would work, rather than the code. In fact, I can use a lot of the code from Paprika in the new project.

One of my ideas is to build everything completely seperately, because I feel that the connections between all the different systems is where things quickly get complicated. So building things seperately allows me to avoid that and really focus on each one. It doesn't matter too much if I change my mind about something, because it's a lot easier to rewrite one system than one system connected to a lot of other ones. This dungeon generator is one of those systems.

But I won't go on too much, because I don't want to sound like another vapourware creator!

Quote from: Slash
English gentlemen seem to be pretty profficient on dungeon generation ;)
Aye, it's going to replace received-pronunciation as the number one English stereotype :P
Title: Re: Messing with dungeon generation
Post by: corremn on September 21, 2007, 02:39:15 AM
One of my ideas is to build everything completely seperately, because I feel that the connections between all the different systems is where things quickly get complicated. So building things seperately allows me to avoid that and really focus on each one. It doesn't matter too much if I change my mind about something, because it's a lot easier to rewrite one system than one system connected to a lot of other ones. This dungeon generator is one of those systems.

Eeek, this way madness lies, just joking ;D. This is one of the first things any programmer says to himself, it is much easier said that done.  Time to get the sketch pad out and start drawing how your modules will interact, try to think about every way needed.  Good luck with this, I hope it goes well.
Title: Re: Messing with dungeon generation
Post by: Ex on September 21, 2007, 05:12:04 PM
How are you deciding on the initial locations to place your rooms? Are you dividing the map initially into sections based on some algorithm, or are your rooms placed by other means? If you don't mind my curiosity.
Title: Re: Messing with dungeon generation
Post by: Robson on September 21, 2007, 07:17:01 PM
One of my ideas is to build everything completely seperately
Eeek, this way madness lies, just joking ;D. This is one of the first things any programmer says to himself, it is much easier said that done.  Time to get the sketch pad out and start drawing how your modules will interact, try to think about every way needed.  Good luck with this, I hope it goes well.
Thanks for the advice corremn. I've written a load of stuff about how I want the game to work, but haven't put too much thought into the code yet. I'm still in the designing stage really and just testing code out for now. I'll do your sketch pad idea when the designing is finished :)

How are you deciding on the initial locations to place your rooms? Are you dividing the map initially into sections based on some algorithm, or are your rooms placed by other means? If you don't mind my curiosity.
I welcome the curiousity, that's why I posted about this ;)

The locations are decided quite simply really. I select a random height and width, which must be an odd number from 3 to 7. Then a random tile is selected from the whole area. A check is made to see if it would overlap with another room. If not, the rectangular room is created. After that a random number of corners are also removed to create more interestingly shaped rooms. When enough rooms have been created, the generating moves along to the next bit.

This part of the code is very fast, the biggest layouts on the examples page take less than 0.02 seconds to select all the locations and create the rooms.
Title: Re: Messing with dungeon generation
Post by: Slash on September 24, 2007, 09:23:26 PM
I used this excellent cellular automata tutorial: http://www.pixelenvy.ca/wa/ca_cave.html I haven't tried L jumps, I'll have to give that a try to see what it looks like.
Ah! I remember the Wa project... a shame it seems to be dead now... IIRC it was one of the few to be developed by a female roguedev

I'll make them a bit rounder at some point :)
They look cool like this :)

I've been planning a new roguelike to replace Paprika. I learnt a lot from writing Paprika, so I feel with that knowledge I can create a better roguelike. I really want to change a lot of fundamental things, so a new project seems to be the best way to go. I'm not calling it a rewrite, because I want to change a lot of ways that the game would work, rather than the code. In fact, I can use a lot of the code from Paprika in the new project.
Yeah, I know how that feels... I hope being able to restart Guardian Angel soon with all I have learned with the rest of projects! (But I won't go on too much, because I don't want to sound like another vapourware creator!)

One of my ideas is to build everything completely seperately, because I feel that the connections between all the different systems is where things quickly get complicated. So building things seperately allows me to avoid that and really focus on each one. It doesn't matter too much if I change my mind about something, because it's a lot easier to rewrite one system than one system connected to a lot of other ones. This dungeon generator is one of those systems.
Ah, thats true... as long as you keep your heading into your GAME direction, and not a generic engine :)
Title: Re: Messing with dungeon generation
Post by: Robson on September 25, 2007, 05:59:38 PM
Quote from: Slash
Quote from: Icey
I used this excellent cellular automata tutorial: http://www.pixelenvy.ca/wa/ca_cave.html I haven't tried L jumps, I'll have to give that a try to see what it looks like.
Ah! I remember the Wa project... a shame it seems to be dead now... IIRC it was one of the few to be developed by a female roguedev
Aye, that's a shame. A little bit more diversity would have been cool.

I had a go with the L jumps though:
http://iceyboard.no-ip.org/stuff/dungeons_l_caves.html (http://iceyboard.no-ip.org/stuff/dungeons_l_caves.html)

The results are interesting and look different to the CA method. I think I'll include both the cellular-automata generator and the l-jump generator, with a 50/50 chance of each being used.

Quote from: Slash
Quote from: Icey
I'll make them a bit rounder at some point :)
They look cool like this :)
Cool. Maybe I'll include both... oh the possibilities!

Quote from: Slash
I hope being able to restart Guardian Angel soon with all I have learned with the rest of projects! (But I won't go on too much, because I don't want to sound like another vapourware creator!)
Heh that sounds like something I'd say! Oh, wait a minute...

I think that's a great idea though. I'm always seeing people talk about your roguelikes, so adding another one will ensure they never shut up :P

Quote from: Slash
Ah, thats true... as long as you keep your heading into your GAME direction, and not a generic engine :)
Oh yes. Most definitely. I'm not interesting in making an engine.
Title: Re: Messing with dungeon generation
Post by: Slash on September 26, 2007, 06:30:23 PM
I had a go with the L jumps though:
http://iceyboard.no-ip.org/stuff/dungeons_l_caves.html (http://iceyboard.no-ip.org/stuff/dungeons_l_caves.html)

The results are interesting and look different to the CA method. I think I'll include both the cellular-automata generator and the l-jump generator, with a 50/50 chance of each being used.
Yeah, they look much less organic while still being irregular... perhaps would be nice for some kind of "crystal" caves or erosion-less environment.

I think that's a great idea though. I'm always seeing people talk about your roguelikes, so adding another one will ensure they never shut up :P
Hehe
Title: Re: Messing with dungeon generation
Post by: Krice on October 21, 2007, 08:28:04 PM
My approach to dungeon generation is quite similar to what Icey has. At the moment I'm re-factoring corridor routine so that it can handle connections to what I call "strict" rooms (that don't overlap with other rooms or structures) and cave style overlapping rooms. Previously I had problems how to accurately find walls from irregular rooms, but then I made a mask map and marked rooms with different directions and also corners.

I have an example pic to show (a mask map of level). It has three types of rooms: irregular rooms which some of them overlap with each other creating bigger areas, and "strict" rectangular rooms plus small rooms which attach themselves directly to other rooms and corridors. There are no corridors yet, because the old routine can't handle connections between different types of rooms...

http://koti.mbnet.fi/paulkp/temp/rooms.gif
Title: Re: Messing with dungeon generation
Post by: Ex on October 22, 2007, 11:18:22 AM
Quote
I have an example pic to show (a mask map of level). It has three types of rooms: irregular rooms which some of them overlap with each other creating bigger areas, and "strict" rectangular rooms plus small rooms which attach themselves directly to other rooms and corridors. There are no corridors yet, because the old routine can't handle connections between different types of rooms...

http://koti.mbnet.fi/paulkp/temp/rooms.gif
That looks really good.
Title: Re: Messing with dungeon generation
Post by: beam on October 23, 2007, 04:32:10 PM
Icey, image #9 (http://iceyboard.no-ip.org/stuff/dg9.png) looks really good. I hope I'll get to play in something like it at some point
Title: Re: Messing with dungeon generation
Post by: valianjuan on October 23, 2007, 05:46:42 PM
These are nice!  I like the variety!
So far I have a simple but effective algorithm.

Make the grid entirely unwalkable.
Check the grid area's size, and choose how many rooms you want to put in.
For each room:
  make a room at a valid random point (save the point)
  Connect point 1 to 2, 2 to 3, etc..., n to 1

Now you have rooms all over that are all connected.  You can change what your rooms look like or the connection algorithm that makes the tunnel.  And everything is filled. (in case you want tunneling or something...

I suppose if I wanted tunnels to split, I could change the algorithm to do that too.
Title: Re: Messing with dungeon generation
Post by: Slash on October 23, 2007, 06:57:40 PM
Icey, image #9 (http://iceyboard.no-ip.org/stuff/dg9.png) looks really good. I hope I'll get to play in something like it at some point
Just wear a bowler hat while programming long enough, you will eventually catch it
Title: Re: Messing with dungeon generation
Post by: Robson on October 25, 2007, 07:34:14 PM
Icey, image #9 (http://iceyboard.no-ip.org/stuff/dg9.png) looks really good. I hope I'll get to play in something like it at some point
Just wear a bowler hat while programming long enough, you will eventually catch it
That is so untrue, I don't even own a-- *suddenly the wardrobe doors fly open and millions of bowler hats fall out*

Ummmm. Right!! I don't care if it is raining, I'm going out to buy some chips!!
Title: Re: Messing with dungeon generation
Post by: Krice on October 29, 2007, 05:38:42 PM
I had an idea that could be worth trying. What if corridors were made first and then rooms as extensions to corridors?
Title: Re: Messing with dungeon generation
Post by: Slash on November 18, 2007, 02:17:26 PM
Isnt a corridor just a (very) narrow room?
Title: Re: Messing with dungeon generation
Post by: Ex on November 20, 2007, 01:41:09 AM
Isnt a corridor just a (very) narrow room?

I think typically rooms are square while hallways usually bend. Also hallways are sometimes allowed to overlap each other which rooms usually aren't.

Mostly I think of the bend in hallways since most rooms are not L shaped.
Title: Re: Messing with dungeon generation
Post by: Krice on December 04, 2007, 09:30:40 PM
Today I was planning a new kind of dungeon generation (trying to solve corridor problems). I still have to test that and if it works I guess I could write an article, because it could be useful. If the plan works it allows very flexible dungeon generation without "grids". I hope it works..
Title: Re: Messing with dungeon generation
Post by: Slash on December 05, 2007, 08:48:08 AM
We await for news about it ;)
Title: Re: Messing with dungeon generation
Post by: Krice on December 07, 2007, 08:15:01 PM
We await for news about it ;)

Yeah.. Really annoying thing is that I'm in square one all the time with dungeon structure generation. Is it just me or does people here have same kind of difficulties with it? The hardest part seems to be connecting rooms with corridors so that it doesn't look stupid and that it works in the first place and doesn't break rooms.
Title: Re: Messing with dungeon generation
Post by: Krice on December 08, 2007, 05:26:13 PM
First take was an epic fail. What's wrong with me? I can't even make corridors.
Title: Re: Messing with dungeon generation
Post by: Anvilfolk on December 08, 2007, 10:45:31 PM
Why don't you try a totally different approach? I've some people using "non-standard" stuff, like cellular automata. You could try creating "abstract digger dwarves" with pseudo-personalities, and have them dig a dungeon through a series of iterations... I might try that when I have free time (somewhere in 2145).
Title: Re: Messing with dungeon generation
Post by: Krice on December 09, 2007, 02:43:37 PM
You could try creating "abstract digger dwarves" with pseudo-personalities, and have them dig a dungeon through a series of iterations...

That sounds really odd and over complex. Anyway I came to the conclusion that "overlapping" rooms were the source of all bad things. They generate two major problems: walls inside the rooms dividing a bigger room area and floors that destroy walls from the original room that was overlapped. This in turn makes it impossible to find a wall facing to certain direction when the other room just wiped them out entirely. Making the two rooms connected wont solve that problem, you would have to connect the two rooms physically to one room with the same room mask id. That was too much for me and I disallowed the creation of overlapping rooms. It's probably going to make some level types less interesting, but I don't care.
Title: Re: Messing with dungeon generation
Post by: elsairon on January 04, 2008, 02:45:36 AM
I came to the conclusion that "overlapping" rooms were the source of all bad things. They generate two major problems: walls inside the rooms dividing a bigger room area and floors that destroy walls from the original room that was overlapped. This in turn makes it impossible to find a wall facing to certain direction when the other room just wiped them out entirely. Making the two rooms connected wont solve that problem, you would have to connect the two rooms physically to one room with the same room mask id. That was too much for me and I disallowed the creation of overlapping rooms. It's probably going to make some level types less interesting, but I don't care.

I know what you mean. Several things I tried to add didn't work right for me. Like making circular rooms on a grid. Eventually I got them working (2 years later) so I didn't include them in the dungeon generator.

I think making it work is first priority. When thats done, improvements can always be made later.

Right now I don't even use a dungeon generator for my tests.. I just load ascii text files that I hand-edit into maps. I'm majorly refactoring my map creation.. so I don't even have a working dungeon generator in my codebase right now.
Title: Re: Messing with dungeon generation
Post by: Krice on January 08, 2008, 10:57:43 AM
I think making it work is first priority. When thats done, improvements can always be made later.

It was working, but then I wanted to have "strict" and overlapping rooms in the same level, which required re-writing and then I couldn't make it work. Anyway, I think after all level generation is quite easy to do, so I'm concentrating to harder aspects of the engine such as game object code.
Title: Re: Messing with dungeon generation
Post by: Gamer_2k4 on January 09, 2008, 05:49:05 PM
Why don't you try a totally different approach? I've some people using "non-standard" stuff, like cellular automata. You could try creating "abstract digger dwarves" with pseudo-personalities, and have them dig a dungeon through a series of iterations... I might try that when I have free time (somewhere in 2145).

My dungeon generator creates maps that looks like caves.  After all, why would a dungeon consist of rooms and halls? You're going into caves and the like; at any rate, nothing will look as neat as the dungeons in ADOM (which seems to be one of the "better" generators).

My process is described here:
http://groups.google.com/group/rec.games.roguelike.development/browse_frm/thread/f2899ee1318b62fd#
Title: Re: Messing with dungeon generation
Post by: JoshuaSmyth on January 24, 2008, 07:11:51 AM
A little while ago I posted some stuff about the random generation in Caverns of Underkeep - It doesnt go into detail, but might provide someone with some tid-bits.

http://www.peachysoft.com/?p=84

Title: Re: Messing with dungeon generation
Post by: Krice on January 24, 2008, 07:52:26 AM
Underkeep tilted my firefox. No matter, Java-based games are always crap.
Title: Re: Messing with dungeon generation
Post by: Anvilfolk on January 24, 2008, 03:23:58 PM
Java is an awesome language to program in, never you mind Krice :) I have to confess I don't like Java from a user's standpoint (as opposed to programmer's). You have to have a virtual machine, there's usually not an exe, speed issues... just little things that bother me. It's more of a quirk, really.

And yes, most games in Java aren't really very good - much like flash. The more mainstream a language is, the more people try doing stuff in it. The more people you have, and assuming 10% of all projects are decent and the rest suck, then yes, you'll see a lot more sucky projects. It's pretty obvious if you think about it.



In any case, I love your maps! They are really, really nice! I might not have played in them, but just form looking, I'm going to venture saying they are some of the best I've ever seen! I say this because you instantly get that idea that it was a dungeon, and that it's been left unatended for centuries, and so some parts have caved-in... none of it is perfect, it seems to have just the right amount of "abandon"!

As far as the cave level goes, it's also awesome! It reminds me of the first levels of Rune! I can imagine waterfalls in there, gloomy environments, mist from the dark, stale pools... very nice work! Congratulations! And the approach does indeed seem simple! I look forward to reading the more complete article!

Keep it up!
Title: Re: Messing with dungeon generation
Post by: JoshuaSmyth on January 24, 2008, 09:11:46 PM
Underkeep tilted my firefox. No matter, Java-based games are always crap.


Will have to try fix, what version of firefox are you running? - The thing I don't like most about Java is that there are so many combinations of platforms that it runs on that to test it on everything is a real pain in the ass.

There are plenty of good and bad things I can say about Java from both a programmers and a users point of view. But I wanted to make a browser based game, my choices? Java or Flash (or Silverlight) in the end, ya just gotta pick one and roll :)

As far as the cave level goes, it's also awesome! It reminds me of the first levels of Rune! I can imagine waterfalls in there, gloomy environments, mist from the dark, stale pools... very nice work! Congratulations! And the approach does indeed seem simple! I look forward to reading the more complete article!

Thanks, I should really add more enviromental stuff to the game. However at this point I'm quite willing to just get Caverns finished and start working on a new game :)
Title: Re: Messing with dungeon generation
Post by: Slash on January 25, 2008, 02:25:25 AM
@Krice: Not true, check out legerdemain and castlevaniaRL

@Anvil: Speed issues for a roguelike? :D Also... I strongly recommend you download a VM... the distribution schema of Java may appear a bit annoying at first, but it ensures games will live forever

Also, being Java doesnt affect how good/bad the game is, I can assure you C++ is much more mainstream than Java or Flash :P

@Joshua: Java was a good choice, have you tried Java Web Start? It may make some things easier...



Title: Re: Messing with dungeon generation
Post by: JoshuaSmyth on January 25, 2008, 03:53:22 AM

@Joshua: Java was a good choice, have you tried Java Web Start? It may make some things easier...


No I haven't - I should probably look into it for the next game though. Thanks for reminding me.
Title: Re: Messing with dungeon generation
Post by: Anvilfolk on January 25, 2008, 04:02:31 AM
Oh, most my classes are in Java, I'm pretty acquainted with the language. I've got the VM on both my OS's partitions. I still don't dislike it, especially applet stuff, but again, it's just a quirk of mine. I prefer unzipping and running an exe. *shrug*

And about the mainstream thing: in my opinion, Java is definitely more mainstream than C++ is. I'm sure C and C++ are still more widely used, but people that are learning programming will be starting with Java or even higher-level languages. First year student's on my course start with Java, and only get into C stuff in computer architecture / OS classes. Some random guy wanting to learn how to code will probably get recommendations to start with Java instead of C, C++. For gaming, Java has direct built-in graphical libraries while you need external ones (which are always a pain to configure your compiler with), it has Eclipse and other fantastic amazing IDE's that work out of the box, etc etc.

With Java, it's just easier. And flash even more. That's why you see tons of really crappy flash games :)
Title: Re: Messing with dungeon generation
Post by: Krice on January 25, 2008, 09:38:09 AM
Browser-based games suck, that's actually what I wanted to say.
Title: Re: Messing with dungeon generation
Post by: Altefcat on February 08, 2008, 09:35:44 PM
I've made a very simple dungeon generator for Lands of Elderlore, it is connected in one piece, but there can be some dead-ends. I've put stairs on the first two, then treasures on the following. Here are some samples :

Code: [Select]
################################################################
################################################################
####>>##########..............##..............##..........######
####..##########..............##..............##..........######
####..##########..............##..............##..........######
####..##########..............##..............##..........######
####..##########..............##..............##..........######
####..##########..............######++######++##..........######
####..##########..............##..........##..##..........######
####..##############++##########..........##..##########++######
####..........................++..........##..##########..######
####..##############..##########..........##..##########++######
####..........................++..........##..##..........######
####..##############..##########++##++######..##..........######
####..##..........##..##########..##..######..##..........######
####..##..........##++##########..##..######..##..........######
####$$##..........##..........##..##..######..##..........######
########..........##..........##..##..######..##..........######
########..........++..........++..............++..........######
####################..........##..##++######++##################
####################..........##..##..........##################
####################..........##..##..........##################
####..............##..........##..##..........##################
####..............##############..##..........##################
####..............##############..##..........##..........######
####..............##############..##..........##..........######
####..............++..............++..........++..........######
################################..##..........##..........######
############<<....................##..........##..........######
################################################################
################################################################
################################################################

Code: [Select]
################################################################
################################################################
############......++..............##..........######$$##########
############..######..............##..........######..##########
########$$........++..............++..........++..##..##>>######
############..##..##..............##..........##..##..##..######
############..##..##..............++..........++..........######
############..##..##..............##..........##..##..##..######
####$$............++..............##..........##..##..##..######
############++##..##############################..##..##..######
####..........##..######......................##..##..##..######
####..........##..######......................##..##..##..######
####..........##..######......................##..##$$##..######
####..........##..######......................##..######..######
####..........##..######......................##..######..######
####..........##..######......................##..######..######
####..........##..##<<##......................##..##$$##..######
####..........##..##..##......................##++##++##++######
####..........##..##..##......................##..........######
####..........##..##..##......................##..........######
####..........##..##..++......................++..........######
############++##..##..##########################..........######
############..##..##..........................++..........######
############++##++##++##########################..........######
####......................######################..........######
####......................######################..........######
####......................######################..........######
####......................######################################
####......................######################################
################################################################
################################################################
################################################################

Code: [Select]
################################################################################################################################
################################################################################################################################
########################..........##############################################################################..........######
########################..........##############################################################################..........######
########################..........##################$$##############################$$....................######..........######
########################..........##################++##################################################++######..........######
########################..........##..................##..................##..........++......++..........++..++..........######
########################++##########..................##..................##..........##########..........######..........######
########..................##########..................##..................##..........##########..........######..........######
########..................##########..................##..................##..........##########..........######++######++######
########..................##########..................##..................++..........++......++..........++......######..######
########..................##########..................######################..........##########..........######..######..######
########..................##########..................######################..........##########..........######..######..######
########..................##########..................######################..........##################++######..######..######
########..................##########..................##############$$######..........##......................##..######..######
########..................##########################++##############++##################......................##..######..######
########..................##$$............................++..............##############......................##..######..######
############++##########++##########################..######..............##############......................##..######..######
############..##########..##################$$##$$........++..............++..........##......................##..######..######
############..##########..##################..##############..............##..........##......................##..######..######
############..##########..##############$$##..##..........##..............##..........##......................##..######..######
############..##########++##############..##..##..........##..............##..........##++##############++######..######..######
############..##..................######..##..##..........##..............##..........##......................##..######..######
############..##..................######..##..##..........##########++######..........##......................##..######..######
############..##..................######......++..........++..............++..........##......................##$$######..######
############..##..................######..##..######################..######..........##......................##########..######
############$$##..................######..##....................$$##..######..........##......................##########$$######
################..................######..##..######################..######..........##++######################################
################..................######..##..##..................##..######..........++............................$$##########
################..................######..##..##..................##..######++##++######..######################################
################..................######..##..##..................++................$$##..######$$##......................######
################..................######..##..##..................##..######++##++######..######..##......................######
################..................######..##$$##..................++..++..........##>>##..######..##......................######
################################++######..######..................##..##..........##..##..######..##......................######
############..............######..######..######..................##$$##..........##..##..######..##......................######
############..............######..######++##############################..........##..##..######..##########++######++##########
############..............######..##$$##..............##..............++..........++..............##..............##..##########
############..............######..##..##..............##..............##..........##..##..######..##..............##..##########
############..............######..##..##..............##..............##..........##..##..##$$##..##..............##..##########
############..............######..##..##..............##..............##..........##..##..##..##..##..............##..##########
############..............++..........++..............++..............##..........##..##<<##..##$$##..............##..##########
############..............######..##..##..............##..............##########++##..######..######..............##..##########
############..............######..##..##..............##..............##$$........................++..............##..##########
############..............######..##..##..............##############################..######..##############++##++##..##########
############..............######..##..##..............++..........................................++..........++..##..##########
####################++##########++##++##..............##############################..######..######..........##..##..##########
############..............##..........##..............##$$..............................$$##..######..........##..##..##########
############..............##..........##############++##############################++######++######..........##..##..##########
############..............##..........##############..##########......................##..........##..........##..##..##########
############..............##..........##############..##########......................##..........##..........##..##..##########
############..............##..........##############..##########......................##..........##..........##..##..##########
############..............##..........##############++##########......................##..........##..........##..##..##########
############..............##..........######..............######......................##..........##..........##..##..##########
############..............##################..............######......................######++##++##########++##++##++##########
############..............##################..............######......................######$$##......................##########
############..............##################..............######......................##########......................##########
############..............##################..............######......................++......++......................##########
############################################..............######################################......................##########
############################################..............##################$$................++......................##########
################################################################################################......................##########
########################################################$$....................................++......................##########
################################################################################################################################
################################################################################################################################
################################################################################################################################

The code is in python in file "el_donjon.py", and it as less than 200 lines. I can provide it if you want.