/** * Canonical tile patterns for linear features. * Each pattern is defined by a base edge mask and a human-readable name. * Patterns can be rotated by 60° increments to produce all placements. */ import type { EdgeMask } from './types.js'; import { HexEdge } from './types.js'; import { edgeMask, rotateMask, edgeCount } from './edge-connectivity.js'; export interface TilePattern { id: string; name: string; baseMask: EdgeMask; /** Number of distinct rotations (accounting for symmetry) */ rotations: number; } /** All canonical patterns for linear features */ export const TILE_PATTERNS: TilePattern[] = [ { id: 'dead-end', name: 'Dead End', baseMask: edgeMask(HexEdge.E), rotations: 6, }, { id: 'straight', name: 'Straight', baseMask: edgeMask(HexEdge.E, HexEdge.W), rotations: 3, // Symmetric: E-W = same as W-E }, { id: 'gentle-curve', name: 'Wide Curve', baseMask: edgeMask(HexEdge.E, HexEdge.SW), rotations: 6, }, { id: 'sharp-bend', name: 'Sharp Bend', baseMask: edgeMask(HexEdge.E, HexEdge.SE), rotations: 6, }, { id: 'y-junction', name: 'Y Split', baseMask: edgeMask(HexEdge.NE, HexEdge.SE, HexEdge.W), rotations: 6, }, { id: 'y-junction-wide', name: 'Y Wide', baseMask: edgeMask(HexEdge.NE, HexEdge.SW, HexEdge.SE), rotations: 6, }, { id: 'crossroads', name: 'Cross', baseMask: edgeMask(HexEdge.NE, HexEdge.E, HexEdge.SW, HexEdge.W), rotations: 3, }, ]; /** * Get all unique rotations for a pattern. * Returns array of { mask, rotation } where rotation is the number of 60° steps. */ export function getPatternRotations(pattern: TilePattern): Array<{ mask: EdgeMask; rotation: number }> { const seen = new Set(); const result: Array<{ mask: EdgeMask; rotation: number }> = []; for (let r = 0; r < 6; r++) { const mask = rotateMask(pattern.baseMask, r); if (!seen.has(mask)) { seen.add(mask); result.push({ mask, rotation: r }); } } return result; } /** * Rotate a mask by N steps (each step = 60° clockwise). */ export function rotatePattern(mask: EdgeMask, steps: number): EdgeMask { return rotateMask(mask, steps); }