1 ;;; chess-eco.el --- Chess opening classification
3 ;; Copyright (C) 2004 Free Software Foundation, Inc.
5 ;; Author: Mario Lang <mlang@delysid.org>
8 ;; This file is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; This file is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GNU Emacs; see the file COPYING. If not, write to
20 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 ;; Boston, MA 02111-1307, USA.
33 (defgroup chess-eco nil
34 "Chess opening classification module."
37 (defcustom chess-eco-max-index 36
38 "*Index at which to stop chess opening announcements."
42 (defvar chess-eco-hash-table
44 (expand-file-name "chess-eco.fen"
45 (file-name-directory load-file-name)))
47 (message "Emacs Chess: Loading ECO openings database...")
48 (insert-file-contents "chess-eco.fen")
50 (let ((fen-data (read (current-buffer)))
51 (hash (make-hash-table :size 10541 :test 'equal)))
53 (puthash (car entry) (cdr entry) hash))
56 (message "Emacs Chess: Loading ECO openings database...done"))))
57 "List of well known chess opening positions.")
59 (defun chess-generate-fen-table ()
60 "Generate chess-eco.fen from the ply lists in chess-eco.pos."
64 (require 'chess-algebraic)
66 (insert-file-contents (car command-line-args-left))
67 (let ((fen-buffer (get-buffer-create "chess-eco.fen"))
68 (pos-data (read (current-buffer))))
69 (with-current-buffer fen-buffer
72 (message "Preparing opening %s (%s)"
73 (car entry) (cadr entry))
74 (let ((pos (chess-pos-create)))
76 (apply 'chess-pos-move
77 pos (chess-ply-changes
78 (chess-algebraic-to-ply pos move))))
79 (split-string (car (cddr entry)) " " t))
80 (list (chess-pos-to-fen pos) (cadr entry) (car entry))))
83 (write-file (cadr command-line-args-left))))))
85 (defvar chess-eco-last-opening nil)
86 (make-variable-buffer-local 'chess-eco-last-opening)
88 (defun chess-eco-classify (game)
89 (when chess-eco-hash-table
90 (let ((plies (chess-game-plies game))
93 (let* ((fen (chess-pos-to-fen (chess-ply-pos (car plies))))
94 (entry (gethash fen chess-eco-hash-table)))
97 (setq plies (cdr plies))))
100 (chess-message-catalog 'english
101 '((announce-opening . "%s (ECO code %s)")))
103 (defun chess-eco-handler (game event &rest args)
104 "Handle for the `chess-eco' module.
105 If you add `chess-eco' to `chess-default-modules', this handler will
106 try to figure out if the current position of a game does match a
107 well known chess opening position."
109 ((eq event 'initialize))
111 ((eq event 'post-move)
112 (when (= (chess-game-index game) 1)
113 (setq chess-eco-last-opening nil))
114 (when (< (chess-game-index game) chess-eco-max-index)
115 (let ((info (chess-eco-classify game)))
116 (when (and info (not (eq info chess-eco-last-opening)))
117 (setq chess-eco-last-opening info)
118 (chess-message 'announce-opening (car info) (cadr info))))))))
120 (defun chess-eco-parse-scid-eco ()
121 (let ((result (list t)))
122 (while (re-search-forward
123 "\\([A-E][0-9][0-9]\\([a-z][0-9]?\\)?\\) \"\\([^\"]+\\)\"[\n ]+\\([^*]*\\|\n\\) +\\*"
128 (list (match-string 1)
130 (mapconcat (lambda (move)
133 "\\(" chess-algebraic-regexp "\\)")
135 (match-string 1 move)
137 (split-string (match-string 4) "[\n ]+") " ")))))
142 ;;; chess-ecos.el ends here