A little Javascript/SVG application to create dungeon maps for role-playing games.

If you’re having trouble, consider the following:

The hash tag I’m using is #Gridmapper, obviously. :)

2017-06-26 Megadungeon Generator

A while ago I started working on a megadungeon map generator which documents every step of its growth using a little picture, and every one of these pictures links to a rendering of said map using Gridmapper for debugging purposes. The actual “result” is simply the link from the last image.

Give it a whirl!

One example of a generated map

I’m interested in ideas for improving the generated maps. I already have some vague ideas:

  • Having the algorithm prefer growing new corridors into sections that are “less dense.” But how does one define that?
  • If that doesn’t eliminate dead ends, have some sort of estimate of whether the corridor will end up in a dead end and abort these outgrows. Or eliminate dead ends after the fact.
  • Placement of statues, altars, treasure chests, tables, beds, open pits and traps.
  • Agressively trying to add more “starting” rooms for levels that are “done” but aren’t “dense enough”. All of these terms need decisions to be made.

When I started the project, the first thing I did was draw the kind of dungeon elements I expected to find in a simple generated megadungeon map.

Megadungeon Elements

Next, I drew a map using the elements I had identified. I also started looking at corridor lengths and the like. That’s what the numbers are for.

Megadungeon example map

And finally, I tried to identify some simple statistics to build a simple table of probabilities, a bit like a Markhov chain.

Megadungeon statistics


Comments on 2017-06-26 Megadungeon Generator

Some thoughts: What about using a census of the region the proposed feature is going to go into, maybe up to 3 or 5 squares away, and the census values fall off by distance (1 square = 2, 2 squares = 1, 3 squares = 0.5, etc), and then if the value is above a figure you set the generator instead chooses a new location? Maybe you could use a random feature generator, something that works like the AD&D DMG dungeon generator, for traps/statues/chests/etc? It looks like you’re using something already, as I see that the generator will throw in the occasional portcullis or statue.

Frotz 2017-06-27 13:46 UTC

