]> code.delx.au - gnu-emacs-elpa/commitdiff
changes
authorJohn Wiegley <johnw@newartisans.com>
Mon, 11 Mar 2002 20:57:21 +0000 (20:57 +0000)
committerJohn Wiegley <johnw@newartisans.com>
Mon, 11 Mar 2002 20:57:21 +0000 (20:57 +0000)
13 files changed:
TODO
chess-algebraic.el
chess-crafty.el [deleted file]
chess-display.el
chess-engines.el [new file with mode: 0644]
chess-game.el
chess-gnuchess.el [deleted file]
chess-pgn.el
chess-ply.el
chess-process.el
chess-session.el
chess-standard.el
chess.el

diff --git a/TODO b/TODO
index 12e56cc7077cefc6bf1bb69aa900696603d29a44..5c70ad997d3a5be8f55976a95e2bd375b410a1f2 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,5 +1,15 @@
 * 2.0
 
+** Breakdown
+
+*** Core library
+*** Display modules
+*** Chess engines
+
+** Finished writing `define-chess-module'
+
+** Call `chess-game-move' in chess-display to move the pieces
+
 ** Keyboard shortcuts
 
 *** Right now "nf, nf", causes an error
index 0b041cb17de5a84ddd5acb584ba25e359cec75ae..d32bbbbcc31d9ed13ce2fabc0492acd5813915f6 100644 (file)
@@ -33,7 +33,6 @@
 
 ;; $Revision$
 
