gamegrid.el 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. ;;; gamegrid.el --- library for implementing grid-based games on Emacs
  2. ;; Copyright (C) 1997-1998, 2001-2012 Free Software Foundation, Inc.
  3. ;; Author: Glynn Clements <glynn@sensei.co.uk>
  4. ;; Version: 1.02
  5. ;; Created: 1997-08-13
  6. ;; Keywords: games
  7. ;; This file is part of GNU Emacs.
  8. ;; GNU Emacs 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 3 of the License, or
  11. ;; (at your option) any later version.
  12. ;; GNU Emacs is distributed in the hope that it will be useful,
  13. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;; GNU General Public License for more details.
  16. ;; You should have received a copy of the GNU General Public License
  17. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  18. ;;; Commentary:
  19. ;;; Code:
  20. (eval-when-compile
  21. (require 'cl))
  22. ;; ;;;;;;;;;;;;; buffer-local variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  23. (defvar gamegrid-use-glyphs t
  24. "Non-nil means use glyphs when available.")
  25. (defvar gamegrid-use-color t
  26. "Non-nil means use color when available.")
  27. (defvar gamegrid-font "-*-courier-medium-r-*-*-*-140-100-75-*-*-iso8859-*"
  28. "Name of the font used in X mode.")
  29. (defvar gamegrid-face nil
  30. "Indicates the face to use as a default.")
  31. (make-variable-buffer-local 'gamegrid-face)
  32. (defvar gamegrid-display-options nil)
  33. (defvar gamegrid-buffer-width 0)
  34. (defvar gamegrid-buffer-height 0)
  35. (defvar gamegrid-blank 0)
  36. (defvar gamegrid-timer nil)
  37. (defvar gamegrid-display-mode nil)
  38. (defvar gamegrid-display-table)
  39. (defvar gamegrid-face-table nil)
  40. (defvar gamegrid-buffer-start 1)
  41. (defvar gamegrid-score-file-length 50
  42. "Number of high scores to keep.")
  43. (defvar gamegrid-user-score-file-directory
  44. (locate-user-emacs-file "games/")
  45. "A directory for game scores which can't be shared.
  46. If Emacs was built without support for shared game scores, then this
  47. directory will be used.")
  48. (make-variable-buffer-local 'gamegrid-use-glyphs)
  49. (make-variable-buffer-local 'gamegrid-use-color)
  50. (make-variable-buffer-local 'gamegrid-font)
  51. (make-variable-buffer-local 'gamegrid-display-options)
  52. (make-variable-buffer-local 'gamegrid-buffer-width)
  53. (make-variable-buffer-local 'gamegrid-buffer-height)
  54. (make-variable-buffer-local 'gamegrid-blank)
  55. (make-variable-buffer-local 'gamegrid-timer)
  56. (make-variable-buffer-local 'gamegrid-display-mode)
  57. (make-variable-buffer-local 'gamegrid-display-table)
  58. (make-variable-buffer-local 'gamegrid-face-table)
  59. (make-variable-buffer-local 'gamegrid-buffer-start)
  60. (make-variable-buffer-local 'gamegrid-score-file-length)
  61. ;; ;;;;;;;;;;;;; global variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  62. (defvar gamegrid-grid-x-face nil)
  63. (defvar gamegrid-mono-x-face nil)
  64. (defvar gamegrid-mono-tty-face nil)
  65. ;; ;;;;;;;;;;;;; constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  66. (defconst gamegrid-glyph-height 16)
  67. (defconst gamegrid-xpm "\
  68. /* XPM */
  69. static char *noname[] = {
  70. /* width height ncolors chars_per_pixel */
  71. \"16 16 3 1\",
  72. /* colors */
  73. \"+ s col1\",
  74. \". s col2\",
  75. \"- s col3\",
  76. /* pixels */
  77. \"---------------+\",
  78. \"--------------++\",
  79. \"--............++\",
  80. \"--............++\",
  81. \"--............++\",
  82. \"--............++\",
  83. \"--............++\",
  84. \"--............++\",
  85. \"--............++\",
  86. \"--............++\",
  87. \"--............++\",
  88. \"--............++\",
  89. \"--............++\",
  90. \"--............++\",
  91. \"-+++++++++++++++\",
  92. \"++++++++++++++++\"
  93. };
  94. "
  95. "XPM format image used for each square")
  96. (defvar gamegrid-xbm "\
  97. /* gamegrid XBM */
  98. #define gamegrid_width 16
  99. #define gamegrid_height 16
  100. static unsigned char gamegrid_bits[] = {
  101. 0xff, 0xff, 0xff, 0x7f, 0xff, 0x3f, 0xaf, 0x0a, 0x57, 0x15, 0xaf, 0x0a,
  102. 0x57, 0x15, 0xaf, 0x0a, 0x57, 0x15, 0xaf, 0x0a, 0x57, 0x15, 0xaf, 0x0a,
  103. 0x57, 0x15, 0x07, 0x00, 0x03, 0x00, 0x01, 0x00 };"
  104. "XBM format image used for each square.")
  105. ;; ;;;;;;;;;;;;;;;; miscellaneous functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  106. (defsubst gamegrid-characterp (arg)
  107. (if (fboundp 'characterp)
  108. (characterp arg)
  109. (integerp arg)))
  110. (defsubst gamegrid-event-x (event)
  111. (if (fboundp 'event-x)
  112. (event-x event)
  113. (car (posn-col-row (event-end event)))))
  114. (defsubst gamegrid-event-y (event)
  115. (if (fboundp 'event-y)
  116. (event-y event)
  117. (cdr (posn-col-row (event-end event)))))
  118. ;; ;;;;;;;;;;;;; display functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  119. (defun gamegrid-color (color shade)
  120. (let* ((v (floor (* shade 255)))
  121. (r (* v (aref color 0)))
  122. (g (* v (aref color 1)))
  123. (b (* v (aref color 2))))
  124. (format "#%02x%02x%02x" r g b)))
  125. (defun gamegrid-set-font (face)
  126. (if gamegrid-font
  127. (condition-case nil
  128. (set-face-font face gamegrid-font)
  129. (error nil))))
  130. (defun gamegrid-setup-face (face color)
  131. (set-face-foreground face color)
  132. (set-face-background face color)
  133. (gamegrid-set-font face)
  134. (condition-case nil
  135. (set-face-background-pixmap face [nothing]);; XEmacs
  136. (error nil))
  137. (condition-case nil
  138. (set-face-background-pixmap face nil);; Emacs
  139. (error nil)))
  140. (defun gamegrid-make-mono-tty-face ()
  141. (let ((face (make-face 'gamegrid-mono-tty-face)))
  142. (set-face-inverse-video-p face t)
  143. face))
  144. (defun gamegrid-make-color-tty-face (color)
  145. (let* ((color-str (if (symbolp color) (symbol-value color) color))
  146. (name (intern (format "gamegrid-color-tty-face-%s" color-str)))
  147. (face (make-face name)))
  148. (gamegrid-setup-face face color-str)
  149. face))
  150. (defun gamegrid-make-grid-x-face ()
  151. (let ((face (make-face 'gamegrid-x-border-face)))
  152. (gamegrid-set-font face)
  153. face))
  154. (defun gamegrid-make-mono-x-face ()
  155. (let ((face (make-face 'gamegrid-mono-x-face))
  156. (color (face-foreground 'default)))
  157. (if (null color)
  158. (setq color
  159. (cdr-safe (assq 'foreground-color (frame-parameters)))))
  160. (gamegrid-setup-face face color)
  161. face))
  162. (defun gamegrid-make-color-x-face (color)
  163. (let* ((hex (gamegrid-color color 1.0))
  164. (name (intern (format "gamegrid-color-x-face-%s" hex)))
  165. (face (make-face name)))
  166. (gamegrid-setup-face face hex)
  167. face))
  168. (defun gamegrid-make-face (data-spec-list color-spec-list)
  169. (let ((data (gamegrid-match-spec-list data-spec-list))
  170. (color (gamegrid-match-spec-list color-spec-list)))
  171. (case data
  172. (color-x
  173. (gamegrid-make-color-x-face color))
  174. (grid-x
  175. (unless gamegrid-grid-x-face
  176. (setq gamegrid-grid-x-face (gamegrid-make-grid-x-face)))
  177. gamegrid-grid-x-face)
  178. (mono-x
  179. (unless gamegrid-mono-x-face
  180. (setq gamegrid-mono-x-face (gamegrid-make-mono-x-face)))
  181. gamegrid-mono-x-face)
  182. (color-tty
  183. (gamegrid-make-color-tty-face color))
  184. (mono-tty
  185. (unless gamegrid-mono-tty-face
  186. (setq gamegrid-mono-tty-face (gamegrid-make-mono-tty-face)))
  187. gamegrid-mono-tty-face))))
  188. (defun gamegrid-colorize-glyph (color)
  189. (find-image `((:type xpm :data ,gamegrid-xpm
  190. :ascent center
  191. :color-symbols
  192. (("col1" . ,(gamegrid-color color 0.6))
  193. ("col2" . ,(gamegrid-color color 0.8))
  194. ("col3" . ,(gamegrid-color color 1.0))))
  195. (:type xbm :data ,gamegrid-xbm
  196. :ascent center
  197. :foreground ,(gamegrid-color color 1.0)
  198. :background ,(gamegrid-color color 0.5)))))
  199. (defun gamegrid-match-spec (spec)
  200. (let ((locale (car spec))
  201. (value (cadr spec)))
  202. (and (or (eq locale t)
  203. (and (listp locale)
  204. (memq gamegrid-display-mode locale))
  205. (and (symbolp locale)
  206. (eq gamegrid-display-mode locale)))
  207. value)))
  208. (defun gamegrid-match-spec-list (spec-list)
  209. (and spec-list
  210. (or (gamegrid-match-spec (car spec-list))
  211. (gamegrid-match-spec-list (cdr spec-list)))))
  212. (defun gamegrid-make-glyph (data-spec-list color-spec-list)
  213. (let ((data (gamegrid-match-spec-list data-spec-list))
  214. (color (gamegrid-match-spec-list color-spec-list)))
  215. (cond ((gamegrid-characterp data)
  216. (vector data))
  217. ((eq data 'colorize)
  218. (gamegrid-colorize-glyph color))
  219. ((listp data)
  220. (find-image data)) ;untested!
  221. ((vectorp data)
  222. (gamegrid-make-image-from-vector data)))))
  223. (defun gamegrid-make-image-from-vector (vect)
  224. "Convert an XEmacs style \"glyph\" to an image-spec."
  225. (let ((l (list 'image :type)))
  226. (dotimes (n (length vect))
  227. (setf l (nconc l (list (aref vect n)))))
  228. (nconc l (list :ascent 'center))))
  229. (defun gamegrid-display-type ()
  230. (cond ((and gamegrid-use-glyphs
  231. (display-images-p))
  232. 'glyph)
  233. ((and gamegrid-use-color
  234. (display-graphic-p)
  235. (display-color-p))
  236. 'color-x)
  237. ((display-graphic-p)
  238. 'mono-x)
  239. ((and gamegrid-use-color
  240. (display-color-p))
  241. 'color-tty)
  242. ((display-multi-font-p) ;???
  243. 'mono-tty)
  244. (t
  245. 'emacs-tty)))
  246. (defun gamegrid-set-display-table ()
  247. (if (featurep 'xemacs)
  248. (add-spec-to-specifier current-display-table
  249. gamegrid-display-table
  250. (current-buffer)
  251. nil
  252. 'remove-locale)
  253. (setq buffer-display-table gamegrid-display-table)))
  254. (declare-function image-size "image.c" (spec &optional pixels frame))
  255. (defun gamegrid-setup-default-font ()
  256. (setq gamegrid-face
  257. (copy-face 'default
  258. (intern (concat "gamegrid-face-" (buffer-name)))))
  259. (when (eq gamegrid-display-mode 'glyph)
  260. (let ((max-height nil))
  261. (loop for c from 0 to 255 do
  262. (let ((glyph (aref gamegrid-display-table c)))
  263. (when (and (listp glyph) (eq (car glyph) 'image))
  264. (let ((height (cdr (image-size glyph))))
  265. (if (or (null max-height)
  266. (< max-height height))
  267. (setq max-height height))))))
  268. (when (and max-height (< max-height 1))
  269. (let ((default-font-height (face-attribute 'default :height))
  270. (resy (/ (display-pixel-height) (/ (display-mm-height) 25.4)))
  271. point-size pixel-size)
  272. (setq point-size (/ (* (float default-font-height) max-height) 10)
  273. pixel-size (floor (* resy (/ point-size 72.27)))
  274. point-size (* (/ pixel-size resy) 72.27))
  275. (face-spec-set gamegrid-face
  276. `((t :height ,(floor (* point-size 10))))))))))
  277. (defun gamegrid-initialize-display ()
  278. (setq gamegrid-display-mode (gamegrid-display-type))
  279. (setq gamegrid-display-table (make-display-table))
  280. (setq gamegrid-face-table (make-vector 256 nil))
  281. (loop for c from 0 to 255 do
  282. (let* ((spec (aref gamegrid-display-options c))
  283. (glyph (gamegrid-make-glyph (car spec) (caddr spec)))
  284. (face (gamegrid-make-face (cadr spec) (caddr spec))))
  285. (aset gamegrid-face-table c face)
  286. (aset gamegrid-display-table c glyph)))
  287. (gamegrid-setup-default-font)
  288. (gamegrid-set-display-table)
  289. (setq cursor-type nil))
  290. (defun gamegrid-set-face (c)
  291. (if (eq gamegrid-display-mode 'glyph)
  292. (add-text-properties (1- (point)) (point)
  293. (list 'display (list (aref gamegrid-display-table c))))
  294. (put-text-property (1- (point))
  295. (point)
  296. 'face
  297. (aref gamegrid-face-table c))))
  298. (defun gamegrid-cell-offset (x y)
  299. (+ gamegrid-buffer-start
  300. (* (1+ gamegrid-buffer-width) y)
  301. x))
  302. ;; ;;;;;;;;;;;;;;;; grid functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  303. (defun gamegrid-get-cell (x y)
  304. (char-after (gamegrid-cell-offset x y)))
  305. (defun gamegrid-set-cell (x y c)
  306. (save-excursion
  307. (let ((buffer-read-only nil))
  308. (goto-char (gamegrid-cell-offset x y))
  309. (delete-char 1)
  310. (insert-char c 1)
  311. (gamegrid-set-face c))))
  312. (defun gamegrid-init-buffer (width height blank)
  313. (setq gamegrid-buffer-width width
  314. gamegrid-buffer-height height)
  315. (let ((line (concat
  316. (make-string width blank)
  317. "\n"))
  318. (buffer-read-only nil))
  319. (erase-buffer)
  320. (setq gamegrid-buffer-start (point))
  321. (dotimes (i height)
  322. (insert line))
  323. ;; Adjust the height of the default face to the height of the
  324. ;; images. Unlike XEmacs, Emacs doesn't allow to make the default
  325. ;; face buffer-local; so we do this with an overlay.
  326. (when (eq gamegrid-display-mode 'glyph)
  327. (overlay-put (make-overlay (point-min) (point-max))
  328. 'face gamegrid-face))
  329. (goto-char (point-min))))
  330. (defun gamegrid-init (options)
  331. (setq buffer-read-only t
  332. truncate-lines t
  333. line-spacing 0
  334. gamegrid-display-options options)
  335. (buffer-disable-undo (current-buffer))
  336. (gamegrid-initialize-display))
  337. ;; ;;;;;;;;;;;;;;;; timer functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  338. (defun gamegrid-start-timer (period func)
  339. (setq gamegrid-timer
  340. (if (featurep 'xemacs)
  341. (start-itimer "Gamegrid"
  342. func
  343. period
  344. period
  345. nil
  346. t
  347. (current-buffer))
  348. (run-with-timer period
  349. period
  350. func
  351. (current-buffer)))))
  352. (defun gamegrid-set-timer (delay)
  353. (if gamegrid-timer
  354. (if (fboundp 'set-itimer-restart)
  355. (set-itimer-restart gamegrid-timer delay)
  356. (timer-set-time gamegrid-timer
  357. (list (aref gamegrid-timer 1)
  358. (aref gamegrid-timer 2)
  359. (aref gamegrid-timer 3))
  360. delay))))
  361. (defun gamegrid-kill-timer ()
  362. (if gamegrid-timer
  363. (if (featurep 'xemacs)
  364. (delete-itimer gamegrid-timer)
  365. (cancel-timer gamegrid-timer)))
  366. (setq gamegrid-timer nil))
  367. ;; ;;;;;;;;;;;;;;; high score functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  368. (defun gamegrid-add-score (file score)
  369. "Add the current score to the high score file.
  370. On POSIX systems there may be a shared game directory for all users in
  371. which the scorefiles are kept. On such systems Emacs doesn't create
  372. the score file FILE in this directory, if it doesn't already exist.
  373. In this case Emacs searches for FILE in the directory specified by
  374. `gamegrid-user-score-file-directory' and creates it there, if
  375. necessary.
  376. To add the score file for a game to the system wide shared game
  377. directory, create the file with the shell command \"touch\" in this
  378. directory and make sure that it is owned by the correct user and
  379. group. You probably need special user privileges to do this.
  380. On non-POSIX systems Emacs searches for FILE in the directory
  381. specified by the variable `temporary-file-directory'. If necessary,
  382. FILE is created there."
  383. (case system-type
  384. ((ms-dos windows-nt)
  385. (gamegrid-add-score-insecure file score))
  386. (t
  387. (gamegrid-add-score-with-update-game-score file score))))
  388. ;; On POSIX systems there are four cases to distinguish:
  389. ;; 1. FILE is an absolute filename. Then it should be a file in
  390. ;; temporary file directory. This is the way,
  391. ;; `gamegrid-add-score' was supposed to be used in the past and
  392. ;; is covered here for backward-compatibility.
  393. ;;
  394. ;; 2. The helper program "update-game-score" is setuid and the
  395. ;; file FILE does already exist in a system wide shared game
  396. ;; directory. This should be the normal case on POSIX systems,
  397. ;; if the game was installed system wide. Use
  398. ;; "update-game-score" to add the score to the file in the
  399. ;; shared game directory.
  400. ;;
  401. ;; 3. "update-game-score" is setuid, but the file FILE does *not*
  402. ;; exist in the system wide shared game directory. Use
  403. ;; `gamegrid-add-score-insecure' to create--if necessary--and
  404. ;; update FILE. This is for the case that a user has installed
  405. ;; a game on her own.
  406. ;;
  407. ;; 4. "update-game-score" is not setuid. Use it to create/update
  408. ;; FILE in the user's home directory. There is presumably no
  409. ;; shared game directory.
  410. (defvar gamegrid-shared-game-dir)
  411. (defun gamegrid-add-score-with-update-game-score (file score)
  412. (let ((gamegrid-shared-game-dir
  413. (not (zerop (logand (file-modes
  414. (expand-file-name "update-game-score"
  415. exec-directory))
  416. #o4000)))))
  417. (cond ((file-name-absolute-p file)
  418. (gamegrid-add-score-insecure file score))
  419. ((and gamegrid-shared-game-dir
  420. (file-exists-p (expand-file-name file shared-game-score-directory)))
  421. ;; Use the setuid "update-game-score" program to update a
  422. ;; system-wide score file.
  423. (gamegrid-add-score-with-update-game-score-1 file
  424. (expand-file-name file shared-game-score-directory) score))
  425. ;; Else: Add the score to a score file in the user's home
  426. ;; directory.
  427. (gamegrid-shared-game-dir
  428. ;; If `gamegrid-shared-game-dir' is non-nil, then
  429. ;; "update-gamescore" program is setuid, so don't use it.
  430. (unless (file-exists-p
  431. (directory-file-name gamegrid-user-score-file-directory))
  432. (make-directory gamegrid-user-score-file-directory t))
  433. (gamegrid-add-score-insecure file score
  434. gamegrid-user-score-file-directory))
  435. (t (let ((f (expand-file-name
  436. gamegrid-user-score-file-directory)))
  437. (when (file-writable-p f)
  438. (unless (eq (car-safe (file-attributes f))
  439. t)
  440. (make-directory f))
  441. (setq f (expand-file-name file f))
  442. (unless (file-exists-p f)
  443. (write-region "" nil f nil 'silent nil 'excl)))
  444. (gamegrid-add-score-with-update-game-score-1 file f score))))))
  445. (defun gamegrid-add-score-with-update-game-score-1 (file target score)
  446. (let ((default-directory "/")
  447. (errbuf (generate-new-buffer " *update-game-score loss*"))
  448. (marker-string (concat
  449. (user-full-name)
  450. " <"
  451. (cond ((fboundp 'user-mail-address)
  452. (user-mail-address))
  453. ((boundp 'user-mail-address)
  454. user-mail-address)
  455. (t ""))
  456. "> "
  457. (current-time-string))))
  458. ;; This can be called from a timer, so enable local quits.
  459. (with-local-quit
  460. (apply
  461. 'call-process
  462. (append
  463. (list
  464. (expand-file-name "update-game-score" exec-directory)
  465. nil errbuf nil
  466. "-m" (int-to-string gamegrid-score-file-length)
  467. "-d" (if gamegrid-shared-game-dir
  468. (expand-file-name shared-game-score-directory)
  469. (file-name-directory target))
  470. file
  471. (int-to-string score)
  472. marker-string))))
  473. (if (buffer-modified-p errbuf)
  474. (progn
  475. (display-buffer errbuf)
  476. (error "Failed to update game score file"))
  477. (kill-buffer errbuf))
  478. (let ((buf (find-buffer-visiting target)))
  479. (save-excursion
  480. (if buf
  481. (progn
  482. (switch-to-buffer buf)
  483. (revert-buffer nil t nil)
  484. (display-buffer buf))
  485. (find-file-read-only target))
  486. (goto-char (point-min))
  487. (search-forward (concat (int-to-string score)
  488. " " (user-login-name) " "
  489. marker-string))
  490. (beginning-of-line)))))
  491. (defun gamegrid-add-score-insecure (file score &optional directory)
  492. (save-excursion
  493. (setq file (expand-file-name file (or directory
  494. temporary-file-directory)))
  495. (find-file-other-window file)
  496. (setq buffer-read-only nil)
  497. (goto-char (point-max))
  498. (insert (format "%05d\t%s\t%s <%s>\n"
  499. score
  500. (current-time-string)
  501. (user-full-name)
  502. (cond ((fboundp 'user-mail-address)
  503. (user-mail-address))
  504. ((boundp 'user-mail-address)
  505. user-mail-address)
  506. (t ""))))
  507. (sort-fields 1 (point-min) (point-max))
  508. (reverse-region (point-min) (point-max))
  509. (goto-char (point-min))
  510. (forward-line gamegrid-score-file-length)
  511. (delete-region (point) (point-max))
  512. (setq buffer-read-only t)
  513. (save-buffer)))
  514. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  515. (provide 'gamegrid)
  516. ;;; gamegrid.el ends here