This file is indexed.

/usr/share/emacs/site-lisp/chess/chess-crafty.el is in emacs-chess 2.0b6-1.1ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Play against crafty!
;;

(require 'chess-common)
(require 'chess-var)

(defgroup chess-crafty nil
  "The publically available chess engine 'crafty'."
  :group 'chess-engine)

(defcustom chess-crafty-path (or (executable-find "crafty")
				 (executable-find "wcrafty"))
  "*The path to the crafty executable."
  :type 'file
  :group 'chess-crafty)

(defvar chess-crafty-evaluation nil)

(make-variable-buffer-local 'chess-crafty-evaluation)

(defvar chess-crafty-analyzing-p nil
  "Non-nil if Crafty is currently in analysis mode.")

(make-variable-buffer-local 'chess-crafty-analyzing-p)

(defvar chess-crafty-regexp-alist
  (list
   (cons (concat "move\\s-+\\(" chess-algebraic-regexp "\\)\\s-*$")
	 (function
	  (lambda ()
	    (funcall chess-engine-response-handler 'move
		     (chess-engine-convert-algebraic (match-string 1) t)))))
   (cons "total evaluation\\.+\\s-+\\([-+0-9.]+\\)"
	 (function
	  (lambda ()
	    (setq chess-crafty-evaluation
		  (string-to-number (match-string 1))))))
   (cons "tellicsnoalias kibitz Hello from\\s-+\\(.+\\)$"
	 (function
	  (lambda ()
	    (setq chess-engine-opponent-name (match-string 1)))))
   (cons "Analyze Mode: type \"exit\" to terminate.$"
	 (function
	  (lambda ()
	    (setq chess-crafty-analyzing-p t))))
   (cons (concat "\t ?\\([0-9]+\\)\\s-+"
		 "\\(-?[0-9]+\\)\\s-+\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-+"
		 "\\(" ;; The list of moves
		   "\\( *[1-9][0-9]*\\. "
		     "\\(\\.\\.\\.\\|" chess-algebraic-regexp "\\)"
		     "\\( " chess-algebraic-regexp "\\)?\\)+\\)$")
	 (function
	  (lambda ()
	    (when chess-crafty-analyzing-p
	      ;; We can translate this information to EPD opcodes
	      (let ((depth (read (match-string 1)))
		    (centipawn (read (match-string 2)))
		    (nodes (match-string 4))
		    (pos (chess-engine-position nil)))
		(chess-pos-set-epd pos 'acd depth)
		(chess-pos-set-epd pos 'ce centipawn)
		(chess-pos-set-epd
		 pos
		 'pv ; predicted variation
		 (save-restriction
		   (narrow-to-region (match-beginning 5) (match-end 5))
		   (let ((var (chess-var-create pos)))
		     (goto-char (point-min))
		     (while (not (eobp))
		       (cond
			((looking-at "[1-9][0-9]*\\.[ .]*")
			 (goto-char (match-end 0)))
			((looking-at chess-algebraic-regexp)
			 (goto-char (match-end 0))
			 (let ((ply (chess-algebraic-to-ply
				     (chess-var-pos var)
				     (match-string-no-properties 0))))
			   (unless ply
			     (error "unable to read move '%s'"
				    (match-string-no-properties 0)))
			   (chess-var-move var ply))))
		       (skip-chars-forward " "))
		     var))))))))
   (cons "analyze complete.$"
	 (function
	  (lambda ()
	    (setq chess-crafty-analyzing-p nil))))
   (cons "{\\(Black\\|White\\) resigns}"
	 (function
	  (lambda ()
	    (funcall chess-engine-response-handler 'resign))))
   (cons "\\(Illegal move\\|unrecognized/illegal command\\):\\s-*\\(.*\\)"
	 (function
	  (lambda ()
	    (error (match-string 1)))))
   (cons "command not legal now"
	 (function
	  (lambda ()
	    (error (match-string 0)))))))

(defun chess-crafty-handler (game event &rest args)
  (unless chess-engine-handling-event
    (cond
     ((eq event 'initialize)
      (let ((proc (chess-common-handler game 'initialize "crafty")))
	(when (and proc (processp proc)
		   (eq (process-status proc) 'run))
	  (process-send-string proc "xboard\n")
	  (setq chess-engine-process proc)
	  t)))

     ((eq event 'setup-pos)
      (chess-engine-send nil (format "setboard %s\n"
				     (chess-pos-to-string (car args)))))

     ((eq event 'evaluate)
      (setq chess-crafty-evaluation nil)
      (chess-engine-send nil "display general\nscore\ndisplay nogeneral\n")
      (let ((limit 50))
	(while (and (null chess-crafty-evaluation)
		    (> (setq limit (1- limit)) 0))
	  (sit-for 0 100 t))
	chess-crafty-evaluation))

     ((eq event 'analyze)
      (if (car args)
	  (chess-engine-send nil "analyze\npost\n")
	(chess-engine-send nil "exit\nnopost\n")))

     ((eq event 'setup-game)
      (let ((file (chess-with-temp-file
		      (insert (chess-game-to-string (car args)) ?\n))))
	(chess-engine-send nil (format "read %s\n" file))))

     ((eq event 'set-option)
      (cond
       ((eq (car args) 'resign)
	(if (cadr args)
	    (chess-engine-send nil "resign 9\n")
	  (chess-engine-send nil "resign -1\n")))
       ((eq (car args) 'ponder)
	(if (cadr args)
	    (chess-engine-send nil "hard\n")
	  (chess-engine-send nil "easy\n")))
       ((eq (car args) 'search-depth)
	(assert (and (integerp (cadr args)) (>= (cadr args) 0)))
	(chess-engine-send nil (format "sd %d\n" (cadr args))))
       ((eq (car args) 'search-time)
	(assert (and (integerp (cadr args)) (> (cadr args) 0)))
	(chess-engine-send nil (format "st %d\n" (cadr args))))))

     (t
      (if (and (eq event 'undo)
	       (= 1 (mod (car args) 2)))
	  (error "Cannot undo until after crafty moves"))

      (apply 'chess-common-handler game event args)))))

(provide 'chess-crafty)

;;; chess-crafty.el ends here