--- C:\Dev\emacs-23.1\lisp\play\snake.el        2009-06-21 12:38:02.000000000 +0100
+++ C:\emacs-23.1\lisp\play\snake.el    2010-07-28 14:20:00.852191800 +0100
@@ -1,7 +1,7 @@
 ;;; snake.el --- implementation of Snake for Emacs

 ;; Copyright (C) 1997, 2001, 2002, 2003, 2004, 2005,
-;;   2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+;;   2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.

 ;; Author: Glynn Clements <glynn@sensei.co.uk>
 ;; Created: 1997-09-10
@@ -32,6 +32,34 @@
 (require 'gamegrid)

 ;; ;;;;;;;;;;;;; customization variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defgroup snake nil
+  "Classic game of Snake (or Nibbles)."
+  :prefix "snake-"
+  :group 'games)
+
+(defcustom snake-buffer-name "*Snake*"
+  "Name used for Snake buffer."
+  :group 'snake :type 'string)
+
+(defcustom snake-initial-length 5
+  "Initial length of snake."
+  :group 'snake :type 'integer)
+
+(defcustom snake-spawn-rate 5
+  "Rate at which new apples will be desposited."
+  :group 'snake :type 'integer)
+
+(defcustom snake-score-file "snake-scores"
+  "File for holding high scores.
+It is not safe to put this in /tmp.
+Someone could make a symlink in /tmp
+pointing to a file you don't want to clobber."
+  :group 'snake :type 'file)
+
+(defcustom snake-randomize-apples t
+  "If non-nil, apples will be deposited at random.
+If nil, then apples will be dropped behind the snake."
+  :group 'snake :type 'boolean)

 (defvar snake-use-glyphs-flag t
   "Non-nil means use glyphs when available.")
@@ -39,9 +67,6 @@
 (defvar snake-use-color-flag t
   "Non-nil means use color when available.")

-(defvar snake-buffer-name "*Snake*"
-  "Name used for Snake buffer.")
-
 (defvar snake-buffer-width 30
   "Width of used portion of buffer.")

@@ -54,9 +79,6 @@
 (defvar snake-height 20
   "Height of playing area.")

-(defvar snake-initial-length 5
-  "Initial length of snake.")
-
 (defvar snake-initial-x 10
   "Initial X position of snake.")

@@ -81,12 +103,6 @@
 (defvar snake-score-y snake-height
   "Y position of score.")

-;; It is not safe to put this in /tmp.
-;; Someone could make a symlink in /tmp
-;; pointing to a file you don't want to clobber.
-(defvar snake-score-file "snake-scores"
-  "File for holding high scores.")
-
 ;; ;;;;;;;;;;;;; display options ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 (defvar snake-blank-options
@@ -194,6 +210,7 @@
 ;; ;;;;;;;;;;;;;;;; game functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 (defun snake-display-options ()
+  "Set snake buffer display options."
   (let ((options (make-vector 256 nil)))
     (loop for c from 0 to 255 do
       (aset options c
@@ -212,6 +229,7 @@
     options))

 (defun snake-update-score ()
+  "Update the score string."
   (let* ((string (format "Score:  %05d" snake-score))
         (len (length string)))
     (loop for x from 0 to (1- len) do
@@ -220,6 +238,7 @@
                         (aref string x)))))

 (defun snake-init-buffer ()
+  "Initialize snake buffer."
   (gamegrid-init-buffer snake-buffer-width
                        snake-buffer-height
                        snake-space)
@@ -232,6 +251,7 @@
                (gamegrid-set-cell x y snake-blank)))))

 (defun snake-reset-game ()
+  "Reset snake game."
   (gamegrid-kill-timer)
   (snake-init-buffer)
   (setq snake-length           snake-initial-length
@@ -276,10 +296,12 @@
                      (tail-pos (cadr last-cons))
                      (x0 (aref tail-pos 0))
                      (y0 (aref tail-pos 1)))
-                (gamegrid-set-cell x0 y0
-                                   (if (= (% snake-cycle 5) 0)
-                                       snake-dot
-                                     snake-blank))
+                 (gamegrid-set-cell x0 y0 snake-blank)
+                 (if (= (% snake-cycle snake-spawn-rate) 0)
+                     ; Maintain existing behaviour as customizable variable.
+                     (if snake-randomize-apples
+                         (snake-put-apple)
+                       (gamegrid-set-cell x0 y0 snake-dot)))
                 (incf snake-cycle)
                 (setcdr last-cons nil))))
        (gamegrid-set-cell x y snake-snake)
@@ -287,7 +309,15 @@
              (cons (vector x y) snake-positions))
          (setq snake-moved-p nil)))))

+(defun snake-put-apple ()
+  "Deposit an apple at a random location."
+  (let ((x (1+ (random (- snake-width 2))))
+        (y (1+ (random (- snake-height 2)))))
+    (if (= (gamegrid-get-cell x y) snake-blank)
+        (gamegrid-set-cell x y snake-dot))))
+
 (defun snake-update-velocity ()
+  "Update the snake's velocity."
   (unless snake-moved-p
     (if snake-velocity-queue
        (let ((new-vel (car (last snake-velocity-queue))))
@@ -350,6 +380,7 @@
   (message (and snake-paused "Game paused (press p to resume)")))

 (defun snake-active-p ()
+  "Is snake the active mode check."
   (eq (current-local-map) snake-mode-map))

 (put 'snake-mode 'mode-class 'special)
@@ -358,8 +389,7 @@
   "A mode for playing Snake.

 Snake mode keybindings:
-   \\{snake-mode-map}
-"
+   \\{snake-mode-map}"
   (kill-all-local-variables)

   (add-hook 'kill-buffer-hook 'gamegrid-kill-timer nil t)
