2013-02-26 Text Mapper

Recently I wanted to create a little hex map and I wanted to do it on an iPad, I wanted to eventually integrate it into my campaign wiki, I wanted it to be SVG based, and so on. All that meant, Hexographer wasn’t the appropriate tool. I needed to cook something up myself. Based on code I wrote nearly five years ago—the Old School Hex Mapper—I wrote up a little something.

I’m calling it the Text Mapper because it takes text input. No interactive fiddling with the map.

There are various sections of the input.


This is simple. Coordinates, terrain.

# map definition
0101 mountain
0102 mountain
0103 hill
0104 forest
0201 mountain
0202 hill
0203 coast
0204 empty
0301 mountain
0302 mountain
0303 plain
0304 sea
0401 hill
0402 sand
0403 forest

The rest of the input determines how things look: what colors to use, what icons to display. When you start the Text Mapper, the input area already contains an example. Start with that before doing anything else.

Terrain attributes

Now it gets tricky. For every terrain we used, the script will generate a hex. We need to provide some SVG attributes! Need documentation? Check out the polygon in the SVG specification and click on show next to presentation attributes. That’s what you should be looking at.

# attributes
empty attributes fill="#ffffff" stroke="black" stroke-width="3"
plain attributes fill="#7cfc00" stroke="black" stroke-width="3"
forest attributes fill="#228b22" stroke="black" stroke-width="3"
hill attributes fill="#daa520" stroke="black" stroke-width="3"
mountain attributes fill="#708090" stroke="black" stroke-width="3"
sand attributes fill="#eedd82" stroke="black" stroke-width="3"
coast attributes fill="#7fffd4" stroke="black" stroke-width="3"
sea attributes fill="#4169e1" stroke="black" stroke-width="3"


In order to add little icons, you can specify a path per terrain.

hill path M -42,11 C -38,5 -34,0 -28,-3 C -20,-6 -11,-5 -5,-0 C -2,2 1,6 3,9 C 4,12 2,13 0,14 C -3,9 -7,5 -13,2 C -21,-1 -30,0 -36,6 C -38,9 -40,11 -43,14 C -43,15 -44,14 -44,13 C -43,12 -43,12 -42,11 z M -5,-0 C 0,-6 7,-12 15,-16 C 21,-18 28,-17 33,-14 C 39,-11 41,-5 43,-0 C 42,2 41,5 39,2 C 37,-2 33,-8 27,-10 C 20,-13 12,-12 6,-7 C 2,-4 -1,-1 -4,1 C -7,4 -6,0 -5,-0 z

plain path M -18,-13 C -13,-6 -13,4 -8,12 C -11,14 -15,21 -18,26 C -20,17 -22,4 -28,0 C -26,-4 -21,-9 -18,-13 z M 5,-31 C 4,-19 3,-6 6,5 C 1,10 -0,14 -3,19 C -2,6 -3,-4 -4,-16 C -4,-21 2,-26 5,-31 z M 26,-1 C 16,6 19,5 9,18 C 12,3 21,-8 34,-17 C 32,-12 29,-6 27,-1 z

If you don’t want this path to be black, you need to specify attributes for the path element.

plain path attributes fill="#76ee00"
hill path attributes fill="#b8860b"

And finally, the coordinates are simple text elements.

text font-size="20pt" dy="15px"

If you wanted a black and white map, for example, you could use different strokes…

empty attributes fill="white" stroke="#b3b3ff" stroke-width="3"
mountain attributes fill="white" stroke="#b3b3ff" stroke-width="3"
hill attributes fill="white" stroke="#b3b3ff" stroke-width="3"
forest attributes fill="white" stroke="#b3b3ff" stroke-width="3"

If you want to create new path elements yourself in Inkscape, you should draw them in a rectangle from (-100,-100) to (100,100) and extract the the path info from the SVG. Yeah, adding new icons isn’t easy.

I need to add more icons. I’d also like to add multiple icons for the same terrain such that the code will pick one at random.

I wonder how easy it’s be to add text labels, roads, rivers and borders. :)

The result of the above:

Example map

(Also on GitHub.)


Add Comment

2009-12-02 Hexcrawl

Zak thinks about hexcrawling and asks: do you just sort of write a few bits about each place and wing the details when the players get there, or what? Brian adds that most of his hexes are empty (about one in ten has interesting stuff). That density certainly looks similar to the Wilderlands of High Fantasy maps such as the Lenap map that I started with.

