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