224 lines
4.0 KiB
Plaintext
224 lines
4.0 KiB
Plaintext
|
|
# 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
|