SMERESKI
  1. PROJECTS
  2. SKILLS
  3. RESUME
  4. BLOG
  5. GAMES
  6. CONTACT

POST · 2026-07-13

2026-07-13 · 6 MIN READ

Twelve pentagons

You cannot tile a sphere with hexagons alone. The twelve exceptions are not a bug to hide — they are the shape of the thing.

gamesalgorithmgodot

Most hex-grid games that call themselves spherical are a flat grid with a sphere painted on. Mine is not, and the reason is a fact of geometry you cannot negotiate with: a sphere cannot be tiled with hexagons alone. Try it and you will always come up short. Euler's formula demands exactly twelve pentagons, no matter how large the board gets. A soccer ball has them. A geodesic dome has them. My tower-defense planet has them, and every system that touches the board has to know it.

The construction is the classic one. Start with an icosahedron — twenty triangular faces, the most sphere-like solid you can make from identical triangles. Subdivide each face into smaller triangles, some number of times; call that the frequency. Project every resulting vertex out onto the sphere. Now take the dual: put a cell at each vertex, and connect cells whose triangles shared an edge. Vertices that had six triangles around them become hexagons. The twelve original corners of the icosahedron had only five, and they become pentagons. That dual is a Goldberg polyhedron, and the cell count falls straight out of the frequency: ten times the frequency squared, plus two. The plus two is the geometry refusing to round off.

The temptation is to paper over the pentagons — special-case them, or hide them at the poles where nobody looks. That is the wrong instinct. They are not a defect in the tiling; they are what makes a closed surface possible at all. So instead of hiding them, the board exposes them: every cell answers whether it is a pentagon, and every consumer decides what that means for itself. A tower on a pentagon has five neighbours instead of six. That is a real, playable difference, and the player can see it if they look. Building the exception into the interface, rather than smuggling it past, is what let the rest of the code stop worrying about it.

Pathing on a sphere breaks the other habit you brought with you: straight-line distance is a lie. The shortest path between two cells is an arc, not a segment, so cost is measured as the great-circle angle between cell centres — the angle you sweep as you travel, not the chord you would cut through the planet. Feed that into A* and enemies walk the surface the way things actually walk on a globe. Feed Euclidean distance in instead and they will happily prefer routes that tunnel through the core.

One thing I had to build by hand: GDScript has no priority queue. A* is not A* without one — swap it for a linear scan of the open set and you have written Dijkstra with extra steps and a performance cliff. So the pathfinder carries a small binary min-heap, sift-up and sift-down, about thirty lines. It is the least glamorous code in the project and the reason the planet paths in time.

The whole board is a plain reference-counted object. No scene, no nodes, no engine types. That was not tidiness for its own sake — it is what let the entire thing be swapped out, which is the subject of another post.

REFERENCES3 LINKS