The way the generator works is that it places elements and based on the element it just placed, it randomly chooses appropriate next steps. The way to describe it right now would thus be something like this:

  1. start with a big room
  2. a big room has an exit
  3. a big room has a 70% chance for another exit
  4. a big room has a 20% chance for another exit
  5. a big room has a 20% chance for a spiral stair case
  6. a room exit goes in a random direction and looks for a wall to place a door
  7. a door out of a room will connect to a corridor that is about 60ft long
  8. at the end of a corridor, there is a 20% for a big room (back to #2)
  9. or a 30% chance for a settlement
  10. or a 50% chance for small room
  11. and so on...

To add a feature, I’d need to hook into this process and say, for example, that a big room without a stair case has a 30% chance of having an altar, and a 30% chance for a statue, and thus an about 10% chance for both.

Or, in a settlement, the last small room has a 50% chance of containing a chest.

– Alex Schroeder 2017-06-28 06:50 UTC

Add Comment

2017-04-23 Cut, Copy and Paste

I wanted to add copy & paste to Gridmapper. But how? With access to the clipboard? And what kind of data would I use? I decided to leverage the existing text export and import functionality.

I wanted to use something like the selection on typical graphical user interfaces. Shift and the arrows keys extends the selection. But I have used Shift for other things:

  • Shift and the mouse doesn’t drag the pointer along, which is nice when trying to use the application with just the mouse; I switched that to Alt
  • Shift and the arrow keys draws the floor, which is nice when you’re using just the keyboard; I switched that to Alt as well
  • I allow Escape to get rid of the active selection
  • Do you think Delete and Backspace should delete the selection if it is currently active?
  • Mouse users: hold Shift while moving the mouse.
  • Also, no documentation. How to mention this on the help pane? How to integrate this into the demo?


Comments on 2017-04-23 Cut, Copy and Paste

I’m on a macbook pro and I can no longer change floors. alt+arrows just draws the floor. Tried every button on the keyboard. Please help.

– xyz 2017-05-24 20:21 UTC

Sadly, I’m away from my Laptop for the next four days. I hope you can figure something out!

If all else fails, you can use an older version, e.g. 1.0,1.1,1.2, or 1.3.

– Alex Schroeder 2017-05-25 09:07 UTC

I just tried it on a MacBook Pro using Chrome, Firefox and Safari – and it worked as intended. Can you describe the exact problem you’re having, the software you’re using, the key’s you’re pressing, what you’re seeing, what you expected to see instead, all the stuff that might help me figure out what the problem is?

– Alex Schroeder 2017-05-30 17:43 UTC

For some reason I get the same problems with the older version, even though it’s shift+arrow key that switches odd.

So I’m on Safari 10.1.1 on a Macbook pro. I used to be able to go up or down floors by holding down left/right shift key and pressing the up and down arrows. Now when I do shift+arrow on versions 1.1-3 (alt+arrow on most recent build), it starts to draw floor tiles instead of switching floors, which effectively limits me to building one-floor dungeons.

xyz 2017-06-09 15:18 UTC

I think you must be confusing Gridmapper with some other application. Shift arrows never changed levels (”floor”). To change levels, use the z key to go down and the y key to go up.

– Alex 2017-06-10 06:51 UTC

Oh god, I’m an idiot. Thank you.

xyz 2017-06-10 16:01 UTC

Add Comment

2017-02-12 Grottos

Gridmapper now does caves (”grottos”). Click the image to get transported into dungeon mapping heavy.



Comments on 2017-02-12 Grottos

And I’ve prepared the ground for end-to-end tests using Nightwatch.js.

– Alex Schroeder 2017-02-12 12:45 UTC

Add Comment

2017-02-03 Map Collaboration

I don’t think anybody ever used the ability to host a Gridmapper map, live. Well, the least used feature just got better! I know, I know. But hey, it’s free, and I liked working on it, so there’s that. The new feature: collaborate on a map. That is, where as before would one of you would be the mapper and the others could get a read-only view of what the mapper was doing, now you can all draw at the same time. That’s what I hope, anyway.

A word of caution: In the spirit of all things Internet, there is currently no protection at all. Anybody can join a map. I’ll probably add optional passwords, soon. Please leave a comment if you were collaborating with friends and vandals joined your map!

Please note that Gridmapper has no chat functionality. You must meet people online, elsewhere. One way to do this is to join the DIY DND chatroom on Discord. It’s like G+, but one ongoing conversation.

And when you do collaborate on a map, please let me know. My current estimate of Gridmapper users is one or two active users.


Add Comment

2017-01-22 Gridmapper Arcs and Diagonals

I’ve spent some time fiddling with Gridmapper. The new version is incompatible with the old version if you used the larger arcs. If you need to load map you saved using the old version, you can use this link:

You’ll note that it uses n to create arcs.

Let’s assume you used those arcs in a map of yours:

Here’s what you’ll get when you switch to the new version: the arcs turned into diagonals with walls.

That’s because the new version supports more variants regarding diagonals and it treats arcs differently.

Just to make sure you can always find the link to an old version of Gridmapper if you need it, I’ve made sure the individual maps currently saved on the wiki all link to Gridmapper 1.1. Just in case. :)

You can always save that and continue working offline – or change the those diagonals to arcs. You can do a text export and replace as follows:

nvvv → avv
nvv  → av
nv   → a

Features of the new Gridmapper

The latest Gridmapper version moves arcs to a separate layer. They’re now “below” the floor, so that you can place stuff on top of the round parts without strange overlaps. That means you can create maps like the following without any hassles:

This solves one of the issues on my list.

It uses a to create arcs.

Diaonals have also been improved. We now have three variants:

  1. the ordinary diagonal tile without any black background
  2. a diagonal tile with a diagonal wall
  3. a square tile with a diagonal wall

You cannot use w to create diagonal walls, unfortunately. You also cannot use wall mode to place walls or doors in the diagonals. Maybe some day. Leave a comment if you need this.


  1. Do you use Gridmapper? Please consider sharing your maps by leaving a link. Or upload a map to social media or imgur.
  2. Do you ever host maps for others to follow along as you map in an online game?


Comments on 2017-01-22 Gridmapper Arcs and Diagonals

Alex, as far as I’m concerned Gridmapper is the single most useful resource on the internet for dungeon creation. I have absolutely no artistic ability, but Gridmapper has enabled me to create fantastic maps that only require slight image processing. Keep up the great work and I’ll stay tuned for further updates. Thanks so much for creating this (also, the diagonal wall is a godsend. Great update).

