Craps — the come-out roll and point-resolution rules come_out(total) resolves the first roll: 7/11 wins, 2/3/12 craps out, any other number becomes the "point"
resolve(point, rolls) plays the rest of the round — rolling the point again wins, a 7 loses. All from a roll log. Run: soma run craps.cell --signal demo Test: soma test craps.cell
A Soma program from the games part of the verified corpus: 77 lines, cells Craps, CrapsTests. It passes soma check with soma 3.2.4.
How it is built
The cell Craps declares 4 signals in its face: come_out(total: Int) -> Map, resolve(point: Int, rolls: List) -> String, play(rolls: List) -> Map and demo() -> Map. Handlers: come_out (line 20), resolve (line 29), play (line 41) and demo (line 51).
The file also holds 1 test cell (CrapsTests) with 12 assertions, run by soma test.
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 = truecraps.cell
// ============================================================================
// Craps — the come-out roll and point-resolution rules
// ============================================================================
//
// come_out(total) resolves the first roll: 7/11 wins, 2/3/12 craps out, any
// other number becomes the "point". resolve(point, rolls) plays the rest of
// the round — rolling the point again wins, a 7 loses. All from a roll log.
//
// Run: soma run craps.cell --signal demo
// Test: soma test craps.cell
cell Craps {
face {
signal come_out(total: Int) -> Map
signal resolve(point: Int, rolls: List) -> String
signal play(rolls: List) -> Map
signal demo() -> Map
}
on come_out(total: Int) {
return match total {
7 || 11 -> map("result", "win", "point", 0)
2 || 3 || 12 -> map("result", "lose", "point", 0)
_ -> map("result", "point", "point", total)
}
}
// After a point is set, scan rolls until the point (win) or a 7 (lose).
on resolve(point: Int, rolls: List) {
let outcome = "open"
for r in rolls {
if outcome == "open" {
if r == point { outcome = "win" }
else if r == 7 { outcome = "lose" }
}
}
return outcome
}
// Full round: first element is the come-out, the rest are point rolls.
on play(rolls: List) {
let co = come_out(rolls[0])
if co.result != "point" {
return map("result", co.result, "point", 0)
}
let rest = []
for i in range(1, len(rolls)) { rest = push(rest, rolls[i]) }
return map("result", resolve(co.point, rest), "point", co.point)
}
on demo() {
// come out 6 (point), then 8, 6 → win on the point
return play([6, 8, 6])
}
}
cell test CrapsTests {
rules {
// natural win / craps out
assert come_out(7).result == "win"
assert come_out(11).result == "win"
assert come_out(2).result == "lose"
assert come_out(12).result == "lose"
// a point is established
assert come_out(6).result == "point"
assert come_out(6).point == 6
// resolving the point: making it wins, a 7 first loses
assert resolve(6, [8, 6]) == "win"
assert resolve(6, [8, 7, 6]) == "lose"
assert resolve(8, [5, 9, 10]) == "open"
// full rounds
assert play([6, 8, 6]).result == "win"
assert play([7]).result == "win"
assert play([4, 7]).result == "lose"
}
}What the toolchain says
$ soma check craps.cell
✓ All checks passed.$ soma test craps.cell
test CrapsTests ...
✓ assert come_out(7).result == "win"
✓ assert come_out(11).result == "win"
✓ assert come_out(2).result == "lose"
✓ assert come_out(12).result == "lose"
✓ assert come_out(6).result == "point"
✓ assert come_out(6).point == 6
✓ assert resolve(6, [8, 6]) == "win"
✓ assert resolve(6, [8, 7, 6]) == "lose"
✓ assert resolve(8, [5, 9, 10]) == "open"
✓ assert play([6, 8, 6]).result == "win"
✓ assert play([7]).result == "win"
✓ assert play([4, 7]).result == "lose"
12 tests: 12 passed, 0 failed$ soma verify craps.cell
Verifying craps.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)