mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
226 lines
12 KiB
Text
226 lines
12 KiB
Text
/- 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
|