;;; Code:
+(eval-when-compile (require 'cl-lib))
(require 'chess-common)
+(require 'chess-polyglot)
+
+(defgroup chess-uci nil
+ "Customisations for Chess engines based on the UCI protocol"
+ :group 'chess)
+
+(defcustom chess-uci-polyglot-book-file nil
+ "The path to a polyglot binary opening book file."
+ :group 'chess-uci
+ :type '(choice (const :tag "Not specified" nil) (file :must-match t)))
+
+(defcustom chess-uci-polyglot-book-strength 1.0
+ "Influence random distribution when picking a ply from the book.
+A value above 1.0 means to prefer known good moves while a value below
+1.0 means to penalize known good moves. 0.0 will stop to consider
+move weights and simply pick a move at random. For simple
+reasons of numerical overflow, this should be strictly less than 4.0."
+ :group 'chess-uci
+ :type '(float :match (lambda (widget value) (and (>= value 0) (< value 4)))))
+
+(defvar chess-uci-book nil
+ "A (polyglot) opening book object.
+See `chess-uci-polyglot-book-file' for details on how to enable this.")
(defvar chess-uci-long-algebraic-regexp "\\([a-h][1-8]\\)\\([a-h][1-8]\\)\\([nbrq]\\)?"
"A regular expression matching a UCI log algebraic move.")
(defun chess-uci-long-algebraic-to-ply (position move)
"Convert the long algebraic notation MOVE for POSITION to a ply."
- (assert (vectorp position))
- (assert (stringp move))
+ (cl-assert (vectorp position))
+ (cl-assert (stringp move))
(let ((case-fold-search nil))
(when (string-match chess-uci-long-algebraic-regexp move)
(let ((color (chess-pos-side-to-move position))
"Default handler for UCI based engines."
(unless chess-engine-handling-event
(cond
+ ((eq event 'initialize)
+ (when chess-uci-polyglot-book-file
+ (unless chess-uci-book
+ (setq chess-uci-book (chess-polyglot-book-open
+ chess-uci-polyglot-book-file))))
+ (apply #'chess-common-handler game event args))
+
+ ((eq event 'new)
+ (chess-engine-send nil "ucinewgame\n")
+ (chess-engine-set-position nil))
+
+ ((eq event 'resign)
+ (chess-game-set-data game 'active nil))
+
((eq event 'move)
(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-uci-position game) "go\n"))
(if (chess-game-over-p game)
(chess-game-set-data game 'active nil)))
+ ((eq event 'post-move)
+ (let ((book-ply (and chess-uci-book (bufferp chess-uci-book)
+ (buffer-live-p chess-uci-book)
+ (chess-polyglot-book-ply
+ chess-uci-book
+ (chess-game-pos game)
+ chess-uci-polyglot-book-strength))))
+ (if book-ply
+ (let ((chess-display-handling-event nil))
+ (funcall chess-engine-response-handler 'move book-ply))
+ (chess-engine-send nil (concat (chess-uci-position game) "go\n")))))
+
(t
(apply 'chess-common-handler game event args)))))