]> code.delx.au - gnu-emacs-elpa/commitdiff
Gnuchess can be played against (up until a pawn take occurs).
authorJohn Wiegley <johnw@newartisans.com>
Wed, 3 Apr 2002 06:34:25 +0000 (06:34 +0000)
committerJohn Wiegley <johnw@newartisans.com>
Wed, 3 Apr 2002 06:34:25 +0000 (06:34 +0000)
chess-algebraic.el
chess-display.el
chess-engine.el
chess-game.el
chess-gnuchess.el
chess-ply.el
chess.el

index c960d4adb091cc279259a83a92ef2c3d7c22428b..de2d95399aea44ada9d927c47b5d6a4d749a4452 100644 (file)
@@ -53,53 +53,54 @@ This regexp handles both long and short form.")
 
 (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))
-          (mate (match-string 10 move))
-          (piece (aref move 0))
-          (changes
-           (if (eq piece ?O)
-               (let ((rank (if color 7 0))
-                     (long (= (length (match-string 1 move)) 5)))
-                 (list (chess-rf-to-index rank 4)
-                       (chess-rf-to-index rank (if long 2 6))
-                       (chess-rf-to-index rank (if long 0 7))
-                       (chess-rf-to-index rank (if long 3 5))))
-             (let ((source (match-string 4 move))
-                   (target (chess-coord-to-index (match-string 7 move))))
-               (if (and source (= (length source) 2))
-                   (list (chess-coord-to-index source) target)
-                 (let (candidates which)
-                   (unless (< piece ?a)
-                     (setq piece ?P))
-                   ;; we must use our knowledge of how pieces can
-                   ;; move, to determine which piece is meant by the
-                   ;; piece indicator
-                   (when (setq candidates
-                               (funcall (or search-func
-                                            'chess-standard-search-position)
-                                        position target (if color piece
-                                                          (downcase piece))))
-                     (if (= (length candidates) 1)
-                         (list (car candidates) target)
-                       (if (null source)
-                           (error "Clarify piece to move by rank or file")
-                         (while candidates
-                           (if (if (>= source ?a)
-                                   (eq (cdar candidates) (- source ?a))
-                                 (eq (caar candidates) (- 7 (- source ?1))))
-                               (setq which (car candidates) candidates nil)
-                             (setq candidates (cdr candidates))))
-                         (if (null which)
-                             (error "Could not determine which piece to use")
-                           (list which target)))))))))))
-      (if mate
-         (nconc changes
-                (list (if (equal mate "#")
-                          ':checkmate
-                        ':check))))
-      (assert changes)
-      (apply 'chess-ply-create position changes))))
+  (unless (string-match chess-algebraic-regexp move)
+    (error "Cannot parse non-algebraic move notation: %s" move))
+  (let* ((color (chess-pos-side-to-move position))
+        (mate (match-string 10 move))
+        (piece (aref move 0))
+        (changes
+         (if (eq piece ?O)
+             (let ((rank (if color 7 0))
+                   (long (= (length (match-string 1 move)) 5)))
+               (list (chess-rf-to-index rank 4)
+                     (chess-rf-to-index rank (if long 2 6))
+                     (chess-rf-to-index rank (if long 0 7))
+                     (chess-rf-to-index rank (if long 3 5))))
+           (let ((source (match-string 4 move))
+                 (target (chess-coord-to-index (match-string 7 move))))
+             (if (and source (= (length source) 2))
+                 (list (chess-coord-to-index source) target)
+               (let (candidates which)
+                 (unless (< piece ?a)
+                   (setq piece ?P))
+                 ;; we must use our knowledge of how pieces can
+                 ;; move, to determine which piece is meant by the
+                 ;; piece indicator
+                 (when (setq candidates
+                             (funcall (or search-func
+                                          'chess-standard-search-position)
+                                      position target (if color piece
+                                                        (downcase piece))))
+                   (if (= (length candidates) 1)
+                       (list (car candidates) target)
+                     (if (null source)
+                         (error "Clarify piece to move by rank or file")
+                       (while candidates
+                         (if (if (>= source ?a)
+                                 (eq (cdar candidates) (- source ?a))
+                               (eq (caar candidates) (- 7 (- source ?1))))
+                             (setq which (car candidates) candidates nil)
+                           (setq candidates (cdr candidates))))
+                       (if (null which)
+                           (error "Could not determine which piece to use")
+                         (list which target)))))))))))
+    (if mate
+       (nconc changes
+              (list (if (equal mate "#")
+                        ':checkmate
+                      ':check))))
+    (assert changes)
+    (apply 'chess-ply-create position changes)))
 
 (defun chess-ply-to-algebraic (ply &optional long search-func)
   "Convert the given PLY to algebraic notation.
index 4e18130a7d2660b7070d6501c809230fe505b599..526d8ca0780e8ddbb7256658f478d4a945079e61 100644 (file)
@@ -259,39 +259,30 @@ change that position object, the display can be updated by calling
        (funcall chess-display-draw-function))
     (chess-display-set-modeline)))
 
-(defun chess-display-move (display start &optional target)
-  "Move a piece on DISPLAY from START to TARGET.
+(defun chess-display-move (display ply)
+  "Move a piece on DISPLAY, by applying the given PLY.
+The position of PLY must match the currently displayed position.
 If only START is given, it must be in algebraic move notation."
   (chess-with-current-buffer display
-    ;; jww (2002-03-28): how is this going to handle castling?  There
-    ;; needs to be a way to "flesh" out a move using the standard
-    ;; search function.
-    (let ((ply (if (null target)
-                  (chess-algebraic-to-ply
-                   (chess-display-position nil) start
-                   (chess-display-search-function nil))
-                (chess-ply-create (chess-display-position nil)
-                                  start target))))
-      (cond
-       ((chess-display-active-p)
-       ;; make the move and then announce it
-       (chess-game-move chess-display-game ply)
-       (chess-session-event chess-display-session 'move ply))
-       (chess-display-game
-       ;; jww (2002-03-28): This should beget a variation within the
-       ;; game, or alter the game, just as SCID allows
-       (unless (= (chess-display-index nil)
-                  (chess-game-index chess-display-game))
-         (error "Cannot move partway in game (index %d != game index %d)"
-                (chess-display-index nil)
-                (chess-game-index chess-display-game)))
-       (chess-game-move chess-display-game ply))
-       (chess-display-variation
-       (nconc chess-display-variation (list ply)))
-       (chess-display-ply
-       (setq chess-display-ply ply))
-       (t                              ; an ordinary position
-       (setq chess-display-position (chess-ply-next-pos ply)))))
+    (cond
+     ((chess-display-active-p)
+      (chess-session-event chess-display-session 'move ply))
+     (chess-display-game
+      ;; jww (2002-03-28): This should beget a variation within the
+      ;; game, or alter the game, just as SCID allows
+      (if (= (chess-display-index nil)
+            (chess-game-index chess-display-game))
+         (setq chess-display-index
+               (1+ (chess-game-index chess-display-game))))
+      (chess-game-move chess-display-game ply))
+     (chess-display-variation
+      ;; jww (2002-04-02): what if we're in the middle?
+      (nconc chess-display-variation (list ply))
+      (setq chess-display-index (1- (length chess-display-variation))))
+     (chess-display-ply
+      (setq chess-display-ply ply))
+     (t                                        ; an ordinary position
+      (setq chess-display-position (chess-ply-next-pos ply))))
     (chess-display-update nil)))
 
 (defun chess-display-highlight (display index &optional mode)
@@ -337,6 +328,11 @@ See `chess-display-type' for the different kinds of displays."
        (chess-display-set-perspective
        display (not (chess-display-perspective display))))
 
+      ((eq event 'move)
+       (chess-display-set-index
+       display (chess-game-index (chess-display-game display)))
+       (chess-display-update display))
+
       (t
        (chess-display-update display))))))
 
@@ -412,7 +408,7 @@ The key bindings available in this mode are:
   (let ((ply (chess-display-ply nil))
        (color (chess-pos-side-to-move (chess-display-position nil)))
        (index (chess-display-index nil)))
-    (if (and index (= index 1))
+    (if (and index (= index 0))
        (setq chess-display-mode-line
              (format "   %s   START" (if color "White" "BLACK")))
       (setq chess-display-mode-line
@@ -425,7 +421,7 @@ The key bindings available in this mode are:
             (if ply
                 (concat ". " (if color "... ")
                         (chess-ply-to-algebraic
-                         ply (chess-display-search-function nil)))))))))
+                         ply nil (chess-display-search-function nil)))))))))
 
 (defsubst chess-display-active-p ()
   "Return non-nil if the displayed chessboard reflects an active game.
@@ -490,7 +486,9 @@ position within the game)."
                  (if (chess-pos-side-to-move (chess-display-position nil))
                      "White" "Black")
                  (1+ (/ (or (chess-display-index nil) 0) 2))))))
-  (chess-display-move nil move))
+  (chess-display-move nil (chess-algebraic-to-ply
+                          (chess-display-position nil) move
+                          (chess-display-search-function nil))))
 
 (defun chess-display-set-current (dir)
   "Change the currently displayed board.
@@ -649,7 +647,9 @@ to the end or beginning."
       (setq moves (delq nil moves))
       (cond
        ((= (length moves) 1)
-       (chess-display-move nil (car moves))
+       (chess-display-move nil (chess-algebraic-to-ply
+                                (chess-display-position nil) (car moves)
+                                (chess-display-search-function nil)))
        (setq chess-move-string nil
              chess-legal-moves nil
              chess-legal-moves-pos nil))
@@ -691,7 +691,9 @@ Clicking once on a piece selects it; then click on the target location."
          (let ((last-sel chess-display-last-selected))
            ;; if they select the same square again, just deselect it
            (if (/= (point) (car last-sel))
-               (chess-display-move nil (cadr last-sel) coord)
+               (chess-display-move
+                nil (chess-ply-create (chess-display-position nil)
+                                      (cadr last-sel) coord))
              ;; put the board back to rights
              (chess-display-update nil))
            (setq chess-display-last-selected nil))
index 678f5c37a72cc6a9f20a55f9e5c2e33a45fc1b91..40090ab3cc85169f34e605f03f15afa1842ba133 100644 (file)
           ,@body)
        ,@body)))
 
+(defun chess-engine-do-move (ply)
+  (cond
+   ((and chess-engine-session
+        chess-engine-game)
+    (chess-session-event chess-engine-session event ply))
+   (chess-engine-game
+    (chess-game-move chess-engine-game ply))
+   (t
+    (apply 'chess-pos-move ply))))
+
 (defun chess-engine-default-handler (event &rest args)
   (cond
    ((eq event 'move)
-    (cond
-     ((chess-engine-session nil)
-      (apply 'chess-session-event (chess-engine-session nil) event args))
-     ((chess-engine-game nil)
-      (chess-game-move (chess-engine-game nil) (car args)))
-     (t
-      (apply 'chess-pos-move (chess-ply-pos (car args))
-            (chess-ply-changes (car args))))))))
+    (chess-engine-do-move (car args)))))
 
 (defun chess-engine-create (module &optional user-handler session search-func)
   (let ((regexp-alist (intern-soft (concat (symbol-name module)
                                           "-regexp-alist")))
        (handler (intern-soft (concat (symbol-name module) "-handler"))))
     (with-current-buffer (generate-new-buffer " *chess-engine*")
-      (setq chess-engine-regexp-alist (symbol-value regexp-alist)
+      (setq chess-engine-session session
+           chess-engine-regexp-alist (symbol-value regexp-alist)
            chess-engine-event-handler handler
            chess-engine-response-handler (or 'chess-engine-default-handler
                                              user-handler))
          (error "Failed to start chess engine process"))
        (set-process-buffer proc (current-buffer))
        (set-process-filter proc 'chess-engine-filter))
-      (chess-engine-set-game nil (chess-game-create nil search-func))
+      (if session
+         (let ((game (chess-session-data session 'current-game)))
+           (if game
+               (chess-engine-set-game nil game)))
+       (chess-engine-set-game nil (chess-game-create nil search-func)))
       (current-buffer))))
 
 (defun chess-engine-destroy (engine)
-  (let ((buf (or display (current-buffer))))
+  (let ((buf (or engine (current-buffer))))
     (if (buffer-live-p buf)
        (kill-buffer buf))))
 
 
 (defun chess-engine-move (engine ply)
   (chess-with-current-buffer engine
-    (cond
-     (chess-engine-game
-      (chess-game-move chess-engine-game ply))
-     (chess-engine-position
-      (apply 'chess-pos-move ply)))
+    (chess-engine-do-move ply)
     (chess-engine-command engine 'move ply)))
 
 (defun chess-engine-pass (engine ply)
 ;;
 
 ;;;###autoload
-(defun chess-engine (session buffer event &rest args)
+(defun chess-engine (session engine event &rest args)
   "Handle any commands being sent to this instance of this module."
   (if (eq event 'initialize)
-      (chess-engine-create (car args) 'chess-engine-session-callback session)
-    (ignore
-     (cond
-      ((eq event 'shutdown)
-       (chess-engine-destroy engine))
-
-      ((eq event 'setup)
-       (chess-engine-set-game engine (car args)))
-
-      ((eq event 'pass)
-       (chess-engine-pass engine))))))
+      (chess-engine-create (car args)
+                          'chess-engine-session-callback session)
+    (with-current-buffer engine
+      (unless (apply chess-engine-event-handler event args)
+       (cond
+        ((eq event 'shutdown)
+         (chess-engine-destroy engine))
+
+        ((eq event 'setup)
+         (chess-engine-set-game engine (car args)))
+
+        ((eq event 'pass)
+         (chess-engine-pass engine)))))))
 
 (defun chess-engine-filter (proc string)
   "Process filter for receiving text from a chess process."
index b321bd1b85914fa2671ca73931e627e53b9b7d3a..7e28405c651336cdf3221816a02cdbbcbcb95168 100644 (file)
@@ -111,8 +111,7 @@ later using the various tag-related methods)."
       (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 (and position
-                                      (chess-pos-copy position))
+                             (or position
                                  (chess-pos-create))))
     (if position
        (chess-game-set-tag game "FEN" (chess-pos-to-fen position)))
index 45980205a46c5ffa7268753d0d3867e91307dc9a..09fe89e70703e225c00fbc48a032d880b2fbf927 100644 (file)
@@ -13,7 +13,7 @@
              (function
               (lambda ()
                 (funcall chess-engine-response-handler 'move
-                         (chess-algebraic-to-ply position
+                         (chess-algebraic-to-ply (chess-engine-position nil)
                                                  (match-string 1))))))
        (cons "Illegal move:"
              (function
index 6b810d460fa7e6f711efd31193fcb02433aeb475..f5261b9f5d3714a1a2ecacccfa0bc769b4e78f8c 100644 (file)
@@ -68,7 +68,9 @@
         (chess-ply-changes ply)))
 
 (defsubst chess-ply-create (position &rest changes)
-  (cons position changes))
+  ;; jww (2002-04-02): if changes is a castling maneuver, then
+  ;; annotate and extend the ply correctly
+  (cons (chess-pos-copy position) changes))
 
 (defun chess-legal-plies (position &optional search-func)
   "Return a list of all legal plies in POSITION."
index 0710dc9092bc6b1edb2d1639088dfaa2f3ff10c4..4d74a4ee12495a098f8380f66e5a23355bdb5599 100644 (file)
--- a/chess.el
+++ b/chess.el
@@ -126,25 +126,24 @@ a0 243
 
 (defun chess-handler (session window-config event &rest args)
   "React to changes on the chess board in a global Emacs way."
-  (cond
-   ((eq event 'initialize)
-    (current-window-configuration))
-
-   ((eq event 'shutdown)
-    (ignore (set-window-configuration window-config)))
+  (if (eq event 'initialize)
+      (current-window-configuration)
+    (ignore
+     (cond
+      ((eq event 'shutdown)
+       (set-window-configuration window-config))
 
-   ((eq event 'setup)
-    (ignore (chess-session-set-data session 'current-game (car args))))
+      ((eq event 'setup)
+       (chess-session-set-data session 'current-game (car args)))
 
-   ((eq event 'pass)
-    (ignore
-     (let ((color (not (chess-session-data session 'my-color))))
-       (message "You are now playing %s" (if color "White" "Black"))
-       (chess-session-set-data session 'my-color (not color)))))
+      ((eq event 'pass)
+       (let ((color (not (chess-session-data session 'my-color))))
+        (message "You are now playing %s" (if color "White" "Black"))
+        (chess-session-set-data session 'my-color (not color))))
 
-   ((eq event 'move)
-    (chess-game-move (chess-session-data session 'current-game)
-                    (car args)))))
+      ((eq event 'move)
+       (chess-game-move (chess-session-data session 'current-game)
+                       (car args)))))))
            (aset chess-puzzle-locations 3 puzzle-engine)))))))
 
 (provide 'chess)