summaryrefslogtreecommitdiff
path: root/chess-input.el
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2002-04-17 08:34:35 +0000
committerJohn Wiegley <johnw@newartisans.com>2002-04-17 08:34:35 +0000
commitc171394743d2a10cfe872ce076c5a8f7269d7b2b (patch)
tree0906d6eb3a7d9e6367e22d32ea1158db2d759f53 /chess-input.el
parent4d1c4c72b5a9c2c0180531246389a452fc034bc8 (diff)
More general bug fixing, efficiency improvements, etc.
Diffstat (limited to 'chess-input.el')
-rw-r--r--chess-input.el132
1 files changed, 132 insertions, 0 deletions
diff --git a/chess-input.el b/chess-input.el
new file mode 100644
index 0000000..9a3a28a
--- /dev/null
+++ b/chess-input.el
@@ -0,0 +1,132 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Keyboard entry of algebraic notation, using shortcut notation
+;;
+;; This scheme was adapted from the way SCID
+;; (http://scid.sourceforge.net), by Shane Hudson, behaves. It's the
+;; only way to move your pieces around!
+;;
+
+(defvar chess-move-string "")
+(defvar chess-legal-moves-pos nil)
+(defvar chess-legal-moves nil)
+(defvar chess-input-move-function nil)
+
+(make-variable-buffer-local 'chess-move-string)
+(make-variable-buffer-local 'chess-legal-moves-pos)
+(make-variable-buffer-local 'chess-legal-moves)
+(make-variable-buffer-local 'chess-input-move-function)
+
+(chess-message-catalog 'english
+ '((not-your-move . "It is not your turn to move")
+ (game-is-over . "This game is over")))
+
+(defun chess-keyboard-test-move (move-ply)
+ "Return the given MOVE if it matches the user's current input."
+ (let* ((move (cdr move-ply))
+ (i 0) (x 0) (l (length move))
+ (xl (length chess-move-string))
+ (match t))
+ (unless (or (and (equal (downcase chess-move-string) "ok")
+ (string-match "\\`O-O[+#]?\\'" move))
+ (and (equal (downcase chess-move-string) "oq")
+ (string-match "\\`O-O-O[+#]?\\'" move)))
+ (while (and (< i l) (< x xl))
+ (let ((move-char (aref move i))
+ (entry-char (aref chess-move-string x)))
+ (if (and (= move-char ?x)
+ (/= entry-char ?x))
+ (setq i (1+ i))
+ (if (/= entry-char (if (< entry-char ?a)
+ move-char
+ (downcase move-char)))
+ (setq match nil i l)
+ (setq i (1+ i) x (1+ x)))))))
+ (if match
+ move-ply)))
+
+(defsubst chess-keyboard-display-moves (&optional move-list)
+ (if (> (length chess-move-string) 0)
+ (message "[%s] %s" chess-move-string
+ (mapconcat 'cdr
+ (or move-list
+ (delq nil (mapcar 'chess-keyboard-test-move
+ (cdr chess-legal-moves))))
+ " "))))
+
+(defun chess-keyboard-shortcut-delete ()
+ (interactive)
+ (when (and chess-move-string
+ (stringp chess-move-string)
+ (> (length chess-move-string) 0))
+ (setq chess-move-string
+ (substring chess-move-string 0 (1- (length chess-move-string))))
+ (chess-keyboard-display-moves)))
+
+(defun chess-keyboard-shortcut (&optional display-only)
+ (interactive)
+ (let* ((position (chess-display-position nil))
+ (color (chess-pos-side-to-move position))
+ char)
+ (chess-display-assert-can-move position)
+ (unless (memq last-command '(chess-keyboard-shortcut
+ chess-keyboard-shortcut-delete))
+ (setq chess-move-string nil))
+ (unless display-only
+ (setq chess-move-string
+ (concat chess-move-string (char-to-string last-command-char))))
+ (unless (and chess-legal-moves
+ (eq position chess-legal-moves-pos)
+ (or (> (length chess-move-string) 1)
+ (eq (car chess-legal-moves) last-command-char)))
+ (setq char (if (eq (downcase last-command-char) ?o) ?k
+ last-command-char)
+ chess-legal-moves-pos position
+ chess-legal-moves
+ (cons char
+ (sort
+ (mapcar
+ (function
+ (lambda (ply)
+ (cons ply (chess-ply-to-algebraic ply))))
+ (if (eq char ?b)
+ (append (chess-legal-plies
+ position :piece (if color ?P ?p) :file 1)
+ (chess-legal-plies
+ position :piece (if color ?B ?b)))
+ (if (and (>= char ?a)
+ (<= char ?h))
+ (chess-legal-plies position
+ :piece (if color ?P ?p)
+ :file (- char ?a))
+ (chess-legal-plies position
+ :piece (if color
+ (upcase char)
+ (downcase char))))))
+ (function
+ (lambda (left right)
+ (string-lessp (cdr left) (cdr right)))))))))
+ (let ((moves (delq nil (mapcar 'chess-keyboard-test-move
+ (cdr chess-legal-moves)))))
+ (cond
+ ((or (= (length moves) 1)
+ ;; if there is an exact match except for case, it must be an
+ ;; abiguity between a bishop and a b-pawn move. In this
+ ;; case, always take the b-pawn move; to select the bishop
+ ;; move, use B to begin the keyboard shortcut
+ (and (= (length moves) 2)
+ (string= (downcase (cdr (car moves)))
+ (downcase (cdr (cadr moves))))
+ (setq moves (cdr moves))))
+ (funcall chess-input-move-function nil (caar moves))
+ (setq chess-move-string nil
+ chess-legal-moves nil
+ chess-legal-moves-pos nil))
+ ((null moves)
+ (chess-keyboard-shortcut-delete))
+ (t
+ (chess-keyboard-display-moves moves)))))
+
+(provide 'chess-input)
+
+;;; chess-input.el ends here