Noah Leben 2017-02-03 21:16 UTC

Below is a map I created using the program and a simple image processing tool. I do have a couple of suggestions that could improve the program even further.

  1. More wall types would be great. Dotted line, two thin lines (for raised platforms), a curved line tile (similar to the diagonal line tile). I also saw at one point you had an “opening” for an archway option. I’d like to see that come back.
  2. More door types, such as a double door that fits into one square. Diagonal doors would be great as well.
  3. Being able to place pillars and doors on vertices would be great but I realize that’s likely beyond the scope of this program.
  4. You should be able to rotate the “c” assets in my opinion.
  5. A bridge icon.

Gridmapper is fantastic but this additional functionality would really make it superb. Thanks again for the great tool.

Noah Leben 2017-02-03 21:44 UTC

WHOA!! This map is super awesome! Thank you for sharing!

– Alex Schroeder 2017-02-04 08:49 UTC

As for the comments:

The problem with raised platforms are the corners. If you don’t use corners, it will be easy to do. I’ll have to think about something.

easy  hard
 ═    ╔═
║     ║

The archway still exists but it’s a door variant. I don’t think I ever had any other?

As for pillars on vertices I guess I could treat them like doors? Maybe something worth investigating. Also doors shifted by half a tile might work because the double doors already work like that.

Rotating chests, beds and tables … I think this can be done.

What would a bridge icon look like? Do you have an example somewhere?

– Alex Schroeder 2017-02-04 09:14 UTC

I added all the items to the issue tracker.

– Alex Schroeder 2017-02-04 20:43 UTC

Rotating chests, beds and tables has been implemented. :)

– Alex Schroeder 2017-02-04 21:10 UTC

You know, I’m not sure what to do for a bridge icon that would fit the parameters of this program. However, while contemplating that I came up with another stair icon that would be useful: a 1-tile stair icon where the lines went all the way across the icon instead of gradually getting smaller. Jennell Jaquays drew stairs like this in Caverns of Thracia. Seems like this tile would allow users to create stairs of any desired length.

– Anonymous 2017-02-04 23:50 UTC

Yeah, but what about the arrow required? Where to place it, how long to draw it, or allow manual placement?

– AlexSchroeder 2017-02-05 07:34 UTC

I guess room 45 shows how to combine it with a tapering off without arrow...

– AlexSchroeder 2017-02-05 07:35 UTC

Personally, I don’t think the arrow is absolutely required, as the direction of the stairs could be handled in the map’s key. But having an arrow wouldn’t necessarily be a bad idea! Also, I saw your post on r/osr! Small world. I’m really excited that some of these updates are going to be implemented.

– Noah Leben 2017-02-05 16:12 UTC

I’ve tried using windows to indicate bridges and it looks pretty OK to me, what do you think?

– Alex Schroeder 2017-02-08 18:02 UTC

That’s not a bad technique! I like the creative re-use of an asset. Very innovative. I tested it just now and it should certainly work for my purposes.

I did think of another potential tile: a circular equivalent to the new “n” tiles. That is, a tile with a curved line bisecting it (you could do one half gray and one full whitejust like the “n” tiles). Not sure if there are any issues in implementing this or not. It would be great to be able to create a circular room within a room.

Noah Leben 2017-02-08 23:04 UTC

Hm. Yes, maybe the three arcs need to exist in a walled variant, too.

Something else, though: Ever wished for color coding? See #11.

Something like this:

Wilderness Map of A Red and Pleasant Land
Picture by El Dado Inquieto

– Alex Schroeder 2017-02-09 08:53 UTC

Yes, the arcs. Would have been clearer had I just said that in the first place, I suppose. Haha.

Color coding would be great. I could see it having a wide variety of applications. In the past I’ve mostly mapped in black and white, but I use color occasionally when necessary (color is easy enough for me to do after the fact with an image processing program, but having it native to the app is always preferable). Love the Red & Pleasant Land map.

Noah Leben 2017-02-09 20:15 UTC

Add Comment

2016-03-15 Internet Explorer

