Justin Pombrio

Hex Boards

There are three regular tilings on the plane - square, triangular, and hexagonal. If you ignore the tiling, and just look at where the center of each tile is, you get the following three patterns:

•   •   •   •   •

•   •   •   •   •

•   •   •   •   •

•   •   •   •   •

•   •   •   •   •



•     •     •     •     •

   •     •     •     •

•     •     •     •     •

   •     •     •     •

•     •     •     •     •

   •     •     •     •

•     •     •     •     •

   •     •     •     •



   •    •          •    •

•          •    •         •

   •    •          •    •

•          •    •         •

   •    •          •    •

•          •    •         •

   •    •          •    •

•          •    •         •

Some board games let you place pieces in one of these patterns: checkers, chess, and Go use the first, while hex and chinese checkers use the second. I don’t know of any game that uses the third, other than unusual Go and hex variants.

In the US, we are used to placing pieces at the center of tiles. 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. But you can’t put the points from the centers of a hexagonal grid onto the vertices of a hexagonal grid; they make different patterns. Instead, you have to put them on a triangular grid. Likewise, points from the centers of a triangular grid may be placed on the vertices of a hexagonal grid. There’s a name for this: triangular and hexagonal tilings are duals of each other, and a square grid is its own dual.

I’m interested in the game of Hex. It uses the second pattern of points, which means it can be drawn on either a triangular or hexagonal grid. It is traditionally drawn on a hexagonal grid, though I find the triangular grid easier on the eyes. There is a surprising lack of triangular hex board grids on the internet, though, so I wrote one 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

% 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.3 0.3 -0.3 s thickgridline
	0.25 -0.25 cellcoord s -0.25 cellcoord drawline
	0.30 -0.35 cellcoord s 0.05 add -0.35 cellcoord drawline
	
} func

11 triangle

showpage