diff options
| -rw-r--r-- | lisp/play/life.el | 45 |
1 files changed, 20 insertions, 25 deletions
diff --git a/lisp/play/life.el b/lisp/play/life.el index e4faecb61bd..abab5c0d9c1 100644 --- a/lisp/play/life.el +++ b/lisp/play/life.el | |||
| @@ -74,14 +74,7 @@ | |||
| 74 | (defmacro life-void-string () (char-to-string (life-void-char))) | 74 | (defmacro life-void-string () (char-to-string (life-void-char))) |
| 75 | (defmacro life-not-void-regexp () (concat "[^" (life-void-string) "\n]")) | 75 | (defmacro life-not-void-regexp () (concat "[^" (life-void-string) "\n]")) |
| 76 | 76 | ||
| 77 | ;; try to optimize the (goto-char (point-min)) & (goto-char (point-max)) | 77 | (defmacro life-increment (variable) (list 'setq variable (list '1+ variable))) |
| 78 | ;; idioms. This depends on goto-char's not griping if we undershoot | ||
| 79 | ;; or overshoot beginning or end of buffer. | ||
| 80 | (defmacro goto-beginning-of-buffer () '(goto-char 1)) | ||
| 81 | (defmacro maxint () (lsh (lsh (lognot 0) 1) -1)) | ||
| 82 | (defmacro goto-end-of-buffer () '(goto-char (maxint))) | ||
| 83 | |||
| 84 | (defmacro increment (variable) (list 'setq variable (list '1+ variable))) | ||
| 85 | 78 | ||
| 86 | 79 | ||
| 87 | ;; list of numbers that tell how many characters to move to get to | 80 | ;; list of numbers that tell how many characters to move to get to |
| @@ -97,7 +90,8 @@ | |||
| 97 | ;; Sadly, mode-line-format won't display numbers. | 90 | ;; Sadly, mode-line-format won't display numbers. |
| 98 | (defconst life-generation-string nil) | 91 | (defconst life-generation-string nil) |
| 99 | 92 | ||
| 100 | (defun abs (n) (if (< n 0) (- n) n)) | 93 | (defvar life-initialized nil |
| 94 | "Non-nil if `life' has been run at least once.") | ||
| 101 | 95 | ||
| 102 | ;;;###autoload | 96 | ;;;###autoload |
| 103 | (defun life (&optional sleeptime) | 97 | (defun life (&optional sleeptime) |
| @@ -106,6 +100,9 @@ The starting pattern is randomly selected. Prefix arg (optional first | |||
| 106 | arg non-nil from a program) is the number of seconds to sleep between | 100 | arg non-nil from a program) is the number of seconds to sleep between |
| 107 | generations (this defaults to 1)." | 101 | generations (this defaults to 1)." |
| 108 | (interactive "p") | 102 | (interactive "p") |
| 103 | (or life-initialized | ||
| 104 | (random t)) | ||
| 105 | (setq life-initialized t) | ||
| 109 | (or sleeptime (setq sleeptime 1)) | 106 | (or sleeptime (setq sleeptime 1)) |
| 110 | (life-setup) | 107 | (life-setup) |
| 111 | (life-display-generation sleeptime) | 108 | (life-display-generation sleeptime) |
| @@ -120,8 +117,6 @@ generations (this defaults to 1)." | |||
| 120 | (defalias 'life-mode 'life) | 117 | (defalias 'life-mode 'life) |
| 121 | (put 'life-mode 'mode-class 'special) | 118 | (put 'life-mode 'mode-class 'special) |
| 122 | 119 | ||
| 123 | (random t) | ||
| 124 | |||
| 125 | (defun life-setup () | 120 | (defun life-setup () |
| 126 | (let (n) | 121 | (let (n) |
| 127 | (switch-to-buffer (get-buffer-create "*Life*") t) | 122 | (switch-to-buffer (get-buffer-create "*Life*") t) |
| @@ -141,11 +136,11 @@ generations (this defaults to 1)." | |||
| 141 | ;; stuff in the random pattern | 136 | ;; stuff in the random pattern |
| 142 | (life-insert-random-pattern) | 137 | (life-insert-random-pattern) |
| 143 | ;; make sure (life-life-char) is used throughout | 138 | ;; make sure (life-life-char) is used throughout |
| 144 | (goto-beginning-of-buffer) | 139 | (goto-char (point-min)) |
| 145 | (while (re-search-forward (life-not-void-regexp) nil t) | 140 | (while (re-search-forward (life-not-void-regexp) nil t) |
| 146 | (replace-match (life-life-string) t t)) | 141 | (replace-match (life-life-string) t t)) |
| 147 | ;; center the pattern horizontally | 142 | ;; center the pattern horizontally |
| 148 | (goto-beginning-of-buffer) | 143 | (goto-char (point-min)) |
| 149 | (setq n (/ (- fill-column (save-excursion (end-of-line) (point))) 2)) | 144 | (setq n (/ (- fill-column (save-excursion (end-of-line) (point))) 2)) |
| 150 | (while (not (eobp)) | 145 | (while (not (eobp)) |
| 151 | (indent-to n) | 146 | (indent-to n) |
| @@ -154,12 +149,12 @@ generations (this defaults to 1)." | |||
| 154 | (setq n (/ (- (1- (window-height)) | 149 | (setq n (/ (- (1- (window-height)) |
| 155 | (count-lines (point-min) (point-max))) | 150 | (count-lines (point-min) (point-max))) |
| 156 | 2)) | 151 | 2)) |
| 157 | (goto-beginning-of-buffer) | 152 | (goto-char (point-min)) |
| 158 | (newline n) | 153 | (newline n) |
| 159 | (goto-end-of-buffer) | 154 | (goto-char (point-max)) |
| 160 | (newline n) | 155 | (newline n) |
| 161 | ;; pad lines out to fill-column | 156 | ;; pad lines out to fill-column |
| 162 | (goto-beginning-of-buffer) | 157 | (goto-char (point-min)) |
| 163 | (while (not (eobp)) | 158 | (while (not (eobp)) |
| 164 | (end-of-line) | 159 | (end-of-line) |
| 165 | (indent-to fill-column) | 160 | (indent-to fill-column) |
| @@ -186,14 +181,14 @@ generations (this defaults to 1)." | |||
| 186 | (insert ?\n)) | 181 | (insert ?\n)) |
| 187 | 182 | ||
| 188 | (defun life-increment-generation () | 183 | (defun life-increment-generation () |
| 189 | (increment life-current-generation) | 184 | (life-increment life-current-generation) |
| 190 | (setq life-generation-string (int-to-string life-current-generation))) | 185 | (setq life-generation-string (int-to-string life-current-generation))) |
| 191 | 186 | ||
| 192 | (defun life-grim-reaper () | 187 | (defun life-grim-reaper () |
| 193 | ;; Clear the match information. Later we check to see if it | 188 | ;; Clear the match information. Later we check to see if it |
| 194 | ;; is still clear, if so then all the cells have died. | 189 | ;; is still clear, if so then all the cells have died. |
| 195 | (store-match-data nil) | 190 | (store-match-data nil) |
| 196 | (goto-beginning-of-buffer) | 191 | (goto-char (point-min)) |
| 197 | ;; For speed declare all local variable outside the loop. | 192 | ;; For speed declare all local variable outside the loop. |
| 198 | (let (point char pivot living-neighbors list) | 193 | (let (point char pivot living-neighbors list) |
| 199 | (while (search-forward (life-life-string) nil t) | 194 | (while (search-forward (life-life-string) nil t) |
| @@ -211,7 +206,7 @@ generations (this defaults to 1)." | |||
| 211 | ((< char 9) | 206 | ((< char 9) |
| 212 | (subst-char-in-region point (1+ point) char 9 t)) | 207 | (subst-char-in-region point (1+ point) char 9 t)) |
| 213 | ((>= char (life-life-char)) | 208 | ((>= char (life-life-char)) |
| 214 | (increment living-neighbors))) | 209 | (life-increment living-neighbors))) |
| 215 | (setq list (cdr list))) | 210 | (setq list (cdr list))) |
| 216 | (if (memq living-neighbors '(2 3)) | 211 | (if (memq living-neighbors '(2 3)) |
| 217 | () | 212 | () |
| @@ -227,13 +222,13 @@ generations (this defaults to 1)." | |||
| 227 | 222 | ||
| 228 | (defun life-expand-plane-if-needed () | 223 | (defun life-expand-plane-if-needed () |
| 229 | (catch 'done | 224 | (catch 'done |
| 230 | (goto-beginning-of-buffer) | 225 | (goto-char (point-min)) |
| 231 | (while (not (eobp)) | 226 | (while (not (eobp)) |
| 232 | ;; check for life at beginning or end of line. If found at | 227 | ;; check for life at beginning or end of line. If found at |
| 233 | ;; either end, expand at both ends, | 228 | ;; either end, expand at both ends, |
| 234 | (cond ((or (eq (following-char) (life-life-char)) | 229 | (cond ((or (eq (following-char) (life-life-char)) |
| 235 | (eq (progn (end-of-line) (preceding-char)) (life-life-char))) | 230 | (eq (progn (end-of-line) (preceding-char)) (life-life-char))) |
| 236 | (goto-beginning-of-buffer) | 231 | (goto-char (point-min)) |
| 237 | (while (not (eobp)) | 232 | (while (not (eobp)) |
| 238 | (insert (life-void-char)) | 233 | (insert (life-void-char)) |
| 239 | (end-of-line) | 234 | (end-of-line) |
| @@ -244,23 +239,23 @@ generations (this defaults to 1)." | |||
| 244 | (life-compute-neighbor-deltas) | 239 | (life-compute-neighbor-deltas) |
| 245 | (throw 'done t))) | 240 | (throw 'done t))) |
| 246 | (forward-line))) | 241 | (forward-line))) |
| 247 | (goto-beginning-of-buffer) | 242 | (goto-char (point-min)) |
| 248 | ;; check for life within the first two lines of the buffer. | 243 | ;; check for life within the first two lines of the buffer. |
| 249 | ;; If present insert two lifeless lines at the beginning.. | 244 | ;; If present insert two lifeless lines at the beginning.. |
| 250 | (cond ((search-forward (life-life-string) | 245 | (cond ((search-forward (life-life-string) |
| 251 | (+ (point) fill-column fill-column 2) t) | 246 | (+ (point) fill-column fill-column 2) t) |
| 252 | (goto-beginning-of-buffer) | 247 | (goto-char (point-min)) |
| 253 | (insert-char (life-void-char) fill-column) | 248 | (insert-char (life-void-char) fill-column) |
| 254 | (insert ?\n) | 249 | (insert ?\n) |
| 255 | (insert-char (life-void-char) fill-column) | 250 | (insert-char (life-void-char) fill-column) |
| 256 | (insert ?\n) | 251 | (insert ?\n) |
| 257 | (setq life-window-start (+ life-window-start fill-column 1)))) | 252 | (setq life-window-start (+ life-window-start fill-column 1)))) |
| 258 | (goto-end-of-buffer) | 253 | (goto-char (point-max)) |
| 259 | ;; check for life within the last two lines of the buffer. | 254 | ;; check for life within the last two lines of the buffer. |
| 260 | ;; If present insert two lifeless lines at the end. | 255 | ;; If present insert two lifeless lines at the end. |
| 261 | (cond ((search-backward (life-life-string) | 256 | (cond ((search-backward (life-life-string) |
| 262 | (- (point) fill-column fill-column 2) t) | 257 | (- (point) fill-column fill-column 2) t) |
| 263 | (goto-end-of-buffer) | 258 | (goto-char (point-max)) |
| 264 | (insert-char (life-void-char) fill-column) | 259 | (insert-char (life-void-char) fill-column) |
| 265 | (insert ?\n) | 260 | (insert ?\n) |
| 266 | (insert-char (life-void-char) fill-column) | 261 | (insert-char (life-void-char) fill-column) |