Fix compilation of xmenu.c and unexcoff.c, clean up MSDOS source files.
[bpt/emacs.git] / lisp / play / tetris.el
CommitLineData
6e44da43 1;;; tetris.el --- implementation of Tetris for Emacs
3d4ae13e 2
67d110f1 3;; Copyright (C) 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
114f9c96 4;; 2009, 2010 Free Software Foundation, Inc.
3d4ae13e
RS
5
6;; Author: Glynn Clements <glynn@sensei.co.uk>
7;; Version: 2.01
8;; Created: 1997-08-13
9;; Keywords: games
10
11;; This file is part of GNU Emacs.
12
b1fc2b50 13;; GNU Emacs is free software: you can redistribute it and/or modify
3d4ae13e 14;; it under the terms of the GNU General Public License as published by
b1fc2b50
GM
15;; the Free Software Foundation, either version 3 of the License, or
16;; (at your option) any later version.
3d4ae13e
RS
17
18;; GNU Emacs is distributed in the hope that it will be useful,
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
b1fc2b50 24;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
3d4ae13e
RS
25
26;;; Commentary:
27
6e44da43
PJ
28;;; Code:
29
3d4ae13e
RS
30(eval-when-compile
31 (require 'cl))
32
33(require 'gamegrid)
34
35;; ;;;;;;;;;;;;; customization variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
36
67ec1c1a 37(defgroup tetris nil
fcc93746 38 "Play a game of Tetris."
67ec1c1a
RS
39 :prefix "tetris-"
40 :group 'games)
41
42(defcustom tetris-use-glyphs t
67d110f1 43 "Non-nil means use glyphs when available."
67ec1c1a
RS
44 :group 'tetris
45 :type 'boolean)
46
47(defcustom tetris-use-color t
67d110f1 48 "Non-nil means use color when available."
67ec1c1a
RS
49 :group 'tetris
50 :type 'boolean)
51
52(defcustom tetris-draw-border-with-glyphs t
67d110f1 53 "Non-nil means draw a border even when using glyphs."
67ec1c1a
RS
54 :group 'tetris
55 :type 'boolean)
56
57(defcustom tetris-default-tick-period 0.3
67d110f1 58 "The default time taken for a shape to drop one row."
67ec1c1a
RS
59 :group 'tetris
60 :type 'number)
61
62(defcustom tetris-update-speed-function
3d4ae13e 63 'tetris-default-update-speed-function
fcc93746 64 "Function run whenever the Tetris score changes.
3d4ae13e 65Called with two arguments: (SHAPES ROWS)
fcc93746
JB
66SHAPES is the number of shapes which have been dropped.
67ROWS is the number of rows which have been completed.
3d4ae13e 68
67ec1c1a
RS
69If the return value is a number, it is used as the timer period."
70 :group 'tetris
71 :type 'function)
3d4ae13e 72
67ec1c1a
RS
73(defcustom tetris-mode-hook nil
74 "Hook run upon starting Tetris."
75 :group 'tetris
76 :type 'hook)
3d4ae13e 77
67ec1c1a 78(defcustom tetris-tty-colors
195e19e4
LH
79 ["blue" "white" "yellow" "magenta" "cyan" "green" "red"]
80 "Vector of colors of the various shapes in text mode."
67ec1c1a
RS
81 :group 'tetris
82 :type (let ((names `("Shape 1" "Shape 2" "Shape 3"
83 "Shape 4" "Shape 5" "Shape 6" "Shape 7"))
195e19e4 84 (result nil))
67ec1c1a 85 (while names
adcce7d5
SS
86 (add-to-list 'result
87 (cons 'choice
88 (cons :tag
89 (cons (car names)
67ec1c1a
RS
90 (mapcar (lambda (color)
91 (list 'const color))
92 (defined-colors)))))
93 t)
94 (setq names (cdr names)))
95 result))
96
97(defcustom tetris-x-colors
195e19e4
LH
98 [[0 0 1] [0.7 0 1] [1 1 0] [1 0 1] [0 1 1] [0 1 0] [1 0 0]]
99 "Vector of colors of the various shapes."
67ec1c1a
RS
100 :group 'tetris
101 :type 'sexp)
102
103(defcustom tetris-buffer-name "*Tetris*"
104 "Name used for Tetris buffer."
105 :group 'tetris
106 :type 'string)
107
108(defcustom tetris-buffer-width 30
109 "Width of used portion of buffer."
110 :group 'tetris
111 :type 'number)
112
113(defcustom tetris-buffer-height 22
114 "Height of used portion of buffer."
115 :group 'tetris
116 :type 'number)
117
118(defcustom tetris-width 10
119 "Width of playing area."
120 :group 'tetris
121 :type 'number)
122
123(defcustom tetris-height 20
124 "Height of playing area."
125 :group 'tetris
126 :type 'number)
127
128(defcustom tetris-top-left-x 3
129 "X position of top left of playing area."
130 :group 'tetris
131 :type 'number)
132
133(defcustom tetris-top-left-y 1
134 "Y position of top left of playing area."
135 :group 'tetris
136 :type 'number)
3d4ae13e
RS
137
138(defvar tetris-next-x (+ (* 2 tetris-top-left-x) tetris-width)
139 "X position of next shape.")
140
141(defvar tetris-next-y tetris-top-left-y
142 "Y position of next shape.")
143
144(defvar tetris-score-x tetris-next-x
145 "X position of score.")
146
147(defvar tetris-score-y (+ tetris-next-y 6)
148 "Y position of score.")
149
9caf26fe 150;; It is not safe to put this in /tmp.
adcce7d5 151;; Someone could make a symlink in /tmp
9caf26fe 152;; pointing to a file you don't want to clobber.
76f1b321 153(defvar tetris-score-file "tetris-scores"
3d4ae13e
RS
154;; anybody with a well-connected server want to host this?
155;(defvar tetris-score-file "/anonymous@ftp.pgt.com:/pub/cgw/tetris-scores"
156 "File for holding high scores.")
157
158;; ;;;;;;;;;;;;; display options ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
159
3d4ae13e
RS
160(defvar tetris-blank-options
161 '(((glyph colorize)
162 (t ?\040))
163 ((color-x color-x)
164 (mono-x grid-x)
ba8cb9c5 165 (color-tty color-tty))
3d4ae13e 166 (((glyph color-x) [0 0 0])
ba8cb9c5 167 (color-tty "black"))))
3d4ae13e
RS
168
169(defvar tetris-cell-options
170 '(((glyph colorize)
171 (emacs-tty ?O)
172 (t ?\040))
173 ((color-x color-x)
174 (mono-x mono-x)
175 (color-tty color-tty)
ba8cb9c5 176 (mono-tty mono-tty))
3d4ae13e
RS
177 ;; color information is taken from tetris-x-colors and tetris-tty-colors
178 ))
179
ba8cb9c5
FP
180(defvar tetris-border-options
181 '(((glyph colorize)
182 (t ?\+))
183 ((color-x color-x)
184 (mono-x grid-x)
185 (color-tty color-tty))
186 (((glyph color-x) [0.5 0.5 0.5])
187 (color-tty "white"))))
188
3d4ae13e
RS
189(defvar tetris-space-options
190 '(((t ?\040))
191 nil
192 nil))
193
194;; ;;;;;;;;;;;;; constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
195
196(defconst tetris-shapes
195e19e4
LH
197 [[[[0 0] [1 0] [0 1] [1 1]]]
198
199 [[[0 0] [1 0] [2 0] [2 1]]
200 [[1 -1] [1 0] [1 1] [0 1]]
201 [[0 -1] [0 0] [1 0] [2 0]]
202 [[1 -1] [2 -1] [1 0] [1 1]]]
203
204 [[[0 0] [1 0] [2 0] [0 1]]
205 [[0 -1] [1 -1] [1 0] [1 1]]
206 [[2 -1] [0 0] [1 0] [2 0]]
207 [[1 -1] [1 0] [1 1] [2 1]]]
208
209 [[[0 0] [1 0] [1 1] [2 1]]
210 [[1 0] [0 1] [1 1] [0 2]]]
211
212 [[[1 0] [2 0] [0 1] [1 1]]
213 [[0 0] [0 1] [1 1] [1 2]]]
214
215 [[[1 0] [0 1] [1 1] [2 1]]
216 [[1 0] [1 1] [2 1] [1 2]]
217 [[0 1] [1 1] [2 1] [1 2]]
218 [[1 0] [0 1] [1 1] [1 2]]]
219
220 [[[0 0] [1 0] [2 0] [3 0]]
221 [[1 -1] [1 0] [1 1] [1 2]]]]
222 "Each shape is described by a vector that contains the coordinates of
223each one of its four blocks.")
3d4ae13e 224
adcce7d5 225;;the scoring rules were taken from "xtetris". Blocks score differently
3d4ae13e
RS
226;;depending on their rotation
227
adcce7d5 228(defconst tetris-shape-scores
195e19e4 229 [[6] [6 7 6 7] [6 7 6 7] [6 7] [6 7] [5 5 6 5] [5 8]] )
3d4ae13e
RS
230
231(defconst tetris-shape-dimensions
232 [[2 2] [3 2] [3 2] [3 2] [3 2] [3 2] [4 1]])
233
195e19e4 234(defconst tetris-blank 7)
3d4ae13e
RS
235
236(defconst tetris-border 8)
237
238(defconst tetris-space 9)
239
240(defun tetris-default-update-speed-function (shapes rows)
241 (/ 20.0 (+ 50.0 rows)))
242
243;; ;;;;;;;;;;;;; variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
244
245(defvar tetris-shape 0)
246(defvar tetris-rot 0)
247(defvar tetris-next-shape 0)
248(defvar tetris-n-shapes 0)
249(defvar tetris-n-rows 0)
250(defvar tetris-score 0)
251(defvar tetris-pos-x 0)
252(defvar tetris-pos-y 0)
253(defvar tetris-paused nil)
254
255(make-variable-buffer-local 'tetris-shape)
256(make-variable-buffer-local 'tetris-rot)
257(make-variable-buffer-local 'tetris-next-shape)
258(make-variable-buffer-local 'tetris-n-shapes)
259(make-variable-buffer-local 'tetris-n-rows)
260(make-variable-buffer-local 'tetris-score)
261(make-variable-buffer-local 'tetris-pos-x)
262(make-variable-buffer-local 'tetris-pos-y)
263(make-variable-buffer-local 'tetris-paused)
264
265;; ;;;;;;;;;;;;; keymaps ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
266
267(defvar tetris-mode-map
fcc93746
JB
268 (let ((map (make-sparse-keymap 'tetris-mode-map)))
269 (define-key map "n" 'tetris-start-game)
270 (define-key map "q" 'tetris-end-game)
271 (define-key map "p" 'tetris-pause-game)
272
273 (define-key map " " 'tetris-move-bottom)
274 (define-key map [left] 'tetris-move-left)
275 (define-key map [right] 'tetris-move-right)
276 (define-key map [up] 'tetris-rotate-prev)
277 (define-key map [down] 'tetris-rotate-next)
278 map))
3d4ae13e
RS
279
280(defvar tetris-null-map
fcc93746
JB
281 (let ((map (make-sparse-keymap 'tetris-null-map)))
282 (define-key map "n" 'tetris-start-game)
283 map))
3d4ae13e
RS
284
285;; ;;;;;;;;;;;;;;;; game functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
286
287(defun tetris-display-options ()
288 (let ((options (make-vector 256 nil)))
289 (loop for c from 0 to 255 do
290 (aset options c
291 (cond ((= c tetris-blank)
292 tetris-blank-options)
195e19e4 293 ((and (>= c 0) (<= c 6))
3d4ae13e
RS
294 (append
295 tetris-cell-options
296 `((((glyph color-x) ,(aref tetris-x-colors c))
297 (color-tty ,(aref tetris-tty-colors c))
298 (t nil)))))
299 ((= c tetris-border)
300 tetris-border-options)
301 ((= c tetris-space)
302 tetris-space-options)
303 (t
304 '(nil nil nil)))))
305 options))
306
307(defun tetris-get-tick-period ()
308 (if (boundp 'tetris-update-speed-function)
309 (let ((period (apply tetris-update-speed-function
310 tetris-n-shapes
311 tetris-n-rows nil)))
312 (and (numberp period) period))))
313
195e19e4
LH
314(defun tetris-get-shape-cell (block)
315 (aref (aref (aref tetris-shapes
316 tetris-shape) tetris-rot)
317 block))
3d4ae13e
RS
318
319(defun tetris-shape-width ()
195e19e4 320 (aref (aref tetris-shape-dimensions tetris-shape) 0))
3d4ae13e 321
195e19e4
LH
322(defun tetris-shape-rotations ()
323 (length (aref tetris-shapes tetris-shape)))
3d4ae13e
RS
324
325(defun tetris-draw-score ()
326 (let ((strings (vector (format "Shapes: %05d" tetris-n-shapes)
327 (format "Rows: %05d" tetris-n-rows)
328 (format "Score: %05d" tetris-score))))
329 (loop for y from 0 to 2 do
330 (let* ((string (aref strings y))
331 (len (length string)))
332 (loop for x from 0 to (1- len) do
333 (gamegrid-set-cell (+ tetris-score-x x)
334 (+ tetris-score-y y)
335 (aref string x)))))))
336
337(defun tetris-update-score ()
338 (tetris-draw-score)
339 (let ((period (tetris-get-tick-period)))
340 (if period (gamegrid-set-timer period))))
341
342(defun tetris-new-shape ()
343 (setq tetris-shape tetris-next-shape)
344 (setq tetris-rot 0)
345 (setq tetris-next-shape (random 7))
346 (setq tetris-pos-x (/ (- tetris-width (tetris-shape-width)) 2))
347 (setq tetris-pos-y 0)
348 (if (tetris-test-shape)
349 (tetris-end-game)
d46b9408
CY
350 (tetris-draw-shape)
351 (tetris-draw-next-shape)
352 (tetris-update-score)))
3d4ae13e
RS
353
354(defun tetris-draw-next-shape ()
195e19e4
LH
355 (loop for x from 0 to 3 do
356 (loop for y from 0 to 3 do
357 (gamegrid-set-cell (+ tetris-next-x x)
358 (+ tetris-next-y y)
359 tetris-blank)))
360 (loop for i from 0 to 3 do
361 (let ((tetris-shape tetris-next-shape)
362 (tetris-rot 0))
363 (gamegrid-set-cell (+ tetris-next-x
364 (aref (tetris-get-shape-cell i) 0))
365 (+ tetris-next-y
366 (aref (tetris-get-shape-cell i) 1))
367 tetris-shape))))
3d4ae13e
RS
368
369(defun tetris-draw-shape ()
195e19e4
LH
370 (loop for i from 0 to 3 do
371 (let ((c (tetris-get-shape-cell i)))
372 (gamegrid-set-cell (+ tetris-top-left-x
373 tetris-pos-x
374 (aref c 0))
375 (+ tetris-top-left-y
376 tetris-pos-y
377 (aref c 1))
378 tetris-shape))))
3d4ae13e
RS
379
380(defun tetris-erase-shape ()
195e19e4
LH
381 (loop for i from 0 to 3 do
382 (let ((c (tetris-get-shape-cell i)))
383 (gamegrid-set-cell (+ tetris-top-left-x
384 tetris-pos-x
385 (aref c 0))
386 (+ tetris-top-left-y
387 tetris-pos-y
388 (aref c 1))
389 tetris-blank))))
3d4ae13e
RS
390
391(defun tetris-test-shape ()
392 (let ((hit nil))
195e19e4
LH
393 (loop for i from 0 to 3 do
394 (unless hit
395 (setq hit
396 (let* ((c (tetris-get-shape-cell i))
397 (xx (+ tetris-pos-x
398 (aref c 0)))
399 (yy (+ tetris-pos-y
400 (aref c 1))))
401 (or (>= xx tetris-width)
402 (>= yy tetris-height)
403 (/= (gamegrid-get-cell
404 (+ xx tetris-top-left-x)
405 (+ yy tetris-top-left-y))
406 tetris-blank))))))
3d4ae13e
RS
407 hit))
408
409(defun tetris-full-row (y)
410 (let ((full t))
411 (loop for x from 0 to (1- tetris-width) do
412 (if (= (gamegrid-get-cell (+ tetris-top-left-x x)
413 (+ tetris-top-left-y y))
414 tetris-blank)
415 (setq full nil)))
416 full))
417
418(defun tetris-shift-row (y)
419 (if (= y 0)
420 (loop for x from 0 to (1- tetris-width) do
421 (gamegrid-set-cell (+ tetris-top-left-x x)
422 (+ tetris-top-left-y y)
423 tetris-blank))
424 (loop for x from 0 to (1- tetris-width) do
425 (let ((c (gamegrid-get-cell (+ tetris-top-left-x x)
426 (+ tetris-top-left-y y -1))))
427 (gamegrid-set-cell (+ tetris-top-left-x x)
428 (+ tetris-top-left-y y)
429 c)))))
430
431(defun tetris-shift-down ()
432 (loop for y0 from 0 to (1- tetris-height) do
433 (if (tetris-full-row y0)
434 (progn (setq tetris-n-rows (1+ tetris-n-rows))
435 (loop for y from y0 downto 0 do
436 (tetris-shift-row y))))))
437
438(defun tetris-draw-border-p ()
439 (or (not (eq gamegrid-display-mode 'glyph))
440 tetris-draw-border-with-glyphs))
441
442(defun tetris-init-buffer ()
443 (gamegrid-init-buffer tetris-buffer-width
444 tetris-buffer-height
445 tetris-space)
446 (let ((buffer-read-only nil))
447 (if (tetris-draw-border-p)
448 (loop for y from -1 to tetris-height do
449 (loop for x from -1 to tetris-width do
450 (gamegrid-set-cell (+ tetris-top-left-x x)
451 (+ tetris-top-left-y y)
452 tetris-border))))
453 (loop for y from 0 to (1- tetris-height) do
454 (loop for x from 0 to (1- tetris-width) do
455 (gamegrid-set-cell (+ tetris-top-left-x x)
456 (+ tetris-top-left-y y)
457 tetris-blank)))
458 (if (tetris-draw-border-p)
459 (loop for y from -1 to 4 do
460 (loop for x from -1 to 4 do
461 (gamegrid-set-cell (+ tetris-next-x x)
462 (+ tetris-next-y y)
463 tetris-border))))))
464
465(defun tetris-reset-game ()
466 (gamegrid-kill-timer)
467 (tetris-init-buffer)
468 (setq tetris-next-shape (random 7))
469 (setq tetris-shape 0
470 tetris-rot 0
471 tetris-pos-x 0
472 tetris-pos-y 0
473 tetris-n-shapes 0
474 tetris-n-rows 0
475 tetris-score 0
476 tetris-paused nil)
477 (tetris-new-shape))
478
479(defun tetris-shape-done ()
480 (tetris-shift-down)
481 (setq tetris-n-shapes (1+ tetris-n-shapes))
482 (setq tetris-score
adcce7d5 483 (+ tetris-score
3d4ae13e
RS
484 (aref (aref tetris-shape-scores tetris-shape) tetris-rot)))
485 (tetris-update-score)
486 (tetris-new-shape))
487
488(defun tetris-update-game (tetris-buffer)
489 "Called on each clock tick.
490Drops the shape one square, testing for collision."
491 (if (and (not tetris-paused)
492 (eq (current-buffer) tetris-buffer))
493 (let (hit)
494 (tetris-erase-shape)
495 (setq tetris-pos-y (1+ tetris-pos-y))
496 (setq hit (tetris-test-shape))
497 (if hit
498 (setq tetris-pos-y (1- tetris-pos-y)))
499 (tetris-draw-shape)
500 (if hit
501 (tetris-shape-done)))))
502
503(defun tetris-move-bottom ()
fcc93746 504 "Drop the shape to the bottom of the playing area."
3d4ae13e 505 (interactive)
195e19e4
LH
506 (unless tetris-paused
507 (let ((hit nil))
508 (tetris-erase-shape)
509 (while (not hit)
510 (setq tetris-pos-y (1+ tetris-pos-y))
511 (setq hit (tetris-test-shape)))
512 (setq tetris-pos-y (1- tetris-pos-y))
513 (tetris-draw-shape)
514 (tetris-shape-done))))
3d4ae13e
RS
515
516(defun tetris-move-left ()
fcc93746 517 "Move the shape one square to the left."
3d4ae13e 518 (interactive)
195e19e4 519 (unless tetris-paused
3d4ae13e
RS
520 (tetris-erase-shape)
521 (setq tetris-pos-x (1- tetris-pos-x))
522 (if (tetris-test-shape)
195e19e4 523 (setq tetris-pos-x (1+ tetris-pos-x)))
3d4ae13e
RS
524 (tetris-draw-shape)))
525
526(defun tetris-move-right ()
fcc93746 527 "Move the shape one square to the right."
3d4ae13e 528 (interactive)
195e19e4 529 (unless tetris-paused
3d4ae13e
RS
530 (tetris-erase-shape)
531 (setq tetris-pos-x (1+ tetris-pos-x))
532 (if (tetris-test-shape)
533 (setq tetris-pos-x (1- tetris-pos-x)))
534 (tetris-draw-shape)))
535
536(defun tetris-rotate-prev ()
fcc93746 537 "Rotate the shape clockwise."
3d4ae13e 538 (interactive)
195e19e4
LH
539 (unless tetris-paused
540 (tetris-erase-shape)
541 (setq tetris-rot (% (+ 1 tetris-rot)
542 (tetris-shape-rotations)))
543 (if (tetris-test-shape)
544 (setq tetris-rot (% (+ 3 tetris-rot)
545 (tetris-shape-rotations))))
546 (tetris-draw-shape)))
3d4ae13e
RS
547
548(defun tetris-rotate-next ()
fcc93746 549 "Rotate the shape anticlockwise."
3d4ae13e 550 (interactive)
195e19e4 551 (unless tetris-paused
297a6dca 552 (tetris-erase-shape)
195e19e4
LH
553 (setq tetris-rot (% (+ 3 tetris-rot)
554 (tetris-shape-rotations)))
297a6dca 555 (if (tetris-test-shape)
195e19e4
LH
556 (setq tetris-rot (% (+ 1 tetris-rot)
557 (tetris-shape-rotations))))
558 (tetris-draw-shape)))
3d4ae13e
RS
559
560(defun tetris-end-game ()
fcc93746 561 "Terminate the current game."
3d4ae13e
RS
562 (interactive)
563 (gamegrid-kill-timer)
564 (use-local-map tetris-null-map)
565 (gamegrid-add-score tetris-score-file tetris-score))
566
567(defun tetris-start-game ()
fcc93746 568 "Start a new game of Tetris."
3d4ae13e
RS
569 (interactive)
570 (tetris-reset-game)
571 (use-local-map tetris-mode-map)
572 (let ((period (or (tetris-get-tick-period)
573 tetris-default-tick-period)))
574 (gamegrid-start-timer period 'tetris-update-game)))
575
576(defun tetris-pause-game ()
fcc93746 577 "Pause (or resume) the current game."
3d4ae13e
RS
578 (interactive)
579 (setq tetris-paused (not tetris-paused))
580 (message (and tetris-paused "Game paused (press p to resume)")))
581
582(defun tetris-active-p ()
583 (eq (current-local-map) tetris-mode-map))
584
585(put 'tetris-mode 'mode-class 'special)
586
fcc93746
JB
587(define-derived-mode tetris-mode nil "Tetris"
588 "A mode for playing Tetris."
3d4ae13e 589
3d4ae13e
RS
590 (add-hook 'kill-buffer-hook 'gamegrid-kill-timer nil t)
591
592 (use-local-map tetris-null-map)
593
2b632b16
RS
594 (unless (featurep 'emacs)
595 (setq mode-popup-menu
596 '("Tetris Commands"
597 ["Start new game" tetris-start-game]
598 ["End game" tetris-end-game
599 (tetris-active-p)]
600 ["Pause" tetris-pause-game
601 (and (tetris-active-p) (not tetris-paused))]
602 ["Resume" tetris-pause-game
603 (and (tetris-active-p) tetris-paused)])))
3d4ae13e 604
fcc93746
JB
605 (setq show-trailing-whitespace nil)
606
3d4ae13e
RS
607 (setq gamegrid-use-glyphs tetris-use-glyphs)
608 (setq gamegrid-use-color tetris-use-color)
609
fcc93746 610 (gamegrid-init (tetris-display-options)))
3d4ae13e
RS
611
612;;;###autoload
613(defun tetris ()
614 "Play the Tetris game.
615Shapes drop from the top of the screen, and the user has to move and
616rotate the shape to fit in with those at the bottom of the screen so
617as to form complete rows.
618
619tetris-mode keybindings:
620 \\<tetris-mode-map>
621\\[tetris-start-game] Starts a new game of Tetris
622\\[tetris-end-game] Terminates the current game
623\\[tetris-pause-game] Pauses (or resumes) the current game
624\\[tetris-move-left] Moves the shape one square to the left
625\\[tetris-move-right] Moves the shape one square to the right
626\\[tetris-rotate-prev] Rotates the shape clockwise
627\\[tetris-rotate-next] Rotates the shape anticlockwise
628\\[tetris-move-bottom] Drops the shape to the bottom of the playing area
629
630"
631 (interactive)
632
fcc93746
JB
633 (select-window (or (get-buffer-window tetris-buffer-name)
634 (selected-window)))
3d4ae13e
RS
635 (switch-to-buffer tetris-buffer-name)
636 (gamegrid-kill-timer)
637 (tetris-mode)
638 (tetris-start-game))
639
d2fe6685
GM
640(random t)
641
3d4ae13e
RS
642(provide 'tetris)
643
cbee283d 644;; arch-tag: fb780d53-3ff0-49f0-8e19-f7f13cf2d49e
3d4ae13e 645;;; tetris.el ends here