Justin Pombrio

Hex Boards

A triangular Hex board. Print two copies and tape them together to make an 11x11 board.


There are just three fully symmetric ways to arrange points on a plane:

Pattern 1:

•   •   •   •   •

•   •   •   •   •

•   •   •   •   •

•   •   •   •   •

•   •   •   •   •


Pattern 2:

•     •     •     •     •

   •     •     •     •

•     •     •     •     •

   •     •     •     •

•     •     •     •     •

   •     •     •     •

•     •     •     •     •

   •     •     •     •


Pattern 3:

   •    •          •    •

•          •    •         •

   •    •          •    •

•          •    •         •

   •    •          •    •

•          •    •         •

   •    •          •    •

•          •    •         •

Some board games let you place pieces in one of these patterns: checkers, chess, and Go use Pattern 1, while hex and chinese checkers use Pattern 2. I don’t know of any game that uses the third.

You might think that these three patterns of points are just the three regular tesselations of the plane: a square grid, a triangular grid, and a hexagonal grid. And they are, but which one is which is actually ambiguous!

In the US, we are used to placing pieces at the center of tiles. By this convention, Pattern 1 comes from a square grid, Pattern 2 comes from a hexagonal grid, and Pattern 3 comes from a triangular grid.

But Go uses a different convention - you place pieces at the intersections of the lines. Go still uses a square grid; you just place the pieces differently. By this convention, Pattern 1 (still) comes from a square grid, Pattern 2 comes from a triangular grid, and Pattern 3 comes from a hexagonal grid. So the hex and triangular grids are swapped. There’s a name for this: triangular and hexagonal tilings are duals of each other, and a square grid is its own dual.


Anyhow, all of this means that there are two kinds of boards you can play Hex on. You can either play on a hexagonal grid and place pieces on the tiles, or play on a triangular grid and place pieces on the intersections. I find that I prefer the latter. But there’s a surprising lack of triangular hex board grids on the internet, though, so I wrote my own in Postscript. I wanted it to fit Go stones and be at least size 11, making it too big to fit on one page. So here is:

Half of a hex board

%!PS
%%Orientation: Landscape

% Take param array , and bind each param.
% e.g. 8 3 [/x /y] params x y sub -> 5
/params {
	dup length 1 sub -1 0 % Iterate over array in reverse
	{1 index exch get 3 -1 roll def} % Define each parameter
	for pop % Pop the array
} def

% Use /params to define a function.
% Just don't use recursion :-/
% Or re-use variable names in functions that call each other...
/func {
	/params cvx exch /bind cvx /exec cvx
	5 packedarray cvx
	def
} def

/halve {2 div} def
/inch {72 mul} def
/mm {inch 25.4 div} def
/ratio 30 cos def
/pagewidth 11 inch def
/pageheight 8.5 inch def
/tostring {20 string cvs} def
/drawline {newpath 4 2 roll moveto lineto stroke} def
/addpt {a b c d} {a c add b d add} func

/boardsize 7 def
/cells {0.84 inch mul} def
/border 0.4 inch def

% Put (0, 0) in the lower-left corner of the landscaped page
90 rotate 0 pageheight neg translate
/Ariel findfont 20 scalefont setfont


% The Drawing %

/S_iter 500 def
/S { % debugging
	100 S_iter moveto tostring show
	/S_iter S_iter 20 sub def
} def

/cellcoord {x y} {
    x cells
      y cells halve add
      border add
    y cells ratio mul
      border add
} func

/gridline {a b c d} {
	a b cellcoord c d cellcoord drawline
} func

/thickgridline {5 setlinewidth gridline 1 setlinewidth} def

/rectangle {ax ay bx by cx cy dx dy} {
    ax ay bx by drawline
    bx by cx cy drawline
    cx cy dx dy drawline
    dx dy ax ay drawline
} func

% unused
/parellelogram {s} {
	/parellelogram_iter {i} {
		i 0 i s gridline
		0 i s i gridline
		i 0 0 i gridline
		i s s i gridline
	} func
	0 1 s {parellelogram_iter} for
} func

/triangle {s} {
	% draw the triangular grid
	/triangle_iter {i} {
		i 0 i s i sub gridline
		0 i s i sub i gridline
		i 0 0 i gridline
	} func
	0 1 s {triangle_iter} for
	% draw the edge labels
	-0.25 0.25 -0.25 s thickgridline

	0.20 -0.20 cellcoord
        s -0.20 cellcoord
        s 0.05 add -0.30 cellcoord
	0.25 -0.30 cellcoord
            rectangle
	
} func

11 triangle

showpage