For my own Alder King game, I decided to take the advice found in one of the books saying that there was much more to be found in each hex. I started out with the original hex and the six surrounding hexes à la M20 – a true Microlite Campaign:

Old School Hex Map Tutorial

As time passed and my players started to explore, the map started to grow.

Alder King Map starts to grow...

The current player map is even bigger, now.

The things I do between sessions:

  1. Make sure the hexes around the player’s current hex and any long range goals they want to pursue are on the map with at least a paragraph of notes for each.
  2. Grow the map if I feel like it.
  3. Add notes for hexes on the map that don’t have any.
  4. Add more notes to hexes in order to interlink the various locations.

Also, How to make a Fantasy Sandbox by Rob Conley is the best advice on the topic I’ve seen.

More reading:



Comments on 2009-12-02 Hexcrawl

6 sided campaign building rules! :D

What I’ve been thinking about recently is fantasy map-building in the same way that Traveller generates subsectors with each hex being an 8-mile area on the grid. Roll to see if there’s a settlement or feature. If it’s over a certain size it’s a village/town/city, if it’s got a trading post, etc……

Hmmm. I feel a blogpost coming on!

greywulf 2009-12-02 10:43 UTC

Hm, I faintly remember seeing something like that… A one-page sandbox campaign-maker for OD&D by Nicolas Dessaux aka. Snorri, via Sean Wills’ One-Page Sandbox Maker “one link, one line” blogpost.

AlexSchroeder 2009-12-02 11:58 UTC

Nice post. I love the look of your large(r) scale hex map.

Brian 2009-12-03 04:32 UTC

How do you make your maps? I love the clean look to them, and the fact that they’re digital is a huge bonus (I have a wiki and we spend a fair amount of time scanning after every session.)

cr0m 2009-12-06 06:20 UTC

Old School Hex Map Tutorial! :)

AlexSchroeder 2009-12-06 11:33 UTC

Thank you!

cr0m 2009-12-06 22:59 UTC

I like the map a lot. Thanks for the link also.

timshorts 2012-07-09 00:56 UTC

Add Comment

2009-09-11 Traveller Map Based on UWP

There is an amazing Traveller Map API available out there. Specifically, there’s a service that will produce a PDF based on your UWP list. But you know how it is. I bet half the Traveller referees are trying to code up subsector generators and mappers. Me too!

Here’s my SVG Mapper for Traveller. It comes with example data so you can figure out what format it expects by looking at it. Just click the Submit button! Remember, you need a browser that knows how to deal with SVG files – Firefox will do.

Source code is available. I got to reuse some of my abandoned Old School Hex Mapper. And figuring out the trigonometry stuff is fun. :)


Comments on 2009-09-11 Traveller Map Based on UWP

Very nice! :-)

It looks very nice, and has a simple interface. This is a very good tool to quickly make a subsector.

You are very generous to release this with the GNU General Public License. This means that I might use it together with my random subsectror generator (that is also written in perl).

I have been thinking of doing my own mapper, (other than the ascii one I have made). My plan was to use GD or ImageMagick.

BeRKA 2009-09-11 05:51 UTC

Heh. I come from a FreeSoftware background. Sharing’s the ethical thing to do. ;)

Is your random subsector generator based on the Mongoose rules, or are they the same as for previous editions? I noticed that the generator I had used for my subsector produced strange trade codes and had to write a Perl script to fix them.

Also, Mongoose Traveller doesn’t say how UWP codes for the various based look like. They just provide Scout and Navy as examples. Do you know of a site that defines it?

AlexSchroeder 2009-09-11 07:21 UTC

My generator is based on previous editions? You can select to use book-3 or book-6 rules, that are slightly different when calculating hydrographics. My trade codes are from book-7.

Base codes can differ depending on the version you use. One common version is found on traveller map.

For Naval and Scout base “2” is also commonly used instead of “A”.

BeRKA 2009-09-11 08:25 UTC

Oh wow. Thanks for the link. This was new to me: “special codes deal with the presence of more than one type of base within the same system in order to maintain a single base code letter per system.”

I think I’m going to focus on the rules I have or I’ll go mad. :)

AlexSchroeder 2009-09-11 08:36 UTC


greywulf 2009-09-11 09:35 UTC

Add Comment

2008-06-26 mkhexgrid

