programextensions/web/demos/life.xtl

A live page: Conway's Life kept by an X_eTaL program and drawn as SVG, one generation per request. The program is the server's request loop. Run: just demo web life, then open http://127.0.0.1:8470/ (New board, Glider; Quit ends the program)

source · imports wb: extensions/web/lib/Web.xtl

ᵘl̲ife : (Num a, Truthy a) => a -> a

function · line 10

Life (as in X_eTaL's demos/life.xtl): every cell plus its neighbors by rotating along both axes and summing; alive next at 3, or 4 if alive

ᵘl̲ife ← { ('+ r̲/₁₂ -1 0 1 o̲-₁₂ ⍵) { (⍺ = 3) + ⍵ × ⍺ = 4 } ⍵ }
Used in: ᵘa̲nswer

ᵘs̲eed : Truthy a => Int -> a

function · line 13

an n by n board, about one cell in four alive; or one glider

ᵘs̲eed ← { n → (n c̲at n) r̲eshape 1 = r̲oll! (n × n) r̲eshape 4 }
Used in: ᵘa̲nswer, last

ᵘg̲lider : Num a => Int -> a

function · line 15

(n * n - 3 is n times n - 3: the rows below the glider)

ᵘg̲lider ← { n → (n c̲at n) r̲eshape (n t̲ake 0 1 0) c̲at (n t̲ake 0 0 1) c̲at (n t̲ake 1 1 1) c̲at (n × n − 3) r̲eshape 0 }
Used in: ᵘa̲nswer

ᵘs̲ize : Char -> Int

function · line 18

the size a request asks for (?n=), 8 to 200, else 48

ᵘs̲ize ← { s →
  0 = t̲ally s ? 48
  8 m̲ax 200 m̲in f̲loor f̲irst n̲umbers s
}
Used in: ᵘa̲nswer

ᵘj̲oin : Box Char -> Char

function · line 25

the board as SVG: one unit square per live cell ("M col row h1v1h-1z") boxed strings joined into one (from "", so no live cells is "")

ᵘj̲oin ← { s → d̲isclose '{ e̲nclose (d̲isclose ⍺) c̲at d̲isclose ⍵ } r̲/ (e̲nclose "") c̲at s }
Used in: ᵘs̲vg

ᵘs̲vg : Truthy a => a -> Char

function · line 26
ᵘs̲vg ← { b →
  n ← t̲ally b
  w ← f̲ormat n
  d ← ᵘj̲oin '{ "M" c̲at (f̲ormat ⍵ m̲od n) c̲at " " c̲at (f̲ormat ⍵ d̲iv n) c̲at "h1v1h-1z" } m̲ap (w̲here r̲avel b) − 1
  "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 " c̲at w c̲at " " c̲at w c̲at "' shape-rendering='crispEdges'><rect width='" c̲at w c̲at "' height='" c̲at w c̲at "' fill='#14161a'/><path fill='#e8483b' d='" c̲at d c̲at "'/></svg>"
}
Used in: ᵘa̲nswer

page : Char

value · line 34

the page: the board, refreshed several times a second

page ← "<!doctype html><html><head><meta charset='utf-8'><title>Life -- X_eTaL on the web</title><style>body{background:#0d0e10;color:#ddd;font-family:system-ui,sans-serif;text-align:center}img{width:min(90vw,600px);image-rendering:pixelated;border:1px solid #333}button{margin:.5em;padding:.4em 1em}</style></head><body><h1>Life, computed in X_eTaL</h1><p>Each frame is one request: the X_eTaL program steps the board and replies with SVG.</p><img id='b' src='/life.svg' alt='the board'><div><button onclick=nw()>New board</button><button onclick=gl()>Glider</button><button onclick=qt()>Quit</button></div><script>let on=true;function nw(){fetch('/new')}function gl(){fetch('/glider')}function qt(){on=false;fetch('/quit')}setInterval(()=>{if(on){document.getElementById('b').src='/life.svg?'+Date.now()}},150)</script></body></html>"
Used in: ᵘa̲nswer

ᵘa̲nswer : (Num a, Truthy a) => a -> a

function · line 38

one request: the board after answering it (an empty board: quit); x r_ight y is y, so a reply is sent and the board passed on

ᵘa̲nswer ← { b →
  0 = t̲ally b ? b
  r ← ʷᵇn̲ext! 60
  r m̲atch "none" ? b
  r m̲atch "GET /" ? (200 ʷᵇr̲eply! page) r̲ight b
  r m̲atch "GET /life.svg" ? (200 ʷᵇr̲eply! ᵘs̲vg b) r̲ight ᵘl̲ife b
  r m̲atch "GET /new" ? (200 ʷᵇr̲eply! "a new board") r̲ight ᵘs̲eed ᵘs̲ize ʷᵇp̲aram "n"
  r m̲atch "GET /glider" ? (200 ʷᵇr̲eply! "a glider") r̲ight ᵘg̲lider ᵘs̲ize ʷᵇp̲aram "n"
  r m̲atch "GET /quit" ? (200 ʷᵇr̲eply! "bye") r̲ight 0 0 r̲eshape 0
  (404 ʷᵇr̲eply! "no such page: " c̲at ʷᵇp̲ath @) r̲ight b
}
Used in: last

port : Int

value · line 50
port ← ʷᵇs̲erve! 8470

last : Int

value · line 52
last ← 100000 'ᵘa̲nswer p̲ower ᵘs̲eed 48

port : Int

value · line 53
port ← ʷᵇs̲top! @