diff options
| author | John Wiegley <johnw@newartisans.com> | 2002-03-01 06:17:46 +0000 |
|---|---|---|
| committer | John Wiegley <johnw@newartisans.com> | 2002-03-01 06:17:46 +0000 |
| commit | f115e4627966ae900aef55cb10f9e6207dbe7adf (patch) | |
| tree | 0718fd859aa8995889a1d7b7a5dc9007c39767df /chess-fen.el | |
Initial revision
Diffstat (limited to 'chess-fen.el')
| -rw-r--r-- | chess-fen.el | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/chess-fen.el b/chess-fen.el new file mode 100644 index 0000000..8ef7ccb --- /dev/null +++ b/chess-fen.el @@ -0,0 +1,113 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Convert a chess position to/from FEN notation +;; +;; FEN notation encodes a chess position using a simple string. The +;; format is: +;; +;; POSITION SIDE FLAGS +;; +;; The POSITION gives all eight ranks, by specifying a letter for each +;; piece on the position, and a number for any intervening spaces. +;; Trailing spaces need not be counted. Uppercase letters signify +;; white, and lowercase black. For example, if your position only had +;; a black king on d8, your POSITION string would be: +;; +;; 3k//////// +;; +;; For the three spaces (a, b and c file), the black king, and then +;; all the remaining ranks (which are all empty, so their spaces can +;; be ignored). +;; +;; The SIDE is w or b, to indicate whose move it is. +;; +;; The FLAGS can contain K, Q, k or q, to signify whether the white or +;; black king can still castle on the king or queen side. You can +;; also have coordinates, such as e4, a5, to specify which pawns may +;; be captured by en passant. +;; +;; The starting chess position always looks like this: +;; +;; rnbqkbnr/pppppppp/////PPPPPPPP/RNBQKBNR/ w KQkq - +;; +;; And in "full" mode (where all spaces are accounted for): +;; +;; rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - +;; +;; It may also have the current game sequence appended, but this +;; relate to the game, not the position. +;; +;; $Revision$ + +(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)) + (rank 0) (file 0) (c ?0) + (position (chess-pos-create t)) + number) + (while (and (/= c ? ) (< i l)) + (setq c (aref fen i)) + (cond + ((= c ?/) + (setq file 0 rank (1+ rank))) + ((and (>= c ?1) (<= c ?9)) + (setq file (+ file (- c ?0)))) + ((/= c ? ) + (chess-pos-set-piece position (chess-rf-to-index rank file) c) + (setq file (1+ file)))) + (setq i (1+ i))) + (chess-pos-set-side-to-move position (= (aref fen i) ?w)) + (setq i (+ i 2) number nil) + (while (< i l) + (setq c (aref fen i)) + (cond + ((= c ?K) (chess-pos-set-can-castle position ?K t)) + ((= c ?Q) (chess-pos-set-can-castle position ?Q t)) + ((= c ?k) (chess-pos-set-can-castle position ?k t)) + ((= c ?q) (chess-pos-set-can-castle position ?q t)) + ((and (>= c ?a) (<= c ?h)) + (chess-pos-set-en-passant position (chess-coord-to-index + (substring fen i (+ i 2)))) + (setq i (1+ i)))) + (setq i (1+ i))) + position)) + +(defun chess-pos-to-fen (position &optional full) + "Convert a chess POSITION to FEN-like notation. +If FULL is non-nil, represent trailing spaces as well." + (let ((blank 0) (str "") output) + (dotimes (rank 8) + (dotimes (file 8) + (let ((p (chess-pos-piece position (chess-rf-to-index rank file)))) + (if (= p ? ) + (setq blank (1+ blank)) + (if (> blank 0) + (setq blank 0 str (concat str (int-to-string blank)))) + (setq str (concat str (char-to-string p)))))) + (if (and full (> blank 0)) + (setq str (concat str (int-to-string blank)))) + (setq blank 0 str (concat str "/"))) + (setq str (if (chess-pos-side-to-move position) + (concat str " w ") + (concat str " b "))) + (if (chess-pos-can-castle position ?K) + (setq str (concat str "K") output t)) + (if (chess-pos-can-castle position ?Q) + (setq str (concat str "Q") output t)) + (if (chess-pos-can-castle position ?k) + (setq str (concat str "k") output t)) + (if (chess-pos-can-castle position ?q) + (setq str (concat str "q") output t)) + (if output + (setq str (concat str " ")) + (setq str (concat str "- "))) + (let ((index (chess-pos-en-passant position))) + (if index + (concat str (chess-index-to-coord index)) + (concat str "-"))))) + +(provide 'chess-fen) + +;;; chess-fen.el ends here |
