soma.cell

Tic-tac-toe win detection — pure board logic

A board is a flat list of 9 cells, each "X", "O", or "" (empty). The winner() handler scans the 8 winning lines and returns the mark of the winner, "draw" if the board is full with no line, or "" if still playing. Run: soma run tic_tac_toe.cell --signal demo Test: soma test tic_tac_toe.cell

A Soma program from the games part of the verified corpus: 67 lines, cells TicTacToe, TicTacToeTests. It passes soma check with soma 3.2.4.

How it is built

The cell TicTacToe declares 3 signals in its face: winner(board: List) -> String, is_full(board: List) -> Bool and demo() -> String. Handlers: is_full (line 28), winner (line 32) and demo (line 47). Private helpers: _lines.

The file also holds 1 test cell (TicTacToeTests) with 6 assertions, run by soma test.

Generated from soma describe on this file.

The source

soma.toml

[package]
name = "games-corpus"
version = "0.1.0"
description = "Training corpus: games & simulations"

# The turn/phase machine is intentionally cyclic (a game loops through
# phases each round) with a `* -> over` escape, so we verify only that no
# reachable state deadlocks — liveness to a terminal is not the contract here.
[verify]
deadlock_free = true

tic_tac_toe.cell

// ============================================================================
// Tic-tac-toe win detection — pure board logic
// ============================================================================
//
// A board is a flat list of 9 cells, each "X", "O", or "" (empty). The
// winner() handler scans the 8 winning lines and returns the mark of the
// winner, "draw" if the board is full with no line, or "" if still playing.
//
// Run:  soma run tic_tac_toe.cell --signal demo
// Test: soma test tic_tac_toe.cell

cell TicTacToe {
    face {
        signal winner(board: List) -> String
        signal is_full(board: List) -> Bool
        signal demo() -> String
    }

    // The 8 winning triples (row, column, diagonal indices).
    on _lines() {
        return [
            [0, 1, 2], [3, 4, 5], [6, 7, 8],   // rows
            [0, 3, 6], [1, 4, 7], [2, 5, 8],   // cols
            [0, 4, 8], [2, 4, 6]               // diagonals
        ]
    }

    on is_full(board: List) {
        return all(board, c => c != "")
    }

    on winner(board: List) {
        let result = ""
        for line in _lines() {
            let a = board[line[0]]
            let b = board[line[1]]
            let c = board[line[2]]
            if a != "" && a == b && b == c {
                result = a
            }
        }
        if result != "" { return result }
        if is_full(board) { return "draw" }
        return ""
    }

    on demo() {
        let b = ["X", "O", "X", "O", "X", "O", "X", "", ""]
        return winner(b)
    }
}

cell test TicTacToeTests {
    rules {
        // X wins the left column (0,3,6)
        assert winner(["X", "O", "O", "X", "", "", "X", "", ""]) == "X"
        // O wins the main diagonal (0,4,8)
        assert winner(["O", "X", "X", "", "O", "", "", "", "O"]) == "O"
        // full board, no line → draw
        assert winner(["X", "O", "X", "X", "O", "O", "O", "X", "X"]) == "draw"
        // game still in progress → ""
        assert winner(["X", "", "", "", "O", "", "", "", ""]) == ""
        assert is_full(["X", "O", "X", "O", "X", "O", "X", "O", "X"]) == true
        assert is_full(["X", "", "X", "O", "X", "O", "X", "O", "X"]) == false
    }
}

What the toolchain says

Run on a fresh copy of the program at build time; the outputs are pasted unedited.

$ soma check tic_tac_toe.cell
✓ All checks passed.
$ soma test tic_tac_toe.cell
test TicTacToeTests ...
  ✓ assert winner(["X", "O", "O", "X", "", "", "X", "", ""]) == "X"
  ✓ assert winner(["O", "X", "X", "", "O", "", "", "", "O"]) == "O"
  ✓ assert winner(["X", "O", "X", "X", "O", "O", "O", "X", "X"]) == "draw"
  ✓ assert winner(["X", "", "", "", "O", "", "", "", ""]) == ""
  ✓ assert is_full(["X", "O", "X", "O", "X", "O", "X", "O", "X"]) == true
  ✓ assert is_full(["X", "", "X", "O", "X", "O", "X", "O", "X"]) == false

6 tests: 6 passed, 0 failed
$ soma verify tic_tac_toe.cell
Verifying tic_tac_toe.cell...
No state machine in this program: nothing to prove beyond `soma check` (invariants and lifecycles are what verify proves).
VERIFY OK (vacuous — no state machine)

Builtins used

all

Source file: /corpus/games/tic_tac_toe.cell · examples/corpus/games/tic_tac_toe.cell