Developer Documentation

This document includes theory for topoi required for the source-code that enables the digital version. Some of this exists standalone in a discrete mathematic setting, defining algebra for moving pieces over a space described by 3-D notation space. The operations which sometimes involve geometry has to be assisted by computationally efficient data-structures and algorithms.

Theory

Notation

For convenient interoperation with programming-languages, this document uses 0-based indexing as opposed to the 1-based indexing in the tutorial.

A position of a piece is described by the notation $(S, H, N)$, which denotes:

  • Side ($S \in \{0\dots 5\}$)
  • Hexagon ($H \in \{0\dots 6\}$)
  • Number ($N \in \{0\dots 5\}$)

Unique Unsigned Integer Identifier We can obtain a unique unsigned integer identifier as:

\begin{equation} \text{uuid}(s, h, n) = \mathbb{I}[h > 0] + 3h(h-1) + hs + n \end{equation}

This follows from that each successive hexagon has $6h$ pieces. Each side has $h$ pieces when excluding the last piece (considering it start of next side). This leads to a simple series sum $6h(h-1)/2 = 3h(h-1)$. Following this cumulative sum, each side can be offset by using $sh$.

Reducing to a unique unsigned identifier is useful for using arrays and this function as a perfect hash to implement an optimized dictionary using an array.

Hover over the markers on the raw-board to see the numbering (in 0-based and 1-based indexing).

Graph Theory

We may use graph theory to model the board. The positions occupied the pieces are vertices or nodes. The connections in the hexagonal lattice created in the board are edges.

Each node is identified by $(S, H, N)$ as described above. The lattice can have at most 6 neighbours for each node. We denote the directions radially from a node as $\{0, 1, 2, 3, 4, 5\}$ with $0$ denoting $y$-axis and the indices rotating counterclockwise.

In this section, we define graph operations to describe moves and controlled traversals to obtain paths which are linear, rotations and such. These are ultimately used to describe moves in the game like Slide, Nudge, Pivot etc.

State

It is important to track the state of the board during the course of the game.

The Graph is stored as an adjacency list (adj). For the central node $(0, 0, 0)$, the entry includes the value of the neighbour in each direction as key:

      
adj[
  0 // '(0, 0, 0)'
] = {
  0: 2, // '(1, 1, 0)'
  1: 1, // '(0, 1, 0)'
  2: 6, // '(5, 1, 0)'
  3: 5, // '(4, 1, 0)'
  4: 4, // '(3, 1, 0)'
  5: 3, // '(2, 1, 0)'
}
      

The information on the location of nodes (empty and non-empty) are stored as a dictionary map.

      
map[
  0 // '(0, 0, 0)'
] = {
   id: Notation(0, 0, 0), 
   loc: Point(240.0, 240.0)
}
      
      
Slide

In slide, a piece or a group of pieces are moved together in a linear fashion. Some examples of these paths include:

  1. $[(4, 7, 0), (4, 6, 0), (4, 5, 0), (4, 4, 0), (4, 3, 0), (4, 2, 0), (4, 1, 0), (0, 0, 0)]$
  2. $[(4, 5, 0), (3, 5, 4), (3, 5, 3), (3, 5, 2), (3, 5, 1), (3, 5, 0), (2, 6, 5)]$

While there are some useful patterns above, it's not obvious how to use modular arithmetic or similar to get a linear path when increments become non-unit. Graph theoretic modelling appears to be simpler here. Using our graph-theoretic model, a slide is move of pieces for steps along a specified direction.

User Interface

Desktop

Touch Devices

Rendering