-(require 'chess-pos)
 (require 'chess-ply)
 
 (defconst chess-algebraic-pieces-regexp "[RNBKQ]")
@@ -52,7 +51,7 @@
   "A regular expression that matches all possible algebraic moves.
 This regexp handles both long and short form.")
 
-(defun chess-algebraic-to-ply (position move)
+(defun chess-algebraic-to-ply (position move &optional search-func)
   "Convert the algebraic notation MOVE for POSITION to a ply."
   (when (string-match chess-algebraic-regexp move)
     (let* ((color (chess-pos-side-to-move position))
@@ -77,10 +76,9 @@ This regexp handles both long and short form.")
                    ;; move, to determine which piece is meant by the
                    ;; piece indicator
                    (when (setq candidates
-                               (funcall (car chess-modules) nil nil
-                                        'search position target
-                                        (if color piece
-                                          (downcase piece))))
+                               (funcall (or search-func chess-standard-search)
+                                        position target (if color piece
+                                                          (downcase piece))))
                      (if (= (length candidates) 1)
                          (list (car candidates) target)
                        (if (null source)
@@ -101,7 +99,7 @@ This regexp handles both long and short form.")
                         ':check))))
       (apply 'chess-ply-create position changes))))
 
-(defun chess-ply-to-algebraic (ply &optional long)
+(defun chess-ply-to-algebraic (ply &optional long search-func)
   "Convert the given PLY to algebraic notation.
 If LONG is non-nil, render the move into long notation."
   (if (null (car (chess-ply-changes ply)))
@@ -122,8 +120,8 @@ If LONG is non-nil, render the move into long notation."
                                 "O-O-O"))))
                str
              (let ((candidates
-                    (funcall (car chess-modules)
-                             nil nil 'search pos to from-piece))
+                    (funcall (or search-func chess-standard-search)
+                             pos to from-piece))
                    (rank 0) (file 0)
                    (from-rank (/ from 8))
                    (from-file (mod from 8))
diff --git a/chess-crafty.el b/chess-crafty.el
deleted file mode 100644 (file)
index d15be54..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; Play against the crafty engine
-;;
-;; $Revision$
-
-(require 'chess-process)
-
-(defgroup chess-crafty nil
-  "Interface code for playing against crafty.  Uses `chess-process'."
-  :group 'chess)
-
-(defcustom chess-crafty-command (and (require 'executable)
-                                    (executable-find "crafty"))
-  "The name of the crafty program."
-  :type 'string
-  :group 'chess-crafty)
-
-;;; Code:
-
-;;;###autoload
-(defun chess-crafty (session buffer event &rest args)
-  (if (not (eq event 'initialize))
-      (apply 'chess-process session buffer event args)
-    (with-current-buffer
-       (chess-process session buffer event chess-process-triggers
-                      chess-crafty-command)
-      (process-send-string (get-buffer-process (current-buffer))
-                          (concat "display nogeneral\n"
-                                  "display nochanges\n"
-                                  "display noextstats\n"
-                                  "display nohashstats\n"
-                                  "display nomoves\n"
-                                  "display nonodes\n"
-                                  "display noply1\n"
-                                  "display nostats\n"
-                                  "display notime\n"
-                                  "display novariation\n"
-                                  "alarm off\n"
-                                  "ansi off\n"))
-      (current-buffer))))
-
-(provide 'chess-crafty)
-
-;;; chess-crafty.el ends here
index 4453d2872c5ecc7a47c71776b51529c95a9d8f3c..d1212b7e8652e696972c001837e8c53ed293cee7 100644 (file)
@@ -185,8 +185,7 @@ The key bindings available in this mode are:
             "   " (int-to-string (if (> index 1)
                                      (/ index 2) (1+ (/ index 2))))
             ". " (if color "... ")
-            (chess-ply-to-algebraic
-             (chess-game-ply chess-display-game (1- index))))))))
+            (chess-game-ply-to-algebraic chess-display-game))))))
 
 (defsubst chess-display-current-p ()
   "Return non-nil if the displayed chessboard reflects the current game.
@@ -237,7 +236,7 @@ This means that no editing is being done."
   "Send the current board configuration to the user."
   (interactive)
   (chess-session-event chess-current-session 'setup
-                      (chess-game-create nil chess-display-position)))
+                      (chess-game-create chess-display-position)))
 
 (defun chess-display-copy-board ()
   "Send the current board configuration to the user."
@@ -283,7 +282,7 @@ This means that no editing is being done."
                      "White" "Black")
                  (1+ (/ chess-display-game-index 2))))))
   (chess-session-event chess-current-session 'move
-                      (chess-algebraic-to-ply chess-display-position move)))
+                      (chess-game-algebraic-to-ply chess-display-game move)))
 
 (defun chess-display-set-current (dir)
   "Change the currently displayed board.
@@ -346,13 +345,14 @@ to the end or beginning."
                  (char-to-string (downcase last-command-char)))))
   (unless (and chess-legal-moves
               (eq chess-display-position chess-legal-moves-pos))
-    (setq chess-legal-moves-pos chess-display-position
-         chess-legal-moves
-         (sort (mapcar 'chess-ply-to-algebraic
-                       (chess-legal-plies chess-display-position
-                                          (chess-pos-side-to-move
-                                           chess-display-position)))
-               'string-lessp)))
+    (let ((search-func (chess-game-search-func chess-display-game)))
+      (setq chess-legal-moves-pos chess-display-position
+           chess-legal-moves
+           (sort (mapcar (function
+                          (lambda (ply)
+                            (chess-ply-to-algebraic ply nil search-func)))
+                  (chess-legal-plies chess-display-position search-func))
+                 'string-lessp))))
   (let ((moves
         (mapcar (function
                  (lambda (move)
@@ -376,9 +376,10 @@ to the end or beginning."
     (setq moves (delq nil moves))
     (cond
      ((= (length moves) 1)
-      (chess-session-event chess-current-session 'move
-                          (chess-algebraic-to-ply chess-display-position
-                                                  (car moves)))
+      (chess-session-event
+       chess-current-session 'move
+       (chess-algebraic-to-ply chess-display-position (car moves)
+                              (chess-game-search-func chess-display-game)))
       (setq chess-move-string nil
            chess-legal-moves nil
            chess-legal-moves-pos nil))
diff --git a/chess-engines.el b/chess-engines.el
new file mode 100644 (file)
index 0000000..c014972
--- /dev/null
@@ -0,0 +1,56 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Play against popular chess engines
+;;
+;; $Revision$
+
+(require 'chess-process)
+
+(define-chess-engine crafty (&rest args)
+  (list (list
+        (concat "\\s-*\\(White\\|Black\\)\\s-*([0-9]+):\\s-+\\("
+                chess-algebraic-regexp "\\)\\s-*$")
+        (function
+         (lambda (color move)
+           (if (string= (if (chess-game-side-to-move chess-process-game)
+                            "White" "Black")
+                        color)
+               (chess-session-event
+                chess-current-session 'move
+                (chess-algebraic-to-ply
+                 (chess-game-pos chess-process-game) move)))))
+        1 2)
+       '("Illegal move:\\s-*\\(.*\\)"
+         (signal 'chess-illegal (match-string 1))))
+  (init (concat "display nogeneral\n"
+               "display nochanges\n"
+               "display noextstats\n"
+               "display nohashstats\n"
+               "display nomoves\n"
+               "display nonodes\n"
+               "display noply1\n"
+               "display nostats\n"
+               "display notime\n"
+               "display novariation\n"
+               "alarm off\n"
+               "ansi off"))
+  (shutdown "quit")
+  (move (chess-game-ply-to-algebraic chess-process-game (car args)))
+  (pass "go"))
+
+(define-chess-engine gnuchess (&rest args)
+  (list (list
+        (concat "My move is : \\(" chess-algebraic-regexp "\\)")
+        (function
+         (lambda (move)
+           (chess-session-event chess-current-session 'move
+                                (chess-algebraic-to-ply
+                                 (chess-game-pos chess-process-game) move))))
+        1)
+       '("Illegal move:\\s-*\\(.*\\)"
+         (signal 'chess-illegal (match-string 1))))
+  (shutdown "quit")
+  (move (chess-game-ply-to-algebraic chess-process-game (car args)))
+  (pass "go"))
+
+;;; chess-engines.el ends here
index 44df33da41e1da16c28373f82ce3a4c845814d3f..b4aceb537d67dac359026c6b618d2abd8a96fa19 100644 (file)
 ;; game, and a list of plies representing the main variation.
 
 (require 'chess-ply)
+(require 'chess-algebraic)
 
 (defconst chess-game-default-tags
-  (list '("Event" . "Computer chess game")
-       '("Round" . "-")
-       (cons "Site" (system-name))
-       '("White" . "?")
-       '("Black" . "?")
-       '("Result" . "*")
-       '("TimeControl" . "-")))
+  `(("Event"      . "Computer chess game")
+    ("Round"      . "-")
+    ("Site"       . ,(system-name))
+    ("White"      . "?")
+    ("Black"      . "?")
+    ("Result"     . "*")
+    ("TimeControl" . "-")))
 
 (defsubst chess-game-tags (game)
   "Return the tags alist associated with GAME."
 
 (defsubst chess-game-plies (game)
   "Return the tags alist associated with GAME."
-  (cdr game))
+  (cddr game))
 
 (defsubst chess-game-set-plies (game plies)
   "Return the tags alist associated with GAME."
-  (setcdr game plies))
+  (setcdr (cdr game) plies))
+
+(defsubst chess-game-validation-func (game)
+  "Return the tags alist associated with GAME."
+  (car (cadr game)))
+
+(defsubst chess-game-set-validation-func (game func)
+  "Return the tags alist associated with GAME."
+  (setcar (cadr game) func))
+
+(defsubst chess-game-search-func (game)
+  "Return the tags alist associated with GAME."
+  (cdr (cadr game)))
+
+(defsubst chess-game-set-search-func (game func)
+  "Return the tags alist associated with GAME."
+  (setcdr (cadr game) func))
 
 (defsubst chess-game-tag (game tag)
   "Return the value for TAG in GAME."
@@ -58,7 +75,7 @@
 
 (defsubst chess-game-index (game)
   "Return the GAME's current position index."
-  (length (cdr game)))
+  (length (chess-game-plies game)))
 
 (defsubst chess-game-seq (game)
   "Return the current GAME sequence."
 (defun chess-game-ply (game &optional index)
   "Return the position related to GAME's INDEX position."
   (if index
-      (nth index (cdr game))
-    (car (last (cdr game)))))
+      (nth index (chess-game-plies game))
+    (car (last (chess-game-plies game)))))
+
+(defsubst chess-game-add-ply (game ply)
+  "Return the position related to GAME's INDEX position."
+  (nconc (chess-game-plies game) (list ply)))
 
 (defun chess-game-pos (game &optional index)
   "Return the position related to GAME's INDEX position."
   (car (chess-game-ply game index)))
 
-(defun chess-game-create (&optional tags position)
+(defun chess-game-create (&rest keywords)
   "Create a new chess game object.
-If TAGS is non-nil, it is a list of cons cell that define starting
-tags to use.  If POSITION is non-nil, the game starts at that
-position."
-  (let ((game (cons nil nil)))
-    (dolist (tag chess-game-default-tags)
-      (chess-game-set-tag game (car tag) (cdr tag)))
-    (chess-game-set-tag game "Date" (format-time-string "%Y.%m.%d"))
-    (dolist (tag tags)
-      (chess-game-set-tag game (car tag) (cdr tag)))
-    (setcdr game (list (chess-ply-create
-                       (or position (chess-pos-create)))))
+Keywords may be specified to customize the game object.  The supported
+keywords are:
+
+  :position POS          ; set the start position
+  :search   FUNC         ; function used to search chess positions
+  :validate FUNC         ; function used to validate chess moves
+  :tags     ALIST"
+  (let ((game (list (cdr (assq ':tags keywords))
+                   (cons (or (cdr (assq ':validate keywords))
+                             chess-standard-validate)
+                         (or (cdr (assq ':search keywords))
+                             chess-standard-search)))))
+    (dolist (tag (cons (cons "Date" (format-time-string "%Y.%m.%d"))
+                      chess-game-default-tags))
+      (unless (chess-game-tag game (car tag))
+       (chess-game-set-tag game (car tag) (cdr tag))))
+    (chess-game-add-ply game (chess-ply-create
+                             (or (cdr (assq ':position keywords))
+                                 (chess-pos-create))))
     game))
 
 (defun chess-game-move (game ply)
@@ -99,7 +128,10 @@ The 'changes' of the last ply reflect whether the game is currently in
 progress (nil), if it is drawn, resigned, mate, etc."
   (let ((current-ply (chess-game-ply game))
        (changes (chess-ply-changes ply)))
-    (assert (equal (chess-ply-pos current-ply) (chess-ply-pos ply)))
+    (unless (equal (chess-ply-pos current-ply)
+                  (chess-ply-pos ply))
+      (error "Positions do not match"))
+    (funcall (chess-game-validation-func game) ply)
     (chess-ply-set-changes current-ply changes)
     (cond
      ((or (memq ':draw changes)
@@ -109,12 +141,26 @@ progress (nil), if it is drawn, resigned, mate, etc."
       (chess-game-set-tag game "Result" "1/2-1/2"))
      ((or (memq ':resign changes)
          (memq ':checkmate changes))
-      (chess-game-set-tag game "Result"
-                         (if (chess-game-side-to-move game)
-                             "0-1" "1-0")))
-     (t (nconc (cdr game)
-              (list (chess-ply-create
-                     (chess-ply-next-pos current-ply))))))))
+      (chess-game-set-tag game "Result" (if (chess-game-side-to-move game)
+                                           "0-1" "1-0")))
+     (t
+      (chess-game-add-ply game (chess-ply-create
+                               (chess-ply-next-pos current-ply)))))))
+
+;; A few convenience functions
+
+(defsubst chess-game-legal-plies (game)
+  "Return all legal plies from GAME's current position."
+  (chess-legal-plies (chess-game-pos game)
+                    (chess-game-search-func game)))
+
+(defsubst chess-game-algebraic-to-ply (game move)
+  (chess-algebraic-to-ply (chess-game-pos game) move
+                         (chess-game-search-func game)))
+
+(defsubst chess-game-ply-to-algebraic (game &optional ply long)
+  (chess-ply-to-algebraic (or ply (chess-game-ply game)) long
+                         (chess-game-search-func game)))
 
 (provide 'chess-game)
 
diff --git a/chess-gnuchess.el b/chess-gnuchess.el
deleted file mode 100644 (file)
index c304a8b..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; Play against the gnuchess engine
-;;
-;; $Revision$
-
-(require 'chess-process)
-
-(defgroup chess-gnuchess nil
-  "Interface code for playing against gnuchess.  Uses `chess-process'."
-  :group 'chess)
-
-(defcustom chess-gnuchess-command (and (require 'executable)
-                                      (executable-find "gnuchess"))
-  "The name of the gnuchess program."
-  :type 'string
-  :group 'chess-gnuchess)
-
-;;;###autoload
-(defun chess-gnuchess (session buffer event &rest args)
-  (if (not (eq event 'initialize))
-      (apply 'chess-process session buffer event args)
-    (chess-process session buffer event
-                  (list (list
-                         (concat "My move is : \\("
-                                 chess-algebraic-regexp "\\)")
-                         (function
-                          (lambda (move)
-                            (chess-session-event
-                             chess-current-session 'move
-                             (chess-algebraic-to-ply
-                              (chess-game-pos chess-process-game) move)))) 1)
-                        '("Illegal move:" (error "Illegal move")))
-                  chess-gnuchess-command)))
-
-(provide 'chess-gnuchess)
-
-;;; chess-gnuchess.el ends here
index 841cccb7631af45db30f9552aa0e90e120696395..36ce3f060ac871dafcc421c2ba52b3544b8ee144 100644 (file)
@@ -18,7 +18,7 @@
        ((looking-at chess-algebraic-regexp)
        (goto-char (match-end 0))
        (setq prevpos position)
-       (let ((ply (chess-algebraic-to-ply position (match-string 0))))
+       (let ((ply (chess-game-algebraic-to-ply game (match-string 0))))
          (setq position (chess-ply-next-pos ply))
          (nconc plies (list ply))))
        ((and top-level
                      (chess-pos-copy chess-starting-position)) t)))
       game)))
 
-(defun chess-pgn-insert-annotations (index ply)
+(defun chess-pgn-insert-annotations (game index ply)
   (dolist (ann (chess-pos-annotations (chess-ply-pos ply)))
     (if (stringp ann)
        (insert (format " {%s}" ann))
       (assert (listp ann))
-      (chess-pgn-insert-plies index ann))))
+      (chess-pgn-insert-plies game index ann))))
 
-(defun chess-pgn-insert-plies (index plies &optional
+(defun chess-pgn-insert-plies (game index plies &optional
                                     for-black indented no-annotations)
   "NYI: Still have to implement INDENTED argument."
   (while plies
     (unless for-black
       (insert (format "%d. %s" index
-                     (chess-ply-to-algebraic (car plies))))
+                     (chess-game-ply-to-algebraic game (car plies))))
       (unless no-annotations
-       (chess-pgn-insert-annotations index (car plies)))
+       (chess-pgn-insert-annotations game index (car plies)))
       (setq plies (cdr plies) index (1+ index)))
     (when plies
       (when for-black
        (insert (format "%d. ..." index))
        (setq for-black nil))
-      (insert (format " %s" (chess-ply-to-algebraic (car plies))))
+      (insert (format " %s" (chess-game-ply-to-algebraic game (car plies))))
       (unless no-annotations
-       (chess-pgn-insert-annotations index (car plies)))
+       (chess-pgn-insert-annotations game index (car plies)))
       (setq plies (cdr plies)))
     (if plies
        (insert ? ))))
@@ -107,7 +107,7 @@ If INDENTED is non-nil, indent the move texts."
     (insert (format "[%s \"%s\"]\n" (car tag) (cdr tag))))
   (insert ?\n)
   (let ((begin (point)))
-    (chess-pgn-insert-plies 1 (chess-game-plies game))
+    (chess-pgn-insert-plies game 1 (chess-game-plies game))
     (insert (or (chess-game-tag game "Result") "*") ?\n)
     (fill-region begin (point))))
 
@@ -116,54 +116,54 @@ If INDENTED is non-nil, indent the move texts."
 ;; PGN-mode for editing and browsing PGN files.
 ;;
 
-(defvar chess-pgn-mode-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map [??] 'describe-mode)
-    (define-key map [?T] 'text-mode)
-    (define-key map [return] 'chess-pgn-move)
-    (define-key map [(control ?m)] 'chess-pgn-move)
-    map)
-  "Keymap used by Chess PGN mode.")
-
-(define-derived-mode chess-pgn-mode text-mode "Chess"
-  "A mode for editing Chess PGN files.")
-
-(defun chess-pgn-move ()
-  "Make a move from a PGN buffer."
-  (interactive)
-  (let ((end (point))
-       coords move)
-    (save-excursion
-      (skip-chars-backward "^ ")
-      (setq move (buffer-substring-no-properties (point) end)
-           coords (chess-algebraic-to-ply chess-display-position move))
-      ;; it will just get reinserted again
-      (delete-region (point) end))
-    (chess-session-event chess-current-session 'move
-                        (chess-algebraic-to-ply chess-display-position))))
-
-(defun chess-pgn-insert-move (move &optional color sequence)
-  "Insert an algebraic move description into a PGN buffer.
-If move is the symbol `wait', it means reflect that we are now waiting
-for the opponent to make his move.  If move is the symbol `ready', it
-means our opponent is now waiting for us to move our move.  Otherwise,
-move should be a string representing the algebraic notation for the
-move."
-  (while (= (char-before) ?.)
-    (delete-backward-char 1))
-  (cond
-   ((eq move 'wait)
-    (insert "..."))
-   ((eq move 'ready) t)
-   (t
-    (if (= (char-syntax (char-before)) ? )
-       (insert move))
-    (if color
-       (move-to-column 11 t)
-      (insert ?\n (format "%d.  " (1+ sequence))))))
-  (let ((wind (get-buffer-window (current-buffer))))
-    (if wind
-       (set-window-point wind (point)))))
+;; (defvar chess-pgn-mode-map
+;;   (let ((map (make-sparse-keymap)))
+;;     (define-key map [??] 'describe-mode)
+;;     (define-key map [?T] 'text-mode)
+;;     (define-key map [return] 'chess-pgn-move)
+;;     (define-key map [(control ?m)] 'chess-pgn-move)
+;;     map)
+;;   "Keymap used by Chess PGN mode.")
+;;
+;; (define-derived-mode chess-pgn-mode text-mode "Chess"
+;;   "A mode for editing Chess PGN files.")
+;;
+;; (defun chess-pgn-move ()
+;;   "Make a move from a PGN buffer."
+;;   (interactive)
+;;   (let ((end (point))
+;;     coords move)
+;;     (save-excursion
+;;       (skip-chars-backward "^ ")
+;;       (setq move (buffer-substring-no-properties (point) end)
+;;         coords (chess-algebraic-to-ply chess-display-position move))
+;;       ;; it will just get reinserted again
+;;       (delete-region (point) end))
+;;     (chess-session-event chess-current-session 'move
+;;                      (chess-algebraic-to-ply chess-display-position))))
+;;
+;; (defun chess-pgn-insert-move (move &optional color sequence)
+;;   "Insert an algebraic move description into a PGN buffer.
+;; If move is the symbol `wait', it means reflect that we are now waiting
+;; for the opponent to make his move.  If move is the symbol `ready', it
+;; means our opponent is now waiting for us to move our move.  Otherwise,
+;; move should be a string representing the algebraic notation for the
+;; move."
+;;   (while (= (char-before) ?.)
+;;     (delete-backward-char 1))
+;;   (cond
+;;    ((eq move 'wait)
+;;     (insert "..."))
+;;    ((eq move 'ready) t)
+;;    (t
+;;     (if (= (char-syntax (char-before)) ? )
+;;     (insert move))
+;;     (if color
+;;     (move-to-column 11 t)
+;;       (insert ?\n (format "%d.  " (1+ sequence))))))
+;;   (let ((wind (get-buffer-window (current-buffer))))
+;;     (if wind
+;;     (set-window-point wind (point)))))
 
 (provide 'chess-pgn)
 
index 172c1545dc6394a477370e1e644698dcb25b5a5f..65c11b7196dc6126ea01eb1b551d509a551b1ff5 100644 (file)
@@ -45,6 +45,7 @@
 ;;; Code:
 
 (require 'chess-pos)
+(require 'chess-standard)
 
 (defgroup chess-ply nil
   "Routines for manipulating chess plies."
 (defsubst chess-ply-create (position &rest changes)
   (cons position changes))
 
-(defun chess-legal-plies (position color)
-  "Return a list of all legal plies in POSITION for COLOR."
+(defun chess-legal-plies (position &optional search-func)
+  "Return a list of all legal plies in POSITION."
   (let (plies)
     (dotimes (rank 8)
       (dotimes (file 8)
        (let* ((to (chess-rf-to-index rank file))
               (piece (chess-pos-piece position to)))
          (when (or (eq piece ? )
-                   (if color
+                   (if (chess-pos-side-to-move position)
                        (> piece ?a)
                      (< piece ?a)))
-           (dolist (candidate (funcall (car chess-modules)
-                                       nil nil 'search position to t))
+           (dolist (candidate (funcall (or search-func
+                                           chess-standard-search)
+                                       position to t))
              (push (chess-ply-create position candidate to)
                    plies))))))
     plies))
index 729cc8bb9729821fccfaf9b0b0b72930a82d1516..21d4cdb43261261f428f30d814a13654fe0c6953 100644 (file)
@@ -36,23 +36,7 @@ related to the resulting process.")
 (make-variable-buffer-local 'chess-process-last-pos)
 (make-variable-buffer-local 'chess-process-working)
 
-(defvar chess-process-triggers
-  (list (list
-        (concat "\\s-*\\(white\\|black\\)\\s-*([0-9]+):\\s-+\\("
-                chess-algebraic-regexp "\\)\\s-*$")
-        (function
-         (lambda (color move)
-           (if (if (chess-game-side-to-move chess-process-game)
-                   (string= (downcase color) "white")
-                 (string= (downcase color) "black"))
-               (chess-session-event
-                chess-current-session 'move
-                (chess-algebraic-to-ply
-                 (chess-game-pos chess-process-game) move)))))
-        1 2)
-       '(".*illegal move:\\s-*\\(.*\\)"
-         (signal 'chess-illegal (match-string 1)))
-       '(".+?\015" (replace-match "")))
+(defvar chess-process-triggers nil
   "A list of regexps and the commands that they trigger.
 The alist should be of the form:
 
@@ -102,25 +86,15 @@ must be handled by modules that derive from this module.")
          (set-process-filter proc 'chess-process-filter))
        buf)))
    ((eq event 'shutdown)
-    (when (buffer-live-p buffer)
-      (ignore-errors
-       (process-send-string (get-buffer-process buffer) "quit\n"))
-      (kill-buffer buffer)))
+    (if (buffer-live-p buffer)
+       (kill-buffer buffer)))
    (t
     (ignore
      (with-current-buffer buffer
-       (let (cmdstr)
-        (cond
-         ((eq event 'setup)
-          (setq chess-process-game (car args)
-                chess-process-last-pos (point-min)))
-         ((eq event 'move)
-          (setq cmdstr (concat (chess-ply-to-algebraic (car args)) "\n")))
-         ((eq event 'pass)
-          (setq cmdstr "go\n")))
-        (if (and cmdstr (not chess-process-working))
-            (process-send-string (get-buffer-process (current-buffer))
-                                 cmdstr))))))))
+       (cond
+       ((eq event 'setup)
+        (setq chess-process-game (car args)
+              chess-process-last-pos (point-min)))))))))
 
 (defun chess-process-filter (proc string)
   "Process filter for receiving text from a chess process."
@@ -163,6 +137,71 @@ must be handled by modules that derive from this module.")
            (setq chess-process-last-pos (point)
                  chess-process-working nil)))))))
 
+(defun chess-process-let (forms)
+  `(let ((str (progn ,@forms)))
+     (if (stringp str)
+        (ignore
+         (process-send-string (get-buffer-process (current-buffer))
+                              (concat str "\n")))
+       str)))
+
+(defun chess-process-insert-forms (event)
+  (if (assq event forms)
+      (chess-process-let
+       (prog1
+          (cdr (assq event forms))
+        (setq forms (assq-delete-all event forms))))))
+
+(defmacro define-chess-engine (name ignored triggers &rest forms)
+  "Define a chess engine.
+NAME is an unquoted symbol name that denotes the engine.  This name is
+used as the default string for the chess engine's external command
+name.
+TRIGGERS is a list of process triggers, which fire when the output
+from the process matches certain regexps.  See
+`chess-process-triggers' for more information.
+FORMS is an alist of event symbols, and forms to evaluate when such an
+event is received by the module.  If these forms return a string, this
+string will be sent to the engine process.
+See the file chess-engines.el for code examples."
+  (let ((namestr (symbol-name name)))
+    `(progn
+       (defcustom ,(intern (concat "chess-" namestr "-command"))
+        (and (require 'executable)
+             (executable-find ,namestr))
+        ,(concat "The name of the " namestr " program.")
+        :type 'file
+        :group 'chess-process)
+
+       (defun ,(intern (concat "chess-" namestr))
+        (session buffer event &rest args)
+        (cond
+         ((eq event 'initialize)
+          (with-current-buffer
+              (chess-process session buffer event ,triggers
+                             ,(intern (concat "chess-" namestr "-command")))
+            ,(chess-process-insert-forms 'init)
+            (current-buffer)))
+         ((eq event 'shutdown)
+          (when (buffer-live-p buffer)
+            (ignore-errors
+              ,(chess-process-insert-forms 'shutdown))
+            (kill-buffer buffer)))
+         (t
+          (ignore
+           (with-current-buffer buffer
+             (cond
+              ((eq event 'setup)
+               (apply 'chess-process session buffer event args)
+               ,(chess-process-insert-forms 'setup))
+              ,@(mapcar
+                 (function
+                  (lambda (entry)
+                    `((eq event (quote ,(car entry)))
+                      ,(chess-process-let (cdr entry))))) forms)
+              (t
+               (apply 'chess-process session buffer event args)))))))))))
+
 (provide 'chess-process)
 
 ;;; chess-process.el ends here
index 6f0dde41436e447526ecff9a897580c34a51879f..e28222389b94da075b4474b9837b7e4c4274646a 100644 (file)
       (setq listeners (cdr listeners)))
     result))
 
+;; (define-chess-module MODULE (&rest args))
+;; (define-chess-module (MODULE BASES...) (&rest args)
+;;   :ctor-args (ARGS...)
+;;   :create-buffer
+;;   (EVENT
+;;    FORMS...)
+;;   ...)
+;;
+;; (chess-call-derived args &optional base-module)
+
 (provide 'chess-session)
 
 ;;; chess-session.el ends here
index bc45d3fa38c4d870b13e97b85e113042bb46ebd8..b70c028bf885b702c39fa5b69a232e62145dab6b 100644 (file)
 
 ;; $Revision$
 
-(require 'chess-session)
-(require 'chess-pos)
-(require 'chess-ply)
-(require 'chess-game)
-
 (defgroup chess-standard nil
   "The rules of standard chess."
   :group 'chess)
 
 ;;; Code:
 
-;;;###autoload
-(defun chess-standard (session var event &rest args)
-  (cond
-   ((eq event 'move)
-    (ignore
-     (chess-standard-validate (car args))
-     (chess-game-move (chess-session-data session 'current-game)
-                     (car args))))
-   ((eq event 'search)
-    (apply 'chess-standard-search args))))
-
 (defun chess-standard-validate (ply)
   "Validate the given PLY against standard chess rules."
   (let* ((pos (chess-ply-pos ply))
index 9d53fd8773624f8ff270000cec9fe8395fe30fa7..3e937ec06f1dca8766801aa807a0e7d72d85921b 100644 (file)
--- a/chess.el
+++ b/chess.el
@@ -84,13 +84,10 @@ a0 243
 (defconst chess-version "2.0a7"
   "The version of the Emacs chess program.")
 (defcustom chess-modules
-  (list 'chess-standard 'chess-crafty
+  (list 'chess-crafty
        (if (display-graphic-p)
            'chess-images 'chess-ascii))
-  "Default module set to be used when starting a chess session.
-Any rules modules, if they are being used, must appear first in this
-list!  This usually means `chess-standard' must be the very first
-entry."
+                                    'chess-images 'chess-ics1)
   :type (list 'radio (apropos-internal "\\`chess-[^-]+\\'" 'functionp))
   :type 'sexp
   :group 'chess)