-;;; life.el --- John Horton Conway's `Life' game for GNU Emacs
+;;; life.el --- John Horton Conway's Game of Life -*- lexical-binding:t -*-
;; Copyright (C) 1988, 2001-2020 Free Software Foundation, Inc.
;; (scroll-up) and (scroll-down) when trying to center the display.
(defvar life-window-start nil)
+(defvar life--max-width nil
+ "If non-nil, restrict width to this positive integer. ")
+
+(defvar life--max-height nil
+ "If non-nil, restrict height to this positive integer. ")
+
;; For mode line
(defvar life-current-generation nil)
;; Sadly, mode-line-format won't display numbers.
(defvar life-generation-string nil)
+(defun life--tick ()
+ "Game tick for `life'."
+ (let ((inhibit-quit t)
+ (inhibit-read-only t))
+ (life-grim-reaper)
+ (life-expand-plane-if-needed)
+ (life-increment-generation)))
+
;;;###autoload
(defun life (&optional step-time)
"Run Conway's Life simulation.
(life-setup)
(catch 'life-exit
(while t
- (let ((inhibit-quit t)
- (inhibit-read-only t))
- (life-display-generation step-time)
- (life-grim-reaper)
- (life-expand-plane-if-needed)
- (life-increment-generation)))))
+ (life-display-generation step-time)
+ (life--tick))))
(define-derived-mode life-mode special-mode "Life"
"Major mode for the buffer of `life'."
(setq-local life-generation-string "0")
(setq-local mode-line-buffer-identification '("Life: generation "
life-generation-string))
- (setq-local fill-column (1- (window-width)))
+ (setq-local fill-column (min (or life--max-width most-positive-fixnum)
+ (1- (window-width))))
(setq-local life-window-start 1)
(buffer-disable-undo))
(indent-to n)
(forward-line)))
;; center the pattern vertically
- (let ((n (/ (- (1- (window-height))
+ (let ((n (/ (- (min (or life--max-height most-positive-fixnum)
+ (1- (window-height)))
(count-lines (point-min) (point-max)))
2)))
(goto-char (point-min))
--- /dev/null
+;;; life-tests.el --- Tests for life.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'life)
+
+(ert-deftest test-life ()
+ (let ((life--max-width 5)
+ (life--max-height 3)
+ (life-patterns [(" @ "
+ " @"
+ "@@@")])
+ (generations '("
+
+ @
+ @
+ @@@
+" "
+
+
+ @ @
+ @@
+ @
+" "
+
+
+ @
+ @ @
+ @@
+" "
+
+
+ @
+ @@
+ @@
+" "
+
+
+ @
+ @
+ @@@
+"
+)))
+ (life-setup)
+ ;; Test initial state.
+ (goto-char (point-min))
+ (dolist (generation generations)
+ ;; Hack to test buffer contents without trailing whitespace,
+ ;; while also not modifying the "*Life*" buffer.
+ (let ((str (buffer-string))
+ (delete-trailing-lines t))
+ (with-temp-buffer
+ (insert str)
+ (delete-trailing-whitespace)
+ (should (equal (buffer-string) generation))))
+ (life--tick))))
+
+(provide 'life-tests)
+
+;;; life-tests.el ends here