diff --git a/examples/game_of_life.sl b/examples/game_of_life.sl new file mode 100644 index 0000000..f1f1770 --- /dev/null +++ b/examples/game_of_life.sl @@ -0,0 +1,223 @@ +# 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