;;; Read an xlife pattern file... ;;; nando, Feb 14 2000 ;;; ;;; Clear the whole cell array of the automata (defun ca-clear (ca) (let* ((dims (array-dimensions (cellaut-cells ca))) (iend (first dims)) (jend (second dims))) (loop for i from 0 below iend do (loop for j from 0 below jend do (ca-set-cell ca i j 0))) ca)) ;;; Get one particular cell (defun ca-get-cell (ca i j) (aref (cellaut-cells ca) i j)) ;;; Set a cell to a value (defun ca-set-cell (ca i j cell) (setf (aref (cellaut-cells ca) i j) cell)) ;;; Load a pattern into an automata ;;; the pattern is a list of lists and must fit within ;;; the automata (the automata has to be big enough) (defun ca-load-pattern (ca pattern &key (center t)) (let* ((dims (array-dimensions (cellaut-cells ca))) (iend (first dims)) (jend (second dims)) (ipat (length pattern)) (jpat (length (first pattern)))) (if (or (> ipat iend) (> jpat jend)) (error "pattern is too large (~s:~s) for automata (~s:~s)~%" ipat jpat iend jend)) (loop for ic from (floor (- (/ iend 2)(/ ipat 2))) for row in pattern do (loop for jc from (floor (- (/ jend 2)(/ jpat 2))) for cell in row do (ca-set-cell ca ic jc cell))) ca)) ;;; Read a pattern from a file ;;; ;;; this version reads ".l" files as defined in xlife ;;; the only tags understood by this function are the "P" ;;; (pattern) tag and the comment tag (see man xlife for ;;; details on the pattern file format). You can find a ;;; lot of .l files in "/usr/lib/xlife", use only the ones ;;; that are defining patterns through the "P" command ;;; (executing 'grep "#P" *.l' in that directory will ;;; list all the files that have pattern commands in them) ;;; The pattern is centered in the existing cellular automata (defun read-pattern (file &key (center t)) (with-open-file (ifile file :direction :input) (loop do (multiple-value-bind (line end) (read-line ifile nil nil) (if end (loop-finish)) ;; decode one line ;;(format t "[[~s]]~%" line) (if (eq (aref line 0) #\#) ;; read and decode a command (cond (;; #[comment]: ignore the line (eq (aref line 1) #\#)) (;; P[attern]: decode the pattern and return a list of lists (eq (aref line 1) #\P) ;; (format t " pattern~%") (let* ((xoffset 0) (yoffset 0)) ;; parse possible offsets (multiple-value-bind (x xend) (parse-integer line :start 2 :junk-allowed t) (if x (multiple-value-bind (y yend) (parse-integer line :start xend :junk-allowed t) (if y (setf xoffset x yoffset y))))) ;; (format t "P[attern] ~s:~s~%" xoffset yoffset) ;; start parsing a P[attern] (loop with l = '() do (multiple-value-bind (line end) (read-line ifile nil nil) (if end (loop-finish)) (setf l `(,.l ,(loop for i from 0 for c across line collect (if (eq c #\.) 0 1))))) finally (return-from read-pattern l)))))))))) #| Load a pattern into a newly created 2d automata (setf x (ca-load-pattern (ca '(30 400) :populate nil) (read-pattern "/usr/lib/xlife/longfuse.l"))) (setf x (ca-load-pattern (ca '(30 60) :populate nil) (read-pattern "/usr/lib/xlife/mediumfish.l"))) |#