I have hopefully improved the situation for users of Internet Explorer – at least marginally. I am now hiding all the elements I know not to work. In this way, Gridmapper is still useful, even if not fully functional.

  • you cannot mix HTML and SVG and therefore:
    • you cannot import or export the map as text
    • you cannot provide a name for the map when you want to save it
    • you cannot provide a name for the map when you want to host it
    • you cannot type a label into a text field
    • you cannot download a PNG image because there’s no canvas in the background
    • you cannot run the demo
  • you cannot use data URIs and therefore:
    • you cannot download a local copy of the file

There are various ways out:

  • when hitting the quote or double-quote character, Gridmapper could switch into a text-entry mode (much like what you get when typing numbers) until you hit the return key
  • we could also use that to name the map, since this is important for saving and hosting
  • saving could also be something that we can do via a request to the Gridmapper server, which provides a form where users can name their map
  • we implement loading and saving of blobs [1]


Comments on 2016-03-15 Internet Explorer

The best comment from my post on Google+: “IE (sometimes even IE8) is often the choice of big businesses because that’s what they’ve always used and they’ve got everything up and running now and can’t be bothered to change it. So basically, how much do you want people to be messing about on Gridmapper at work?”

Everybody else uses Chrome, Firefox, or Safari, I’d say. Thus, no features for IE?

Well, actually I did implement downloading of the SVG file for Internet Explorer. :)

– Alex Schroeder 2016-03-17 21:10 UTC

Add Comment

2016-03-12 A Day Wasted

Gridmapper is a web application because it runs in a web browser. It consists of an SVG document and some Javascript which adds and removes elements to the SVG document in your browser’s memory. Sadly, where as SVG has a way to get key press events and mouse events and touch events – all the stuff Javascript knows about – it doesn’t have text fields and text areas like HTML does. So, what now? In theory, it’s easy: include XHTML in the SVG document – this is possible because both are XML dialects and SVG has an element that reserves space for non-SVG elements: foreignObject. So if I don’t want to re-implement all of the things that text fields and text areas do, all the cursor movements, selection, copy, cut, paste, and all that, then this is what I’ll have to do.

I currently have a way to do that, but I didn’t like it. It looks a bit off on the iPad Pro. It doesn’t look exactly the way I want it to on different operating systems. And so I decided to change it. Replace a lot of the XHTML other than the text area with pure SVG.

And then, when it was nearly done, I ran into weird problems with Chrome.

This was the first problem: When you click on the Download link, it turns invisible and some text that was invisible instead shows up. With the rewrite, making the Download link invisible turned all of the text invisible. Huh? After many iterations, I turned out that if I rearranged the links so that it wasn’t the first link, it worked. Huh?

The second problem was that the text area suddenly started jumping to the left if more than a few lines of code were inserted by the Text Export link. Huh?

I decided to kill it all. And now I’m sad.

Update: And literally minutes later, I think of something... try it... works!? The simple addition of “position: fixed” is the solution!? 🙀

Update: Oh well, I just found that the PNG export doesn’t work in Safari. Apparently not an unknown problem. [1] The solution in my case was to create a new SVG node and import all the nodes I need without importing any of the nodes containing the foreign objects:

  // PNG download hides user interface. We must actually *remove* all
  // the foreignObject elements because it causes a security exception
  // in Safari.
  var clone = document.createElementNS("", "svg");
  var background = svg.getElementById('background');
  clone.setAttribute('width', svg.getAttribute('width'));
  clone.setAttribute('height', svg.getAttribute('width'));
  source = btoa(unescape(encodeURIComponent(new XMLSerializer().serializeToString(clone))));

  link  = document.getElementById('download_png');
  // SVG to PNG using canvas
  var canvas = document.createElementNS(xhtmlNs, 'canvas');
  var rect = Map.ui.getBoundingClientRect();
  canvas.width = (Map.width + 2) * Map.tileWidth; // see resizeSVG
  canvas.height = (Map.width + 2) * Map.tileWidth;
  var ctx = canvas.getContext('2d');
  var img = document.createElementNS(xhtmlNs, 'img');
  img.setAttribute('src', 'data:image/svg+xml;base64,' + source);

  // when the image arrived in the canvas, set the link
  img.onload = function() {
    ctx.drawImage(img, 0, 0);
    link.setAttributeNS(xlinkNs, 'href', canvas.toDataURL('image/png'));

Update: I think I took care of all these issues and I even implemented a new feature: Z will now cycle through the following three states:

  1. hide other levels (the old functionality)
  2. use a black background
  3. back to the default: light gray background and transparent images of the levels above and below

Not wasted after all. :)


