/** * Canonical tile patterns for linear features. * Each pattern has a base edge mask and can be rotated in 60° increments. * Coastlines only use 2-edge patterns and have an additional waterSide property. */ import type { EdgeMask } from './types.js'; import { HexEdge } from './types.js'; import { edgeMask, rotateMask } from './edge-connectivity.js'; export interface TilePattern { id: string; name: string; baseMask: EdgeMask; /** Max distinct rotations (accounting for symmetry) */ rotations: number; /** Number of connected edges */ edgeCount: number; } /** General patterns for road/river (all edge counts) */ export const GENERAL_PATTERNS: TilePattern[] = [ { id: 'dead-end', name: 'Dead End', baseMask: edgeMask(HexEdge.E), rotations: 6, edgeCount: 1, }, { id: 'straight', name: 'Straight', baseMask: edgeMask(HexEdge.E, HexEdge.W), rotations: 3, edgeCount: 2, }, { id: 'gentle-curve', name: 'Wide Curve', baseMask: edgeMask(HexEdge.E, HexEdge.SW), rotations: 6, edgeCount: 2, }, { id: 'sharp-bend', name: 'Sharp Bend', baseMask: edgeMask(HexEdge.E, HexEdge.SE), rotations: 6, edgeCount: 2, }, { id: 'y-junction', name: 'Y Split', baseMask: edgeMask(HexEdge.NE, HexEdge.SE, HexEdge.W), rotations: 6, edgeCount: 3, }, { id: 'y-junction-wide', name: 'Y Wide', baseMask: edgeMask(HexEdge.NE, HexEdge.SW, HexEdge.SE), rotations: 6, edgeCount: 3, }, { id: 'crossroads', name: 'Cross', baseMask: edgeMask(HexEdge.NE, HexEdge.E, HexEdge.SW, HexEdge.W), rotations: 3, edgeCount: 4, }, ]; /** Coastline patterns — only 2-edge (a coast is always a line from A to B) */ export const COASTLINE_PATTERNS: TilePattern[] = [ { id: 'straight', name: 'Straight', baseMask: edgeMask(HexEdge.E, HexEdge.W), rotations: 3, edgeCount: 2, }, { id: 'gentle-curve', name: 'Wide Curve', baseMask: edgeMask(HexEdge.E, HexEdge.SW), rotations: 6, edgeCount: 2, }, { id: 'sharp-bend', name: 'Sharp Bend', baseMask: edgeMask(HexEdge.E, HexEdge.SE), rotations: 6, edgeCount: 2, }, ]; /** * Get the appropriate patterns for a terrain type. */ export function getPatternsForTerrain(terrainId: string): TilePattern[] { if (terrainId === 'coastline') return COASTLINE_PATTERNS; return GENERAL_PATTERNS; } /** * Rotate a mask by N steps (each step = 60° clockwise). */ export function rotatePattern(mask: EdgeMask, steps: number): EdgeMask { return rotateMask(mask, steps); }