From bc1b6e4f3789f4401ac5fe9bb9708459648345b0 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 3 Apr 2002 02:11:46 +0000 Subject: More work to get engines working. --- chess-ascii.el | 206 ------------------------------------------------------ chess-crafty.el | 15 ++-- chess-display.el | 17 +++-- chess-engine.el | 5 ++ chess-game.el | 17 +++-- chess-gnuchess.el | 47 +++++++++++++ chess-ics1.el | 74 ++++++++++++++++++++ chess-images.el | 2 +- chess-plain.el | 134 +++++++++++++++++++++++++++++++++++ chess.el | 18 +++-- 10 files changed, 302 insertions(+), 233 deletions(-) delete mode 100644 chess-ascii.el create mode 100644 chess-gnuchess.el create mode 100644 chess-ics1.el create mode 100644 chess-plain.el diff --git a/chess-ascii.el b/chess-ascii.el deleted file mode 100644 index 63a3d0e..0000000 --- a/chess-ascii.el +++ /dev/null @@ -1,206 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; ASCII chess displays -;; -;; $Revision$ - -(require 'chess-display) - -(defgroup chess-ascii nil - "A set of ASCII chess displays: ics1, plain. -`ICS1' is similar to what is used by Internet chess servers. -`plain' is uses a minimum number of chars, with an optional border -and customizable piece characters." - :group 'chess-display) - -;;; Code: - -;;; ICS1 style display - -(defun chess-ics1-draw () - "Draw the given POSITION from PERSPECTIVE's point of view. -PERSPECTIVE is t for white or nil for black." - (if (null (get-buffer-window (current-buffer) t)) - (pop-to-buffer (current-buffer))) - (let ((inhibit-redisplay t) - (pos (point))) - (erase-buffer) - (let* ((position (chess-display-position nil)) - (inverted (null (chess-display-perspective nil))) - (rank (if inverted 7 0)) - (file (if inverted 7 0)) - beg) - (insert "\n +---+---+---+---+---+---+---+---+\n") - (while (if inverted (>= rank 0) (< rank 8)) - (if (/= rank (if inverted 7 0)) - (insert " +---+---+---+---+---+---+---+---+\n")) - (while (if inverted (>= file 0) (< file 8)) - (let ((piece (chess-pos-piece position - (chess-rf-to-index rank file))) - begin) - (if (= file (if inverted 7 0)) - (insert (format " %d " (1+ (- 7 rank))))) - (insert "| ") - (setq begin (1- (point))) - (if (and chess-display-use-faces (/= ? piece)) - (let ((p (char-to-string piece))) - (add-text-properties - 0 1 (list 'face (if (> piece ?a) - 'chess-display-black-face - 'chess-display-white-face)) p) - (insert p)) - (insert piece)) - (insert ? ) - (add-text-properties begin (point) - (list 'chess-coord - (chess-rf-to-index rank file)))) - (setq file (if inverted (1- file) (1+ file)))) - (insert "|\n") - (setq file (if inverted 7 0) - rank (if inverted (1- rank) (1+ rank)))) - (insert " +---+---+---+---+---+---+---+---+\n") - (if inverted - (insert " h g f e d c b a\n") - (insert " a b c d e f g h\n"))) - (set-buffer-modified-p nil) - (goto-char pos))) - -(defun chess-ics1-highlight (index &optional mode) - (if (null (get-buffer-window (current-buffer) t)) - (pop-to-buffer (current-buffer))) - (let (beg end) - (save-excursion - (beginning-of-line) - (goto-line (+ 2 (chess-index-rank index))) - (forward-char (+ 8 (* 4 (chess-index-file index)))) - (skip-chars-backward "^|") - (setq beg (point)) - (skip-chars-forward "^|") - (put-text-property beg (point) 'face 'chess-display-highlight-face)))) - -;; Plain display - -(defgroup chess-plain nil - "A minimal, customizable ASCII display." - :group 'chess-ascii) - -(defcustom chess-plain-draw-border nil - "*Non-nil if a border should be drawn (using `chess-plain-border-chars')." - :group 'chess-plain - :type 'boolean) - -(defcustom chess-plain-border-chars '(?+ ?- ?+ ?| ?| ?+ ?- ?+) - "*Characters used to draw borders." - :group 'chess-plain - :type '(list character character character character - character character character character)) - -(defcustom chess-plain-black-square-char ?. - "*Character used to indicate black squares." - :group 'chess-plain - :type 'character) - -(defcustom chess-plain-white-square-char ?. - "*Character used to indicate white squares." - :group 'chess-plain - :type 'character) - -(defcustom chess-plain-piece-chars - '((?K . ?K) - (?Q . ?Q) - (?R . ?R) - (?B . ?B) - (?N . ?N) - (?P . ?P) - (?k . ?k) - (?q . ?q) - (?r . ?r) - (?b . ?b) - (?n . ?n) - (?p . ?p)) - "*Alist of pieces and their corresponding characters." - :group 'chess-plain - :type '(alist :key-type character :value-type character)) - -(defcustom chess-plain-upcase-indicates 'color - "*Defines what a upcase char should indicate. -The default is 'color, meaning a upcase char is a white piece, a -lowercase char a black piece. Possible values: 'color (default), -'square-color. If set to 'square-color, a uppercase character -indicates a piece on a black square. (Note that you also need to -modify `chess-plain-piece-chars' to avoid real confusion.)" - :group 'chess-plain - :type '(choice (const 'color) (const 'square-color))) - ;; fails somehow - -(defun chess-plain-draw () - "Draw the given POSITION from PERSPECTIVE's point of view. -PERSPECTIVE is t for white or nil for black." - (if (null (get-buffer-window (current-buffer) t)) - (pop-to-buffer (current-buffer))) - (let ((inhibit-redisplay t) - (pos (point))) - (erase-buffer) - (let* ((position (chess-display-position nil)) - (inverted (null (chess-display-perspective nil))) - (rank (if inverted 7 0)) - (file (if inverted 7 0)) - beg) - (if chess-plain-draw-border - (insert ? (nth 0 chess-plain-border-chars) - (make-string 8 (nth 1 chess-plain-border-chars)) - (nth 2 chess-plain-border-chars) ?\n)) - (while (if inverted (>= rank 0) (< rank 8)) - (if chess-plain-border-chars - (insert (number-to-string (- 8 rank)) - (nth 3 chess-plain-border-chars))) - (while (if inverted (>= file 0) (< file 8)) - (let ((piece (chess-pos-piece position - (chess-rf-to-index rank file))) - (white-square (evenp (+ file rank))) - (begin (point))) - (insert (if (eq piece ? ) - (if white-square - chess-plain-white-square-char - chess-plain-black-square-char) - (let ((what chess-plain-upcase-indicates) - (pchar (cdr (assq piece chess-plain-piece-chars)))) - (cond - ((eq what 'square-color) - (if white-square - (downcase pchar) - (upcase pchar))) - (t pchar))))) - (add-text-properties begin (point) - (list 'chess-coord - (chess-rf-to-index rank file)))) - (setq file (if inverted (1- file) (1+ file)))) - (if chess-plain-draw-border - (insert (nth 4 chess-plain-border-chars) ?\n)) - (setq file (if inverted 7 0) - rank (if inverted (1- rank) (1+ rank)))) - (if chess-plain-draw-border - (insert ? (nth 5 chess-plain-border-chars) - (make-string 8 (nth 6 chess-plain-border-chars)) - (nth 7 chess-plain-border-chars) ?\n - ? ? (if (not inverted) "abcdefgh" "hgfedcba"))) - (set-buffer-modified-p nil) - (goto-char pos)))) - -(defun chess-plain-highlight (index &optional mode) - (if (null (get-buffer-window (current-buffer) t)) - (pop-to-buffer (current-buffer))) - (save-excursion - (beginning-of-line) - (goto-line (if chess-plain-draw-border - (+ 2 (chess-index-rank index)) - (1+ (chess-index-rank index)))) - (forward-char (if chess-plain-draw-border - (1+ (chess-index-file index)) - (chess-index-file index))) - (put-text-property (point) (1+ (point)) 'face - 'chess-display-highlight-face))) - -(provide 'chess-ascii) - -;;; chess-ascii.el ends here diff --git a/chess-crafty.el b/chess-crafty.el index 5418d36..d9038db 100644 --- a/chess-crafty.el +++ b/chess-crafty.el @@ -56,14 +56,11 @@ ((eq event 'pass) (chess-engine-send nil "go\n")) ((eq event 'move) - (cond - ((chess-engine-game nil) - (chess-game-move (chess-engine-game nil) (car args))) - (t - (apply 'chess-pos-move (car args)))) - (chess-engine-send nil (concat (chess-ply-to-algebraic - (car args) nil - (chess-engine-search-function nil)) - "\n"))))) + (chess-engine-send + nil (concat (chess-ply-to-algebraic + (car args) nil + (chess-engine-search-function nil)) "\n"))))) + +(provide 'chess-crafty) ;;; chess-crafty.el ends here diff --git a/chess-display.el b/chess-display.el index 58658ec..4e18130 100644 --- a/chess-display.el +++ b/chess-display.el @@ -57,6 +57,7 @@ (defvar chess-display-perspective) (defvar chess-display-draw-function nil) (defvar chess-display-highlight-function nil) +(defvar chess-display-edit-mode nil) (defvar chess-display-mode-line "") (make-variable-buffer-local 'chess-display-session) @@ -69,6 +70,7 @@ (make-variable-buffer-local 'chess-display-perspective) (make-variable-buffer-local 'chess-display-draw-function) (make-variable-buffer-local 'chess-display-highlight-function) +(make-variable-buffer-local 'chess-display-edit-mode) (make-variable-buffer-local 'chess-display-mode-line) (defmacro chess-with-current-buffer (buffer &rest body) @@ -80,9 +82,12 @@ (defun chess-display-create (style perspective &optional session search-func) "Create a chess display, for displaying chess objects." - (let ((draw (intern-soft (concat (symbol-name style) "-draw"))) - (highlight (intern-soft (concat (symbol-name style) "-highlight"))) - (initialize (intern-soft (concat (symbol-name style) "-initialize")))) + (let* ((name (symbol-name style)) + (draw (intern-soft (concat name "-draw"))) + (highlight (intern-soft (concat name "-highlight"))) + (initialize (intern-soft (concat name "-initialize")))) + (unless initialize + (error "There is no known chessboard display style '%s'" name)) (with-current-buffer (generate-new-buffer "*Chessboard*") (setq cursor-type nil chess-display-session session @@ -277,7 +282,9 @@ If only START is given, it must be in algebraic move notation." ;; game, or alter the game, just as SCID allows (unless (= (chess-display-index nil) (chess-game-index chess-display-game)) - (error "Cannot move partway in a game")) + (error "Cannot move partway in game (index %d != game index %d)" + (chess-display-index nil) + (chess-game-index chess-display-game))) (chess-game-move chess-display-game ply)) (chess-display-variation (nconc chess-display-variation (list ply))) @@ -429,7 +436,7 @@ that game (i.e., not editing the position, or reviewing an earlier position within the game)." (and chess-display-session chess-display-game - (= (chess-display index nil) + (= (chess-display-index nil) (chess-game-index chess-display-game)) (not chess-display-edit-mode))) diff --git a/chess-engine.el b/chess-engine.el index 3bbfb91..678f5c3 100644 --- a/chess-engine.el +++ b/chess-engine.el @@ -139,6 +139,11 @@ (defun chess-engine-move (engine ply) (chess-with-current-buffer engine + (cond + (chess-engine-game + (chess-game-move chess-engine-game ply)) + (chess-engine-position + (apply 'chess-pos-move ply))) (chess-engine-command engine 'move ply))) (defun chess-engine-pass (engine ply) diff --git a/chess-game.el b/chess-game.el index 1177b18..b321bd1 100644 --- a/chess-game.el +++ b/chess-game.el @@ -86,11 +86,14 @@ (nth index (chess-game-plies game)) (car (last (chess-game-plies game))))) -(defsubst chess-game-add-ply (game ply) +(defun chess-game-add-ply (game ply) "Return the position related to GAME's INDEX position." - (nconc (chess-game-plies game) (list ply))) + (let ((plies (chess-game-plies game))) + (if plies + (nconc plies (list ply)) + (chess-game-set-plies game (list ply))))) -(defun chess-game-pos (game &optional index) +(defsubst chess-game-pos (game &optional index) "Return the position related to GAME's INDEX position." (car (chess-game-ply game index))) @@ -102,13 +105,15 @@ SEARCH-FUNC specifies the function used to test the legality of moves. TAGS is the starting set of game tags (which can always be changed later using the various tag-related methods)." (let ((game (list tags - (or search-func 'chess-standard-search-position) - (or position (chess-pos-create))))) + (or search-func 'chess-standard-search-position)))) (dolist (tag (cons (cons "Date" (format-time-string "%Y.%m.%d")) chess-game-default-tags)) (unless (chess-game-tag game (car tag)) (chess-game-set-tag game (car tag) (cdr tag)))) - (chess-game-add-ply game (chess-ply-create (or position (chess-pos-create)))) + (chess-game-add-ply game (chess-ply-create + (or (and position + (chess-pos-copy position)) + (chess-pos-create)))) (if position (chess-game-set-tag game "FEN" (chess-pos-to-fen position))) game)) diff --git a/chess-gnuchess.el b/chess-gnuchess.el new file mode 100644 index 0000000..4598020 --- /dev/null +++ b/chess-gnuchess.el @@ -0,0 +1,47 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Play against gnuchess! +;; +;; $Revision$ + +(require 'chess-engine) +(require 'chess-fen) +(require 'chess-algebraic) + +(defvar chess-gnuchess-regexp-alist + (list (cons (concat "My move is : \\(" chess-algebraic-regexp "\\)") + (function + (lambda () + (funcall chess-engine-response-handler 'move + (chess-algebraic-to-ply position + (match-string 1)))))) + (cons "Illegal move:" + (function + (lambda () + (signal 'chess-illegal "Illegal move")))))) + +(defun chess-gnuchess-handler (event &rest args) + (cond + ((eq event 'initialize) + (let (proc) + (message "Starting chess program 'gnuchess'...") + (setq proc (start-process "chess-process" (current-buffer) + (executable-find "gnuchess"))) + (message "Starting chess program 'gnuchess'...done") + proc)) + ((eq event 'shutdown) + (chess-engine-send nil "quit\n")) + ((eq event 'setup) + (chess-engine-send nil (format "setboard %s\n" + (chess-pos-to-fen (car args))))) + ((eq event 'pass) + (chess-engine-send nil "go\n")) + ((eq event 'move) + (chess-engine-send + nil (concat (chess-ply-to-algebraic + (car args) nil + (chess-engine-search-function nil)) "\n"))))) + +(provide 'chess-gnuchess) + +;;; chess-gnuchess.el ends here diff --git a/chess-ics1.el b/chess-ics1.el new file mode 100644 index 0000000..33e0a75 --- /dev/null +++ b/chess-ics1.el @@ -0,0 +1,74 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; ICS1 style display +;; +;; $Revision$ + +(require 'chess-display) + +;;; Code: + +(defun chess-ics1-draw (&optional disppos) + "Draw the given POSITION from PERSPECTIVE's point of view. +PERSPECTIVE is t for white or nil for black." + (if (null (get-buffer-window (current-buffer) t)) + (pop-to-buffer (current-buffer))) + (let ((inhibit-redisplay t) + (pos (point))) + (erase-buffer) + (let* ((position (or disppos (chess-display-position nil))) + (inverted (null (chess-display-perspective nil))) + (rank (if inverted 7 0)) + (file (if inverted 7 0)) + beg) + (insert "\n +---+---+---+---+---+---+---+---+\n") + (while (if inverted (>= rank 0) (< rank 8)) + (if (/= rank (if inverted 7 0)) + (insert " +---+---+---+---+---+---+---+---+\n")) + (while (if inverted (>= file 0) (< file 8)) + (let ((piece (chess-pos-piece position + (chess-rf-to-index rank file))) + begin) + (if (= file (if inverted 7 0)) + (insert (format " %d " (1+ (- 7 rank))))) + (insert "| ") + (setq begin (1- (point))) + (if (and chess-display-use-faces (/= ? piece)) + (let ((p (char-to-string piece))) + (add-text-properties + 0 1 (list 'face (if (> piece ?a) + 'chess-display-black-face + 'chess-display-white-face)) p) + (insert p)) + (insert piece)) + (insert ? ) + (add-text-properties begin (point) + (list 'chess-coord + (chess-rf-to-index rank file)))) + (setq file (if inverted (1- file) (1+ file)))) + (insert "|\n") + (setq file (if inverted 7 0) + rank (if inverted (1- rank) (1+ rank)))) + (insert " +---+---+---+---+---+---+---+---+\n") + (if inverted + (insert " h g f e d c b a\n") + (insert " a b c d e f g h\n"))) + (set-buffer-modified-p nil) + (goto-char pos))) + +(defun chess-ics1-highlight (index &optional mode) + (if (null (get-buffer-window (current-buffer) t)) + (pop-to-buffer (current-buffer))) + (let (beg end) + (save-excursion + (beginning-of-line) + (goto-line (+ 2 (chess-index-rank index))) + (forward-char (+ 8 (* 4 (chess-index-file index)))) + (skip-chars-backward "^|") + (setq beg (point)) + (skip-chars-forward "^|") + (put-text-property beg (point) 'face 'chess-display-highlight-face)))) + +(provide 'chess-ics1) + +;;; chess-ics1.el ends here diff --git a/chess-images.el b/chess-images.el index b0d972e..eb47d02 100644 --- a/chess-images.el +++ b/chess-images.el @@ -1,6 +1,6 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; -;; Display a chessboard using graphical images +;; Chessboard display style using graphical images ;; ;; $Revision$ diff --git a/chess-plain.el b/chess-plain.el new file mode 100644 index 0000000..c067664 --- /dev/null +++ b/chess-plain.el @@ -0,0 +1,134 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Plain ASCII chess display +;; +;; $Revision$ + +(require 'chess-display) + +;;; Code: + +(defgroup chess-plain nil + "A minimal, customizable ASCII display." + :group 'chess-ascii) + +(defcustom chess-plain-draw-border nil + "*Non-nil if a border should be drawn (using `chess-plain-border-chars')." + :group 'chess-plain + :type 'boolean) + +(defcustom chess-plain-border-chars '(?+ ?- ?+ ?| ?| ?+ ?- ?+) + "*Characters used to draw borders." + :group 'chess-plain + :type '(list character character character character + character character character character)) + +(defcustom chess-plain-black-square-char ?. + "*Character used to indicate black squares." + :group 'chess-plain + :type 'character) + +(defcustom chess-plain-white-square-char ?. + "*Character used to indicate white squares." + :group 'chess-plain + :type 'character) + +(defcustom chess-plain-piece-chars + '((?K . ?K) + (?Q . ?Q) + (?R . ?R) + (?B . ?B) + (?N . ?N) + (?P . ?P) + (?k . ?k) + (?q . ?q) + (?r . ?r) + (?b . ?b) + (?n . ?n) + (?p . ?p)) + "*Alist of pieces and their corresponding characters." + :group 'chess-plain + :type '(alist :key-type character :value-type character)) + +(defcustom chess-plain-upcase-indicates 'color + "*Defines what a upcase char should indicate. +The default is 'color, meaning a upcase char is a white piece, a +lowercase char a black piece. Possible values: 'color (default), +'square-color. If set to 'square-color, a uppercase character +indicates a piece on a black square. (Note that you also need to +modify `chess-plain-piece-chars' to avoid real confusion.)" + :group 'chess-plain + :type '(choice (const 'color) (const 'square-color))) + ;; fails somehow + +(defun chess-plain-draw () + "Draw the given POSITION from PERSPECTIVE's point of view. +PERSPECTIVE is t for white or nil for black." + (if (null (get-buffer-window (current-buffer) t)) + (pop-to-buffer (current-buffer))) + (let ((inhibit-redisplay t) + (pos (point))) + (erase-buffer) + (let* ((position (chess-display-position nil)) + (inverted (null (chess-display-perspective nil))) + (rank (if inverted 7 0)) + (file (if inverted 7 0)) + beg) + (if chess-plain-draw-border + (insert ? (nth 0 chess-plain-border-chars) + (make-string 8 (nth 1 chess-plain-border-chars)) + (nth 2 chess-plain-border-chars) ?\n)) + (while (if inverted (>= rank 0) (< rank 8)) + (if chess-plain-border-chars + (insert (number-to-string (- 8 rank)) + (nth 3 chess-plain-border-chars))) + (while (if inverted (>= file 0) (< file 8)) + (let ((piece (chess-pos-piece position + (chess-rf-to-index rank file))) + (white-square (evenp (+ file rank))) + (begin (point))) + (insert (if (eq piece ? ) + (if white-square + chess-plain-white-square-char + chess-plain-black-square-char) + (let ((what chess-plain-upcase-indicates) + (pchar (cdr (assq piece chess-plain-piece-chars)))) + (cond + ((eq what 'square-color) + (if white-square + (downcase pchar) + (upcase pchar))) + (t pchar))))) + (add-text-properties begin (point) + (list 'chess-coord + (chess-rf-to-index rank file)))) + (setq file (if inverted (1- file) (1+ file)))) + (if chess-plain-draw-border + (insert (nth 4 chess-plain-border-chars) ?\n)) + (setq file (if inverted 7 0) + rank (if inverted (1- rank) (1+ rank)))) + (if chess-plain-draw-border + (insert ? (nth 5 chess-plain-border-chars) + (make-string 8 (nth 6 chess-plain-border-chars)) + (nth 7 chess-plain-border-chars) ?\n + ? ? (if (not inverted) "abcdefgh" "hgfedcba"))) + (set-buffer-modified-p nil) + (goto-char pos)))) + +(defun chess-plain-highlight (index &optional mode) + (if (null (get-buffer-window (current-buffer) t)) + (pop-to-buffer (current-buffer))) + (save-excursion + (beginning-of-line) + (goto-line (if chess-plain-draw-border + (+ 2 (chess-index-rank index)) + (1+ (chess-index-rank index)))) + (forward-char (if chess-plain-draw-border + (1+ (chess-index-file index)) + (chess-index-file index))) + (put-text-property (point) (1+ (point)) 'face + 'chess-display-highlight-face))) + +(provide 'chess-plain) + +;;; chess-plain.el ends here diff --git a/chess.el b/chess.el index 31e0bd3..0710dc9 100644 --- a/chess.el +++ b/chess.el @@ -75,6 +75,8 @@ a0 243 ;;; Code: (require 'chess-session) +(require 'chess-game) +(require 'chess-display) (require 'chess-pgn) (defgroup chess nil @@ -103,20 +105,24 @@ a0 243 ;; setup `chess-handler' to receive all events first (chess-session-add-listener session 'chess-handler) (chess-session-set-data session 'my-color perspective) - ;; unless prefix arg is given, use `chess-default-engine' to play - ;; against; otherwise, just create a board for play between two - ;; people - (unless arg - (chess-session-add-listener session chess-default-engine)) ;; initialize all of the modules, and setup a new game (chess-session-event session 'initialize) (chess-session-event session 'setup (chess-game-create)) ;; create a display object linked to the session, and add it to ;; the event chain; it is via this object that session events will ;; for the most part be generated + (require chess-default-display) (chess-session-add-listener session 'chess-display nil (chess-display-create chess-default-display - perspective session)))) + perspective session)) + ;; unless prefix arg is given, use `chess-default-engine' to play + ;; against; otherwise, just create a board for play between two + ;; people + (unless arg + (require chess-default-engine) + (chess-session-add-listener session 'chess-engine nil + (chess-engine-create chess-default-engine + nil session))))) (defun chess-handler (session window-config event &rest args) "React to changes on the chess board in a global Emacs way." -- cgit v1.2.3