;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ICS2 style display ;; Author: Dmitry "Troydm" Geurkov (dgeurkov@gmail.com) (require 'chess-display) (require 'chess-engine) (defgroup chess-ics2 nil "The ICS2 style based on ICS1 ASCII display." :group 'chess-display) (defface chess-ics2-black-face '((((class color) (background light)) (:foreground "Black" :background "color-209")) (((class color) (background dark)) (:foreground "Black" :background "color-209")) (t (:bold t))) "*The face used for black pieces on the ASCII display." :group 'chess-ics2) (defface chess-ics2-black-face-alt '((((class color) (background light)) (:foreground "Black" :background "color-130")) (((class color) (background dark)) (:foreground "Black" :background "color-130")) (t (:bold t))) "*The alternative face used for black pieces on the ASCII display." :group 'chess-ics2) (defface chess-ics2-white-face '((((class color) (background light)) (:foreground "White" :background "color-209")) (((class color) (background dark)) (:foreground "White" :background "color-209")) (t (:bold t))) "*The face used for white pieces on the ASCII display." :group 'chess-ics2) (defface chess-ics2-white-face-alt '((((class color) (background light)) (:foreground "White" :background "color-130")) (((class color) (background dark)) (:foreground "White" :background "color-130")) (t (:bold t))) "*The alternative face used for white pieces on the ASCII display." :group 'chess-ics2) (defface chess-ics2-highlight-face '((((class color) (background light)) (:foreground "Black" :background "#add8e6")) (((class color) (background dark)) (:foreground "Black" :background "#add8e6"))) "Face to use for highlighting pieces that have been selected." :group 'chess-ics2) (defcustom chess-ics2-piece-chars '((?\040 . ?\040) (?k . ?♛) (?q . ?♚) (?r . ?♜) (?b . ?♝) (?n . ?♞) (?p . ?♟) (?K . ?♛) (?Q . ?♚) (?R . ?♜) (?B . ?♝) (?N . ?♞) (?P . ?♟)) "*Alist of pieces and their corresponding characters." :group 'chess-ics2 :type '(alist :key-type (character :tag "Internal representation") :value-type (character :tag "Printed representation"))) (defcustom chess-ics2-popup-function 'chess-ics2-popup "The function used to popup a chess-ics1 display." :type 'function :group 'chess-ics2) (defcustom chess-ics2-separate-frame nil "If non-nil, display the chessboard in its own frame." :type 'boolean :group 'chess-ics2) ;;; Code: (defun chess-ics2-handler (event &rest args) (cond ((eq event 'initialize) t) ((eq event 'popup) (funcall chess-ics2-popup-function)) ((eq event 'draw) (apply 'chess-ics2-draw args)) ((eq event 'draw-square) (apply 'chess-ics2-draw-square args)) ((eq event 'highlight) (apply 'chess-ics2-highlight args)))) (defun chess-ics2-popup () (if chess-ics2-separate-frame (chess-display-popup-in-frame 21 43 nil nil t) (chess-display-popup-in-window))) (defsubst chess-ics2-piece-text (piece rank file) (let ((p (char-to-string (cdr (assq piece chess-ics2-piece-chars)))) (a (% (+ rank file) 2))) (add-text-properties 0 1 (list 'face (if (> piece ?a) (if (= a 0) 'chess-ics2-black-face 'chess-ics2-black-face-alt) (if (= a 0) 'chess-ics2-white-face 'chess-ics2-white-face-alt))) p) p)) (defun chess-ics2-piece-text-draw (piece rank file) (insert (chess-ics2-piece-text piece rank file)) (insert (chess-ics2-piece-text ? rank file))) (defsubst chess-ics2-draw-square (pos piece index) "Draw a piece image at point on an already drawn display." (save-excursion (let ((inhibit-redisplay t)) (message (concat (int-to-string pos) " " (int-to-string index) " " (char-to-string piece))) (if (= (% (+ (/ index 8) pos) 2) 1) (goto-char pos) (goto-char (1- pos))) (delete-char 2) (insert (chess-ics2-piece-text piece (/ index 8) index)) (insert (chess-ics2-piece-text ? (/ index 8) index)) (add-text-properties pos (point) (list 'chess-coord index))))) (defun chess-ics2-draw (position perspective) "Draw the given POSITION from PERSPECTIVE's point of view. PERSPECTIVE is t for white or nil for black." (let ((inhibit-redisplay t) (pos (point))) (erase-buffer) (let* ((inverted (not perspective)) (rank (if inverted 7 0)) (file (if inverted 7 0)) beg) (insert "\n\n") (while (if inverted (>= rank 0) (< rank 8)) (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))))) (setq begin (point)) (chess-ics2-piece-text-draw piece rank file) (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)))) (if inverted (insert " h g f e d c b a\n\n") (insert " a b c d e f g h\n\n"))) (set-buffer-modified-p nil) (goto-char pos))) (defun chess-ics2-highlight (index &optional mode) (let ((pos (chess-display-index-pos nil index)) (piece (chess-pos-piece (chess-display-position nil) index))) (put-text-property pos (save-excursion (goto-char (+ pos 2)) (point)) 'face (cond ((eq mode :selected) 'chess-ics2-highlight-face) ((eq mode :unselected) (if (> piece ?a) (if (= a 0) 'chess-ics2-black-face 'chess-ics2-black-face-alt) (if (= a 0) 'chess-ics2-white-face 'chess-ics2-white-face-alt))) (t (chess-display-get-face mode)))))) (defun chess-ics2-debug-position (&optional position) "This is a debugging function, and not meant from general use." (interactive) (let ((pos (or position (chess-engine-position nil)))) (with-current-buffer (get-buffer-create "*scratch*") (chess-ics2-draw pos t) (funcall chess-ics2-popup-function)))) (provide 'chess-ics2) ;;; chess-ics2.el ends here