diff options
| author | John Wiegley <johnw@newartisans.com> | 2002-04-13 11:13:33 +0000 |
|---|---|---|
| committer | John Wiegley <johnw@newartisans.com> | 2002-04-13 11:13:33 +0000 |
| commit | 7e960384fa89c02c2fc2be1f61fe18645f8a13fe (patch) | |
| tree | 66d17d5fb9a7f73a3291e6261f1df2e12612eb2e | |
| parent | f4639c9095c34caa60b4122e2cf4d6b1402508e3 (diff) | |
added message catalog support
| -rw-r--r-- | TODO | 2 | ||||
| -rw-r--r-- | chess-algebraic.el | 20 | ||||
| -rw-r--r-- | chess-announce.el | 67 | ||||
| -rw-r--r-- | chess-common.el | 15 | ||||
| -rw-r--r-- | chess-display.el | 124 | ||||
| -rw-r--r-- | chess-engine.el | 88 | ||||
| -rw-r--r-- | chess-game.el | 8 | ||||
| -rw-r--r-- | chess-gnuchess.el | 2 | ||||
| -rw-r--r-- | chess-ics.el | 18 | ||||
| -rw-r--r-- | chess-images.el | 13 | ||||
| -rw-r--r-- | chess-irc.el | 22 | ||||
| -rw-r--r-- | chess-message.el | 47 | ||||
| -rw-r--r-- | chess-network.el | 11 | ||||
| -rw-r--r-- | chess-pgn.el | 8 | ||||
| -rw-r--r-- | chess-ply.el | 67 | ||||
| -rw-r--r-- | chess-pos.el | 34 | ||||
| -rw-r--r-- | chess-var.el | 5 | ||||
| -rw-r--r-- | chess.el | 8 |
18 files changed, 381 insertions, 178 deletions
@@ -27,8 +27,6 @@ laptop. ---------------------------------------------------------------------- -- test making an en passant capture - - the game should go inactive once I lose by stalemate/checkmate - detect draw/resign/abort/retract, etc., from ICS and common engines diff --git a/chess-algebraic.el b/chess-algebraic.el index 0960a35..7a430fc 100644 --- a/chess-algebraic.el +++ b/chess-algebraic.el @@ -55,6 +55,12 @@ This regexp handles both long and short form.") (defconst chess-algebraic-regexp-entire (concat chess-algebraic-regexp "$")) +(chess-message-catalog 'english + '((clarify-piece . "Clarify piece to move by rank or file") + (could-not-clarify . "Could not determine which piece to use") + (could-not-diff . "Could not differentiate piece") + (no-candidates . "There are no candidate moves for '%s'"))) + (defun chess-algebraic-to-ply (position move &optional trust) "Convert the algebraic notation MOVE for POSITION to a ply." (when (string-match chess-algebraic-regexp-entire move) @@ -89,7 +95,7 @@ This regexp handles both long and short form.") (if (= (length candidates) 1) (list (car candidates) target) (if (null source) - (error "Clarify piece to move by rank or file") + (chess-error 'clarify-piece) (nconc changes (list :which source)) (while candidates (if (if (>= source ?a) @@ -101,10 +107,9 @@ This regexp handles both long and short form.") candidates nil) (setq candidates (cdr candidates)))) (if (null which) - (error "Could not determine which piece to use") + (chess-error could-not-clarify) (list which target)))) - (error "There are no candidate moves for '%s'" - move)))))) + (chess-error no-candidates move)))))) (if promotion (nconc changes (list :promote (aref promotion 0)))))) @@ -145,7 +150,7 @@ If LONG is non-nil, render the move into long notation." (setq differentiator (+ from-file ?a))) ((= rank 1) (setq differentiator (+ (- 7 from-rank) ?1))) - (t (error "Could not differentiate piece")))))) + (t (chess-error 'could-not-diff)))))) (concat (unless (= (upcase from-piece) ?P) (char-to-string (upcase from-piece))) @@ -157,10 +162,11 @@ If LONG is non-nil, render the move into long notation." (/= (chess-index-file from) (chess-index-file to))) (char-to-string (+ (chess-index-file from) ?a))))) - (if (/= ? (chess-pos-piece pos to)) + (if (or (/= ? (chess-pos-piece pos to)) + (chess-ply-keyword ply :en-passant)) "x" (if long "-")) (chess-index-to-coord to) - (let ((promote (memq :promote (chess-ply-changes ply)))) + (let ((promote (chess-ply-keyword ply :promote))) (if promote (concat "=" (char-to-string (upcase (cadr promote)))))) diff --git a/chess-announce.el b/chess-announce.el index f4c8f11..ff1a331 100644 --- a/chess-announce.el +++ b/chess-announce.el @@ -6,13 +6,28 @@ (require 'chess-game) +(chess-message-catalog 'english + '((queen . "queen") + (king . "king") + (bishop . "bishop") + (knight . "knight") + (rook . "rook") + (pawn . "pawn") + (short-castle . "short castle") + (long-castle . "long castle") + (check . "check") + (checkmate . "checkmate") + (stalemate . "stalemate") + (piece-moves . "%s to %s") + (piece-takes . "%s takes %s at %s"))) + (defvar chess-announce-names - '((?q . "queen") - (?k . "king") - (?b . "bishop") - (?n . "knight") - (?r . "rook") - (?p . "pawn"))) + '((?q . queen) + (?k . king) + (?b . bishop) + (?n . knight) + (?r . rook) + (?p . pawn))) (autoload 'festival-start-process "festival") (autoload 'festival-kill-process "festival") @@ -58,31 +73,35 @@ See `chess-display-type' for the different kinds of displays." (setq which (char-to-string which))) (cond ((chess-ply-keyword ply :castle) - (setq text "short castle")) + (setq text (chess-string 'short-castle))) ((chess-ply-keyword ply :long-castle) - (setq text "long castle")) + (setq text (chess-string 'long-castle))) ((= t-piece ? ) - (setq text (concat which - (cdr (assq (downcase s-piece) - chess-announce-names)) - " to " - (chess-index-to-coord target)))) + (setq text + (concat which + (chess-string 'piece-moves + (chess-string + (cdr (assq (downcase s-piece) + chess-announce-names))) + (chess-index-to-coord target))))) (t - (setq text (concat which - (cdr (assq (downcase s-piece) - chess-announce-names)) - " takes " - (cdr (assq (downcase t-piece) - chess-announce-names)) - " at " - (chess-index-to-coord target))))) + (setq text + (concat which + (chess-string 'piece-takes + (chess-string + (cdr (assq (downcase s-piece) + chess-announce-names))) + (chess-string + (cdr (assq (downcase t-piece) + chess-announce-names))) + (chess-index-to-coord target)))))) (if (chess-ply-keyword ply :check) - (setq text (concat text ", check"))) + (setq text (concat text ", " (chess-string 'check)))) (if (chess-ply-keyword ply :checkmate) - (setq text (concat text ", checkmate"))) + (setq text (concat text ", " (chess-string 'checkmate)))) (if (chess-ply-keyword ply :stalemate) - (setq text (concat text ", stalemate"))) + (setq text (concat text ", " (chess-string 'stalemate)))) (funcall (nth 1 chess-announce-functions) text))))))) diff --git a/chess-common.el b/chess-common.el index 66a4b99..f468dca 100644 --- a/chess-common.el +++ b/chess-common.el @@ -21,6 +21,13 @@ (put 'chess-with-temp-file 'lisp-indent-function 1) +(chess-message-catalog 'english + '((starting-engine . "Starting chess program '%s'...") + (starting-engine-done . "Starting chess program '%s'...done") + (could-not-find-engine . "Cannot find %s executable; check `%s'") + (draw-offer-declined . "Your draw offer was declined") + (illegal-move . "Illegal move"))) + (defun chess-common-handler (event &rest args) "Initialize the network chess engine." (cond @@ -28,12 +35,12 @@ (let* ((name (car args)) (path (intern (concat "chess-" name "-path"))) proc) - (message "Starting chess program '%s'..." name) + (chess-message 'starting-engine name) (unless (boundp path) - (error "Cannot find %s executable; check `%s'" name path)) + (chess-error 'could-not-find-engine name path)) (setq proc (start-process (concat "chess-" name) (current-buffer) (symbol-value path))) - (message "Starting chess program '%s'...done" name) + (chess-message 'starting-engine-done name) proc)) ((eq event 'ready) @@ -53,7 +60,7 @@ (chess-engine-send nil "resign\n")) ((eq event 'draw) - (message "Your draw offer was declined")) + (chess-message 'draw-offer-declined)) ((memq event '(resign abort)) (chess-engine-send nil "new\n") diff --git a/chess-display.el b/chess-display.el index ca75eeb..cc0106a 100644 --- a/chess-display.el +++ b/chess-display.el @@ -4,8 +4,6 @@ ;; ;; $Revision$ -;;; Code: - (require 'chess-game) (require 'chess-var) (require 'chess-algebraic) @@ -64,6 +62,9 @@ ,@body) ,@body))) +(chess-message-catalog 'english + '((no-such-style . "There is no such chessboard display style '%s'"))) + (defun chess-display-create (game style perspective &optional main read-only) "Create a chess display, for displaying chess objects. The display is drawn using the given STYLE, from the PERSPECTIVE @@ -75,7 +76,7 @@ makes moves, or any other changes to the underlying game." (let* ((name (symbol-name style)) (handler (intern-soft (concat name "-handler")))) (unless handler - (error "There is no such chessboard display style '%s'" name)) + (chess-error 'no-such-style name)) (with-current-buffer (generate-new-buffer "*Chessboard*") (chess-display-mode read-only) (funcall handler 'initialize) @@ -549,6 +550,9 @@ Basically, it means we are playing, not editing or reviewing." (chess-game-run-hooks chess-display-game 'shutdown) (chess-display-destroy nil))) +(chess-message-catalog 'english + '((illegal-notation . "Illegal move notation: %s"))) + (defun chess-display-manual-move (move) "Move a piece manually, using chess notation." (interactive @@ -559,7 +563,7 @@ Basically, it means we are playing, not editing or reviewing." (1+ (/ (or chess-display-index 0) 2)))))) (let ((ply (chess-algebraic-to-ply (chess-display-position nil) move))) (unless ply - (error "Illegal move notation: %s" move)) + (chess-error 'illegal-notation move)) (chess-display-move nil ply))) (defun chess-display-remote (display) @@ -616,12 +620,15 @@ Basically, it means we are playing, not editing or reviewing." (chess-game-run-hooks chess-display-game 'abort) (ding))) +(chess-message-catalog 'english + '((draw-offer . "You offer a draw"))) + (defun chess-display-draw () "Offer to draw the current game." (interactive) (if (chess-display-active-p) (progn - (message "You offer a draw") + (chess-message 'draw-offer) (chess-game-run-hooks chess-display-game 'draw)) (ding))) @@ -663,6 +670,9 @@ Basically, it means we are playing, not editing or reviewing." (call-interactively lb-command)) (fset 'buffer-list buffer-list-func)))) +(chess-message-catalog 'english + '((return-to-current . "Use '>' to return to the current position"))) + (defun chess-display-set-current (dir) "Change the currently displayed board. Direction may be - or +, to move forward or back, or t or nil to jump @@ -674,7 +684,7 @@ to the end or beginning." (chess-display-set-index nil (or index (chess-game-index chess-display-game))) (unless (chess-display-active-p) - (message "Use '>' to return to the current position")))) + (chess-message 'return-to-current)))) (defun chess-display-move-backward () (interactive) @@ -713,6 +723,10 @@ to the end or beginning." map) "The mode map used for editing a chessboard position.") +(chess-message-catalog 'english + '((editing-directly + . "Now editing position directly, use S when complete..."))) + (defun chess-display-edit-board () "Setup the current board for editing." (interactive) @@ -722,7 +736,7 @@ to the end or beginning." ;; 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 - (message "Now editing position directly, use S when complete...")) + (chess-message 'editing-directly)) (defun chess-display-send-board () "Send the current board configuration to the user." @@ -804,17 +818,21 @@ to the end or beginning." (make-variable-buffer-local 'chess-legal-moves-pos) (make-variable-buffer-local 'chess-legal-moves) +(chess-message-catalog 'english + '((not-your-move . "It is not your turn to move") + (game-is-over . "This game is over"))) + (defun chess-display-assert-can-move () (if (and (chess-display-active-p) ;; `active' means we're playing against an engine (chess-game-data chess-display-game 'active) (not (eq (chess-game-data chess-display-game 'my-color) (chess-pos-side-to-move position)))) - (error "It is not your turn to move") + (chess-error 'not-your-move) (if (and (= chess-display-index (chess-game-index chess-display-game)) (chess-game-over-p chess-display-game)) - (error "This game is over")))) + (chess-error 'game-is-over)))) (defun chess-keyboard-test-move (move-ply) "Return the given MOVE if it matches the user's current input." @@ -929,49 +947,63 @@ to the end or beginning." (make-variable-buffer-local 'chess-display-last-selected) +(chess-message-catalog 'english + '((cannot-mount . "You cannot move pieces on top of each other") + (move-not-legal . "That is not a legal move") + (wrong-color . "You cannot move your opponent's pieces") + (selected-empty . "You cannot select an empty square") + (piece-immobile . "That piece cannot move now"))) + (defun chess-display-select-piece () "Select the piece under the cursor. Clicking once on a piece selects it; then click on the target location." (interactive) (let ((coord (get-text-property (point) 'chess-coord)) - (position (chess-display-position nil))) + (position (chess-display-position nil)) + message) (when coord - (condition-case err - (if chess-display-last-selected - (let ((last-sel chess-display-last-selected)) - ;; if they select the same square again, just deselect it - (if (= (point) (car last-sel)) - (error "") - (let ((s-piece (chess-pos-piece position (cadr 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)))) - (error "You cannot move pieces on top of each other")) - (unless (setq ply (chess-ply-create position - (cadr last-sel) coord)) - (error "That is not a legal move")) - (chess-display-move nil ply))) - (setq chess-display-last-selected nil)) - (chess-display-assert-can-move) - (let ((piece (chess-pos-piece position coord))) - (cond - ((eq piece ? ) - (error "You cannot select an empty square")) - ((if (chess-pos-side-to-move position) - (> piece ?a) - (< piece ?a)) - (error "You cannot move your opponent's pieces"))) - (setq chess-display-last-selected (list (point) coord)) - (chess-display-highlight nil coord) - (if chess-display-highlight-legal - (chess-display-highlight-legal nil coord)))) - (error - (setq chess-display-last-selected nil) - (chess-display-update nil) - (message (error-message-string err))))))) + (setq message + (catch 'message + (if chess-display-last-selected + (let ((last-sel chess-display-last-selected)) + ;; if they select the same square again, just deselect + ;; it by redrawing the display and removing all + ;; highlights + (if (= (point) (car last-sel)) + (chess-display-update nil) + (let ((s-piece (chess-pos-piece position + (cadr 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 + (cadr last-sel) coord)) + (throw 'message (chess-string 'move-not-legal))) + (chess-display-move nil ply))) + (setq chess-display-last-selected nil)) + (chess-display-assert-can-move) + (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)) + (throw 'message (chess-string 'wrong-color))) + ((null (chess-legal-plies position :index coord)) + (throw 'message (chess-string 'piece-immobile)))) + (setq chess-display-last-selected (list (point) coord)) + (chess-display-highlight nil coord) + (if chess-display-highlight-legal + (chess-display-highlight-legal nil coord)))))) + (when message + (setq chess-display-last-selected nil) + (chess-display-update nil) + (error message))))) (defun chess-display-mouse-select-piece (event) "Select the piece the user clicked on." diff --git a/chess-engine.el b/chess-engine.el index f05ff56..3f2a8a0 100644 --- a/chess-engine.el +++ b/chess-engine.el @@ -48,6 +48,32 @@ ;; User interface ;; +(chess-message-catalog 'english + '((invalid-fen . "Received invalid FEN string: %s") + (invalid-pgn . "Received invalid PGN text") + (now-black . "Your opponent played the first move, you are now black") + (move-passed . "Your opponent has passed the move to you") + (want-to-play . "Do you wish to play a chess game against %s? ") + (want-to-play-a . "Do you wish to play a chess game against an anonymous opponent? ") + (opp-quit . "Your opponent has quit playing") + (opp-resigned . "Your opponent has resigned") + (opp-draw . "Your opponent offers a draw, accept? ") + (opp-abort . "Your opponent wants to abort this game, accept? ") + (opp-undo . "Your opponent wants to take back %d moves, accept? ") + (opp-ready . "Your opponent, %s, is now ready to play") + (opp-ready-a . "Your opponent is now ready to play") + (opp-draw-acc . "Your draw offer was accepted") + (opp-abort-acc . "Your offer to abort was accepted") + (opp-undo-acc . "Request to undo %d moves was accepted") + (opp-draw-dec . "Your draw offer was declined") + (opp-abort-dec . "Your offer to abort was declined") + (opp-undo-dec . "Your request to undo %d moves was decline") + (opp-draw-ret . "Your opponent has retracted their draw offer") + (opp-abort-ret . "Your opponent has retracted their offer to abort") + (opp-undo-ret . "Your opponent has retracted their request to undo %d moves") + (opp-illegal . "Your opponent states your last command was illegal") + (failed-start . "Failed to start chess engine process"))) + (defmacro chess-with-current-buffer (buffer &rest body) `(let ((buf ,buffer)) (if buf @@ -62,12 +88,12 @@ (defsubst chess-engine-convert-fen (fen) (or (chess-fen-to-pos fen) (ignore - (message "Received invalid FEN string: %s" fen)))) + (chess-message 'invalid-fen fen)))) (defsubst chess-engine-convert-pgn (pgn) (or (chess-pgn-to-game pgn) (ignore - (message "Received invalid PGN text")))) + (chess-message 'invalid-pgn)))) (defun chess-engine-default-handler (event &rest args) (cond @@ -81,7 +107,7 @@ (when (and (not chess-engine-inhibit-auto-pass) (chess-game-data chess-engine-game 'my-color) (= (chess-game-index chess-engine-game) 0)) - (message "Your opponent played the first move, you are now black") + (chess-message 'now-black) (chess-game-run-hooks chess-engine-game 'pass) ;; if no one else flipped my-color, we'll do it (if (chess-game-data chess-engine-game 'my-color) @@ -91,7 +117,7 @@ ((eq event 'pass) (when (chess-game-data chess-engine-game 'active) - (message "Your opponent has passed the move to you") + (chess-message 'move-passed) t)) ((eq event 'match) @@ -99,9 +125,8 @@ (chess-engine-command nil 'busy) (if (y-or-n-p (if (and (car args) (> (length (car args)) 0)) - (format "Do you wish to play a chess game against %s? " - (car args)) - (format "Do you wish to play a chess game against an anonymous opponent? "))) + (chess-string 'want-to-play (car args)) + (chess-string 'want-to-play-a))) (progn (let ((chess-engine-handling-event t)) (chess-engine-set-position nil)) @@ -130,20 +155,20 @@ t)) ((eq event 'quit) - (message "Your opponent has quit playing") + (chess-message 'opp-quit) (let ((chess-engine-handling-event t)) (chess-game-set-data chess-engine-game 'active nil)) t) ((eq event 'resign) (let ((chess-engine-handling-event t)) - (message "Your opponent has resigned") + (chess-message 'opp-resigned) (chess-game-end chess-engine-game :resign) (chess-game-set-data chess-engine-game 'active nil) t)) ((eq event 'draw) - (if (y-or-n-p "Your opponent offers a draw, accept? ") + (if (y-or-n-p (chess-string 'opp-draw)) (progn (let ((chess-engine-handling-event t)) (chess-game-end chess-engine-game :draw) @@ -153,7 +178,7 @@ t) ((eq event 'abort) - (if (y-or-n-p "Your opponent wants to abort this game, accept? ") + (if (y-or-n-p (chess-string 'opp-abort)) (progn (let ((chess-engine-handling-event t)) (chess-game-set-data chess-engine-game 'active nil)) @@ -162,9 +187,7 @@ t) ((eq event 'undo) - (if (y-or-n-p - (format "Your opponent wants to take back %d moves, accept? " - (car args))) + (if (y-or-n-p (chess-string 'opp-undo (car args))) (progn (let ((chess-engine-handling-event t)) (chess-game-undo chess-engine-game (car args))) @@ -177,25 +200,23 @@ (if (eq chess-engine-pending-offer 'match) (unless (chess-game-data chess-engine-game 'active) (if (and (car args) (> (length (car args)) 0)) - (message "Your opponent, %s, is now ready to play" - (car args)) - (message "Your opponent is now ready to play")) + (chess-message 'opp-ready (car args)) + (chess-message 'opp-ready-a)) (let ((chess-engine-handling-event t)) (chess-engine-set-position nil))) (let ((chess-engine-handling-event t)) (cond ((eq chess-engine-pending-offer 'draw) - (message "Your draw offer was accepted") + (chess-message 'opp-draw-acc) (chess-game-end chess-engine-game :draw) (chess-game-set-data chess-engine-game 'active nil)) ((eq chess-engine-pending-offer 'abort) - (message "Your offer to abort was accepted") + (chess-message 'opp-abort-acc) (chess-game-set-data chess-engine-game 'active nil)) ((eq chess-engine-pending-offer 'undo) - (message "Request to undo %d moves was accepted" - chess-engine-pending-arg) + (chess-message 'opp-undo-acc chess-engine-pending-arg) (chess-game-undo chess-engine-game (car args)))))) (setq chess-engine-pending-offer nil chess-engine-pending-arg nil) @@ -205,14 +226,13 @@ (when chess-engine-pending-offer (cond ((eq chess-engine-pending-offer 'draw) - (message "Your draw offer was declined")) + (chess-message 'opp-draw-dec)) ((eq chess-engine-pending-offer 'abort) - (message "Your offer to abort was declined")) + (chess-message 'opp-abort-dec)) ((eq chess-engine-pending-offer 'undo) - (message "Your request to undo %d moves was decline" - chess-engine-pending-arg))) + (chess-message 'opp-undo-dec chess-engine-pending-arg))) (setq chess-engine-pending-offer nil chess-engine-pending-arg nil) @@ -222,21 +242,20 @@ (when chess-engine-pending-offer (cond ((eq chess-engine-pending-offer 'draw) - (message "Your opponent has retracted their draw offer")) + (chess-message 'opp-draw-ret)) ((eq chess-engine-pending-offer 'abort) - (message "Your opponent has retracted their offer to abort")) + (chess-message 'opp-abort-ret)) ((eq chess-engine-pending-offer 'undo) - (message "Your opponent has retracted their request to undo %d moves" - chess-engine-pending-arg))) + (chess-message 'opp-undo-ret chess-engine-pending-arg))) (setq chess-engine-pending-offer nil chess-engine-pending-arg nil) t)) ((eq event 'illegal) - (message "Your opponent states your last command was illegal")))) + (chess-message 'opp-illegal)))) (defun chess-engine-create (game module &optional response-handler &rest handler-ctor-args) @@ -252,7 +271,7 @@ (chess-engine-set-game* nil game t) (when (processp proc) (unless (memq (process-status proc) '(run open)) - (error "Failed to start chess engine process")) + (chess-error 'failed-engine-start)) (setq chess-engine-process proc) (set-process-buffer proc (current-buffer)) (set-process-filter proc 'chess-engine-filter)) @@ -350,6 +369,9 @@ (chess-game-move chess-engine-game ply) (chess-engine-command engine 'move ply))) +(chess-message-catalog 'english + '((engine-not-running . "The engine you were using is no longer running"))) + (defun chess-engine-send (engine string) "Send the given STRING to ENGINE." (chess-with-current-buffer engine @@ -357,7 +379,7 @@ (if proc (if (memq (process-status proc) '(run open)) (process-send-string proc string) - (message "The engine you were using is no longer running") + (chess-message 'engine-not-running) (chess-engine-command nil 'destroy)) (chess-engine-command nil 'send string))))) @@ -367,7 +389,7 @@ (let ((proc chess-engine-process)) (when (and (processp proc) (not (memq (process-status proc) '(run open)))) - (message "The engine you were using is no longer running") + (chess-message 'engine-not-running) (chess-engine-command nil 'destroy)) (chess-engine-filter nil string)))) diff --git a/chess-game.el b/chess-game.el index 25d089d..c3d281a 100644 --- a/chess-game.el +++ b/chess-game.el @@ -163,10 +163,14 @@ matches." (let ((chess-game-inhibit-events t)) (chess-game-set-plies game (list ply)))))) +(chess-message-catalog 'english + '((undo-limit-reached . "Cannot undo further") + (add-to-completed . "Cannot add moves to a completed game"))) + (defun chess-game-undo (game count) "Undo the last COUNT plies of GAME." (if (> count (chess-game-index game)) - (error "Cannot undo further")) + (chess-error 'undo-limit-reached)) (let ((chess-game-inhibit-events t)) (chess-game-set-plies game (nbutlast (chess-game-plies game) count))) (chess-game-run-hooks game 'update)) @@ -208,7 +212,7 @@ progress (nil), if it is drawn, resigned, mate, etc." (changes (chess-ply-changes ply)) (position (chess-ply-pos ply))) (if (chess-ply-final-p current-ply) - (error "Cannot add moves to a completed game")) + (chess-error 'add-to-completed)) (assert (equal position (chess-ply-pos current-ply))) (chess-ply-set-changes current-ply changes) (chess-game-add-ply game (chess-ply-create diff --git a/chess-gnuchess.el b/chess-gnuchess.el index 8f08b3a..225ee30 100644 --- a/chess-gnuchess.el +++ b/chess-gnuchess.el @@ -29,7 +29,7 @@ (cons "Illegal move:" (function (lambda () - (error "Illegal move")))) + (chess-error 'illegal-move)))) (cons "Board is wrong!" (function (lambda () diff --git a/chess-ics.el b/chess-ics.el index 3df958c..2ca62a2 100644 --- a/chess-ics.el +++ b/chess-ics.el @@ -161,6 +161,12 @@ who is black." (funcall chess-engine-response-handler 'match (match-string 1))))))) +(chess-message-catalog 'english + '((ics-server-prompt . "Connect to chess server: ") + (ics-connecting . "Connecting to Internet Chess Server '%s'...") + (ics-connected . "Connecting to Internet Chess Server '%s'...done") + (challenge-whom . "Whom would you like challenge? "))) + (defun chess-ics-handler (event &rest args) (cond ((eq event 'initialize) @@ -169,20 +175,19 @@ who is black." (let ((server (if (= (length chess-ics-server-list) 1) (car chess-ics-server-list) - (assoc (completing-read "Connect to chess server: " + (assoc (completing-read (chess-string 'ics-server-prompt) chess-ics-server-list nil t (caar chess-ics-server-list)) chess-ics-server-list)))) - (message "Connecting to Internet Chess Server '%s'..." (car server)) + (chess-message 'ics-connecting (car server)) (let ((buf (apply 'make-comint "chess-ics" (if (nth 3 server) (cons (nth 4 server) (nth 5 server)) (list (cons (nth 0 server) (nth 1 server))))))) - (message "Connecting to Internet Chess Server '%s'...done" - (car server)) + (chess-message 'ics-connected (car server)) (display-buffer buf) (set-buffer buf) @@ -210,8 +215,9 @@ who is black." ((eq event 'match) (setq chess-engine-pending-offer 'match) - (chess-engine-send nil (format "match %s\n" - (read-string "Whom would you like challenge? ")))) + (chess-engine-send + nil (format "match %s\n" + (read-string (chess-string 'challenge-whom))))) ((eq event 'move) (unless chess-ics-ensure-ics12 diff --git a/chess-images.el b/chess-images.el index ff90c49..d8dfba9 100644 --- a/chess-images.el +++ b/chess-images.el @@ -181,9 +181,12 @@ called." (x-display-pixel-width display) (display-pixel-width)) 20))))) +(chess-message-catalog 'english + '((no-images . "Cannot find any piece images; check `chess-images-directory'"))) + (defun chess-images-popup () (unless chess-images-size - (error "Cannot find any piece images; check `chess-images-directory'")) + (chess-error 'no-images)) (if chess-images-separate-frame (let* ((size (float (+ (* (or chess-images-border-width 0) 8) (* chess-images-size 8)))) @@ -411,9 +414,13 @@ This is necessary for bizzare Emacs reasons." (create-image file nil (string-match "\\`/\\* XPM \\*/" file) :color-symbols syms)))) +(chess-message-catalog 'english + '((piece-images-loading . "Loading chess piece images...") + (piece-images-loaded . "Loading chess piece images...done"))) + (defun chess-images-init-cache () "Initialize the display image cache." - (message "Loading chess piece images...") + (chess-message 'piece-images-loading) ;; Make a vector of two vectors of 6-item vectors: each piece of ;; each color on each color square; and lastly two slots for the ;; blank squares @@ -496,7 +503,7 @@ This is necessary for bizzare Emacs reasons." chess-images-border-width) nil t :color-symbols (list (cons "background" chess-images-border-color)))))) - (message "Loading chess piece images...done")) + (chess-message 'piece-images-loaded)) (provide 'chess-images) diff --git a/chess-irc.el b/chess-irc.el index 1934037..2f284cb 100644 --- a/chess-irc.el +++ b/chess-irc.el @@ -25,13 +25,22 @@ :type 'string :group 'chess-irc) +;;; Code: + +(chess-message-catalog 'english + '((opponent-says . "Your opponent says: %s") + (irc-connecting . "Connecting to IRC server '%s:%d'...") + (irc-logging-in . "Connected, now logging in as '%s'...") + (irc-waiting . "Now waiting for 'name USER' via /msg, or `M-x chess-irc-engage'") + (irc-challenge . "IRC nick of user to challenge: "))) + (defvar chess-irc-regexp-alist (append chess-network-regexp-alist (list (cons ".+" (function (lambda () - (message "Your opponent says: %s" - (match-string 0)))))))) + (chess-message 'opponent-says + (match-string 0)))))))) (defvar chess-irc-process) (defvar chess-irc-engine) @@ -51,14 +60,13 @@ "This is an example of a generic transport engine." (cond ((eq event 'initialize) - (message "Connecting to IRC server '%s:%d'..." - chess-irc-server chess-irc-port) + (chess-message 'irc-connecting chess-irc-server chess-irc-port) (let ((engine (current-buffer)) proc) (with-current-buffer (generate-new-buffer " *chess-irc*") (setq chess-irc-engine engine proc (open-network-stream "*chess-irc*" (current-buffer) chess-irc-server chess-irc-port)) - (message "Connected, now logging in as '%s'..." chess-irc-nick) + (chess-message 'irc-logging-in chess-irc-nick) (when (and proc (eq (process-status proc) 'open)) (process-send-string proc (format "USER %s 0 * :%s\n" (user-login-name) @@ -67,12 +75,12 @@ (set-process-filter proc 'chess-irc-filter) (set-process-buffer proc (current-buffer)) (set-marker (process-mark proc) (point)) - (message "Now waiting for 'name USER' via /msg, or `M-x chess-irc-engage'"))) + (chess-message 'irc-waiting))) (setq chess-irc-process proc)) nil) ((eq event 'match) - (setq chess-irc-opponent (read-string "IRC nick of user to challenge: ")) + (setq chess-irc-opponent (read-string (chess-string 'irc-challenge))) (chess-network-handler 'match chess-irc-opponent)) ((eq event 'shutdown) diff --git a/chess-message.el b/chess-message.el new file mode 100644 index 0000000..79786ff --- /dev/null +++ b/chess-message.el @@ -0,0 +1,47 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Code shared by all chess displays +;; +;; $Revision$ + +(defgroup chess-message nil + "Support for message catalogs in chess.el." + :group 'chess) + +(defcustom chess-message-language 'english + "The language to use when reporting messages." + :type 'symbol + :group 'chess-message) + +;;; Code: + +(defvar chess-message-catalog nil) + +(defun chess-message-catalog (catalog definitions) + (let ((entry (assq catalog chess-message-catalog))) + (if entry + (dolist (def definitions) + (let ((str (assq (car def) (cdr entry)))) + (if str + (setcdr str (cdr def)) + (push def (cdr entry))))) + (push (cons catalog definitions) chess-message-catalog)))) + +(defun chess-string (key &rest arguments) + (let* ((entry (assq chess-message-language chess-message-catalog)) + (msg (and entry (cdr (assq key (cdr entry)))))) + (if msg + (apply 'format msg arguments) + "message not found"))) + +(defsubst chess-message (key &rest arguments) + (message (apply 'chess-string key arguments))) + +(defsubst chess-error (key &rest arguments) + (error (apply 'chess-string key arguments))) + +(put 'chess-message-catalog 'lisp-indent-function 1) + +(provide 'chess-message) + +;;; chess-message.el ends here diff --git a/chess-network.el b/chess-network.el index b4456d8..f44d4b0 100644 --- a/chess-network.el +++ b/chess-network.el @@ -69,13 +69,18 @@ (lambda () (funcall chess-engine-response-handler 'retract)))))) +(chess-message-catalog 'english + '((network-starting . "Starting network client/server...") + (network-waiting . "Now waiting for your opponent to connect...") + (network-connected ."You have connected; pass now or make your move."))) + (defun chess-network-handler (event &rest args) "Initialize the network chess engine." (cond ((eq event 'initialize) (let ((which (read-char "Are you the c)lient or s)erver? ")) proc) - (message "Starting network client/server...") + (chess-message 'network-starting) (setq proc (if (eq which ?s) (start-process "*chess-network*" (current-buffer) "/usr/bin/nc" @@ -84,9 +89,9 @@ (read-string "Host: ") (read-string "Port: ")))) (if (eq which ?s) - (message "Now waiting for your opponent to connect...") + (chess-message 'network-waiting) (chess-network-handler 'match) - (message "You have connected; pass now or make your move.")) + (chess-message 'network-connected)) proc)) ((eq event 'shutdown) diff --git a/chess-pgn.el b/chess-pgn.el index 9d0ebf5..67ec901 100644 --- a/chess-pgn.el +++ b/chess-pgn.el @@ -11,6 +11,10 @@ (defvar chess-pgn-fill-column 60) +(chess-message-catalog 'english + '((pgn-read-error . "Error reading move: %s") + (pgn-parse-error . "Error parsing PGN syntax"))) + (defun chess-pgn-read-plies (game position &optional top-level) (let ((plies (list t)) prevpos done) (while (not (or done (eobp))) @@ -23,7 +27,7 @@ (let* ((move (match-string 0)) (ply (chess-algebraic-to-ply position (match-string 0)))) (unless ply - (error "Error reading move: %s" move)) + (chess-error 'pgn-read-error move)) (setq position (chess-ply-next-pos ply)) (nconc plies (list ply)))) ((and top-level @@ -49,7 +53,7 @@ (looking-at ")")) (forward-char) (setq done t)) - (t (error "Error parsing PGN syntax"))) + (t (chess-error 'pgn-parse-error))) (skip-chars-forward " \t\n")) (cdr plies))) diff --git a/chess-ply.el b/chess-ply.el index 7e44a04..22e22d7 100644 --- a/chess-ply.el +++ b/chess-ply.el @@ -44,7 +44,6 @@ ;;; Code: -(require 'cl) (require 'chess-pos) (defgroup chess-ply nil @@ -158,19 +157,25 @@ maneuver." (chess-ply-create-castle position long))) (setcdr ply new-changes)))) - ;; is this a pawn move to the ultimate rank? if so, and we - ;; haven't already been told, ask for the piece to promote it to - (if (and (= piece (if color ?P ?p)) - (not (memq :promote changes)) - (= (if color 0 7) (chess-index-rank (cadr changes)))) - (let ((new-piece (completing-read - "Promote pawn to queen/rook/knight/bishop? " - chess-piece-name-table nil t "queen"))) - (setq new-piece - (cdr (assoc new-piece chess-piece-name-table))) - (if color - (setq new-piece (upcase new-piece))) - (nconc changes (list :promote new-piece)))) + (when (= piece (if color ?P ?p)) + ;; is this a pawn move to the ultimate rank? if so, and we + ;; haven't already been told, ask for the piece to promote + ;; it to + (if (and (not (memq :promote changes)) + (= (if color 0 7) (chess-index-rank (cadr changes)))) + (let ((new-piece (completing-read + "Promote pawn to queen/rook/knight/bishop? " + chess-piece-name-table nil t "queen"))) + (setq new-piece + (cdr (assoc new-piece chess-piece-name-table))) + (if color + (setq new-piece (upcase new-piece))) + (nconc changes (list :promote new-piece)))) + + ;; is this an en-passant capture? + (if (= (or (chess-pos-en-passant position) 100) + (or (chess-incr-index (cadr changes) (if color 1 -1) 0) 200)) + (nconc changes (list :en-passant)))) (unless (or (memq :check changes) (memq :checkmate changes) @@ -258,9 +263,10 @@ criteria." (let* ((piece (cadr (memq :piece keywords))) (color (if piece (< piece ?a) (chess-pos-side-to-move position))) - (test-piece (if piece (upcase piece) - (chess-pos-piece position - (cadr (memq :index keywords))))) + (test-piece + (upcase (or piece + (chess-pos-piece position + (cadr (memq :index keywords)))))) pos plies file) ;; since we're looking for moves of a particular piece, do a ;; more focused search @@ -289,12 +295,20 @@ criteria." (if (and (= (if color 6 1) (chess-index-rank candidate)) (chess-pos-piece-p position 2ahead ? )) (chess-ply--add (if color -2 2) 0))) - (if (and (setq pos (chess-incr-index candidate bias -1)) - (chess-pos-piece-p position pos (not color))) - (chess-ply--add nil nil pos)) - (if (and (setq pos (chess-incr-index candidate bias 1)) - (chess-pos-piece-p position pos (not color))) - (chess-ply--add nil nil pos)))) + (when (setq pos (chess-incr-index candidate bias -1)) + (if (chess-pos-piece-p position pos (not color)) + (chess-ply--add nil nil pos)) + ;; check for en passant capture toward queenside + (if (= (or (chess-pos-en-passant position) 100) + (or (chess-incr-index pos (if color 1 -1) 0) 200)) + (chess-ply--add nil nil pos))) + (when (setq pos (chess-incr-index candidate bias 1)) + (if (chess-pos-piece-p position pos (not color)) + (chess-ply--add nil nil pos)) + ;; check for en passant capture toward kingside + (if (= (or (chess-pos-en-passant position) 100) + (or (chess-incr-index pos (if color 1 -1) 0) 200)) + (chess-ply--add nil nil pos))))) ;; the rook, bishop and queen are the easiest; just look along ;; rank and file and/or diagonal for the nearest pieces! @@ -302,7 +316,7 @@ criteria." (dolist (dir (cond ((= test-piece ?R) '( (-1 0) - (0 -1) (0 1) + (0 -1) (0 1) (1 0))) ((= test-piece ?B) '((-1 -1) (-1 1) @@ -354,8 +368,9 @@ criteria." (chess-pos-piece-p position pos (not color)))) (chess-ply--add nil nil pos)))) - (t (error "Unrecognized piece identifier")))) - plies)))) + (t (chess-error 'piece-unrecognized)))) + + (delq nil plies))))) (provide 'chess-ply) diff --git a/chess-pos.el b/chess-pos.el index 4390072..fb8516c 100644 --- a/chess-pos.el +++ b/chess-pos.el @@ -71,6 +71,9 @@ ;;; Code: +(require 'cl) +(require 'chess-message) + (defgroup chess-pos nil "Routines for manipulating chess positions." :group 'chess) @@ -250,6 +253,9 @@ color will do." chess-pos-piece-values))))) value)) +(chess-message-catalog 'english + '((move-from-blank . "Attempted piece move from blank square %s"))) + (defun chess-pos-move (position &rest changes) "Move a piece on the POSITION directly, using the indices FROM and TO. This function does not check any rules, it only makes sure you are not @@ -263,8 +269,7 @@ trying to move a blank square." (to (cadr ch)) (piece (chess-pos-piece position from))) (if (= piece ? ) - (error "Attempted piece move from blank square %s" - (chess-index-to-coord from))) + (chess-error 'move-from-blank (chess-index-to-coord from))) (chess-pos-set-piece position from ? ) (chess-pos-set-piece position to piece)) (setq ch (cddr ch))))) @@ -272,6 +277,12 @@ trying to move a blank square." ;; now fix up the resulting position (let ((color (chess-pos-side-to-move position))) + ;; if the move was en-passant, remove the captured pawn + (if (memq :en-passant changes) + (chess-pos-set-piece position (chess-incr-index (cadr changes) + (if color 1 -1) 0) + ? )) + ;; once a piece is moved, en passant is no longer available (chess-pos-set-en-passant position nil) @@ -321,6 +332,9 @@ trying to move a blank square." ;; return the final position position)) +(chess-message-catalog 'english + '((piece-unrecognized . "Unrecognized piece identifier"))) + (defun chess-search-position (position target piece) "Look on POSITION from TARGET for a PIECE that can move there. This routine looks along legal paths of movement for PIECE. It @@ -362,11 +376,17 @@ indices which indicate where a piece may have moved from." (if (if (= p ? ) ;; check for en passant (and (= (chess-index-rank target) (if color 2 5)) - (setq pos (chess-incr-index target bias 0)) - (chess-pos-piece-p position pos (if color ?p ?P)) ;; make this fail if no en-passant is possible - (= (or (chess-pos-en-passant position) 100) target) - (setq candidates (list pos))) + (= (or (chess-pos-en-passant position) 100) + (chess-incr-index target (if color 1 -1) 0)) + (or (and (setq pos (chess-incr-index target + (if color 1 -1) -1)) + (chess-pos-piece-p position pos + (if color ?P ?p))) + (and (setq pos (chess-incr-index target + (if color 1 -1) 1)) + (chess-pos-piece-p position pos + (if color ?P ?p))))) (if color (> p ?a) (< p ?a))) (let ((cands (list t))) (setq pos (chess-incr-index target (- bias) -1)) @@ -470,7 +490,7 @@ indices which indicate where a piece may have moved from." (nconc candidates (list pos)))) (setq candidates (cdr candidates))) - (t (error "Unrecognized piece identifier"))) + (t (chess-error 'piece-unrecognized))) ;; prune from the discovered candidates list any moves which would ;; leave the king in check; castling through check has already diff --git a/chess-var.el b/chess-var.el index c33b243..f5c789a 100644 --- a/chess-var.el +++ b/chess-var.el @@ -59,9 +59,8 @@ progress (nil), if it is drawn, resigned, mate, etc." (changes (chess-ply-changes ply)) (position (chess-ply-pos ply))) (if (chess-ply-final-p current-ply) - (error "Cannot add moves to a completed game")) - (unless (equal position (chess-ply-pos current-ply)) - (error "Positions do not match")) + (chess-error 'add-to-completed)) + (assert (equal position (chess-ply-pos current-ply))) (chess-ply-set-changes current-ply changes) (chess-var-add-ply var (chess-ply-create (chess-ply-next-pos current-ply))))) @@ -111,6 +111,9 @@ minibuffer, which works well for Emacspeak users." :type 'string :group 'chess) +(chess-message-catalog 'english + '((no-images-fallback . "Could not find suitable chess images; using ics1 display"))) + ;;;###autoload (defun chess (&optional engine disable-popup engine-response-handler &rest engine-ctor-args) @@ -135,7 +138,7 @@ minibuffer, which works well for Emacspeak users." (when (and (eq chess-default-display 'chess-images) (with-current-buffer display (null chess-images-size))) - (message "Could not find suitable chess images; using ics1 display") + (chess-message 'no-images-fallback) (chess-display-destroy display) (require 'chess-ics1) (setq display (chess-display-create game 'chess-ics1 my-color))) @@ -155,7 +158,8 @@ minibuffer, which works well for Emacspeak users." ;; let them know we're ready to begin (chess-engine-command engine 'ready)) - (when chess-announce-moves + (when (and (not (eq engine-module 'chess-none)) + chess-announce-moves) (if (and (not (eq chess-announce-moves t)) (symbolp chess-announce-moves)) (let ((name (symbol-name chess-announce-moves))) |
