-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
+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.
----------------------------------------------------------------------
- BEFORE FINAL RELEASE
-
- port the code to XEmacs
- profile
- mem profile
- docstring
- texi
- elint
- checkdoc
;; chess-algebraic-regexp
;;
-(require 'chess-ply)
-
(defconst chess-algebraic-pieces-regexp "[RNBKQ]")
(defconst chess-algebraic-regexp
(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))
(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"))
(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))
(require 'chess-module)
(require 'chess-var)
-(require 'chess-algebraic)
-(require 'chess-fen)
(require 'chess-input)
(defgroup chess-display nil
(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 " "
(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)
(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."
(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)
(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
(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
(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.
(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
(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)))))
(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)
(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)
(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? ")))
;; 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.")
(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 ()
(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
(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
(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))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; 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."
((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))))
(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
;; 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))
;; game, and a list of plies representing the main variation.
(require 'chess-ply)
+(require 'chess-pgn)
(defvar chess-game-inhibit-events nil)
"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)
((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)
(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.
(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)
(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)
;;
(require 'chess-common)
-(require 'chess-fen)
-(require 'chess-algebraic)
(defvar chess-network-regexp-alist
(list
(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 ()
(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)
((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
;; 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
(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)
(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
"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)
((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 ? )
(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.
;;; Code:
(require 'chess-pos)
+(require 'chess-algebraic)
(defgroup chess-ply nil
"Routines for manipulating chess plies."
(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)
;;; Code:
-(require 'cl)
(require 'chess-message)
+(require 'chess-fen)
(defgroup chess-pos nil
"Routines for manipulating chess positions."
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 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
(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
(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)
(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)
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 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
(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."
(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)
(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)