]> code.delx.au - gnu-emacs-elpa/commitdiff
Bug fixes and reducing the TODO list.
authorJohn Wiegley <johnw@newartisans.com>
Mon, 22 Apr 2002 19:23:45 +0000 (19:23 +0000)
committerJohn Wiegley <johnw@newartisans.com>
Mon, 22 Apr 2002 19:23:45 +0000 (19:23 +0000)
22 files changed:
PLAN
TODO
chess-algebraic.el
chess-autosave.el
chess-common.el
chess-database.el
chess-display.el
chess-engine.el
chess-fen.el
chess-game.el
chess-ics1.el
chess-images.el
chess-link.el
chess-network.el
chess-pgn.el
chess-plain.el
chess-ply.el
chess-pos.el
chess-puzzle.el [new file with mode: 0644]
chess-random.el
chess-tutorial.el [new file with mode: 0644]
chess.el

diff --git a/PLAN b/PLAN
index 1a84c8f435f0655dce554b28973c4f7383e47824..9ce2f0d4a9926e46b0142fabe5045c794a4bf1b6 100644 (file)
--- a/PLAN
+++ b/PLAN
@@ -1,34 +1,36 @@
-chess-algebraic
-chess-announce   99%
-chess-autosave   90%  [what about multiple simultaneous games?]
-chess-clock
-chess-common
-chess-crafty
-chess-database
-chess-display
+TEST: chess-chat, chess-kibitz, chess-scid, chess-irc (CTCP)
+TRANSLATE: chess-german
+
+chess-pos
+- break chess-legal-plies into two parts, one of which would be the
+  inverse of chess-search-position, and would live in chess-pos.el
+
 chess-engine
-chess-fen
-chess-file
-chess-game
-chess-gnuchess
+- the game should go inactive once I lose by stalemate/checkmate
+- detect draw/resign/abort/retract, etc., from ICS and common engines
+- find a way that regexp-alist entries that only need to fire once are
+  only scanned once.
+- in chess-engine-filter and chess-ics-filter, if an error is
+  encountered, skip that line so the same error isn't triggered again
+- implement engine options; then, in chess-puzzle set the option that
+  tells the engine not to resign.
+
 chess-ics
-chess-ics1
-chess-images
-chess-irc
-chess-link
-chess-maint
-chess-message
-chess-module
-chess-network
-chess-none
-chess-pgn
-chess-phalanx
-chess-plain
-chess-ply
-chess-pos
-chess-random
-chess-scid
-chess-sound
-chess-transport
-chess-var
-chess
+- add support for ICS observing
+- make sure that helpers are allowed in the ics-server-alist
+
+chess-clock
+- when a clock runs down, indicate this in the modeline, and allow the
+  user to call-flag in order to win on time; note: the user should be
+  allowed to try anyway, in case our clock has become out-of-sync with
+  the server's
+
+                        BEFORE FINAL RELEASE
+
+  use more asserts throughout the code
+  break my dependency on cl
+* profile
+* mem profile
+  docstring/texi
+  checkdoc
+  elint
diff --git a/TODO b/TODO
index d5d3a67ac2f7368956e9c70fa194fa93d9ed6d9b..319a432445cca0c2e5060f2d59d0d37525c751c5 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,91 +1,55 @@
+These are features scheduled for future 2.x releases.
 
-                              Hotlist
-
-- After I resign (against crafty, for example), the mode-line does not
-  look as it should; the board is not reset, which causes C-l to fail
-  because chess-display-index is now bogus
-
-- Follow what `edit-env' does, in order to make chess-query.el
-
-- Make ( create variations in a display, and C-f and C-b move into and
-  out of them
-
-- Find a way that regexp-alist entries that only need to fire once are
-  only scanned once.
-
-- Add support for ICS observing
+----------------------------------------------------------------------
 
-- Use server-side sockets in chess-network, if Emacs supports it
+                          General Features
 
-- Allow ASCII displays to use a separate frame
+- Make ( create variations in a display, and keys to move into and out
+  of them.  At the moment, variations are supported programmatically,
+  but not in the UI.
 
-- Still need to test many areas: position editing
+- Make a display read-only mode, which allows people to view/browse
+  but not alter a game.  This could be used for remoting displays in
+  order that people on other X servers might observe a game.
 
-- In chess-ics.el, setup a completion function based on handles
+- Implement the "50 moves after irreversible" draw rule in chess-ply
 
-- Break chess-legal-plies into two parts, one of which would be the
-  inverse of chess-search-position, and would live in chess-pos.el
+- Port the code to XEmacs
 
-- Have elp.el not instrument defsubst functions; it obscures the
-  results too much
+- Find a way to display pieces on Windows platforms, or at least
+  document how to build XPM support into Emacs for Windows
 
 ----------------------------------------------------------------------
 
-                             To-do List
+                             ICS Client
 
-- Copy some of ics.el's nicer functionality into chess-ics.el
-
-- Need to implement the "50 moves after irreversible" draw rule
-
-- The game should go inactive once I lose by stalemate/checkmate
+- Add a completion function against logged in users
 
-- When a clock runs down, indicate this in the modeline, and all the
-  user to call-flag in order to win on time
-
-- Detect draw/resign/abort/retract, etc., from ICS and common engines
+- Copy some of ics.el's nicer functionality into chess-ics.el
 
-- in chess-engine-filter and chess-ics-filter, if an error is
-  encountered, skip that line so the same error isn't triggered again
+----------------------------------------------------------------------
 
-- SPACE to pass, then try to move (against an engine) fails saying:
-  it's not our turn to move
+                           Chess by Mail
 
 - Add support for adjournments; also, implement this is such a way
   that an e-mail or postal game is basically a game that's adjourned
   after every move; use BBDB if available
 
-- Allow databases to return a game moniker, which can be used to
-  reference that game again
-
-- There needs to be much more robustness; it's too easy to get the
-  game into an unplayable state right now
-
-- Break my dependency on cl
-
-- Use more asserts throughout the code
-
-- Read-only mode needs to be more vigorous.  There's nothing
-  preventing the user from using M-x commands.
-
-- Complete chess-pgn-mode's automatic entry, using chess-input, and
-  making space/return perform the move
-
 - Use MIME attachments (application/x-chess-pgn) for sending e-mail
   chess games back and forth.
 
-- In edit mode, mouse-2 and mouse-3 should provide a drop-down list of
-  pieces the square can be set to.  Cursor movement is really not the
-  best for chess-images.  I still need to figure out how best to
-  handle cursor-type with that display.
+----------------------------------------------------------------------
 
-- Implement engine options; then, in chess-puzzle set the option that
-  tells the engine not to resign.
+                        Database Interaction
 
-- Remote displays are horribly insecure.
+- Enable UI commands in chess-display to interact with databases.  As
+  of 2.0, this support is programmatic only.
+
+- Follow what `edit-env' does, in order to make chess-query.el.
 
 ----------------------------------------------------------------------
 
