#!/usr/bin/env uxlisp -shell (require "virtty") (defconstant +width+ 50) (defconstant +height+ 25) (defconstant +max-y+ (- +height+ 1)) (defglobal *buf* (create-vector (* +width+ +height+))) (defconstant +out+ (standard-output)) (defconstant +max-fade+ 50) (defglobal *avg-frames* 0) (defglobal *avg-time* 0.0) (defconstant +esc+ (convert 27 )) (defun ctrl (&rest args) (format +out+ "~C[~A" +esc+ args)) (defun home () (ctrl "H")) (defun init () (for ((i 0 (+ i 1))) ((> i +width+)) (setf (elt *buf* i) #xff)) (tycls)) (defmacro inc (x) `(setq ,x (+ ,x 1))) (defmacro dec (x) `(setq ,x (- ,x 1))) (defmacro foreach (lim &rest body) (let ((i (gensym))) `(for ((,i 0 (+ ,i 1))) ((> ,i ,lim)) ,@body))) (defun render () (let ((t0 (get-internal-real-time)) (i -1)) (foreach +max-y+ (for ((x 0 (+ x 1))) ((> x +width+)) (let ((v (elt *buf* (inc i))) (j (+ i +width+))) (if (and (> x 0) (< x (- +width+ 1))) (inc j (- 1 (random 3)))) (setf (elt *buf* j) (if (> v 0) (- v (random (min +max-fade+ (+ v 1)))) v))))) (setq i (+ i width 1)) (let ((prev-g nil)) (home) (for ((y 0 (+ y 1))) ((> y +height+)) (for ((x 0 (+ x 1))) ((> x +width+)) (let* ((g (elt *buf* (dec i))) (r (if (> g 0) #xff 0)) (b (if (= g #xff) #xff 0))) (if (= g prev-g) (print +out+ " ") (ctrl "48;2;" r ";" (setq prev-g g) ";" b "m ")))) (print +out+ #\newline))) (setq *avg-time* (+ *avg-time* (- (get-internal-real-time) t0))) (inc *avg-frames*))) (defun restore () (ctrl "0m") (tycls) (home)) (defun print (arg1 &rest args) (if (null arg) (format (standard-output) "~A~%" arg1) (format arg1 "~A~%" (car args)))) (defun main () (init) (for ((i 0 (+ i 1))) ((> i 50)) (render)) (restore) (print (/ (* (internal-time-units-per-second) *avg-frames*) *avg-time*))) (main)