1 ;;; gamegrid.el -- Library for implementing grid-based games on Emacs.
3 ;; Copyright (C) 1998 Free Software Foundation, Inc.
5 ;; Author: Glynn Clements <glynn@gclements.plus.com>
10 ;; This file is part of XEmacs.
12 ;; XEmacs is free software; you can redistribute it and/or modify it
13 ;; under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2 of the License, or
15 ;; (at your option) any later version.
17 ;; XEmacs is distributed in the hope that it will be useful, but
18 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ;; General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with XEmacs; see the file COPYING. If not, write to the Free
24 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 ;;; Synched up with: Not synched.
31 ;; Modified: 1998-01-27, added gamegrid-event-x/y
32 ;; Modified: 1998-05-28, enclose body of gamegrid-add-score in save-excursion
33 ;; Modified: 1998-06-23, copyright assigned to FSF
34 ;; Modified: 2003-06-14, update email address, remove URL
36 ;; Tested with XEmacs 20.3/4/5 and Emacs 19.34
41 (defun-when-void put-display-table (range value display-table)
42 "Set the value for char RANGE to VALUE in DISPLAY-TABLE. "
43 (if (sequencep display-table)
44 (aset display-table range value)
45 (put-char-table range value display-table)))
47 (defun-when-void get-display-table (character display-table)
48 "Find value for CHARACTER in DISPLAY-TABLE. "
49 (if (sequencep display-table)
50 (aref display-table character)
51 (get-char-table character display-table)))
53 ;; ;;;;;;;;;;;;; buffer-local variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
55 (defvar gamegrid-use-glyphs t
56 "Non-nil means use glyphs when available")
58 (defvar gamegrid-use-color t
59 "Non-nil means use color when available")
61 (defvar gamegrid-font "-*-courier-medium-r-*-*-*-140-100-75-*-*-iso8859-*"
62 "Name of the font used in X mode")
64 (defvar gamegrid-display-options nil)
66 (defvar gamegrid-buffer-width 0)
67 (defvar gamegrid-buffer-height 0)
68 (defvar gamegrid-blank 0)
70 (defvar gamegrid-timer nil)
72 (defvar gamegrid-display-mode nil)
74 (defvar gamegrid-display-table)
76 (defvar gamegrid-face-table nil)
78 (defvar gamegrid-buffer-start 1)
80 (defvar gamegrid-score-file-length 50
81 "Number of high scores to keep")
83 (make-variable-buffer-local 'gamegrid-use-glyphs)
84 (make-variable-buffer-local 'gamegrid-use-color)
85 (make-variable-buffer-local 'gamegrid-font)
86 (make-variable-buffer-local 'gamegrid-display-options)
87 (make-variable-buffer-local 'gamegrid-buffer-width)
88 (make-variable-buffer-local 'gamegrid-buffer-height)
89 (make-variable-buffer-local 'gamegrid-blank)
90 (make-variable-buffer-local 'gamegrid-timer)
91 (make-variable-buffer-local 'gamegrid-display-mode)
92 (make-variable-buffer-local 'gamegrid-display-table)
93 (make-variable-buffer-local 'gamegrid-face-table)
94 (make-variable-buffer-local 'gamegrid-buffer-start)
95 (make-variable-buffer-local 'gamegrid-score-file-length)
97 ;; ;;;;;;;;;;;;; global variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
99 (defvar gamegrid-grid-x-face nil)
100 (defvar gamegrid-mono-x-face nil)
101 (defvar gamegrid-mono-tty-face nil)
103 ;; ;;;;;;;;;;;;; constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
105 (defconst gamegrid-glyph-height 16)
107 (defconst gamegrid-xpm "\
109 static char *noname[] = {
110 /* width height ncolors chars_per_pixel */
117 \"---------------+\",
118 \"--------------++\",
119 \"--............++\",
120 \"--............++\",
121 \"--............++\",
122 \"--............++\",
123 \"--............++\",
124 \"--............++\",
125 \"--............++\",
126 \"--............++\",
127 \"--............++\",
128 \"--............++\",
129 \"--............++\",
130 \"--............++\",
131 \"-+++++++++++++++\",
135 "XPM format image used for each square")
137 ;; ;;;;;;;;;;;;;;;; miscellaneous functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
139 (defsubst gamegrid-characterp (arg)
140 (if (fboundp 'characterp)
144 (defsubst gamegrid-event-x (event)
145 (if (fboundp 'event-x)
147 (car (posn-col-row (event-end event)))))
149 (defsubst gamegrid-event-y (event)
150 (if (fboundp 'event-y)
152 (cdr (posn-col-row (event-end event)))))
154 ;; ;;;;;;;;;;;;; display functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
156 (defun gamegrid-color (color shade)
157 (let* ((v (floor (* shade 255)))
158 (r (* v (aref color 0)))
159 (g (* v (aref color 1)))
160 (b (* v (aref color 2))))
161 (format "#%02x%02x%02x" r g b)))
163 (defun gamegrid-set-font (face)
166 (set-face-font face gamegrid-font)
169 (defun gamegrid-setup-face (face color)
170 (set-face-foreground face color)
171 (set-face-background face color)
172 (gamegrid-set-font face)
174 (set-face-background-pixmap face [nothing]);; XEmacs
177 (set-face-background-pixmap face nil);; Emacs
180 (defun gamegrid-make-mono-tty-face ()
181 (let ((face (make-face 'gamegrid-mono-tty-face)))
183 (set-face-property face 'reverse t)
187 (defun gamegrid-make-color-tty-face (color)
188 (let* ((hex (gamegrid-color color 1.0))
189 (name (intern (format "gamegrid-color-tty-face-%s" hex)))
190 (face (make-face name)))
191 (gamegrid-setup-face face color)
194 (defun gamegrid-make-grid-x-face ()
195 (let ((face (make-face 'gamegrid-x-border-face)))
196 (gamegrid-set-font face)
199 (defun gamegrid-make-mono-x-face ()
200 (let ((face (make-face 'gamegrid-mono-x-face))
201 (color (face-foreground 'default)))
204 (cdr-safe (assq 'foreground-color (frame-parameters)))))
205 (gamegrid-setup-face face color)
208 (defun gamegrid-make-color-x-face (color)
209 (let* ((hex (gamegrid-color color 1.0))
210 (name (intern (format "gamegrid-color-x-face-%s" hex)))
211 (face (make-face name)))
212 (gamegrid-setup-face face (gamegrid-color color 1.0))
215 (defun gamegrid-make-face (data-spec-list color-spec-list)
216 (let ((data (gamegrid-match-spec-list data-spec-list))
217 (color (gamegrid-match-spec-list color-spec-list)))
220 (gamegrid-make-color-x-face color))
222 (unless gamegrid-grid-x-face
223 (setq gamegrid-grid-x-face (gamegrid-make-grid-x-face)))
224 gamegrid-grid-x-face)
226 (unless gamegrid-mono-x-face
227 (setq gamegrid-mono-x-face (gamegrid-make-mono-x-face)))
228 gamegrid-mono-x-face)
230 (gamegrid-make-color-tty-face color))
232 (unless gamegrid-mono-tty-face
233 (setq gamegrid-mono-tty-face (gamegrid-make-mono-tty-face)))
234 gamegrid-mono-tty-face))))
236 (defun gamegrid-colorize-glyph (color)
241 :color-symbols (list (cons "col1" (gamegrid-color color 0.6))
242 (cons "col2" (gamegrid-color color 0.8))
243 (cons "col3" (gamegrid-color color 1.0))))))
245 (defun gamegrid-match-spec (spec)
246 (let ((locale (car spec))
248 (and (or (eq locale t)
250 (memq gamegrid-display-mode locale))
251 (and (symbolp locale)
252 (eq gamegrid-display-mode locale)))
255 (defun gamegrid-match-spec-list (spec-list)
257 (or (gamegrid-match-spec (car spec-list))
258 (gamegrid-match-spec-list (cdr spec-list)))))
260 (defun gamegrid-make-glyph (data-spec-list color-spec-list)
261 (let ((data (gamegrid-match-spec-list data-spec-list))
262 (color (gamegrid-match-spec-list color-spec-list)))
263 (cond ((gamegrid-characterp data)
266 (gamegrid-colorize-glyph color))
268 (make-glyph data)))))
270 (defun gamegrid-color-display-p ()
271 (if (fboundp 'device-class)
272 (eq (device-class (selected-device)) 'color)
273 (eq (cdr-safe (assq 'display-type (frame-parameters))) 'color)))
275 (defun gamegrid-display-type ()
276 (let ((window-system-p
277 (or (and (fboundp 'console-on-window-system-p)
278 (console-on-window-system-p))
280 (cond ((and gamegrid-use-glyphs
284 ((and gamegrid-use-color
286 (gamegrid-color-display-p))
290 ((and gamegrid-use-color
291 (gamegrid-color-display-p))
293 ((fboundp 'set-face-property)
298 (defun gamegrid-set-display-table ()
299 (if (fboundp 'specifierp)
300 (add-spec-to-specifier current-display-table
301 gamegrid-display-table
305 (setq buffer-display-table gamegrid-display-table)))
307 (defun gamegrid-hide-cursor ()
308 (if (fboundp 'specifierp)
309 (set-specifier text-cursor-visible-p nil (current-buffer))))
311 (defun gamegrid-setup-default-font ()
312 (cond ((eq gamegrid-display-mode 'glyph)
313 (let* ((font-spec (face-property 'default 'font))
314 (name (font-name font-spec))
316 (loop for c from 0 to 255 do
317 (let ((glyph (get-display-table c gamegrid-display-table)))
318 (cond ((glyphp glyph)
319 (let ((height (glyph-height glyph)))
320 (if (or (null max-height)
321 (< max-height height))
322 (setq max-height height)))))))
324 (while (and (> (font-height font-spec) max-height)
327 ((eq window-system 'x)
328 (x-find-smaller-font name))
329 ((eq window-system 'mswindows)
330 (mswindows-find-smaller-font name)))))
331 (add-spec-to-specifier font-spec name (current-buffer))))))))
333 (defun gamegrid-initialize-display ()
334 (setq gamegrid-display-mode (gamegrid-display-type))
335 (setq gamegrid-display-table (make-display-table))
336 (setq gamegrid-face-table (make-vector 256 nil))
337 (loop for c from 0 to 255 do
338 (let* ((spec (aref gamegrid-display-options c))
339 (glyph (gamegrid-make-glyph (car spec) (caddr spec)))
340 (face (gamegrid-make-face (cadr spec) (caddr spec))))
341 (aset gamegrid-face-table c face)
342 (put-display-table c glyph gamegrid-display-table)))
343 (gamegrid-setup-default-font)
344 (gamegrid-set-display-table)
345 (gamegrid-hide-cursor))
348 (defun gamegrid-set-face (c)
349 (unless (eq gamegrid-display-mode 'glyph)
350 (put-text-property (1- (point))
353 (aref gamegrid-face-table c))))
355 (defun gamegrid-cell-offset (x y)
356 (+ gamegrid-buffer-start
357 (* (1+ gamegrid-buffer-width) y)
360 ;; ;;;;;;;;;;;;;;;; grid functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
362 (defun gamegrid-get-cell (x y)
363 (char-after (gamegrid-cell-offset x y)))
365 (defun gamegrid-set-cell (x y c)
367 (let ((buffer-read-only nil))
368 (goto-char (gamegrid-cell-offset x y))
371 (gamegrid-set-face c))))
373 (defun gamegrid-init-buffer (width height blank)
374 (setq gamegrid-buffer-width width
375 gamegrid-buffer-height height)
377 (make-string width blank)
379 (buffer-read-only nil))
381 (setq gamegrid-buffer-start (point))
383 (insert-string line))
384 (goto-char (point-min))))
386 (defun gamegrid-init (options)
387 (setq buffer-read-only t
389 gamegrid-display-options options)
390 (buffer-disable-undo (current-buffer))
391 (gamegrid-initialize-display))
393 ;; ;;;;;;;;;;;;;;;; timer functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
395 (defun gamegrid-start-timer (period func)
397 (if (featurep 'itimer)
398 (start-itimer "Gamegrid"
405 (run-with-timer period
410 (defun gamegrid-set-timer (delay)
412 (if (featurep 'itimer)
413 (set-itimer-restart gamegrid-timer delay)
414 (timer-set-time gamegrid-timer
415 (list (aref gamegrid-timer 1)
416 (aref gamegrid-timer 2)
417 (aref gamegrid-timer 3))
420 (defun gamegrid-kill-timer ()
422 (if (featurep 'itimer)
423 (delete-itimer gamegrid-timer)
424 (timer-set-time gamegrid-timer '(0 0 0) nil)))
425 (setq gamegrid-timer nil))
427 ;; ;;;;;;;;;;;;;;; high score functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
429 (defun gamegrid-add-score (file score)
430 "Adds the current score to the high score file"
432 (find-file-other-window file)
433 (setq buffer-read-only nil)
434 (goto-char (point-max))
435 (insert (format "%05d\t%s\t%s <%s>\n"
437 (current-time-string)
439 (cond ((fboundp 'user-mail-address)
441 ((boundp 'user-mail-address)
444 ;; Prefixing numbers 0's will make `sort-numeric-fields' sort with
445 ;; sort-numeric-base of 8.
446 ;; One workaround is to use `sort-regexp-fields-numerically',
447 ;; on the number, excluding leading 0's.
448 (sort-regexp-fields-numerically
450 "^[0]*\\([1-9][0-9]+\\)\\>.+$" "\\1" (point-min) (point-max))
451 (reverse-region (point-min) (point-max))
452 (goto-line (1+ gamegrid-score-file-length))
453 (delete-region (point) (point-max))
454 (setq buffer-read-only t)
457 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;