summaryrefslogtreecommitdiff
path: root/lisp/play/solitaire.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/play/solitaire.el')
-rw-r--r--lisp/play/solitaire.el455
1 files changed, 0 insertions, 455 deletions
diff --git a/lisp/play/solitaire.el b/lisp/play/solitaire.el
deleted file mode 100644
index 4ce8b7d3ff0..00000000000
--- a/lisp/play/solitaire.el
+++ /dev/null
@@ -1,455 +0,0 @@
-;;; solitaire.el --- game of solitaire in Emacs Lisp
-
-;; Copyright (C) 1994 Free Software Foundation, Inc.
-
-;; Author: Jan Schormann <Jan.Schormann@informatik.uni-oldenburg.de>
-;; Created: Fri afternoon, Jun 3, 1994
-;; Keywords: games
-
-;; 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 2, 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; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This mode is for playing a well-known game of solitaire
-;; in which you jump pegs across other pegs.
-
-;; The game itself is somehow self-explanatory. Read the help text to
-;; solitaire, and try it.
-
-;;; Code:
-
-(defvar solitaire-mode-map nil
- "Keymap for playing solitaire.")
-
-(if solitaire-mode-map
- ()
- (setq solitaire-mode-map (make-sparse-keymap))
- (suppress-keymap solitaire-mode-map t)
- (define-key solitaire-mode-map "\C-f" 'solitaire-right)
- (define-key solitaire-mode-map "\C-b" 'solitaire-left)
- (define-key solitaire-mode-map "\C-p" 'solitaire-up)
- (define-key solitaire-mode-map "\C-n" 'solitaire-down)
- (define-key solitaire-mode-map [return] 'solitaire-move)
- (substitute-key-definition 'undo 'solitaire-undo
- solitaire-mode-map global-map)
- (define-key solitaire-mode-map " " 'solitaire-do-check)
- (define-key solitaire-mode-map "q" 'solitaire-quit)
-
- (define-key solitaire-mode-map [right] 'solitaire-right)
- (define-key solitaire-mode-map [left] 'solitaire-left)
- (define-key solitaire-mode-map [up] 'solitaire-up)
- (define-key solitaire-mode-map [down] 'solitaire-down)
-
- (define-key solitaire-mode-map [S-right] 'solitaire-move-right)
- (define-key solitaire-mode-map [S-left] 'solitaire-move-left)
- (define-key solitaire-mode-map [S-up] 'solitaire-move-up)
- (define-key solitaire-mode-map [S-down] 'solitaire-move-down)
-
- (define-key solitaire-mode-map [kp-6] 'solitaire-right)
- (define-key solitaire-mode-map [kp-4] 'solitaire-left)
- (define-key solitaire-mode-map [kp-8] 'solitaire-up)
- (define-key solitaire-mode-map [kp-2] 'solitaire-down)
- (define-key solitaire-mode-map [kp-5] 'solitaire-center-point)
-
- (define-key solitaire-mode-map [S-kp-6] 'solitaire-move-right)
- (define-key solitaire-mode-map [S-kp-4] 'solitaire-move-left)
- (define-key solitaire-mode-map [S-kp-8] 'solitaire-move-up)
- (define-key solitaire-mode-map [S-kp-2] 'solitaire-move-down)
-
- (define-key solitaire-mode-map [kp-enter] 'solitaire-move)
- (define-key solitaire-mode-map [kp-0] 'solitaire-undo)
-
- ;; spoil it with s ;)
- (define-key solitaire-mode-map [?s] 'solitaire-solve)
-
- ;; (define-key solitaire-mode-map [kp-0] 'solitaire-hint) - Not yet provided ;)
- )
-
-;; Solitaire mode is suitable only for specially formatted data.
-(put 'solitaire-mode 'mode-class 'special)
-
-(defun solitaire-mode ()
- "Major mode for playing solitaire.
-To learn how to play solitaire, see the documentation for function
-`solitaire'.
-\\<solitaire-mode-map>
-The usual mnemonic keys move the cursor around the board; in addition,
-\\[solitaire-move] is a prefix character for actually moving a stone on the board."
- (interactive)
- (kill-all-local-variables)
- (use-local-map solitaire-mode-map)
- (setq truncate-lines t)
- (setq major-mode 'solitaire-mode)
- (setq mode-name "Solitaire")
- (run-hooks 'solitaire-mode-hook))
-
-(defvar solitaire-stones 0
- "Counter for the stones that are still there.")
-
-(defvar solitaire-center nil
- "Center of the board.")
-
-(defvar solitaire-start nil
- "Upper left corner of the board.")
-
-(defvar solitaire-start-x nil)
-(defvar solitaire-start-y nil)
-
-(defvar solitaire-end nil
- "Lower right corner of the board.")
-
-(defvar solitaire-end-x nil)
-(defvar solitaire-end-y nil)
-
-(defvar solitaire-auto-eval t
- "*Non-nil means check for possible moves after each major change.
-This takes a while, so switch this on if you like to be informed when
-the game is over, or off, if you are working on a slow machine.")
-
-(defconst solitaire-valid-directions
- '(solitaire-left solitaire-right solitaire-up solitaire-down))
-
-;;;###autoload
-(defun solitaire (arg)
- "Play Solitaire.
-
-To play Solitaire, type \\[solitaire].
-\\<solitaire-mode-map>
-Move around the board using the cursor keys.
-Move stones using \\[solitaire-move] followed by a direction key.
-Undo moves using \\[solitaire-undo].
-Check for possible moves using \\[solitaire-do-check].
-\(The variable solitaire-auto-eval controls whether to automatically
-check after each move or undo)
-
-What is Solitaire?
-
-I don't know who invented this game, but it seems to be rather old and
-its origin seems be northern Africa. Here's how to play:
-Initially, the board will look similar to this:
-
- Le Solitaire
- ============
-
- o o o
-
- o o o
-
- o o o o o o o
-
- o o o . o o o
-
- o o o o o o o
-
- o o o
-
- o o o
-
-Let's call the o's stones and the .'s holes. One stone fits into one
-hole. As you can see, all holes but one are occupied by stones. The
-aim of the game is to get rid of all but one stone, leaving that last
-one in the middle of the board if you're cool.
-
-A stone can be moved if there is another stone next to it, and a hole
-after that one. Thus there must be three fields in a row, either
-horizontally or vertically, up, down, left or right, which look like
-this: o o .
-
-Then the first stone is moved to the hole, jumping over the second,
-which therefore is taken away. The above thus `evaluates' to: . . o
-
-That's all. Here's the board after two moves:
-
- o o o
-
- . o o
-
- o o . o o o o
-
- o . o o o o o
-
- o o o o o o o
-
- o o o
-
- o o o
-
-Pick your favourite shortcuts:
-
-\\{solitaire-mode-map}"
-
- (interactive "P")
- (switch-to-buffer "*Solitaire*")
- (solitaire-mode)
- (setq buffer-read-only t)
- (setq solitaire-stones 32)
- (solitaire-insert-board)
- (solitaire-build-modeline)
- (goto-char (point-max))
- (setq solitaire-center (search-backward "."))
- (setq buffer-undo-list (list (point)))
- (set-buffer-modified-p nil))
-
-(defun solitaire-build-modeline ()
- (setq mode-line-format
- (list "" "---" 'mode-line-buffer-identification
- (if (< 1 solitaire-stones)
- (format "--> There are %d stones left <--" solitaire-stones)
- "------")
- 'global-mode-string " %[(" 'mode-name 'minor-mode-alist "%n"
- ")%]-%-"))
- (force-mode-line-update))
-
-(defun solitaire-insert-board ()
- (let* ((buffer-read-only nil)
- (w (window-width))
- (h (window-height))
- (hsep (cond ((> w 26) " ")
- ((> w 20) " ")
- (t "")))
- (vsep (cond ((> h 17) "\n\n")
- (t "\n")))
- (indent (make-string (/ (- w 7 (* 6 (length hsep))) 2) ?\ )))
- (erase-buffer)
- (insert (make-string (/ (- h 7 (if (> h 12) 3 0)
- (* 6 (1- (length vsep)))) 2) ?\n))
- (if (or (string= vsep "\n\n") (> h 12))
- (progn
- (insert (format "%sLe Solitaire\n" indent))
- (insert (format "%s============\n\n" indent))))
- (insert indent)
- (setq solitaire-start (point))
- (setq solitaire-start-x (current-column))
- (setq solitaire-start-y (solitaire-current-line))
- (insert (format " %s %so%so%so%s" hsep hsep hsep hsep vsep))
- (insert (format "%s %s %so%so%so%s" indent hsep hsep hsep hsep vsep))
- (insert (format "%so%so%so%so%so%so%so%s" indent hsep hsep hsep hsep hsep hsep vsep))
- (insert (format "%so%so%so%s" indent hsep hsep hsep))
- (setq solitaire-center (point))
- (insert (format ".%so%so%so%s" hsep hsep hsep vsep))
- (insert (format "%so%so%so%so%so%so%so%s" indent hsep hsep hsep hsep hsep hsep vsep))
- (insert (format "%s %s %so%so%so%s" indent hsep hsep hsep hsep vsep))
- (insert (format "%s %s %so%so%so%s %s " indent hsep hsep hsep hsep hsep hsep))
- (setq solitaire-end (point))
- (setq solitaire-end-x (current-column))
- (setq solitaire-end-y (solitaire-current-line))
- ))
-
-(defun solitaire-right ()
- (interactive)
- (let ((start (point)))
- (forward-char)
- (while (= ?\ (following-char))
- (forward-char))
- (if (or (= 0 (following-char))
- (= ?\ (following-char))
- (= ?\n (following-char)))
- (goto-char start))))
-
-(defun solitaire-left ()
- (interactive)
- (let ((start (point)))
- (backward-char)
- (while (= ?\ (following-char))
- (backward-char))
- (if (or (= 0 (preceding-char))
- (= ?\ (following-char))
- (= ?\n (following-char)))
- (goto-char start))))
-
-(defun solitaire-up ()
- (interactive)
- (let ((start (point))
- (c (current-column)))
- (forward-line -1)
- (move-to-column c)
- (while (and (= ?\n (following-char))
- (forward-line -1)
- (move-to-column c)
- (not (bolp))))
- (if (or (= 0 (preceding-char))
- (= ?\ (following-char))
- (= ?\= (following-char))
- (= ?\n (following-char)))
- (goto-char start)
- )))
-
-(defun solitaire-down ()
- (interactive)
- (let ((start (point))
- (c (current-column)))
- (forward-line 1)
- (move-to-column c)
- (while (and (= ?\n (following-char))
- (forward-line 1)
- (move-to-column c)
- (not (eolp))))
- (if (or (= 0 (following-char))
- (= ?\ (following-char))
- (= ?\n (following-char)))
- (goto-char start))))
-
-(defun solitaire-center-point ()
- (interactive)
- (goto-char solitaire-center))
-
-(defun solitaire-move-right () (interactive) (solitaire-move '[right]))
-(defun solitaire-move-left () (interactive) (solitaire-move '[left]))
-(defun solitaire-move-up () (interactive) (solitaire-move '[up]))
-(defun solitaire-move-down () (interactive) (solitaire-move '[down]))
-
-(defun solitaire-possible-move (movesymbol)
- "Check if a move is possible from current point in the specified direction.
-MOVESYMBOL specifies the direction.
-Returns either a string, indicating cause of contraindication, or a
-list containing three numbers: starting field, skipped field (from
-which a stone will be taken away) and target."
-
- (save-excursion
- (let (move)
- (fset 'move movesymbol)
- (if (memq movesymbol solitaire-valid-directions)
- (let ((start (point))
- (skip (progn (move) (point)))
- (target (progn (move) (point))))
- (if (= skip target)
- "Off Board!"
- (if (or (/= ?o (char-after start))
- (/= ?o (char-after skip))
- (/= ?. (char-after target)))
- "Wrong move!"
- (list start skip target))))
- "Not a valid direction"))))
-
-(defun solitaire-move (dir)
- "Pseudo-prefix command to move a stone in Solitaire."
- (interactive "kMove where? ")
- (let* ((class (solitaire-possible-move (lookup-key solitaire-mode-map dir)))
- (buffer-read-only nil))
- (if (stringp class)
- (error class)
- (let ((start (car class))
- (skip (car (cdr class)))
- (target (car (cdr (cdr class)))))
- (goto-char start)
- (delete-char 1)
- (insert ?.)
- (goto-char skip)
- (delete-char 1)
- (insert ?.)
- (goto-char target)
- (delete-char 1)
- (insert ?o)
- (goto-char target)
- (setq solitaire-stones (1- solitaire-stones))
- (solitaire-build-modeline)
- (if solitaire-auto-eval (solitaire-do-check))))))
-
-(defun solitaire-undo (arg)
- "Undo a move in Solitaire."
- (interactive "P")
- (let ((buffer-read-only nil))
- (undo arg))
- (save-excursion
- (setq solitaire-stones
- (let ((count 0))
- (goto-char solitaire-end)
- (while (search-backward "o" solitaire-start 'done)
- (and (>= (current-column) solitaire-start-x)
- (<= (current-column) solitaire-end-x)
- (>= (solitaire-current-line) solitaire-start-y)
- (<= (solitaire-current-line) solitaire-end-y)
- (setq count (1+ count))))
- count)))
- (solitaire-build-modeline)
- (if solitaire-auto-eval (solitaire-do-check)))
-
-(defun solitaire-check ()
- (save-excursion
- (if (= 1 solitaire-stones)
- 0
- (goto-char solitaire-end)
- (let ((count 0))
- (while (search-backward "o" solitaire-start 'done)
- (and (>= (current-column) solitaire-start-x)
- (<= (current-column) solitaire-end-x)
- (>= (solitaire-current-line) solitaire-start-y)
- (<= (solitaire-current-line) solitaire-end-y)
- (mapcar
- (lambda (movesymbol)
- (if (listp (solitaire-possible-move movesymbol))
- (setq count (1+ count))))
- solitaire-valid-directions)))
- count))))
-
-(defun solitaire-do-check (&optional arg)
- "Check for any possible moves in Solitaire."
- (interactive "P")
- (let ((moves (solitaire-check)))
- (cond ((= 1 solitaire-stones)
- (message "Yeah! You made it! Only the King is left!"))
- ((zerop moves)
- (message "Sorry, no more possible moves."))
- ((= 1 moves)
- (message "There is one possible move."))
- (t (message "There are %d possible moves." moves)))))
-
-(defun solitaire-current-line ()
- "Return the vertical position of point.
-Seen in info on text lines."
- (+ (count-lines (point-min) (point))
- (if (= (current-column) 0) 1 0)
- -1))
-
-(defun solitaire-quit ()
- "Quit playing Solitaire."
- (interactive)
- (kill-buffer "*Solitaire*"))
-
-;; And here's the spoiler:)
-(defun solitaire-solve ()
- "Spoil solitaire by solving the game for you - nearly ...
-... stops with five stones left ;)"
- (interactive)
- (let ((allmoves [up up S-down up left left S-right up up left S-down
- up up right right S-left down down down S-up up
- S-down down down down S-up left left down
- S-right left left up up S-down right right right
- S-left left S-right right right right S-left
- right down down S-up down down left left S-right
- up up up S-down down S-up up up up S-down up
- right right S-left down right right down S-up
- left left left S-right right S-left down down
- left S-right S-up S-left S-left S-down S-right
- up S-right left left])
- ;; down down S-up left S-right
- ;; right S-left
- (solitaire-auto-eval nil))
- (solitaire-center-point)
- (mapcar (lambda (op)
- (if (memq op '(S-left S-right S-up S-down))
- (sit-for 0.2))
- (execute-kbd-macro (vector op))
- (if (memq op '(S-left S-right S-up S-down))
- (sit-for 0.4)))
- allmoves))
- (solitaire-do-check))
-
-(provide 'solitaire)
-
-;;; solitaire.el ends here