Add Comment

2016-03-09 How to Save

I really should find a better way to do this. It’s confusing!

I’m mostly concerned about option 4, saving the SVG file.

I should take a look at how Tiddly Wiki does saving. They must run into the same problems. I guess they do. Perhaps I can use some of their wording.


Add Comment

2016-03-06 Gridmapper using Web Sockets

Wohoo, I’m super excited because the next release of Gridmapper will do away with auto-saving and auto-loading. Instead, it will use a small server component on Campaign Wiki and allow users to host Gridmapper sessions. Thus a mapper could load the page, name his session “Nuclear Doom” and anybody else who knows this name can also load the page and join this session. And it will be more or less in real time because of WebSocket.

Update: Currently it’s not working because of web server issues. Site uses HTTPS and so the requests for the WebSocket server need to get proxied from Apache to the backend using mod_proxy_wstunnel. [1] This module requires Apache 2.4 and I have 2.2.22 installed – I’m still running Debian Wheezy. Trying to compile and install just the module failed. [2] So right now, I’m stuck. Loading Gridmapper via HTTPS will not allow me to make a connection to the backend using an unencrypted connection, and that requires the module, which my web server doesn’t support... Gah!

Update: Apparently I need to install both mod_proxy and mod_proxy_wstunnel after recompiling a patched Apache. [3]

Update: OK, it seems to be working, now. And with less weird error messages by Chrome. I had to use Hypnotoad instead of Toadfarm because there can only be a single worker. After all, all the maps, clients and servers are stored in memory and not on disk. The names of the maps currently being hosted can be seen from the web page that goes along with the server component:

Update: When you’re hosting a map, the page above will now offer a link to join that map. Thus, here’s how you start your session:

  1. open Gridmapper and start drawing
  2. provide a name in the text area
  3. click Host
  4. friends look at the waiting room and click the appropriate link


Add Comment

2016-03-04 Simple File Load using VanillaJS

Gridmapper allows users to save and load maps. As Gridmapper is a Javascript app, it runs in a sandbox and has no access to your filesystem. The maps are therefore saved in a dedicated Gridmapper Wiki. When loading a map, I need a user interface allowing people to click a link (a modal “open file” dialog would be the traditional way to solve this). Since I wanted a solution using VanillaJS, I simply show a div full of links. There’s no close button (it just fades after a while if you don’t click anything), there’s no scroll bar. And as the list of maps grew, I realized that I was running out of space. So now it adds more columns if possible. But still, this won’t scale.

Then again, perhaps I’d better use the wiki to navigate: Clicking load opens the wiki, and on the wiki there’s a special kind of link that opens Gridmapper with a particular map?

Well, I still have a two or three columns to fill, so there’s no rush.

For the moment, I implemented an intermediary step: When the app loads, it looks at its own SVG code and initializes the data structures accordingly (in case the file was loaded from the file system), looks at the URL and loads a map if so instructed (this is the new part), or simply interprets the keys it sees (this is what “Prepare Link” would generate).

Let’s try the new thing: load The Sewer Prison.

Now that we have a way to load maps via the URL, Gridmapper will add that URL to maps it saves to the Gridmapper wiki (using Oddmuse URL abbreviations, so-called interlinks). You can see the new link being added here, at the Demo Dungeon.


Add Comment



Please make sure you contribute only your own work, or work licensed under the GNU Free Documentation License. See Info for text formatting rules. You can edit the comment page if you need to fix typos. You can subscribe to new comments by email without leaving a comment.

To save this page you must answer this question:

Please say HELLO.

Referrers: Dragonsfoot • View topic - [Holmes Basic] Sample Dungeon Map in G... Pinboard: public bookmarks for eeeickythump Ynas Midgard's RPG Blog ZENOPUS ARCHIVES ZENOPUS ARCHIVES: Sample Dungeon in Gridmapper dndnext