So I’m trying to build mkhexgrid.

  1. libpng 👌
  2. ignore libjpg for the moment 👌
  3. FreeType 2 👌
  4. libgd 👎 – I had to configure and build this inside a X11 session!
  5. fortunately I already have libz! :)
  6. and I need the Boost C++ Libraries – I had too add -I/Users/alex/Source/boost_1_35_0 to CPPFLAGS in the Makefile
  7. mkhexgrid 👌

The X11 dependency was surprising. I assume there’s a better way to do it, but I don’t know what it is. The error I got without X11:

Pyrobombus:~/Source/gd-2.0.36RC1 alex$  gcc -DHAVE_CONFIG_H -I. -I/usr/local/include/freetype2 -I/usr/local/include -I/usr/local/include/libpng12 -g -O2 -MT gdft.lo -MD -MP -MF .deps/gdft.Tpo -c gdft.c  -fno-common -DPIC -o .libs/gdft.o
gdft.c:1405:35: error: fontconfig/fontconfig.h: No such file or directory
gdft.c:1468: error: parse error before '*' token
gdft.c:1468: error: parse error before '*' token

I also noticed that SVG output required px units, which is not true. I submitted the following patch to version 0.1.1:

diff -c /Users/alex/Source/mkhexgrid-0.1.1/grid.cpp\~ /Users/alex/Source/mkhexgrid-0.1.1/grid.cpp
*** /Users/alex/Source/mkhexgrid-0.1.1/grid.cpp~	Wed Jan 10 14:37:42 2007
--- /Users/alex/Source/mkhexgrid-0.1.1/grid.cpp	Thu Jun 26 14:06:37 2008
*** 646,652 ****
              throw runtime_error(string(o) + " is not in px");
        case SVG:
!          if (u != "px") throw runtime_error(string(o) + " is not in px");
        case PS:
           if      (u == "pt") ;               // 1 point per point :)
--- 646,657 ----
              throw runtime_error(string(o) + " is not in px");
        case SVG:
!          if      (u == "pt") ;               // 1 point per point :)
!          else if (u == "cm") d *= 72/2.54;   // ~28.35 points per cm
!          else if (u == "mm") d *= 72/25.4;   // ~2.835 points per mm
!          else if (u == "in") d *= 72;        // 72 points per inch
!          else throw runtime_error(string(o) +
!             " has unrecognized unit `" + u + "'");
        case PS:
           if      (u == "pt") ;               // 1 point per point :)

Diff finished.  Thu Jun 26 14:08:15 2008

I just used copy & paste to use the same code that was available for PS output.

And finally this is the specfile I used for my map:


Yay!! :)


Comments on 2008-06-26 mkhexgrid

I also found a python extension to generate hex maps in Inkscape via the Cartographers’ Guild thred index. There seems to be a bug that prevents the hexes from actually having coordinates. I’d have to investigate.

AlexSchroeder 2008-08-01 00:53 UTC

Add Comment

2007-06-08 Old School Hex Mapper Getting Better

The Old School Hex Mapper is getting better. Notice how it creates the loop at the bottom using a very small number of simple rules. I have the feeling that it should be possible to formulate the rules required for a decent layouting of roads.

Funny how some skills thought long lost are coming back. 90° – a² + b² = c². 90° & 60° – ½ : √3 : 1.

(Also on GitHub.)


Add Comment

2007-06-06 Hex Mapping – Roads

I worked some more on the “Old School Hex Mapper” I mentioned before (2007-06-02 Hex Mapping). It does roads! Well, it does them in a crummy way. Basically there’s a road-segment connecting the center of a hex with the edge, which I then copy, rotate, and translate as necessary.

Check out this map with a road. (You need a SVG enabled browser.)

Notice how the ASCII input starts to show limitations when there are more possiblities. Look at this unintended (?) three-way crossing near the city.

The ugly part is that the roads go right through the icons. In fact, they have to, because every road segment has one of its ends in the center of the hex.

So that’s what I’ll try to work on next. I think what I’ll do is have four road tiles, one connecting two adjacent sides (60°), one connecting roads at an angle (120°), and one connecting two opposite sides (180°). Then I can have the connecting parts avoid the center of the hex.

And I’ll get rid of extra three-way crossings near cities and towns. That should be easy to do.

In the mean time, feel free to experiment:

To be honest, I still don’t know whether this is worth pursuing. My hand-drawn hex maps look much better! (My players are not supposed to click the link. :))


Comments on 2007-06-06 Hex Mapping – Roads

