home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / games / getris.el < prev    next >
Encoding:
Text File  |  1990-03-21  |  14.0 KB  |  531 lines

  1. ;From: mad@math.keio.JUNET (MAEDA Atusi)
  2. ;Newsgroups: comp.emacs
  3. ;Subject: getris.el -- clone of a famous Russian game program.
  4. ;Message-ID: <MAD.89Sep14193115@cabbage.math.keio.JUNET>
  5. ;Date: 14 Sep 89 10:31:15 GMT
  6. ;Reply-To: mad@nakanishi.math.keio.junet
  7. ;Organization: Faculty of Sci. and Tech., Keio Univ., Yokohama, Japan.
  8. ;Lines: 521
  9.  
  10. ;;; Getris -- clone of a famous Russian game program.
  11. ;; Copyright (C) 1989 by MAEDA Atusi
  12. ;; Originally written by MAEDA Atusi
  13. ;; Modified by Hideto Sazuka Thu Jun 29 12:09:36 1989
  14. ;; Modified by MAEDA Atusi Thu Jun 29 20:50:16 1989
  15. ;; Modified by MAEDA Atusi Wed Jul  5 20:21:31 1989
  16.  
  17. ;; This file is part of GNU Emacs.
  18.  
  19. ;; GNU Emacs is distributed in the hope that it will be useful,
  20. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  21. ;; accepts responsibility to anyone for the consequences of using it
  22. ;; or for whether it serves any particular purpose or works at all,
  23. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  24. ;; License for full details.
  25.  
  26. ;; Everyone is granted permission to copy, modify and redistribute
  27. ;; GNU Emacs, but only under the conditions described in the
  28. ;; GNU Emacs General Public License.   A copy of this license is
  29. ;; supposed to have been given to you along with GNU Emacs so you
  30. ;; can know your rights and responsibilities.  It should be in a
  31. ;; file named COPYING.  Among other things, the copyright notice
  32. ;; and this notice must be preserved on all copies.
  33.  
  34. (provide 'getris)
  35. ;(require 'boss)
  36.  
  37. ;;; User customizable variables.
  38.  
  39. (defvar getris-initial-delay 200
  40.   "*Delay count to control the speed of getris game.  Bigger means slower.
  41. You should substitute this value according to your system's performance.")
  42.  
  43. (defvar getris-min-delay 2
  44.   "*Minimum delay count to control the maximum speed of getris game.
  45. Smaller means faster.  The default value, 2, means `as fast as possible.'")
  46.  
  47. (defvar getris-acceleration 200
  48.   "*Acceleration rate of getris game.
  49. Smaller value means quicker speed-up.  This value is performance independent.")
  50.  
  51. (defvar getris-high-score-file
  52.   (or (getenv "GETRISFILE")
  53.       "$HOME/.getris")
  54.   "*File name where top ten scores of getris are recorded.
  55. Initialized from GETRISFILE environment variable.
  56. Nil means does not record scores.")
  57.  
  58. (defvar getris-block-string
  59.   (if (and (boundp kanji-flag) kanji-flag) "\242\243" "[]")
  60.   "*String for getris block.  Must be width of two column.")
  61.  
  62. (defvar getris-width 10
  63.   "*Width of getris board (number of blocks).  Each block occupies two
  64. column width on window.")
  65.  
  66. (defvar getris-use-full-window nil
  67.   "*Non-nil means that starting Getris game deletes other windows.")
  68.  
  69. (defun getris ()
  70.   "Clone of a famous Russian game program."
  71.   (interactive)
  72.   (setq getris-previous-window-configuration
  73.     (current-window-configuration))
  74.   (switch-to-buffer "*Getris*")
  75.   (getris-mode)
  76.   (getris-startup))
  77.  
  78. ;;; Internal variables.
  79.  
  80. (defvar getris-command-vector nil
  81.   "Vector of functions which maps character to getris command.")
  82.  
  83. (defvar getris-mode-map nil)
  84.  
  85. (defvar getris-piece-data nil
  86.   "Vector of piece data.
  87. Each element of this vector is vector of size four, which correspond
  88. to four directions of piece.  And each element of four size vectors is
  89. a list of form:
  90.     (max-y-offset (x1 . y1) (x2 . y2) (x3 . y3) (x4 . y4))
  91. where:
  92.     (x1 . y1) ... (x4 . y4) are offsets of dot from imaginary `origin'
  93.                 at upper-left side of the piece,
  94.     0 <= y[1-4] <= max-y-offset.")
  95.  
  96. (defvar getris-left-margin)
  97. (defvar getris-height)
  98. (defvar getris-previous-window-configuration nil)
  99. (defvar getris-blank-line)
  100. (defvar getris-complete-line)
  101. (defvar getris-line-length)
  102.  
  103. (defun getris-startup ()
  104.   (setq buffer-read-only nil)
  105.   (erase-buffer)
  106.   (goto-char (point-min))
  107.   (insert (substitute-command-keys "
  108.  
  109. <<< G E T R I S >>>
  110.  
  111. Clone of a famous Russian game program.
  112.  
  113. Originally written by
  114. MAEDA Atusi
  115. mad@nakanishi.math.keio.junet
  116.  
  117.  
  118. <Type \\[getris-mode-help] for help, \\[getris-start] to start game.>
  119. "))
  120.   (center-region (point-min) (point-max))
  121.   (setq buffer-read-only t))
  122.  
  123. (defun getris-mode-help ()
  124.   (interactive)
  125.   (message (concat
  126.         (substitute-command-keys "\\[getris-mode-help]:Print this  ")
  127.         (substitute-command-keys "\\[getris-start]:Start new game  ")
  128.         (substitute-command-keys "\\[getris-help]:List action keys  ")
  129.         (substitute-command-keys "\\[boss-has-come]:Boss has come!  ")
  130.         (substitute-command-keys "\\[getris-exit]:Exit"))))
  131.  
  132. (or getris-mode-map
  133.     (progn
  134.       (setq getris-mode-map (make-sparse-keymap))
  135.       (define-key getris-mode-map "?" 'getris-mode-help)
  136.       (define-key getris-mode-map "\C-m" 'getris-start)
  137.       (define-key getris-mode-map "h" 'getris-help)
  138.       (define-key getris-mode-map "\e" 'boss-has-come)
  139.       (define-key getris-mode-map "q" 'getris-exit)))
  140.  
  141. (defun getris-help ()
  142.   (interactive)
  143.   (message "j:Left  k:Rotate  l:Right  Space:Drop  ESC:Escape  q:Exit"))
  144.  
  145. (or getris-command-vector
  146.     (progn
  147.       (setq getris-command-vector (make-vector 256 'getris-help))
  148.       (aset getris-command-vector ?j 'getris-move-left)
  149.       (aset getris-command-vector ?k 'getris-rotate)
  150.       (aset getris-command-vector ?l 'getris-move-right)
  151.       (aset getris-command-vector ?  'getris-drop)
  152.       (aset getris-command-vector ?q 'getris-quit)
  153.       (aset getris-command-vector ?\e 'getris-boss-has-come)))
  154.  
  155. (defun getris-mode ()
  156.   "Major mode for playing getris game.
  157. \\{getris-mode-map}
  158. Type \\[getris-help] for key action in the game.
  159. Entry to this mode calls the value of getris-mode-hook
  160. if that value is non-nil."
  161.   (interactive)
  162.   (kill-all-local-variables)
  163.   (make-local-variable 'global-mode-string)
  164.   (setq major-mode 'getris-mode)
  165.   (setq mode-name "Getris")
  166.   (use-local-map getris-mode-map)
  167.   (buffer-flush-undo (current-buffer))
  168.   (setq buffer-read-only t)
  169.   (getris-mode-help)
  170.   (run-hooks 'getris-mode-hook))
  171.  
  172. (defun getris-start ()
  173.   (interactive)
  174.   (switch-to-buffer "*Getris*")
  175.   (if getris-use-full-window
  176.       (delete-other-windows)
  177.     ;; Enlarge window size if necessary.
  178.     (progn
  179.       (getris-get-window-size)
  180.       (if (< getris-left-margin 5)
  181.       (enlarge-window (1+ (* 2 (- 5 getris-left-margin))) t))
  182.       (if (< getris-height 20)
  183.       (enlarge-window (- 20 getris-height)))))
  184.   (getris-get-window-size)        ;again
  185.   (if (or (< getris-height 20)
  186.       (< getris-left-margin 5))
  187.       (error "Window size too small for getris."))
  188.   (let ((left-margin-space (make-string (1- getris-left-margin) ? )))
  189.     (setq getris-blank-line
  190.       (concat left-margin-space "||"
  191.           (make-string (* 2 getris-width) ? ) "||\n"))
  192.     (setq getris-complete-line
  193.       (regexp-quote (concat left-margin-space "||"
  194.                 (getris-repeat-string getris-block-string
  195.                               getris-width)
  196.                 "||")))
  197.     (setq getris-line-length (length getris-blank-line))
  198.     (setq buffer-read-only nil)
  199.     (erase-buffer)
  200.     (let ((i 0))
  201.       (while (< i getris-height)
  202.     (insert getris-blank-line)
  203.     (setq i (1+ i))))
  204.     (insert (concat left-margin-space
  205.             (make-string (+ 4 (* 2 getris-width)) ?=))))
  206.   (random t)                ;randomize by current time
  207.   (catch 'getris-quit-tag
  208.     (getris-main-loop)
  209.     (getris-mode-help)))
  210.  
  211. (defun getris-get-window-size ()
  212.   (setq getris-height (- (window-height) 2))
  213.   (setq getris-left-margin
  214.     (/ (- (window-width)
  215.           (* 2 getris-width)
  216.           4)
  217.        2)))
  218.  
  219. (defun getris-repeat-string (string times)
  220.   (let ((result ""))
  221.     (while (> times 0)
  222.       (setq result (concat string result))
  223.       (setq times (1- times)))
  224.     result))
  225.  
  226. (defun getris-exit ()
  227.   (interactive)
  228.   (set-window-configuration getris-previous-window-configuration))
  229.  
  230. (defun abs (number)
  231.   (if (< number 0)
  232.       (- number)
  233.     number))
  234.  
  235. (defun getris-main-loop ()
  236.   (let ((delay getris-initial-delay)
  237.     (score 0)
  238.     (loop-count 0)
  239.     (center (+ getris-left-margin (logior getris-width 1) -2))
  240.     (disp (/ getris-width 4))
  241.     delay-count
  242.     x y direction kind)
  243.     (while (progn (setq x (+ center (ash (mod (random) disp) 1))
  244.             y -1
  245.             direction (mod (abs (random)) 4)
  246.             piece-num (mod (abs (random)) 7)
  247.             piece-vector (aref getris-piece-data piece-num)
  248.             piece-data (aref piece-vector direction))
  249.           (getris-puttable-p x 0 piece-data))
  250.       (while (getris-puttable-p x (1+ y) piece-data)
  251.     (getris-set-piece x (setq y (1+ y)) piece-data)
  252.     (setq delay (max getris-min-delay
  253.              2
  254.              (- getris-initial-delay
  255.                 (/ loop-count
  256.                    getris-acceleration))))
  257.     (setq delay-count delay)
  258.     (while (> (setq delay-count (1- delay-count))
  259.           0)
  260.       (setq loop-count (1+ loop-count))
  261.       (if (input-pending-p)
  262.           ;; Execute a command.
  263.           ;; Variable values may be modified.
  264.           (funcall (aref getris-command-vector (read-char)))))
  265.     (getris-unset-piece x y piece-data))
  266.       (getris-set-piece x y piece-data)
  267.       (setq score (+ score (car piece-data)
  268.              (getris-test-delete-line y piece-data)))
  269.       (getris-show-score))
  270.     (end-of-line 1)
  271.     (insert "*** GAME OVER ***")
  272.     (setq buffer-read-only t)
  273.     (if getris-high-score-file
  274.     (getris-show-high-score))))
  275.  
  276. (defmacro getris-goto-x-y (x y)
  277.   (`(goto-char (+ (* (, y) getris-line-length)
  278.           (, x)
  279.           1))))
  280.  
  281. (defmacro sit-for-getris (n)
  282.   (`(progn (goto-char (point-min))
  283.        (sit-for (, n)))))
  284.  
  285. (defun getris-puttable-p (x y piece-data)
  286.   (let ((result t))
  287.     (while (and (setq piece-data (cdr piece-data)) result)
  288.       (getris-goto-x-y (+ x (car (car piece-data)))
  289.                (+ y (cdr (car piece-data))))
  290.       (if (not (= (following-char) ? ))
  291.       (setq result nil)))
  292.     result))
  293.  
  294. (defun getris-set-piece (x y piece-data)
  295.   (while (setq piece-data (cdr piece-data))
  296.     (getris-goto-x-y (+ x (car (car piece-data)))
  297.              (+ y (cdr (car piece-data))))
  298.     (delete-char 2)
  299.     (insert getris-block-string)
  300.   (sit-for-getris 0)))
  301.  
  302. (defun getris-unset-piece (x y piece-data)
  303.   (while (setq piece-data (cdr piece-data))
  304.     (getris-goto-x-y (+ x (car (car piece-data)))
  305.              (+ y (cdr (car piece-data))))
  306.     (delete-char 2)
  307.     (insert "  ")))
  308.  
  309. (defun getris-test-delete-line (y piece-data)
  310.   (let ((max-y (+ y (car piece-data)))
  311.     (lines-deleted 0))
  312.     (while (<= y max-y)
  313.       (getris-goto-x-y 0 y)
  314.       (if (looking-at getris-complete-line)
  315.       (progn (setq lines-deleted (1+ lines-deleted))
  316.          (ding)
  317.          (delete-region (point)
  318.                 (progn (next-line 1) (point)))
  319.          (insert getris-blank-line)
  320.          (sit-for 1)
  321.          (delete-region (point)
  322.                 (progn (previous-line 1) (point)))
  323.          (goto-char (point-min))
  324.          (insert getris-blank-line)
  325.          (sit-for-getris 0)))
  326.       (setq y (1+ y)))
  327.     (* lines-deleted lines-deleted lines-deleted)))
  328.  
  329. (defun getris-show-score ()
  330.   (setq global-mode-string (format "Score: %d" score))
  331.   (save-excursion (set-buffer (other-buffer)))
  332.   (set-buffer-modified-p (buffer-modified-p))
  333.   (sit-for 0))
  334.  
  335. (defun getris-show-high-score ()
  336.   (let ((file (substitute-in-file-name getris-high-score-file)))
  337.     (find-file-other-window file)
  338.     (goto-char (point-max))
  339.     (insert (format "  %08d %20s at %s on %s\n"
  340.             score
  341.             (user-full-name)
  342.             (current-time-string)
  343.             (system-name)))
  344.     (sort-fields -1 (point-min) (point-max))
  345.     (goto-line 11)
  346.     (move-to-column 0)
  347.     (delete-region (point) (point-max))
  348.     (write-file file)
  349.     (goto-char (point-min))
  350.     (pop-to-buffer "*Getris*")))
  351.  
  352. (defun getris-move-left ()
  353.   (getris-unset-piece x y piece-data)
  354.   (getris-set-piece
  355.    (if (getris-puttable-p (- x 2) y piece-data)
  356.        (setq x (- x 2))
  357.      x)
  358.    y piece-data))
  359.  
  360. (defun getris-move-right ()
  361.   (getris-unset-piece x y piece-data)
  362.   (getris-set-piece
  363.    (if (getris-puttable-p (+ x 2) y piece-data)
  364.        (setq x (+ x 2))
  365.      x)
  366.    y piece-data))
  367.  
  368. (defun getris-rotate ()
  369.   (let ((new-direction (if (= direction 3)
  370.                0
  371.              (1+ direction))))
  372.     (getris-unset-piece x y piece-data)
  373.     (getris-set-piece
  374.      x y
  375.      (if (getris-puttable-p x y (aref piece-vector new-direction))
  376.      (setq piece-data
  377.            (aref piece-vector (setq direction new-direction)))
  378.        piece-data))))
  379.  
  380. (defun getris-drop ()
  381.   (getris-unset-piece x y piece-data)
  382.   (while (getris-puttable-p x (1+ y) piece-data)
  383.     (setq y (1+ y)))
  384.   (setq delay-count delay))
  385.  
  386. (defun getris-quit ()
  387.   (if (y-or-n-p "Are you sure to quit Getris? ")
  388.       (progn
  389.     (setq buffer-read-only t)
  390.     (throw 'getris-quit-tag (getris-exit)))))
  391.  
  392. (defun getris-boss-has-come ()
  393.   ;; Need improvement.
  394.   (save-window-excursion
  395.     (boss-has-come)
  396.     (local-set-key "\C-c\C-c" 'getris-boss-goes-away)
  397.     (recursive-edit)))
  398.  
  399. (defun getris-boss-goes-away ()
  400.   (interactive)
  401.   (boss-goes-away)
  402.   (exit-recursive-edit))
  403.  
  404. (defun getris-make-piece-data (raw-piece-data)
  405.   (setq getris-piece-data (make-vector (length raw-piece-data) nil))
  406.   (let ((kind 0))
  407.     (while raw-piece-data
  408.       (let ((direction 0)
  409.         (four-list (car raw-piece-data))
  410.         (four-vector (make-vector 4 nil)))
  411.     (while four-list
  412.       (let ((y 0)
  413.         (piece-data nil)
  414.         (max-y 0)
  415.         (lines (car four-list)))
  416.         (while lines
  417.           (let ((x 0)
  418.             (line (car lines))
  419.             (len (length (car lines))))
  420.         (while (< x len)
  421.           (if (= (aref line x) ?#)
  422.               (progn
  423.             (setq piece-data
  424.                   (cons (cons (+ x x) y) piece-data))
  425.             (if (> y max-y)
  426.                 (setq max-y y))))
  427.           (setq x (1+ x)))
  428.         (setq lines (cdr lines)
  429.               y (1+ y))))
  430.         (aset four-vector direction (cons max-y piece-data)))
  431.       (setq four-list (cdr four-list)
  432.         direction (1+ direction)))
  433.     (aset getris-piece-data kind four-vector))
  434.       (setq raw-piece-data (cdr raw-piece-data)
  435.         kind (1+ kind)))))
  436.  
  437. (or getris-piece-data
  438.     (getris-make-piece-data
  439.      '(
  440.        ;; ####
  441.        ( (""
  442.       ""
  443.       "####"
  444.       "")
  445.      (" #"
  446.       " #"
  447.       " #"
  448.       " #")
  449.      (""
  450.       "####"
  451.       ""
  452.       "")
  453.      ("  #"
  454.       "  #"
  455.       "  #"
  456.       "  #"))
  457.        ;; ##
  458.        ;; ##
  459.        ( ("##"
  460.       "##")
  461.      ("##"
  462.       "##")
  463.      ("##"
  464.       "##")
  465.      ("##"
  466.       "##"))
  467.        ;; ##
  468.        ;;  ##
  469.        ( ("##"
  470.       " ##")
  471.      (" #"
  472.       "##"
  473.       "#")
  474.      ("##"
  475.       " ##")
  476.      (" #"
  477.       "##"
  478.       "#"))
  479.        ;;  ##
  480.        ;; ##
  481.        ( (" ##"
  482.       "##")
  483.      ("#"
  484.       "##"
  485.       " #")
  486.      (" ##"
  487.       "##")
  488.      ("#"
  489.       "##"
  490.       " #"))
  491.        ;;  #
  492.        ;; ###
  493.        ( (" #"
  494.       "###")
  495.      (" #"
  496.       "##"
  497.       " #")
  498.      (""
  499.       "###"
  500.       " #")
  501.      (" #"
  502.       " ##"
  503.       " #"))
  504.        ;; ###
  505.        ;; #
  506.        ( (""
  507.       "###"
  508.       "#")
  509.      ("#"
  510.       "#"
  511.       "##")
  512.      ("  #"
  513.       "###")
  514.      (" ##"
  515.       "  #"
  516.       "  #"))
  517.        ;; #
  518.        ;; ###
  519.        ( (""
  520.       "###"
  521.       "  #")
  522.      ("##"
  523.       "#"
  524.       "#")
  525.      ("#"
  526.       "###")
  527.      ("  #"
  528.       "  #"
  529.       " ##"))
  530.        )))
  531.