b56590ddc9
Now life.tlv and gemini.tlv are also minimizing how much of the standard library they pull in, just to be easy to read.
595 lines
19 KiB
Lua
595 lines
19 KiB
Lua
# .tlv file generated by https://github.com/akkartik/teliva
|
|
# You may edit it if you are careful; however, you may see cryptic errors if you
|
|
# violate Teliva's assumptions.
|
|
#
|
|
# .tlv files are representations of Teliva programs. Teliva programs consist of
|
|
# sequences of definitions. Each definition is a table of key/value pairs. Keys
|
|
# and values are both strings.
|
|
#
|
|
# Lines in .tlv files always follow exactly one of the following forms:
|
|
# - comment lines at the top of the file starting with '#' at column 0
|
|
# - beginnings of definitions starting with '- ' at column 0, followed by a
|
|
# key/value pair
|
|
# - key/value pairs consisting of ' ' at column 0, containing either a
|
|
# spaceless value on the same line, or a multi-line value
|
|
# - multiline values indented by more than 2 spaces, starting with a '>'
|
|
#
|
|
# If these constraints are violated, Teliva may unceremoniously crash. Please
|
|
# report bugs at http://akkartik.name/contact
|
|
- __teliva_timestamp: original
|
|
str_helpers:
|
|
>-- some string helpers from http://lua-users.org/wiki/StringIndexing
|
|
>
|
|
>-- index characters using []
|
|
>getmetatable('').__index = function(str,i)
|
|
> if type(i) == 'number' then
|
|
> return str:sub(i,i)
|
|
> else
|
|
> return string[i]
|
|
> end
|
|
>end
|
|
>
|
|
>-- ranges using (), selected bytes using {}
|
|
>getmetatable('').__call = function(str,i,j)
|
|
> if type(i)~='table' then
|
|
> return str:sub(i,j)
|
|
> else
|
|
> local t={}
|
|
> for k,v in ipairs(i) do
|
|
> t[k]=str:sub(v,v)
|
|
> end
|
|
> return table.concat(t)
|
|
> end
|
|
>end
|
|
>
|
|
>-- iterate over an ordered sequence
|
|
>function q(x)
|
|
> if type(x) == 'string' then
|
|
> return x:gmatch('.')
|
|
> else
|
|
> return ipairs(x)
|
|
> end
|
|
>end
|
|
>
|
|
>-- insert within string
|
|
>function string.insert(str1, str2, pos)
|
|
> return str1:sub(1,pos)..str2..str1:sub(pos+1)
|
|
>end
|
|
>
|
|
>function string.remove(s, pos)
|
|
> return s:sub(1,pos-1)..s:sub(pos+1)
|
|
>end
|
|
>
|
|
>function string.pos(s, sub)
|
|
> return string.find(s, sub, 1, true) -- plain=true to disable regular expressions
|
|
>end
|
|
>
|
|
>-- TODO: backport utf-8 support from Lua 5.3
|
|
- __teliva_timestamp: original
|
|
debugy:
|
|
>debugy = 5
|
|
- __teliva_timestamp: original
|
|
dbg:
|
|
>-- helper for debug by print; overlay debug information towards the right
|
|
>-- reset debugy every time you refresh screen
|
|
>function dbg(window, s)
|
|
> local oldy = 0
|
|
> local oldx = 0
|
|
> oldy, oldx = window:getyx()
|
|
> window:mvaddstr(debugy, 60, s)
|
|
> debugy = debugy+1
|
|
> window:mvaddstr(oldy, oldx, '')
|
|
>end
|
|
- __teliva_timestamp: original
|
|
check:
|
|
>function check(x, msg)
|
|
> if x then
|
|
> Window:addch('.')
|
|
> else
|
|
> print('F - '..msg)
|
|
> print(' '..str(x)..' is false/nil')
|
|
> teliva_num_test_failures = teliva_num_test_failures + 1
|
|
> -- overlay first test failure on editors
|
|
> if teliva_first_failure == nil then
|
|
> teliva_first_failure = msg
|
|
> end
|
|
> end
|
|
>end
|
|
- __teliva_timestamp: original
|
|
check_eq:
|
|
>function check_eq(x, expected, msg)
|
|
> if eq(x, expected) then
|
|
> Window:addch('.')
|
|
> else
|
|
> print('F - '..msg)
|
|
> print(' expected '..str(expected)..' but got '..str(x))
|
|
> teliva_num_test_failures = teliva_num_test_failures + 1
|
|
> -- overlay first test failure on editors
|
|
> if teliva_first_failure == nil then
|
|
> teliva_first_failure = msg
|
|
> end
|
|
> end
|
|
>end
|
|
- __teliva_timestamp: original
|
|
eq:
|
|
>function eq(a, b)
|
|
> if type(a) ~= type(b) then return false end
|
|
> if type(a) == 'table' then
|
|
> if #a ~= #b then return false end
|
|
> for k, v in pairs(a) do
|
|
> if b[k] ~= v then
|
|
> return false
|
|
> end
|
|
> end
|
|
> for k, v in pairs(b) do
|
|
> if a[k] ~= v then
|
|
> return false
|
|
> end
|
|
> end
|
|
> return true
|
|
> end
|
|
> return a == b
|
|
>end
|
|
- __teliva_timestamp: original
|
|
str:
|
|
>-- smarter tostring
|
|
>-- slow; used only for debugging
|
|
>function str(x)
|
|
> if type(x) == 'table' then
|
|
> local result = ''
|
|
> result = result..#x..'{'
|
|
> for k, v in pairs(x) do
|
|
> result = result..str(k)..'='..str(v)..', '
|
|
> end
|
|
> result = result..'}'
|
|
> return result
|
|
> elseif type(x) == 'string' then
|
|
> return '"'..x..'"'
|
|
> end
|
|
> return tostring(x)
|
|
>end
|
|
- __teliva_timestamp: original
|
|
menu:
|
|
>-- To show app-specific hotkeys in the menu bar, add hotkey/command
|
|
>-- arrays of strings to the menu array.
|
|
>menu = {}
|
|
- __teliva_timestamp: original
|
|
window:
|
|
>-- constructor for fake screen and window
|
|
>-- call it like this:
|
|
>-- local w = window{
|
|
>-- kbd=kbd('abc'),
|
|
>-- scr=scr{h=5, w=4},
|
|
>-- }
|
|
>-- eventually it'll do everything a real ncurses window can
|
|
>function window(h)
|
|
> h.__index = h
|
|
> setmetatable(h, h)
|
|
> h.__index = function(table, key)
|
|
> return rawget(h, key)
|
|
> end
|
|
> h.attrset = function(self, x)
|
|
> self.scr.attrs = x
|
|
> end
|
|
> h.attron = function(self, x)
|
|
> -- currently same as attrset since Lua 5.1 doesn't have bitwise operators
|
|
> -- doesn't support multiple attrs at once
|
|
>-- local old = self.scr.attrs
|
|
>-- self.scr.attrs = old|x
|
|
> self.scr.attrs = x
|
|
> end
|
|
> h.attroff = function(self, x)
|
|
> -- currently borked since Lua 5.1 doesn't have bitwise operators
|
|
> -- doesn't support multiple attrs at once
|
|
>-- local old = self.scr.attrs
|
|
>-- self.scr.attrs = old & (~x)
|
|
> self.scr.attrs = curses.A_NORMAL
|
|
> end
|
|
> h.getch = function(self)
|
|
> local c = table.remove(h.kbd, 1)
|
|
> if c == nil then return c end
|
|
> return string.byte(c) -- for verisimilitude with ncurses
|
|
> end
|
|
> h.addch = function(self, c)
|
|
> local scr = self.scr
|
|
> if c == '\n' then
|
|
> scr.cursy = scr.cursy+1
|
|
> scr.cursx = 0
|
|
> return
|
|
> end
|
|
> if scr.cursy <= scr.h then
|
|
> scr[scr.cursy][scr.cursx] = {data=c, attrs=scr.attrs}
|
|
> scr.cursx = scr.cursx+1
|
|
> if scr.cursx > scr.w then
|
|
> scr.cursy = scr.cursy+1
|
|
> scr.cursx = 1
|
|
> end
|
|
> end
|
|
> end
|
|
> h.addstr = function(self, s)
|
|
> for i=1,s:len() do
|
|
> self:addch(s[i])
|
|
> end
|
|
> end
|
|
> h.mvaddch = function(self, y, x, c)
|
|
> self.scr.cursy = y
|
|
> self.scr.cursx = x
|
|
> self:addch(c)
|
|
> end
|
|
> h.mvaddstr = function(self, y, x, s)
|
|
> self.scr.cursy = y
|
|
> self.scr.cursx = x
|
|
> self:addstr(s)
|
|
> end
|
|
> h.clear = function(self)
|
|
> clear_scr(self.scr)
|
|
> end
|
|
> h.refresh = function(self)
|
|
> -- nothing
|
|
> end
|
|
> return h
|
|
>end
|
|
- __teliva_timestamp: original
|
|
kbd:
|
|
>function kbd(keys)
|
|
> local result = {}
|
|
> for i=1,keys:len() do
|
|
> table.insert(result, keys[i])
|
|
> end
|
|
> return result
|
|
>end
|
|
- __teliva_timestamp: original
|
|
scr:
|
|
>function scr(props)
|
|
> props.cursx = 1
|
|
> props.cursy = 1
|
|
> clear_scr(props)
|
|
> return props
|
|
>end
|
|
- __teliva_timestamp: original
|
|
clear_scr:
|
|
>function clear_scr(props)
|
|
> props.cursy = 1
|
|
> props.cursx = 1
|
|
> for y=1,props.h do
|
|
> props[y] = {}
|
|
> for x=1,props.w do
|
|
> props[y][x] = {data=' ', attrs=curses.A_NORMAL}
|
|
> end
|
|
> end
|
|
> return props
|
|
>end
|
|
- __teliva_timestamp: original
|
|
check_screen:
|
|
>function check_screen(window, contents, message)
|
|
> local x, y = 1, 1
|
|
> for i=1,contents:len() do
|
|
> check_eq(window.scr[y][x].data, contents[i], message..'/'..y..','..x)
|
|
> x = x+1
|
|
> if x > window.scr.w then
|
|
> y = y+1
|
|
> x = 1
|
|
> end
|
|
> end
|
|
>end
|
|
>
|
|
>-- putting it all together, an example test of both keyboard and screen
|
|
>function test_check_screen()
|
|
> local lines = {
|
|
> c='123',
|
|
> d='234',
|
|
> a='345',
|
|
> b='456',
|
|
> }
|
|
> local w = window{
|
|
> kbd=kbd('abc'),
|
|
> scr=scr{h=3, w=5},
|
|
> }
|
|
> local y = 1
|
|
> while true do
|
|
> local b = w:getch()
|
|
> if b == nil then break end
|
|
> w:mvaddstr(y, 1, lines[string.char(b)])
|
|
> y = y+1
|
|
> end
|
|
> check_screen(w, '345 '..
|
|
> '456 '..
|
|
> '123 ',
|
|
> 'test_check_screen')
|
|
>end
|
|
- __teliva_timestamp: original
|
|
grid:
|
|
>-- main data structure
|
|
>grid = {}
|
|
>for i=1,lines*4 do
|
|
> grid[i] = {}
|
|
> for j=1,cols*2 do
|
|
> grid[i][j] = 0
|
|
> end
|
|
>end
|
|
- __teliva_timestamp: original
|
|
Window:
|
|
>Window = curses.stdscr()
|
|
>-- animation-based app
|
|
>Window:nodelay(true)
|
|
>curses.curs_set(0)
|
|
>lines, cols = Window:getmaxyx()
|
|
- __teliva_timestamp: original
|
|
grid_char:
|
|
>-- grab a 4x2 chunk of grid
|
|
>function grid_char(line, col)
|
|
> result = {}
|
|
> for l, row in ipairs({unpack(grid, (line-1)*4+1, line*4)}) do
|
|
> result[l] = {unpack(row, (col-1)*2+1, col*2)}
|
|
> end
|
|
> return result
|
|
>end
|
|
- __teliva_timestamp: original
|
|
print_grid_char:
|
|
>function print_grid_char(window, x)
|
|
> result = {}
|
|
> for l, row in ipairs(x) do
|
|
> for c, val in ipairs(row) do
|
|
> window:mvaddstr(l, c, val)
|
|
> end
|
|
> end
|
|
> return result
|
|
>end
|
|
- __teliva_timestamp: original
|
|
glyph:
|
|
>-- look up the braille pattern corresponding to a 4x2 chunk of grid
|
|
>-- https://en.wikipedia.org/wiki/Braille_Patterns
|
|
>-- not obviously programmatic because Unicode added 4x2 after 3x2
|
|
>glyph = {
|
|
> 0x2800, 0x2801, 0x2802, 0x2803, 0x2804, 0x2805, 0x2806, 0x2807, 0x2840, 0x2841, 0x2842, 0x2843, 0x2844, 0x2845, 0x2846, 0x2847,
|
|
> 0x2808, 0x2809, 0x280a, 0x280b, 0x280c, 0x280d, 0x280e, 0x280f, 0x2848, 0x2849, 0x284a, 0x284b, 0x284c, 0x284d, 0x284e, 0x284f,
|
|
> 0x2810, 0x2811, 0x2812, 0x2813, 0x2814, 0x2815, 0x2816, 0x2817, 0x2850, 0x2851, 0x2852, 0x2853, 0x2854, 0x2855, 0x2856, 0x2857,
|
|
> 0x2818, 0x2819, 0x281a, 0x281b, 0x281c, 0x281d, 0x281e, 0x281f, 0x2858, 0x2859, 0x285a, 0x285b, 0x285c, 0x285d, 0x285e, 0x285f,
|
|
> 0x2820, 0x2821, 0x2822, 0x2823, 0x2824, 0x2825, 0x2826, 0x2827, 0x2860, 0x2861, 0x2862, 0x2863, 0x2864, 0x2865, 0x2866, 0x2867,
|
|
> 0x2828, 0x2829, 0x282a, 0x282b, 0x282c, 0x282d, 0x282e, 0x282f, 0x2868, 0x2869, 0x286a, 0x286b, 0x286c, 0x286d, 0x286e, 0x286f,
|
|
> 0x2830, 0x2831, 0x2832, 0x2833, 0x2834, 0x2835, 0x2836, 0x2837, 0x2870, 0x2871, 0x2872, 0x2873, 0x2874, 0x2875, 0x2876, 0x2877,
|
|
> 0x2838, 0x2839, 0x283a, 0x283b, 0x283c, 0x283d, 0x283e, 0x283f, 0x2878, 0x2879, 0x287a, 0x287b, 0x287c, 0x287d, 0x287e, 0x287f,
|
|
>
|
|
> 0x2880, 0x2881, 0x2882, 0x2883, 0x2884, 0x2885, 0x2886, 0x2887, 0x28c0, 0x28c1, 0x28c2, 0x28c3, 0x28c4, 0x28c5, 0x28c6, 0x28c7,
|
|
> 0x2888, 0x2889, 0x288a, 0x288b, 0x288c, 0x288d, 0x288e, 0x288f, 0x28c8, 0x28c9, 0x28ca, 0x28cb, 0x28cc, 0x28cd, 0x28ce, 0x28cf,
|
|
> 0x2890, 0x2891, 0x2892, 0x2893, 0x2894, 0x2895, 0x2896, 0x2897, 0x28d0, 0x28d1, 0x28d2, 0x28d3, 0x28d4, 0x28d5, 0x28d6, 0x28d7,
|
|
> 0x2898, 0x2899, 0x289a, 0x289b, 0x289c, 0x289d, 0x289e, 0x289f, 0x28d8, 0x28d9, 0x28da, 0x28db, 0x28dc, 0x28dd, 0x28de, 0x28df,
|
|
> 0x28a0, 0x28a1, 0x28a2, 0x28a3, 0x28a4, 0x28a5, 0x28a6, 0x28a7, 0x28e0, 0x28e1, 0x28e2, 0x28e3, 0x28e4, 0x28e5, 0x28e6, 0x28e7,
|
|
> 0x28a8, 0x28a9, 0x28aa, 0x28ab, 0x28ac, 0x28ad, 0x28ae, 0x28af, 0x28e8, 0x28e9, 0x28ea, 0x28eb, 0x28ec, 0x28ed, 0x28ee, 0x28ef,
|
|
> 0x28b0, 0x28b1, 0x28b2, 0x28b3, 0x28b4, 0x28b5, 0x28b6, 0x28b7, 0x28f0, 0x28f1, 0x28f2, 0x28f3, 0x28f4, 0x28f5, 0x28f6, 0x28f7,
|
|
> 0x28b8, 0x28b9, 0x28ba, 0x28bb, 0x28bc, 0x28bd, 0x28be, 0x28bf, 0x28f8, 0x28f9, 0x28fa, 0x28fb, 0x28fc, 0x28fd, 0x28fe, 0x28ff,
|
|
>}
|
|
- __teliva_timestamp: original
|
|
utf8:
|
|
>-- https://stackoverflow.com/questions/7983574/how-to-write-a-unicode-symbol-in-lua
|
|
>function utf8(decimal)
|
|
> local bytemarkers = { {0x7FF,192}, {0xFFFF,224}, {0x1FFFFF,240} }
|
|
> if decimal<128 then return string.char(decimal) end
|
|
> local charbytes = {}
|
|
> for bytes,vals in ipairs(bytemarkers) do
|
|
> if decimal<=vals[1] then
|
|
> for b=bytes+1,2,-1 do
|
|
> local mod = decimal%64
|
|
> decimal = (decimal-mod)/64
|
|
> charbytes[b] = string.char(128+mod)
|
|
> end
|
|
> charbytes[1] = string.char(vals[2]+decimal)
|
|
> break
|
|
> end
|
|
> end
|
|
> return table.concat(charbytes)
|
|
>end
|
|
- __teliva_timestamp: original
|
|
grid_char_to_glyph_index:
|
|
>-- convert a chunk of grid into a number
|
|
>function grid_char_to_glyph_index(g)
|
|
> return g[1][1] + g[2][1]*2 + g[3][1]*4 + g[4][1]*8 +
|
|
> g[1][2]*16 + g[2][2]*32 + g[3][2]*64 + g[4][2]*128 +
|
|
> 1 -- 1-indexing
|
|
>end
|
|
- __teliva_timestamp: original
|
|
render:
|
|
>function render(window)
|
|
> window:clear()
|
|
> window:attron(curses.color_pair(1))
|
|
> for line=1,lines do
|
|
> for col=1,cols do
|
|
> window:addstr(utf8(glyph[grid_char_to_glyph_index(grid_char(line, col))]))
|
|
> end
|
|
> end
|
|
> window:attroff(curses.color_pair(1))
|
|
> window:refresh()
|
|
>end
|
|
- __teliva_timestamp: original
|
|
state:
|
|
>function state(line, col)
|
|
> if line < 1 or line > #grid or col < 1 or col > #grid[1] then
|
|
> return 0
|
|
> end
|
|
> return grid[line][col]
|
|
>end
|
|
- __teliva_timestamp: original
|
|
num_live_neighbors:
|
|
>function num_live_neighbors(line, col)
|
|
> return state(line-1, col-1) + state(line-1, col) + state(line-1, col+1) +
|
|
> state(line, col-1) + state(line, col+1) +
|
|
> state(line+1, col-1) + state(line+1, col) + state(line+1, col+1)
|
|
>end
|
|
- __teliva_timestamp: original
|
|
step:
|
|
>function step()
|
|
> local new_grid = {}
|
|
> for line=1,#grid do
|
|
> new_grid[line] = {}
|
|
> for col=1,#grid[1] do
|
|
> local n = num_live_neighbors(line, col)
|
|
> if n == 3 then
|
|
> new_grid[line][col] = 1
|
|
> elseif n == 2 then
|
|
> new_grid[line][col] = grid[line][col]
|
|
> else
|
|
> new_grid[line][col] = 0
|
|
> end
|
|
> end
|
|
> end
|
|
> grid = new_grid
|
|
>end
|
|
- __teliva_timestamp: original
|
|
sleep:
|
|
>function sleep(a)
|
|
> local sec = tonumber(os.clock() + a);
|
|
> while (os.clock() < sec) do
|
|
> end
|
|
>end
|
|
- __teliva_timestamp: original
|
|
load_file:
|
|
>function load_file(window, fs, filename)
|
|
> local infile = start_reading(fs, filename)
|
|
> if infile == nil then return end
|
|
> local line_index = lines -- quarter of the way down in pixels
|
|
> while true do
|
|
> local line = infile.read()
|
|
> if line == nil then break end
|
|
> if line:sub(1,1) ~= '!' then -- comment; plaintext files can't have whitespace before comments
|
|
> local col_index = cols
|
|
> for c in line:gmatch(".") do
|
|
> if c == '\r' then break end -- DOS line ending
|
|
> if c == '.' then
|
|
> grid[line_index][col_index] = 0
|
|
> else
|
|
> grid[line_index][col_index] = 1
|
|
> end
|
|
> col_index = col_index+1
|
|
> end
|
|
> line_index = line_index+1
|
|
> end
|
|
> end
|
|
>end
|
|
- __teliva_timestamp: original
|
|
update:
|
|
>menu = {{"arrow", "pan"}}
|
|
>
|
|
>function update(window, c)
|
|
> if c == curses.KEY_LEFT then
|
|
> for i=1,lines*4 do
|
|
> for j=2,cols*2 do
|
|
> grid[i][j-1] = grid[i][j]
|
|
> end
|
|
> grid[i][cols*2] = 0
|
|
> end
|
|
> elseif c == curses.KEY_DOWN then
|
|
> for i=lines*4-1,1,-1 do
|
|
> for j=1,cols*2 do
|
|
> grid[i+1][j] = grid[i][j]
|
|
> end
|
|
> end
|
|
> for j=1,cols*2 do
|
|
> grid[1][j] = 0
|
|
> end
|
|
> elseif c == curses.KEY_UP then
|
|
> for i=2,lines*4 do
|
|
> for j=1,cols*2 do
|
|
> grid[i-1][j] = grid[i][j]
|
|
> end
|
|
> end
|
|
> for j=1,cols*2 do
|
|
> grid[lines*4][j] = 0
|
|
> end
|
|
> elseif c == curses.KEY_RIGHT then
|
|
> for i=1,lines*4 do
|
|
> for j=cols*2-1,1,-1 do
|
|
> grid[i][j+1] = grid[i][j]
|
|
> end
|
|
> grid[i][1] = 0
|
|
> end
|
|
> end
|
|
>end
|
|
- __teliva_timestamp: original
|
|
main:
|
|
>function main()
|
|
> curses.init_pair(1, 22, 189)
|
|
>
|
|
> -- initialize grid based on commandline args
|
|
> if (#arg == 0) then
|
|
> -- by default, start from a deterministically random state
|
|
> for i=1,lines*4 do
|
|
> for j=1,cols*2 do
|
|
> grid[i][j] = math.random(0, 1)
|
|
> end
|
|
> end
|
|
> elseif arg[1] == "random" then
|
|
> -- start from a non-deterministically random start state
|
|
> math.randomseed(os.time())
|
|
> for i=1,lines*4 do
|
|
> for j=1,cols*2 do
|
|
> grid[i][j] = math.random(0, 1)
|
|
> end
|
|
> end
|
|
> -- shortcuts for some common patterns
|
|
> elseif arg[1] == "pentomino" then
|
|
> -- https://www.conwaylife.com/wiki/Pentomino
|
|
> grid[83][172] = 1
|
|
> grid[83][173] = 1
|
|
> grid[84][173] = 1
|
|
> grid[84][174] = 1
|
|
> grid[85][173] = 1
|
|
> elseif arg[1] == "glider" then
|
|
> -- https://www.conwaylife.com/wiki/Glider
|
|
> grid[5][4] = 1
|
|
> grid[6][5] = 1
|
|
> grid[7][3] = 1
|
|
> grid[7][4] = 1
|
|
> grid[7][5] = 1
|
|
> elseif arg[1] == "blinker" then
|
|
> -- https://www.conwaylife.com/wiki/Blinker
|
|
> grid[7][3] = 1
|
|
> grid[7][4] = 1
|
|
> grid[7][5] = 1
|
|
> elseif arg[1] == "block" then
|
|
> -- https://www.conwaylife.com/wiki/Block
|
|
> grid[5][4] = 1
|
|
> grid[5][5] = 1
|
|
> grid[6][4] = 1
|
|
> grid[6][5] = 1
|
|
> elseif arg[1] == "loaf" then
|
|
> -- https://www.conwaylife.com/wiki/Loaf
|
|
> grid[5][4] = 1
|
|
> grid[5][5] = 1
|
|
> grid[6][6] = 1
|
|
> grid[7][6] = 1
|
|
> grid[8][5] = 1
|
|
> grid[7][4] = 1
|
|
> grid[6][3] = 1
|
|
> else
|
|
> -- Load a file in the standard "plaintext" format: https://www.conwaylife.com/wiki/Plaintext
|
|
> --
|
|
> -- Each pattern page at https://www.conwaylife.com/wiki provides its
|
|
> -- plaintext representation in a block called "Pattern Files" on the right.
|
|
> --
|
|
> -- For example, check out the list of Important Patterns at
|
|
> -- https://www.conwaylife.com/wiki/Category:Patterns_with_Catagolue_frequency_class_0
|
|
> load_file(Window, nil, arg[1])
|
|
> end
|
|
>
|
|
> -- main loop
|
|
> while true do
|
|
> render(Window)
|
|
> c = Window:getch()
|
|
> update(Window, c)
|
|
> step()
|
|
> end
|
|
>end
|
|
- __teliva_timestamp:
|
|
>Thu Feb 17 19:58:19 2022
|
|
doc:blurb:
|
|
>Conway's Game of Life
|
|
>
|
|
>To get around limitations of text mode we use the braille character set to render 8 cells per character.
|
|
>
|
|
>By default it initializes the space with a random state of cells. You can also start it up with .cells files from https://conwaylife.com/wiki, or with a few special names:
|
|
> $ src/teliva life.tlv block
|
|
> $ src/teliva life.tlv loaf
|
|
> $ src/teliva life.tlv blinker
|
|
> $ src/teliva life.tlv glider
|
|
> $ src/teliva life.tlv pentomino
|