-                              Training
+                         Training/Tutorials
 
 - Write a scripted chess-tutorial.
 
@@ -130,12 +94,3 @@ Need a way to play bughouse/crazyhouse games.
 
 ----------------------------------------------------------------------
 
-                        BEFORE FINAL RELEASE
-
-  port the code to XEmacs
-  profile
-  mem profile
-  docstring
-  texi
-  elint
-  checkdoc
index 7cdb253f0c21e9307d6619ad09358be37f5d9316..95b5bc6788c93de58c23970ee4618759cd0c3cfe 100644 (file)
@@ -32,8 +32,6 @@
 ;;    chess-algebraic-regexp
 ;;
 
-(require 'chess-ply)
-
 (defconst chess-algebraic-pieces-regexp "[RNBKQ]")
 
 (defconst chess-algebraic-regexp
index f8f7369a4567bf8332a98ef73c23ae5ab3fca536..909e3155983f9c61462da3feddc8ad9f1c35e1e0 100644 (file)
 
 (chess-message-catalog 'english
   '((chess-read-autosave   . "There is a chess autosave file, read it? ")
-    (chess-delete-autosave . "Delete the autosave file? ")))
+    (chess-delete-autosave . "Delete the autosave file? ")
+    (chess-disable-autosave . "Disable autosaving for this game? ")))
 
 (defun chess-autosave-handler (game event &rest args)
   (cond
    ((eq event 'initialize)
-    (if (file-readable-p chess-autosave-file)
-       (if (y-or-n-p (chess-string 'chess-read-autosave))
-           (prog1
-               (chess-game-copy-game
-                game (chess-autosave-read chess-autosave-file))
-             (delete-file chess-autosave-file))
-         (ignore
-          (if (y-or-n-p (chess-string 'chess-delete-autosave))
-              (delete-file chess-autosave-file)))))
-    (kill-buffer (current-buffer))
-    (set-buffer (find-file-noselect chess-autosave-file t))
-    t)
+    (let ((result t))
+      (if (file-readable-p chess-autosave-file)
+         (if (y-or-n-p (chess-string 'chess-read-autosave))
+             (progn
+               (chess-game-copy-game game (chess-autosave-read
+                                           chess-autosave-file))
+               (delete-file chess-autosave-file))
+           (if (y-or-n-p (chess-string 'chess-delete-autosave))
+               (delete-file chess-autosave-file)
+             (if (y-or-n-p (chess-string 'chess-disable-autosave))
+                 (setq result nil)))))
+      (kill-buffer (current-buffer))
+      (set-buffer (find-file-noselect chess-autosave-file t))
+      result))
 
    ((eq event 'post-move)
     (chess-autosave-write game chess-autosave-file))
index 775dc4a50cbbeb5f411961cc4e6cbba8e6c608a8..167ee4dc7f853d5c4a8224a78c92618b2e6f13c2 100644 (file)
       (chess-game-undo game (car args))))
 
    ((eq event 'move)
-    (if (= 0 (chess-game-index game))
-       (chess-game-set-tag game "White" chess-full-name)
-      (if (= 1 (chess-game-index game))
-         (chess-game-set-tag game "Black" chess-engine-opponent-name)))
+    (when (= 1 (chess-game-index game))
+      (chess-game-set-tag game "White" chess-full-name)
+      (chess-game-set-tag game "Black" chess-engine-opponent-name))
 
     (chess-engine-send nil (concat (chess-ply-to-algebraic (car args)) "\n"))
 
index b3a78189a7788cb4c757625f299cf43086057b2e..4095f06a686d727a752b53b202a13f8c89976668 100644 (file)
 (defun chess-database-count (database)
   (chess-database-command database 'count))
 
-(defun chess-database-read (database index)
-  (chess-database-command database 'read index))
+(defun chess-database-read (database index-or-moniker)
+  (if (integerp index-or-moniker)
+      (chess-database-command database 'read index)
+    (if (string-match "\\`\\([^:]+\\):\\([^#]+\\)#\\([0-9]+\\)\\'"
+                     index-or-moniker)
+       (let* ((type (match-string 1 index-or-moniker))
+              (path (match-string 2 index-or-moniker))
+              (index (string-to-int
+                      (match-string 3 index-or-moniker)))
+              (db (chess-database-open
+                   (intern (concat "chess-" type)) path)))
+         (if db
+             (chess-database-read db index))))))
 
 (defun chess-database-write (database game)
   (chess-database-command database 'write game))
index 47303f1e64fd9a19aee5be1d67fced5a7e2fb09a..164185d115ab1e13249f9549d3036b701b0ce977 100644 (file)
@@ -5,8 +5,6 @@
 
 (require 'chess-module)
 (require 'chess-var)
-(require 'chess-algebraic)
-(require 'chess-fen)
 (require 'chess-input)
 
 (defgroup chess-display nil
@@ -30,7 +28,8 @@
     (mode-checkmate . "CHECKMATE")
     (mode-resigned  . "RESIGNED")
     (mode-stalemate . "STALEMATE")
-    (mode-drawn     . "DRAWN")))
+    (mode-drawn     . "DRAWN")
+    (mode-edit      . "EDIT")))
 
 (defcustom chess-display-mode-line-format
   '("   " chess-display-side-to-move "   "
@@ -61,6 +60,7 @@ See `mode-line-format' for syntax details."
 (defvar chess-display-event-handler nil)
 (defvar chess-display-no-popup nil)
 (defvar chess-display-edit-mode nil)
+(defvar chess-display-index-positions nil)
 
 (make-variable-buffer-local 'chess-display-index)
 (make-variable-buffer-local 'chess-display-move-text)
@@ -69,13 +69,14 @@ See `mode-line-format' for syntax details."
 (make-variable-buffer-local 'chess-display-event-handler)
 (make-variable-buffer-local 'chess-display-no-popup)
 (make-variable-buffer-local 'chess-display-edit-mode)
+(make-variable-buffer-local 'chess-display-index-positions)
 
 (defvar chess-display-handling-event nil)
+(defvar chess-display-style)
 
 (chess-message-catalog 'english
-  '((no-such-style . "There is no such chessboard display style '%s'")))
-
-(defvar chess-display-style)
+  '((no-such-style . "There is no such chessboard display style '%s'")
+    (cannot-yet-add . "Cannot insert moves into a game (yet)")))
 
 (defun chess-display-create (game style perspective)
   "Create a chess display, for displaying chess objects."
@@ -100,7 +101,8 @@ See `mode-line-format' for syntax details."
 
 (defun chess-display-set-perspective* (display perspective)
   (chess-with-current-buffer display
-    (setq chess-display-perspective perspective)
+    (setq chess-display-perspective perspective
+         chess-display-index-positions nil)
     (erase-buffer)))                   ; force a complete redraw
 
 (defun chess-display-set-perspective (display perspective)
@@ -122,7 +124,9 @@ See `mode-line-format' for syntax details."
 (defun chess-display-position (display)
   "Return the position currently viewed."
   (chess-with-current-buffer display
-    (chess-game-pos chess-module-game chess-display-index)))
+    (if chess-display-edit-mode
+       chess-display-edit-position
+      (chess-game-pos chess-module-game chess-display-index))))
 
 (defun chess-display-set-ply (display ply)
   (chess-with-current-buffer display
@@ -240,10 +244,6 @@ also view the same game."
       (chess-display-update nil)
       (goto-char here))))
 
-(defvar chess-display-index-positions nil)
-
-(make-variable-buffer-local 'chess-display-index-positions)
-
 (defun chess-display-index-pos (display index)
   (chess-with-current-buffer display
     (unless chess-display-index-positions
@@ -289,14 +289,14 @@ If only START is given, it must be in algebraic move notation."
                  (chess-game-index chess-module-game))
               (chess-game-over-p chess-module-game))
          (chess-error 'game-is-over)))
-    ;; jww (2002-03-28): This should beget a variation within the
-    ;; game, or alter the game, just as SCID allows
     (if (= chess-display-index (chess-game-index chess-module-game))
        (let ((chess-display-handling-event t))
          (chess-display-paint-move nil ply)
          (chess-game-move chess-module-game ply)
          (chess-display-set-index* nil (chess-game-index chess-module-game)))
-      (error "What to do here??  NYI"))))
+      ;; jww (2002-03-28): This should beget a variation within the
+      ;; game, or alter the game, just as SCID allows
+      (chess-error 'cannot-yet-add))))
 
 (defun chess-display-highlight (display &rest args)
   "Highlight the square at INDEX on the current position.
@@ -345,7 +345,8 @@ that is supported by most displays, and is the default mode."
   (unless (get-buffer-window (current-buffer))
     (fit-window-to-buffer (display-buffer (current-buffer)))))
 
-(defun chess-display-popup-in-frame (height width &optional display)
+(defun chess-display-popup-in-frame (height width &optional
+                                           display no-minibuffer)
   "Popup the given DISPLAY, so that it's visible to the user."
   (let ((window (get-buffer-window (current-buffer) t)))
     (if window
@@ -357,6 +358,8 @@ that is supported by most displays, and is the default mode."
                          (cons 'width width))))
        (if display
            (push (cons 'display display) params))
+       (if no-minibuffer
+           (push (cons 'minibuffer nil) params))
        (select-frame (make-frame params))
        (set-window-dedicated-p (selected-window) t)))))
 
@@ -452,14 +455,13 @@ See `chess-display-type' for the different kinds of displays."
     (define-key map [(meta ?w)] 'chess-display-kill-board)
 
     (define-key map [(control ?l)] 'chess-display-redraw)
-    (define-key map [(control ?n)] 'chess-display-move-forward)
-    (define-key map [(control ?p)] 'chess-display-move-backward)
 
     map)
   "The mode map used in read-only display buffers.")
 
 (defvar chess-display-mode-map
   (let ((map (copy-keymap chess-display-safe-map)))
+    (define-key map [space] 'chess-display-pass)
     (define-key map [? ] 'chess-display-pass)
     (define-key map [??] 'describe-mode)
     (define-key map [?@] 'chess-display-remote)
@@ -497,13 +499,16 @@ See `chess-display-type' for the different kinds of displays."
     (cond
      ((featurep 'xemacs)
       (define-key map [(button1)] 'chess-display-mouse-select-piece)
-      (define-key map [(button2)] 'chess-display-mouse-select-piece))
+      (define-key map [(button2)] 'chess-display-mouse-select-piece)
+      (define-key map [(button3)] 'ignore))
      (t
       (define-key map [down-mouse-1] 'chess-display-mouse-select-piece)
       (define-key map [drag-mouse-1] 'chess-display-mouse-select-piece)
 
       (define-key map [down-mouse-2] 'chess-display-mouse-select-piece)
-      (define-key map [drag-mouse-2] 'chess-display-mouse-select-piece)))
+      (define-key map [drag-mouse-2] 'chess-display-mouse-select-piece)
+
+      (define-key map [mouse-3] 'ignore)))
 
     (define-key map [menu-bar files] 'undefined)
     (define-key map [menu-bar edit] 'undefined)
@@ -681,16 +686,6 @@ Basically, it means we are playing, not editing or reviewing."
   (interactive)
   (chess-display-search-backward t))
 
-(defun chess-display-set-piece ()
-  "Set the piece under point to command character, or space for clear."
-  (interactive)
-  (unless (chess-display-active-p)
-    (let ((index (get-text-property (point) 'chess-coord)))
-      (chess-pos-set-piece (chess-display-position nil) index
-                          last-command-char)
-      (funcall chess-display-event-handler 'draw-square
-              (point) last-command-char index))))
-
 (chess-message-catalog 'english
   '((illegal-notation . "Illegal move notation: %s")
     (want-to-quit     . "Do you really want to quit? ")))
@@ -860,19 +855,47 @@ to the end or beginning."
 ;; chess-display-edit-mode (for editing the position directly)
 ;;
 
+(defvar chess-display-edit-position nil)
+
+(make-variable-buffer-local 'chess-display-edit-position)
+
 (defvar chess-display-edit-mode-map
   (let ((map (make-keymap)))
     (suppress-keymap map)
-    (set-keymap-parent map chess-display-mode-map)
+
+    (define-key map [(control ?l)] 'chess-display-redraw)
+    (define-key map [(control ?i)] 'chess-display-invert)
+    (define-key map [tab] 'chess-display-invert)
+
+    (define-key map [??] 'describe-mode)
+    (define-key map [?L] 'chess-display-list-buffers)
+    ;;(define-key map [?C] 'chess-display-duplicate)
+    (define-key map [?I] 'chess-display-invert)
 
     (define-key map [?C] 'chess-display-clear-board)
     (define-key map [?G] 'chess-display-restore-board)
     (define-key map [?S] 'chess-display-send-board)
+    (define-key map [?X] 'chess-display-quit)
 
     (let ((keys '(?  ?p ?r ?n ?b ?q ?k ?P ?R ?N ?B ?Q ?K)))
       (while keys
        (define-key map (vector (car keys)) 'chess-display-set-piece)
        (setq keys (cdr keys))))
+
+    (cond
+     ((featurep 'xemacs)
+      (define-key map [(button1)] 'chess-display-mouse-select-piece)
+      (define-key map [(button2)] 'chess-display-mouse-set-piece)
+      (define-key map [(button3)] 'chess-display-mouse-set-piece))
+     (t
+      (define-key map [down-mouse-1] 'chess-display-mouse-select-piece)
+      (define-key map [drag-mouse-1] 'chess-display-mouse-select-piece)
+
+      (define-key map [mouse-2] 'chess-display-mouse-set-piece)
+      (define-key map [down-mouse-2] 'chess-display-mouse-set-piece)
+      (define-key map [mouse-3] 'chess-display-mouse-set-piece)
+      (define-key map [down-mouse-3] 'chess-display-mouse-set-piece)))
+
     map)
   "The mode map used for editing a chessboard position.")
 
@@ -883,26 +906,33 @@ to the end or beginning."
 (defun chess-display-edit-board ()
   "Setup the current board for editing."
   (interactive)
-  (setq chess-display-edit-mode t)
-  ;; Take us out of any game/ply/variation we might be looking at,
-  ;; since we are not moving pieces now, but rather placing them --
-  ;; for which purpose the movement keys can still be used.
-  (chess-display-set-position nil (chess-display-position nil))
-  ;; jww (2002-03-28): setup edit-mode keymap here
+  (setq chess-display-edit-position
+       (chess-pos-copy (chess-display-position nil))
+       chess-display-edit-mode t
+       chess-display-side-to-move (chess-string 'mode-edit))
+  (force-mode-line-update)
+  (use-local-map chess-display-edit-mode-map)
+  (funcall chess-display-event-handler 'start-edit)
   (chess-message 'editing-directly))
 
+(defun chess-display-end-edit-mode ()
+  (setq chess-display-edit-mode nil)
+  (funcall chess-display-event-handler 'end-edit)
+  (use-local-map chess-display-mode-map))
+
 (defun chess-display-send-board ()
   "Send the current board configuration to the user."
   (interactive)
+  (chess-display-end-edit-mode)
   (chess-game-set-start-position chess-module-game
-                                (chess-display-position nil))
-  (setq chess-display-edit-mode nil))
+                                chess-display-edit-position))
 
 (defun chess-display-restore-board ()
   "Setup the current board for editing."
   (interactive)
-  ;; jww (2002-03-28): NYI
-  (setq chess-display-edit-mode nil)
+  (chess-display-end-edit-mode)
+  ;; reset the modeline
+  (chess-display-set-index* display chess-display-index)
   (chess-display-update nil))
 
 (defun chess-display-clear-board ()
@@ -915,6 +945,42 @@ to the end or beginning."
          (chess-pos-set-piece position (cons rank file) ? ))))
     (chess-display-update nil)))
 
+(defun chess-display-set-piece (&optional piece)
+  "Set the piece under point to command character, or space for clear."
+  (interactive)
+  (if (or (null piece) (char-valid-p piece))
+      (let ((index (get-text-property (point) 'chess-coord)))
+       (chess-pos-set-piece chess-display-edit-position index
+                            (or piece last-command-char))
+       (funcall chess-display-event-handler 'draw-square
+                (point) (or piece last-command-char) index))))
+
+(defun chess-display-mouse-set-piece (event)
+  "Select the piece the user clicked on."
+  (interactive "e")
+  (if (fboundp 'event-window)          ; XEmacs
+      (progn
+       (set-buffer (window-buffer (event-window event)))
+       (and (event-point event) (goto-char (event-point event))))
+    (set-buffer (window-buffer (posn-window (event-start event))))
+    (goto-char (posn-point (event-start event))))
+  (let ((pieces (if (memq (car event) '(down-mouse-3 mouse-3))
+                   '("Set black piece"
+                     ("Pieces"
+                      ("Pawn"   . ?p)
+                      ("Knight" . ?n)
+                      ("Bishop" . ?b)
+                      ("Queen"  . ?q)
+                      ("King"   . ?k)))
+                 '("Set white piece"
+                   ("Pieces"
+                    ("Pawn"   . ?P)
+                    ("Knight" . ?N)
+                    ("Bishop" . ?B)
+                    ("Queen"  . ?Q)
+                    ("King"   . ?K))))))
+    (chess-display-set-piece (x-popup-menu t pieces))))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
 ;; Mousing around on the chess-display
@@ -951,36 +1017,43 @@ Clicking once on a piece selects it; then click on the target location."
                                 (car last-sel)
                                 (chess-pos-piece position (cdr last-sel))
                                 (cdr last-sel))
-                     (let ((s-piece (chess-pos-piece position
-                                                     (cdr last-sel)))
-                           (t-piece (chess-pos-piece position coord))
-                           ply)
-                       (if (and (/= t-piece ? )
-                                (or (and (< t-piece ?a)
-                                         (< s-piece ?a))
-                                    (and (> t-piece ?a)
-                                         (> s-piece ?a))))
-                           (throw 'message (chess-string 'cannot-mount)))
-                       (unless (setq ply (chess-ply-create position nil
-                                                           (cdr last-sel)
-                                                           coord))
-                         (throw 'message (chess-string 'move-not-legal)))
-                       (chess-display-move nil ply (car last-sel) (point))))
+                     (let ((s-piece (chess-pos-piece position (cdr last-sel)))
+                           (t-piece (chess-pos-piece position coord)) ply)
+                       (if chess-display-edit-mode
+                           (progn
+                             (chess-pos-set-piece position (cdr last-sel) ? )
+                             (chess-pos-set-piece position coord s-piece)
+                             (chess-display-update nil))
+                         (if (and (/= t-piece ? )
+                                  (or (and (< t-piece ?a)
+                                           (< s-piece ?a))
+                                      (and (> t-piece ?a)
+                                           (> s-piece ?a))))
+                             (throw 'message (chess-string 'cannot-mount)))
+                         (unless (setq ply (chess-ply-create position nil
+                                                             (cdr last-sel)
+                                                             coord))
+                           (throw 'message (chess-string 'move-not-legal)))
+                         (chess-display-move nil ply
+                                             (car last-sel) (point)))))
                    (setq chess-display-last-selected nil))
                (let ((piece (chess-pos-piece position coord)))
                  (cond
                   ((eq piece ? )
                    (throw 'message (chess-string 'selected-empty)))
-                  ((if (chess-pos-side-to-move position)
-                       (> piece ?a)
-                     (< piece ?a))
+                  ((and (not chess-display-edit-mode)
+                        (if (chess-pos-side-to-move position)
+                            (> piece ?a)
+                          (< piece ?a)))
                    (throw 'message (chess-string 'wrong-color)))
-                  ((and chess-display-highlight-legal
+                  ((and (not chess-display-edit-mode)
+                        chess-display-highlight-legal
                         (null (chess-legal-plies position :any :index coord)))
                    (throw 'message (chess-string 'piece-immobile))))
                  (setq chess-display-last-selected (cons (point) coord))
                  (chess-display-highlight nil coord)
-                 (if chess-display-highlight-legal
+                 (if (and (not chess-display-edit-mode)
+                          chess-display-highlight-legal)
                      (chess-display-highlight-legal nil coord))))))
       (when message
        (when chess-display-last-selected
@@ -1002,10 +1075,9 @@ Clicking once on a piece selects it; then click on the target location."
     (if (equal (event-start event) (event-end event))
        (progn
          (set-buffer (window-buffer (posn-window (event-start event))))
-         (goto-char (posn-point (event-start event)))
-         (chess-display-select-piece))
-      (goto-char (posn-point (event-end event)))
-      (chess-display-select-piece))))
+         (goto-char (posn-point (event-start event))))
+      (goto-char (posn-point (event-end event)))))
+  (chess-display-select-piece))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
index 826b9e2a3b339dd349ac11e11749ab924d43c887..315856a288e194077e8dcfa6c233156b8e07aa72 100644 (file)
@@ -6,9 +6,6 @@
 ;;; Commentary:
 
 (require 'chess-module)
-(require 'chess-game)
-(require 'chess-algebraic)
-(require 'chess-fen)
 
 (defgroup chess-engine nil
   "Code for reading movements and other commands from an engine."
      ((eq event 'illegal)
       (chess-message 'opp-illegal))
 
+     ((eq event 'call-flag)
+      ;; jww (2002-04-21): what to do here?
+      )
+
      ((eq event 'kibitz)
       (let ((chess-engine-handling-event t))
        (chess-game-run-hooks game 'kibitz (car args))))
        (chess-game-set-start-position chess-module-game
                                       chess-starting-position)
        (chess-game-set-data chess-module-game 'my-color t))
-      (chess-game-set-data chess-module-game 'active t))))
+      (chess-game-set-data chess-module-game 'active t))
+    (chess-game-run-hooks chess-module-game 'orient)))
 
 (defun chess-engine-position (engine)
   (chess-with-current-buffer engine
index 03c674971c7e9ff351622b3cfe0c228a1dca312a..91ee68366197d60f8b90f8075b5f11db7caf5262 100644 (file)
@@ -38,8 +38,6 @@
 ;; relate to the game, not the position.
 ;;
 
-(require 'chess-pos)
-
 (defun chess-fen-to-pos (fen)
   "Convert a FEN-like notation string to a chess position."
   (let ((i 0) (l (length fen))
index 99131dbecabeaaeb7fecd8655c902be2c915c962..7c90b38e7e38030c8eeae3a14c6b68e303863c6d 100644 (file)
@@ -9,6 +9,7 @@
 ;; game, and a list of plies representing the main variation.
 
 (require 'chess-ply)
+(require 'chess-pgn)
 
 (defvar chess-game-inhibit-events nil)
 
index 4d0d35c5f8ae7fdc57dd0acc3e8b0cb184db69ff..6b2aa9c383daf3eaaccef5275faca4838570a139 100644 (file)
   "Face to use for highlighting pieces that have been selected."
   :group 'chess-ics1)
 
-(defcustom chess-ics1-popup-function 'chess-display-popup-in-window
+(defcustom chess-ics1-popup-function 'chess-ics1-popup
   "The function used to popup a chess-ics1 display."
   :type 'function
   :group 'chess-ics1)
 
+(defcustom chess-ics1-separate-frame nil
+  "If non-nil, display the chessboard in its own frame."
+  :type 'boolean
+  :group 'chess-ics1)
+
 ;;; Code:
 
 (defun chess-ics1-handler (event &rest args)
    ((eq event 'highlight)
     (apply 'chess-ics1-highlight args))))
 
+(defun chess-ics1-popup ()
+  (if chess-ics1-separate-frame
+      (chess-display-popup-in-frame 21 43 nil t)
+    (chess-display-popup-in-window)))
+
 (defsubst chess-ics1-piece-text (piece)
   (let ((p (char-to-string piece)))
     (add-text-properties 0 1 (list 'face (if (> piece ?a)
@@ -66,7 +76,8 @@
     (let ((inhibit-redisplay t))
       (goto-char pos)
       (delete-char 3)
-      (insert ?  (chess-ics1-piece-text piece) ? ))))
+      (insert ?  (chess-ics1-piece-text piece) ? )
+      (add-text-properties pos (point) (list 'chess-coord index)))))
 
 (defun chess-ics1-draw (position perspective)
   "Draw the given POSITION from PERSPECTIVE's point of view.
index 60d02d7738d2e08fae6d04ce20b47d8fd744d727..5ffa01deac0dfd45a6279a7aae23aef72e0f5593 100644 (file)
@@ -182,7 +182,13 @@ called."
     (apply 'chess-images-draw-square args))
 
    ((eq event 'highlight)
-    (apply 'chess-images-highlight args))))
+    (apply 'chess-images-highlight args))
+
+   ((eq event 'start-edit)
+    (setq cursor-type t))
+
+   ((eq event 'end-edit)
+    (setq cursor-type nil))))
 
 (defun chess-images-determine-size ()
   (let ((display (and (stringp chess-images-separate-frame)
index 6448196074cd56b06dd9981231268c0424a68a3d..1e4350a941ba0a97e71d559372dea82f6c1d305a 100644 (file)
@@ -50,7 +50,7 @@ engine, and the computer the second engine."
   (setq first-engine-type (intern (concat "chess-" first-engine-type))
        second-engine-type (intern (concat "chess-" second-engine-type)))
   (let* ((my-color t)                  ; we start out as white always
-        (display (chess-create-display-object my-color))
+        (display (chess-create-display my-color t))
         (game (chess-display-game display)))
     (chess-game-set-data game 'my-color my-color)
     (chess-module-set-leader display)
index 7b38ed79f053cdc9a30d1d0bf9261a8946563593..ed1c5128f2b1ef7a24337fc593307dd3d5bba69a 100644 (file)
@@ -4,8 +4,6 @@
 ;;
 
 (require 'chess-common)
-(require 'chess-fen)
-(require 'chess-algebraic)
 
 (defvar chess-network-regexp-alist
   (list
         (function
          (lambda ()
            (funcall chess-engine-response-handler 'illegal))))
+   (cons "call flag$"
+        (function
+         (lambda ()
+           (funcall chess-engine-response-handler 'call-flag))))
    (cons "kibitz\\s-+\\(.+\\)$"
         (function
          (lambda ()
       (let ((which (read-char "Are you the c)lient or s)erver? "))
            proc)
        (chess-message 'network-starting)
-       (setq proc (if (eq which ?s)
-                      (start-process "*chess-network*"
-                                     (current-buffer) "/usr/bin/nc"
-                                     "-l" "-p" (read-string "Port: "))
-                    (open-network-stream "*chess-network*" (current-buffer)
-                                         (read-string "Host: ")
-                                         (read-string "Port: "))))
+       (setq proc
+             (if (eq which ?s)
+                 (if (fboundp 'open-network-stream-server)
+                     (open-network-stream-server "*chess-network*"
+                                                 (current-buffer)
+                                                 (read-string "Port: "))
+                   (start-process "*chess-network*"
+                                  (current-buffer) "/usr/bin/nc"
+                                  "-l" "-p" (read-string "Port: ")))
+               (open-network-stream "*chess-network*" (current-buffer)
+                                    (read-string "Host: ")
+                                    (read-string "Port: "))))
        (if (eq which ?s)
            (chess-message 'network-waiting)
          (chess-network-handler 'match)
      ((eq event 'illegal)
       (chess-engine-send nil "illegal\n"))
 
+     ((eq event 'call-flag)
+      (chess-engine-send nil "call flag\n"))
+
      ((eq event 'kibitz)
       (chess-engine-send nil (format "kibitz %s\n"
                                     (chess-network-flatten-multiline
index dc43083e415f09c2e97ab9eae9dc5a0f8b99d56b..01e4722496d28335d356c46838274415b8282d2c 100644 (file)
@@ -3,11 +3,6 @@
 ;; Convert a chess game to/from PGN notation
 ;;
 
-(require 'chess-game)
-(require 'chess-pos)
-(require 'chess-algebraic)
-(require 'chess-fen)
-
 (defvar chess-pgn-fill-column 60)
 
 (chess-message-catalog 'english
@@ -219,7 +214,10 @@ If INDENTED is non-nil, indent the move texts."
     (define-key map [?T] 'text-mode)
     (define-key map [(control ?c) (control ?c)] 'chess-pgn-show-position)
     (define-key map [mouse-2] 'chess-pgn-mouse-show-position)
-    (define-key map [(control ?m)] 'chess-pgn-move)
+
+    ;;(define-key map [(control ?m)] 'chess-pgn-move)
+    ;;(define-key map [space] 'chess-pgn-move)
+    ;;(define-key map [? ] 'chess-pgn-move)
 
     (when (require 'pcomplete nil t)
       (set (make-variable-buffer-local 'pcomplete-default-completion-function)
@@ -241,9 +239,6 @@ If INDENTED is non-nil, indent the move texts."
 
 (font-lock-add-keywords 'chess-pgn-mode
   (list (list "\\[\\(\\S-+\\)\\s-+\".*\"\\]" 1 'font-lock-keyword-face)
-       ;; jww (2002-04-16): this is a bit heavy
-       ;;(cons chess-pgn-move-regexp
-       ;;      'chess-pgn-bold-face)
        (cons "\\(1-0\\|0-1\\|\\*\\)$" 'chess-pgn-bold-face)))
 
 ;;;###autoload
index 5f1ab4b7be6b38c668e86153cfbd369b5b291e6d..084b43f96f05efc3badb11a0b1237cdaff811577 100644 (file)
@@ -91,11 +91,16 @@ modify `chess-plain-piece-chars' to avoid real confusion.)"
   "Face to use for highlighting pieces that have been selected."
   :group 'chess-plain)
 
-(defcustom chess-plain-popup-function 'chess-display-popup-in-window
+(defcustom chess-plain-popup-function 'chess-plain-popup
   "The function used to popup a chess-plain display."
   :type 'function
   :group 'chess-plain)
 
+(defcustom chess-plain-separate-frame nil
+  "If non-nil, display the chessboard in its own frame."
+  :type 'boolean
+  :group 'chess-plain)
+
 ;;; Code:
 
 (defun chess-plain-handler (event &rest args)
@@ -115,6 +120,11 @@ modify `chess-plain-piece-chars' to avoid real confusion.)"
    ((eq event 'highlight)
     (apply 'chess-plain-highlight args))))
 
+(defun chess-plain-popup ()
+  (if chess-plain-separate-frame
+      (chess-display-popup-in-frame 9 (* (1+ chess-plain-spacing) 8) nil t)
+    (chess-display-popup-in-window)))
+
 (defun chess-plain-piece-text (piece rank file)
   (let ((white-square (= (% (+ file rank) 2) 0)))
     (if (eq piece ? )
@@ -141,7 +151,8 @@ modify `chess-plain-piece-chars' to avoid real confusion.)"
     (goto-char pos)
     (delete-char 1)
     (insert (chess-plain-piece-text piece (chess-index-rank index)
-                                   (chess-index-file index)))))
+                                   (chess-index-file index)))
+    (add-text-properties pos (point) (list 'chess-coord index))))
 
 (defun chess-plain-draw (position perspective)
   "Draw the given POSITION from PERSPECTIVE's point of view.
index 1bfbfcf0f668b283e1827e21dcfdba6f7667e77a..750e8b278db04ca267bea0fe50ef4a453de5922f 100644 (file)
@@ -44,6 +44,7 @@
 ;;; Code:
 
 (require 'chess-pos)
+(require 'chess-algebraic)
 
 (defgroup chess-ply nil
   "Routines for manipulating chess plies."
   (apply 'chess-pos-move (chess-pos-copy (chess-ply-pos ply))
         (chess-ply-changes ply)))
 
+(defsubst chess-ply-to-string (ply &optional long)
+  (chess-ply-to-algebraic ply long))
+
+(defsubst chess-ply-from-string (position move)
+  (chess-algebraic-to-ply position move))
+
 (defconst chess-piece-name-table
   '(("queen"  . ?q)
     ("rook"   . ?r)
index b2d46395cc5b0abad8537a41b6725436c5bfcba7..4cdd15ea368d2485f95c6223f5abdb543d2b6eb3 100644 (file)
@@ -70,8 +70,8 @@
 
 ;;; Code:
 
-(require 'cl)
 (require 'chess-message)
+(require 'chess-fen)
 
 (defgroup chess-pos nil
   "Routines for manipulating chess positions."
diff --git a/chess-puzzle.el b/chess-puzzle.el
new file mode 100644 (file)
index 0000000..e47dfe1
--- /dev/null
@@ -0,0 +1,69 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; A special kind of display that merely autosaves the game
+;;
+
+(require 'chess-game)
+(require 'chess-random)
+(require 'chess-database)
+(require 'chess-file)
+
+(defvar chess-puzzle-indices nil)
+(defvar chess-puzzle-position nil)
+
+(make-variable-buffer-local 'chess-puzzle-indices)
+(make-variable-buffer-local 'chess-puzzle-position)
+
+(chess-message-catalog 'english
+  '((bad-game-read . "Error reading game at position %d")
+    (end-of-puzzles . "There are no more puzzles in this collection")))
+
+;;;###autoload
+(defun chess-puzzle (file &optional index)
+  "Pick a random puzzle from FILE, and solve it against the default engine.
+The spacebar in the display buffer is bound to `chess-puzzle-next',
+making it easy to go on to the next puzzle once you've solved one."
+  (interactive "fRead chess puzzles from: ")
+  (let* ((database (chess-database-open 'chess-file file))
+        (objects (and database (chess-session)))
+        (display (cadr objects)))
+    (when database
+      (with-current-buffer display
+       ;; make sure the database is closed when the display is shutdown
+       (chess-game-add-hook (chess-display-game nil)
+                            'chess-database-event-handler database)
+       (chess-game-set-data (chess-display-game nil) 'database database)
+       (define-key (current-local-map) [? ] 'chess-puzzle-next)
+       (let ((count (chess-database-count database)))
+         (setq chess-puzzle-indices (make-vector count nil))
+         (dotimes (i count)
+           (aset chess-puzzle-indices i i))
+         (random t)
+         (chess-shuffle-vector chess-puzzle-indices)
+         (setq chess-puzzle-position 0))
+       (chess-puzzle-next)))))
+
+(defun chess-puzzle-next ()
+  "Play the next puzzle in the collection, selected randomly."
+  (interactive)
+  (let* ((game (chess-display-game nil))
+        (database (chess-game-data game 'database))
+        (index chess-puzzle-position)
+        next-game)
+    (if (= index (length chess-puzzle-indices))
+       (chess-message 'end-of-puzzles)
+      (setq chess-puzzle-position (1+ chess-puzzle-position))
+      (if (null (setq next-game
+                     (chess-database-read database
+                                          (aref chess-puzzle-indices index))))
+         (chess-error 'bag-game-read
+                      (aref chess-puzzle-indices index))
+       (chess-display-set-game nil next-game 0)
+       (chess-game-set-data game 'my-color
+                            (chess-pos-side-to-move (chess-game-pos game)))
+       (dolist (key '(database database-index database-count))
+         (chess-game-set-data game key (chess-game-data next-game key)))))))
+
+(provide 'chess-puzzle)
+
+;;; chess-puzzle.el ends here
index c6cbe1cfcbd774796e282672de890e05cbb3aa98..fc41853bf201da8efaf78a39c4a20a1f96750780 100644 (file)
@@ -10,7 +10,7 @@
 
 (defvar pieces-vector [?r ?n ?b ?q ?k ?b ?n ?r])
 
-(defun shuffle-vector (vector)
+(defun chess-shuffle-vector (vector)
   "Randomly permute the elements of VECTOR (all permutations equally likely)"
   (let ((i 0)
        j
@@ -28,7 +28,7 @@
 (defun chess-fischer-random-position ()
   (let (pieces position)
     (while (null position)
-      (setq pieces (shuffle-vector pieces-vector))
+      (setq pieces (chess-shuffle-vector pieces-vector))
       (let (first-bishop first-rook king)
        (catch 'retry
          (dotimes (i 8)
       (chess-pos-set-piece position (chess-rf-to-index 7 i)
                           (upcase (aref pieces i))))
 
-    ;; jww (2002-04-12): Until I fully support Fischer Random
-    ;; castling, I will disable it here
-    (chess-pos-set-can-castle position ?K nil)
-    (chess-pos-set-can-castle position ?Q nil)
-    (chess-pos-set-can-castle position ?k nil)
-    (chess-pos-set-can-castle position ?q nil)
-
     position))
 
 (provide 'chess-random)
diff --git a/chess-tutorial.el b/chess-tutorial.el
new file mode 100644 (file)
index 0000000..58f7343
--- /dev/null
@@ -0,0 +1,39 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; A special kind of display that merely autosaves the game
+;;
+
+(require 'chess-game)
+
+(chess-message-catalog 'english
+  '((queen-would-take . "The queen would take your knight!")
+    (congratulations  . "Congratulations!")
+    (knight-1-done    . "Goal: take all the pawns, without letting the queen take your knight")))
+
+(defun chess-tutorial-knight-1 (game ignore event &rest args)
+  (if (eq event 'move)
+      (let ((position (chess-game-pos game)))
+       (if (null (chess-pos-search position ?p))
+           (chess-message 'congratulations)
+         (when (chess-search-position
+                position (car (chess-pos-search position ?N)) ?q)
+           (chess-game-run-hooks chess-module-game 'undo 1)
+           (chess-display-update nil)
+           (chess-error 'queen-would-take))))))
+
+(defun chess-tutorial ()
+  (interactive)
+  (let* (chess-default-modules
+        (display (chess-create-display)))
+    (with-current-buffer display
+      (chess-game-set-start-position
+       (chess-display-game nil)
+       (chess-fen-to-pos "8/3p1p/2p3p/4q/2p3p/3p1p/8/N w - -"))
+      (chess-game-add-hook (chess-display-game nil) 'chess-tutorial-knight-1)
+      (setq chess-pos-always-white t)
+      (chess-display-popup nil)
+      (chess-message 'knight-1-done))))
+
+(provide 'chess-tutorial)
+
+;;; chess-tutorial.el ends here
index 8a1f707792888af20e94007ea4aded4925ff3c34..8018a5fc44007036ce3c39dc4a5161b5d6b3e151 100644 (file)
--- a/chess.el
+++ b/chess.el
@@ -76,9 +76,6 @@
 (require 'chess-game)
 (require 'chess-display)
 (require 'chess-engine)
-(require 'chess-random)
-(require 'chess-database)
-(require 'chess-file)
 
 (defgroup chess nil
   "An Emacs chess playing program."
@@ -193,10 +190,11 @@ available."
     (nconc objects (chess-create-modules chess-default-modules
                                         'chess-module-create game))
 
-    (push (car (chess-create-modules (list (or engine chess-default-engine))
-                                    'chess--create-engine game
-                                    engine-response-handler
-                                    engine-ctor-args))
+    (push (unless (eq engine 'none)
+           (car (chess-create-modules (list (or engine chess-default-engine))
+                                      'chess--create-engine game
+                                      engine-response-handler
+                                      engine-ctor-args)))
          objects)
 
     (unless (car objects)
@@ -208,98 +206,16 @@ available."
 (defalias 'chess-session 'chess)
 
 ;;;###autoload
-(defun chess-create-display ()
-  "Just make a display to use, letting chess.el decide the style."
-  (cadr (chess-session 'chess-none)))
-
-;;;###autoload
-(defun chess-create-display-object (perspective)
-  (car (chess-create-modules (list chess-default-display)
-                            'chess--create-display
-                            (chess-game-create) perspective nil)))
-
-(defvar chess-puzzle-indices nil)
-(defvar chess-puzzle-position nil)
-(make-variable-buffer-local 'chess-puzzle-indices)
-(make-variable-buffer-local 'chess-puzzle-position)
-
-;;;###autoload
-(defun chess-puzzle (file &optional index)
-  "Pick a random puzzle from FILE, and solve it against the default engine.
-The spacebar in the display buffer is bound to `chess-puzzle-next',
-making it easy to go on to the next puzzle once you've solved one."
-  (interactive "fRead chess puzzles from: ")
-  (let* ((database (chess-database-open 'chess-file file))
-        (objects (and database (chess-session)))
-        (display (cadr objects)))
-    (when database
-      (with-current-buffer display
-       ;; make sure the database is closed when the display is shutdown
-       (chess-game-add-hook (chess-display-game nil)
-                            'chess-database-event-handler database)
-       (chess-game-set-data (chess-display-game nil) 'database database)
-       (define-key (current-local-map) [? ] 'chess-puzzle-next)
-       (let ((count (chess-database-count database)))
-         (setq chess-puzzle-indices (make-vector count nil))
-         (dotimes (i count)
-           (aset chess-puzzle-indices i i))
-         (random t)
-         (shuffle-vector chess-puzzle-indices)
-         (setq chess-puzzle-position 0))
-       (chess-puzzle-next)))))
-
-(chess-message-catalog 'english
-  '((bad-game-read . "Error reading game at position %d")
-    (end-of-puzzles . "There are no more puzzles in this collection")))
-
-(defun chess-puzzle-next ()
-  "Play the next puzzle in the collection, selected randomly."
-  (interactive)
-  (let* ((game (chess-display-game nil))
-        (database (chess-game-data game 'database))
-        (index chess-puzzle-position)
-        next-game)
-    (if (= index (length chess-puzzle-indices))
-       (chess-message 'end-of-puzzles)
-      (setq chess-puzzle-position (1+ chess-puzzle-position))
-      (if (null (setq next-game
-                     (chess-database-read database
-                                          (aref chess-puzzle-indices index))))
-         (chess-error 'bag-game-read
-                      (aref chess-puzzle-indices index))
-       (chess-display-set-game nil next-game 0)
-       (chess-game-set-data game 'my-color
-                            (chess-pos-side-to-move (chess-game-pos game)))
-       (dolist (key '(database database-index database-count))
-         (chess-game-set-data game key (chess-game-data next-game key)))))))
-
-(chess-message-catalog 'english
-  '((queen-would-take . "The queen would take your knight!")
-    (congratulations  . "Congratulations!")))
-
-(defun chess-tutorial-knight-1 (game ignore event &rest args)
-  (if (eq event 'move)
-      (let ((position (chess-game-pos game)))
-       (if (null (chess-pos-search position ?p))
-           (chess-message 'congratulations)
-         (when (chess-search-position
-                position (car (chess-pos-search position ?N)) ?q)
-           (chess-game-run-hooks chess-module-game 'undo 1)
-           (chess-display-update nil)
-           (chess-error 'queen-would-take))))))
-
-(defun chess-tutorial ()
-  (interactive)
-  (let* (chess-default-modules
-        (display (chess-create-display)))
-    (with-current-buffer display
-      (chess-game-set-start-position
-       (chess-display-game nil)
-       (chess-fen-to-pos "8/3p1p/2p3p/4q/2p3p/3p1p/8/N w - -"))
-      (chess-game-add-hook (chess-display-game nil) 'chess-tutorial-knight-1)
-      (setq chess-pos-always-white t)
-      (chess-display-popup nil)
-      (message "Goal: take all the pawns, without letting the queen take your knight"))))
+(defun chess-create-display (perspective &optional display-only)
+  "Create a display, letting the user's customization decide the style.
+If DISPLAY-ONLY is non-nil, then only a display is created, with none
+of the usual ancillary modules."
+  (if display-only
+      (car (chess-create-modules (list chess-default-display)
+                                'chess--create-display
+                                (chess-game-create) perspective nil))
+    (let ((display (cadr (chess-session 'none))))
+      (chess-display-set-perspective* display perspective))))
 
 (provide 'chess)