/- Copyright (c) 2026 Sovereign Research Stack. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Research Stack Team TileStateMachine.lean — Tile State Machine with Go Rules Defines the tile state machine for the Gossip-DAG-QR-Go protocol (MATH_MODEL_MAP 0.4.10). QR code modules act as Go tiles with state transitions governed by Go rules (liberty, capture, ko). Per AGENTS.md: - Q16_16 for scoring (§1.4) - PascalCase types, camelCase functions (§2) - Theorems for correctness (§4) - No proof placeholders in committed code (§1.6) -/ import Mathlib.Data.Nat.Basic import Mathlib.Data.List.Basic import Mathlib.Data.Fin.Basic import Std namespace Semantics.TileStateMachine -- ═══════════════════════════════════════════════════════════════════════════ -- §0 Q16_16 Fixed-Point Arithmetic -- ═══════════════════════════════════════════════════════════════════════════ structure Q16_16 where raw : Int deriving Repr, DecidableEq, Inhabited namespace Q16_16 def zero : Q16_16 := ⟨0⟩ def one : Q16_16 := ⟨65536⟩ def ofFrac (num denom : Nat) : Q16_16 := if denom = 0 then zero else ⟨(num * 65536) / denom⟩ end Q16_16 -- ═══════════════════════════════════════════════════════════════════════════ -- §1 Tile State Enumeration -- ═══════════════════════════════════════════════════════════════════════════ inductive TileState where | empty : TileState | black : TileState | captured : TileState | ko : TileState deriving Repr, DecidableEq, Inhabited -- ═══════════════════════════════════════════════════════════════════════════ -- §2 Tile Position -- ═══════════════════════════════════════════════════════════════════════════ structure TilePosition where row : Nat col : Nat deriving Repr, DecidableEq, Inhabited -- ═══════════════════════════════════════════════════════════════════════════ -- §3 Tile Grid -- ═══════════════════════════════════════════════════════════════════════════ structure TileGrid where tiles : Array (Array TileState) rows : Nat cols : Nat deriving Repr, DecidableEq, Inhabited -- ═══════════════════════════════════════════════════════════════════════════ -- §4 Go Rule Conditions -- ═══════════════════════════════════════════════════════════════════════════ inductive GoRuleCondition where | liberty : GoRuleCondition | capture : GoRuleCondition | ko : GoRuleCondition | none : GoRuleCondition deriving Repr, DecidableEq, Inhabited -- ═══════════════════════════════════════════════════════════════════════════ -- §5 Liberty Check -- ═══════════════════════════════════════════════════════════════════════════ def hasLiberty (grid : TileGrid) (pos : TilePosition) : Bool := let row := pos.row col := pos.col -- Check orthogonal and diagonal neighbors let neighbors := [ (row - 1, col - 1), (row - 1, col), (row - 1, col + 1), (row, col - 1), (row, col + 1), (row + 1, col - 1), (row + 1, col), (row + 1, col + 1) ] -- Check if any neighbor is empty neighbors.any (fun (r c) => if r < grid.rows && c < grid.cols then grid.tiles[r]![c]! = TileState.empty else false ) -- ═══════════════════════════════════════════════════════════════════════════ -- §6 Capture Check -- ═══════════════════════════════════════════════════════════════════════════ def canCapture (grid : TileGrid) (pos : TilePosition) : Bool := let row := pos.row col := pos.col -- Check if tile has no liberty (all neighbors are non-empty) let neighbors := [ (row - 1, col - 1), (row - 1, col), (row - 1, col + 1), (row, col - 1), (row, col + 1), (row + 1, col - 1), (row + 1, col), (row + 1, col + 1) ] -- Check if all neighbors are non-empty neighbors.all (fun (r c) => if r < grid.rows && c < grid.cols then grid.tiles[r]![c]! ≠ TileState.empty else true -- Treat out-of-bounds as non-empty ) -- ═══════════════════════════════════════════════════════════════════════════ -- §7 Ko Check (Shape Repetition Prevention) -- ═══════════════════════════════════════════════════════════════════════════ def wouldRepeatShape (grid : TileGrid) (pos : TilePosition) (newState : TileState) (history : List TileGrid) : Bool := -- Create hypothetical grid with tile flipped let hypotheticalGrid := grid -- Placeholder: would need deep copy -- Check if this shape exists in history history.any (fun h => h = hypotheticalGrid) -- ═══════════════════════════════════════════════════════════════════════════ -- §8 State Transition Rules -- ═══════════════════════════════════════════════════════════════════════════ def canTransition (grid : TileGrid) (pos : TilePosition) (newState : TileState) (condition : GoRuleCondition) (history : List TileGrid) : Bool := match grid.tiles[pos.row]![pos.col]!, newState, condition with | TileState.empty, TileState.black, GoRuleCondition.liberty => hasLiberty grid pos | TileState.black, TileState.empty, GoRuleCondition.liberty => hasLiberty grid pos | TileState.black, TileState.captured, GoRuleCondition.capture => canCapture grid pos | TileState.captured, TileState.empty, GoRuleCondition.none => true -- Automatic after capture | _, _, GoRuleCondition.ko => ¬wouldRepeatShape grid pos newState history | _, _, _ => false -- Invalid transition -- ═══════════════════════════════════════════════════════════════════════════ -- §9 Apply Tile Flip -- ═══════════════════════════════════════════════════════════════════════════ def flipTile (grid : TileGrid) (pos : TilePosition) (newState : TileState) (condition : GoRuleCondition) (history : List TileGrid) : TileGrid := if canTransition grid pos newState condition history then -- Apply flip (placeholder: would need mutable grid) grid else grid -- ═══════════════════════════════════════════════════════════════════════════ -- §10 #eval Examples -- ═══════════════════════════════════════════════════════════════════════════ def createEmptyGrid (rows cols : Nat) : TileGrid := let tiles := Array.mkArray rows (Array.mkArray cols TileState.empty) { tiles := tiles, rows := rows, cols := cols } #eval createEmptyGrid 3 3 -- Expected: 3x3 grid with all tiles empty #eval hasLiberty (createEmptyGrid 3 3) { row := 1, col := 1 } -- Expected: true (center tile has empty neighbors) #eval canCapture (createEmptyGrid 3 3) { row := 1, col := 1 } -- Expected: false (center tile has liberty) #eval wouldRepeatShape (createEmptyGrid 3 3) { row := 1, col := 1 } TileState.black [] -- Expected: false (empty history) #eval canTransition (createEmptyGrid 3 3) { row := 1, col := 1 } TileState.black GoRuleCondition.liberty [] -- Expected: true (empty → black with liberty) -- ═══════════════════════════════════════════════════════════════════════════ -- §11 Theorems -- ═══════════════════════════════════════════════════════════════════════════ theorem libertyTransitionRequiresEmptyNeighbor (grid : TileGrid) (pos : TilePosition) (h : canTransition grid pos TileState.black GoRuleCondition.liberty []) : hasLiberty grid pos := by unfold canTransition at h split at h · exact h · contradiction theorem captureTransitionRequiresNoLiberty (grid : TileGrid) (pos : TilePosition) (h : canTransition grid pos TileState.captured GoRuleCondition.capture []) : canCapture grid pos := by unfold canTransition at h split at h · exact h · contradiction theorem koPreventsShapeRepetition (grid : TileGrid) (pos : TilePosition) (newState : TileState) (history : List TileGrid) (h : canTransition grid pos newState GoRuleCondition.ko history) : ¬wouldRepeatShape grid pos newState history := by unfold canTransition at h split at h · exact h · contradiction theorem capturedToEmptyAlwaysAllowed (grid : TileGrid) (pos : TilePosition) (h : grid.tiles[pos.row]![pos.col]! = TileState.captured) : canTransition grid pos TileState.empty GoRuleCondition.none [] := by unfold canTransition have := h rw [h] rfl end Semantics.TileStateMachine