[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

melting program for Rel 7.

Here's a short program for inclusion in the SLUG library.  I think I
sent this out once before; this version will work in Rel 7.1.
 Share and Enjoy,
 Steve Strassmann
 MIT Media Lab / Thinking Machines Corp.

;;; -*- Mode: LISP; Base: 10.; Package: (HACKS); Syntax: Common-lisp -*-
; Nuclear meltdown
; Written while waiting for some Chinese take-out dinner
; on March 23, 1986, when the US started a war with Libya.
; by Steve Strassmann, MIT Media Lab
; Fixed August 14, 1987 for Release 7, in time for the war with Iran,
; by Steve Strassmann.
; Inspired by a similar hack on the Apple Macintosh, and by Our President.
; Permission is granted for redistribution as long as this header is retained
; in its entirety.
; Send fan mail to straz@media-lab.media.mit.edu.
; To use this file:
;    Call (HACKS:MELT) or do Hyper-M in the editor.
(defun array-width (array)
  (array-dimension-n 2 array))

(defun array-height (array)
  (array-dimension-n 1 array))
; Install hack in useful places

; Install on Hyper-M in the editor. Numeric argument speeds the meltdown.
; Hyper-super-M melts the wholine.
; Hyper-refresh cleans up the mess.
(defun zwei:com-melt ()
  "Gee, Steve, your screen is getting all melty!"
  (melt zwei:*numeric-arg*))

(defun zwei:com-melt-wholine ()
  "Why neglect the wholine?"
  (melt zwei:*numeric-arg* tv:who-line-screen))

(defun zwei:com-refresh-sheet ()
  "Cleans down to the last pixel for a bright, no-wax shine."
  (send tv:main-screen :refresh)
  (send tv:who-line-screen :refresh)

(zwei:set-comtab zwei:*standard-comtab*
		 '(#\h-M zwei:com-melt))	        ; hyper-M
(zwei:set-comtab zwei:*standard-comtab*
		 '(#\s-h-M zwei:com-melt-wholine))	; super-hyper-M
(zwei:set-comtab zwei:*standard-comtab*
		 '(#\h-refresh zwei:com-refresh-sheet))	; hyper-refresh

(defun melt (&optional (speed 1) (window tv:main-screen))
  "What happens when you drain the freon out of a Cray"
  (loop with array = (send (send window :screen) :screen-array)
	for left = (pick-column array)
	for bottom = (pick-bottom left array)
	for drop = (pick-drop left bottom speed array)
	for width = (pick-width left bottom drop array)
	for ok? = (and (plusp bottom) (plusp drop) (plusp width))
	for top = (and ok? (random bottom))
	for height = (and ok? (- bottom top))
	if ok?
	  do (bitblt tv:alu-seta width (- height)
		     array left top array left (+ drop top))))	; Copy melt portion of screen

(defun pick-column (array)
  "Pick a likely left edge to melt"
  (random (array-width array)))

(defun pick-bottom (column array)
  "Pick a white pixel in column to get melted"
  (loop for try from 0
	for y = (1+ (random (1- (array-height array))))
	for pixel = (aref array y column)
	until (zerop pixel)
	if (= try 5) return 0			; Don't waste your time on this column
	finally (return y)))			; Found a good bottom

(defun pick-drop (column bottom speed array)
  "Pick how far to drop melted column"
  (if (< bottom 2) 1
      (loop for drop from 0 below (min speed (- (array-height array)
						1 bottom))	; Not too far down
	    for pixel = (aref array (+ bottom drop) column)
	    until (plusp pixel)
	    finally (return drop))))

(defun pick-width (left bottom drop array)
  "Move rightwards until you hit a black pixel"
  (loop for x from left to (random (- (array-width array) left))
	for black-pixel? = (loop for y from bottom to (+ bottom drop)
				 for pixel = (aref array y x)
				 if (plusp pixel)
				   do (return t))
	until black-pixel?
	finally (return (- x left 1))))