I think I’ve worked myself into a dead end, here. Before doing any more development, I should do the following:

  1. Use a hex tile centered on (0,0) in order to facilitate any rotations.
  2. Use a coordinate system with an y axis slanted by 60° instead of the zig-zag I’m currently using in order to facilitiate lookup operations when working on roads.
  3. Split it up in decent subroutines.

AlexSchroeder 2007-06-07 17:05 UTC

I quite like the three-way crossing you’ve got there. It’s unusual features like this which make for good maps, to my mind. After all if it’s like that, there must be a reason :)

Perhaps a lord’s castle is at one of the crossing points and the city is:

  1. abandoned and/or haunted
  2. of a different race (dwarven miners?)
  3. in a different country - the road follows the boundary

Alternatively, maybe the other road leading north from the hills is an Old Road, and largely unused now due to bandits/goblin raiders/lizardkin/whatever. ie, it’s a dangerous route which the players will (innevitably) take :)

GreyWulf 2007-06-08 09:56 UTC

Interesting perspective. :) I was planning on trying to avoid three way crossings in the immediate vicinities of settlements. That’s feasible with a bit of extra coding without requiring too much intelligence built into the system. Thus, if there’s at least one other segment between the crossing and the settlement, we still get three way crossings. Or at least I hope we do.

I’m half way through my rewrite of the code. It uses – God forbid! – objects in Perl! :)

AlexSchroeder 2007-06-08 11:40 UTC

Add Comment

2007-06-02 Hex Mapping

I’ve always wanted to produce good-looking old-school black-on-white hex maps for my roleplaying games. But I didn’t want to use Windows.

Update: Now available as a CGI script! You can also link to your maps directly. Check out the Perl sources of the script.

I broke down and wrote a prototype. Behold my awesome SVG powah! :D

The input file is plain text! Behold my awesome ASCII art powah, too!! :D

The output is SVG, which I then convert via EPS to PDF. Check out the PDF result.

I found that the best solution was to convert from SVG to EPS using InkScape, and from EPS to PDF using ps2pdf or the OSX Viewer. In my particular case, I just used the following Makefile:

%.eps: %.svg
	echo Ignore Gdk-CRITICAL and WARNING messages
	/Applications/ \
	--without-gui --export-area-drawing --export-eps $@ $^

%.pdf: %.eps
	ps2pdf $^ $@

Producing the SVG was the tricky part. I used a little Perl script called

What next? Add more “tiles”, obviously!

Here’s how to do it. First, produce a SVG file using a single dot as the map. This gives you the empty hex.

echo . | perl > empty.svg

Then fill it with some strokes, simplify them, delete a few extra points on the paths, and save. Open the file in you favorite editor and extract the stuff you added, move it into the script data at the beginning, in the defs element, following the grass example. Add an appropriate character mapping to the %char table and you’re done!

That’s what I’ll do right now.

I’m not yet sure how to add roads and rivers.

I’m already starting to wonder… would it make more sense to have all the hex types in the current directory, and use their filename as the reference, and include them as necessary? :) Maybe if this turns out to be the greatest thing since sliced bread. Perhaps I should turn this into a CGI script…


Comments on 2007-06-02 Hex Mapping

Very neat!

Reminds me of the Realms generator I created for Fields of Blood. Here's the code for the Realms stuff and this is the hexmap builder.

That was much fun to hack, and my scrappy code might give you a few ideas too :)

GreyWulf 2007-06-03 08:31 UTC

Yikes! “My next challenge is roads, coastlines and rivers.” Sounds familiar…

AlexSchroeder 2007-06-03 08:37 UTC

Unfortunately I moved onto other things after failing to drum up enough support for Fields of Blood in my group. Boo!

Now I really need a good hex mapper, so methinks I’ll go back to this and carry on with it. I liked the look of the maps :)

GreyWulf 2007-06-03 09:05 UTC

Heh. My code has the benefit of producing SVG, which you can scale and print and it still looks good. You could replace the tiles I’ve been using by translating the $im->line stuff with the appropriate elements. I just looked at output Inkscape generated and the SVG spec and was all set.

I’ll have to think of a solution for rivers, roads and frontiers. Or perhaps I should just give up and keep hand-drawing my maps. Yesterday I ended up printing an empty hex map and hand drawing everything else in it. I thought it looked great. I’ll have to scan it in once my players have been through it.

I might as well just stick to hex paper. Hm…

AlexSchroeder 2007-06-03 09:19 UTC

Add Comment