Files
l2/examples/game_of_life.sl

224 lines
4.0 KiB
Plaintext
Raw Normal View History

# Conway's Game of Life
import stdlib/stdlib.sl
import stdlib/io.sl
import stdlib/mem.sl
macro WIDTH 0 40 ;
macro HEIGHT 0 24 ;
macro GENERATIONS 0 80 ;
macro CELLS 0 WIDTH HEIGHT * ;
macro FRAME_DELAY 0 35000000;
#cell_addr [*, grid, x | y] -> [* | addr]
word cell_addr
WIDTH * + 8 * +
end
#get_cell [*, grid, x | y] -> [* | value]
word get_cell
dup 0 < if
2drop drop 0
else dup HEIGHT >= if
2drop drop 0
else over 0 < if
2drop drop 0
else over WIDTH >= if
2drop drop 0
else
cell_addr @
end
end
#term_enter [*] -> [*]
word term_enter
# Enter alternate screen: ESC[?1049h
27 putc 91 putc 63 putc 49 putc 48 putc 52 putc 57 putc 104 putc
# Hide cursor: ESC[?25l
27 putc 91 putc 63 putc 50 putc 53 putc 108 putc
end
#term_leave [*] -> [*]
word term_leave
# Show cursor: ESC[?25h
27 putc 91 putc 63 putc 50 putc 53 putc 104 putc
# Leave alternate screen (restores original terminal view): ESC[?1049l
27 putc 91 putc 63 putc 49 putc 48 putc 52 putc 57 putc 108 putc
end
#clear_screen_home [*] -> [*]
word clear_screen_home
# Clear full screen: ESC[2J
27 putc 91 putc 50 putc 74 putc
# Move cursor home: ESC[H
27 putc 91 putc 72 putc
end
#frame_sleep [*] -> [*]
word frame_sleep
# Busy wait between frames; tune FRAME_DELAY for your machine.
FRAME_DELAY for
1 drop
end
end
#set_cell [*, grid, x, y | value] -> [*]
word set_cell
>r
cell_addr
r> !
end
#count_neighbors [*, grid, x | y] -> [* | n]
word count_neighbors
with g x y in
0
g x 1 - y 1 - get_cell +
g x y 1 - get_cell +
g x 1 + y 1 - get_cell +
g x 1 - y get_cell +
g x 1 + y get_cell +
g x 1 - y 1 + get_cell +
g x y 1 + get_cell +
g x 1 + y 1 + get_cell +
end
end
#print_cell [* | state] -> [*]
word print_cell
if 35 putc else 46 putc end
end
#print_board [* | grid] -> [*]
word print_board
0
while dup HEIGHT < do
0
while dup WIDTH < do
2 pick
1 pick
3 pick
get_cell print_cell
1 +
end
drop
10 putc
1 +
end
drop
drop
10 putc
end
#evolve [*, state | neighbors] -> [* | new_state]
word evolve
over 1 == if
nip
dup 2 == if
drop 1
else
dup 3 == if drop 1 else drop 0 end
end
else
nip
dup 3 == if drop 1 else drop 0 end
end
end
#copy_qwords [*, dst, src | count] -> [*]
word copy_qwords
while dup 0 > do
over @
3 pick swap !
swap 8 + swap
rot 8 + -rot
1 -
end
drop 2drop
end
#clear_board [* | grid] -> [*]
word clear_board
0
while dup CELLS < do
over over 8 * + 0 !
1 +
end
drop
drop
end
#seed_glider [* | grid] -> [*]
word seed_glider
dup 1 0 1 set_cell
dup 2 1 1 set_cell
dup 0 2 1 set_cell
dup 1 2 1 set_cell
dup 2 2 1 set_cell
drop
end
#step [*, current | next] -> [*, current | next]
word step
0
while dup HEIGHT < do
0
while dup WIDTH < do
# current next y x
3 pick
1 pick
3 pick
get_cell
# current next y x state
4 pick
2 pick
4 pick
count_neighbors
# current next y x state neighbors
evolve
# current next y x new_state
3 pick
2 pick
4 pick
cell_addr
swap !
# current next y x
1 +
end
drop
1 +
end
drop
end
word main
CELLS 8 * alloc
CELLS 8 * alloc
over clear_board
dup clear_board
over seed_glider
term_enter
GENERATIONS for
clear_screen_home
over print_board
frame_sleep
2dup step
over over CELLS copy_qwords
end
term_leave
swap CELLS 8 * free
CELLS 8 * free
0
end