It's Valentines Day. The only one you ever loved left you yesterday for this guy she always found "stupid and uninteresting". On your way home, you've been stuck in traffic, listening to old songs on the radio, the rain hitting the windscreen is rocking you. After a while in your car, you find yourself alone in your small apartment being unable to think of something else but her. There is no light and you stare trough the window, letting darkness surrounds you. There is no one to talk to, your friends are now gone a long time ago after warning you about this new girl haunting your mind. You start up your computer, as it's the only thing you can do, open your browser and post a new programming puzzle to stackexchange, in an attempt to change your mind.


Write a program in the language of your choice simulating the rain which falls on the ground. The output can be composed of ASCII characters or 2D/3D rendered. The camera is fixed : you are above looking straight to the ground. Your program must includes some kind of animation like refreshing the console or the page each time you generate a new "frame". It has to be realistic, I know it's a bit subjective but let's say you can't just fill all the ground in only one big drop.

The output don't have to be an image but if you're using cryptic language it's better to provide a .gif to illustrate how it looks in action (but of course, it will not affect your score if you don't).


  • Your score is the total of bytes used
  • -20 points if you use colours
  • -50 if you achieve to render some kind of wind
  • Lowest score wins


A very basic example of what should be rendered:

I hope you'll do better and enjoy this challenge.

Sorry for my english, feel free to edit my post if you want to correct some errors

Leader board

If your name is not listed it's because your attempt has been considered not fitting the rules.

Tobia - APL - 35  
j6m8 - Processing.js - 38
The Guy with The Hat - Processing - 42  
ace - Processing - 74  
kelunik - JS/CSS - 89  
Riot - Bash - 91  
Michael - JS/jQuery - 105  
Florent - HTML/JS - 123  
David Carraher - Mathematica - 134  
Doorknob - HTML/JS - 150  
undergroundmonorail - Python - 175

Congratulations to Tobia !

  • 52
    \$\begingroup\$ I sincerely hope the first paragraph isn't a true story. \$\endgroup\$ Commented Feb 13, 2014 at 20:53
  • 1
    \$\begingroup\$ @DavidCarraher yes, like you're in the sky looking at the floor. \$\endgroup\$
    – user16229
    Commented Feb 14, 2014 at 10:12
  • 8
    \$\begingroup\$ I don't think this should be code-golf as there's too much leniency on the potential outputs \$\endgroup\$
    – Cruncher
    Commented Feb 14, 2014 at 13:56
  • 4
    \$\begingroup\$ The first paragraph along with the camera position for this rendering is quite macabre. \$\endgroup\$
    – Tobia
    Commented Feb 14, 2014 at 19:09
  • 3
    \$\begingroup\$ "stupid and uninteresting" \$\endgroup\$
    – user7906
    Commented Feb 14, 2014 at 21:52

15 Answers 15


Bash: 111 bytes - 20 = 91 points!

A contemplative gentle drizzle in your terminal. Adjust the numbers 819 and 41 for different height and width respectively.

e='printf \e';while :;do for i in {0..819};do((RANDOM<9))&&$e[1\;36m.||$e[1C;((i%41<1))&&$e'


A pleasant bonus is the way the cursor pitter-patters across the rain area.

Edit: shortening from 140 bytes to 129 bytes thanks to @manatwork's suggestions. 2nd edit: shortening from 129 bytes to 111 bytes thanks to @manatwork's and @Tobia's suggestions, plus additional inspiration - see comments.

(Note: screenshot shows previous less-golfed version of the code, which is functionally identical)

  • 1
    \$\begingroup\$ You can spare: 2 characters by joining echo's options; 2 characters by using \e instead of \033; 3 characters by using : instead of true; 5 characters by using arithmetic evaluation (((…))): e='echo -ne \e';while :;do for i in {0..19};do for i in {0..40};do ((RANDOM<9))&&$e"[1;36m".||$e[1C;done;$e' ';done;$e[20A;done. \$\endgroup\$
    – manatwork
    Commented Feb 14, 2014 at 9:46
  • 1
    \$\begingroup\$ You not need the sigil inside arithmetic evaluation. And there must be a trailing newline at the end of your code. Should be only 127 characters. \$\endgroup\$
    – manatwork
    Commented Feb 14, 2014 at 17:46
  • 1
    \$\begingroup\$ I believe what @manatwork means is that you don't need to use the dollar sign inside double parentheses: ((RANDOM<9)) works just as well. Also, you could try shrinking your code by combining the two for {0..19} and {0..40} into a single for {0..819}, using something like $((i%41)) inside it. \$\endgroup\$
    – Tobia
    Commented Feb 14, 2014 at 19:24
  • 1
    \$\begingroup\$ Someone stop me!! e='printf \e' is 2 char shorter than e='echo -ne \e'! \$\endgroup\$
    – Tobia
    Commented Feb 14, 2014 at 19:34
  • 1
    \$\begingroup\$ And trim another char by using $e[C \$\endgroup\$
    – Tobia
    Commented Feb 14, 2014 at 19:47

Python, 312 bytes - 50 (wind) = 262

from pygame import*
a=[[R(0,t),R(0,u),R(3,6)]for i in r]
while time.wait(9):
 d.flip();event.get();s.fill(R(0,99)<1and w)
 for i in r:x,y,z=a[i];draw.line(s,w,(x,y),(x+z,y+2*z));a[i][0]=(x+z)%t;a[i][1]=(y+z*2)%u

Sample output (a 50-frame loop):

Actual playpack is significantly faster than gifs allow.

  • 3
    \$\begingroup\$ @ChristianCareaga I could, but I think white looks better. \$\endgroup\$
    – primo
    Commented Feb 14, 2014 at 7:53
  • 8
    \$\begingroup\$ Only problem in my eyes: You're viewing the rain from the side, while the rules state a fixed camera looking straight down. \$\endgroup\$ Commented Feb 14, 2014 at 9:13
  • 7
    \$\begingroup\$ @JohannesH. Or, it's a very, very windy day. \$\endgroup\$
    – primo
    Commented Feb 14, 2014 at 9:16
  • 20
    \$\begingroup\$ I like the occasional flashes of lightning! :P \$\endgroup\$ Commented Feb 14, 2014 at 16:56
  • 3
    \$\begingroup\$ One character gets saved by using R=__import__("random").randint instead of the from random... line. \$\endgroup\$
    – SimonT
    Commented Feb 15, 2014 at 6:29

HTML / JS, 170 chars - 20 = 150 points

<canvas id=c></canvas><script>d=400;with(c)width=height=d,t=getContext('2d');t.fillStyle='blue';setInterval("t.fillRect(Math.random()*d,Math.random()*d,5,5)",50)</script>

(sidenote: golfed further by passing a string to setInterval, with, automatic ID variable names... it feels so wrong! shudders)

It just draws random blue rectangles.

HTML / JS, 309 chars - 20 - 50 = 239 points

Now with wind!

<canvas id=c></canvas><script>s=400;r=Math.random;with(c)width=height=s,t=getContext('2d');t.fillStyle='blue';o=[];setInterval("t.clearRect(0,0,s,s);for(i=0;++i<o.length;)d=o[i],t.fillRect(d[0],d[1],d[2],d[2]),d[0]+=1,d[1]+=2,d[2]-=1,d[2]<0?o.splice(i,1):0;if(r()<.6)o.push([r()*400,r()*400,20])",50)</script>

  • \$\begingroup\$ 163 bytes: <canvas id=c /><script>d=400;with(c)width=height=d,t=getContext('2d');t.fillStyle='blue';setInterval("t.fillRect(Math.random()*d,Math.random()*d,5,5)",50)</script> AAAHHH! I used with! I feel dirtier than passing a string to setInterval :p \$\endgroup\$ Commented Feb 13, 2014 at 23:23
  • \$\begingroup\$ @NiettheDarkAbsol Thanks ;) It seems that (on Chrome at least) canvas can't auto-close, but other than that that works perfectly! (Also, using automatic ID variable names feels so dirty as well :D) \$\endgroup\$
    – Doorknob
    Commented Feb 13, 2014 at 23:29
  • \$\begingroup\$ Some browsers seem more lenient in that area... But it avoids having to use onload. I must say I like @Florent's way of avoiding the duplicate Math.random() \$\endgroup\$ Commented Feb 13, 2014 at 23:30
  • \$\begingroup\$ @Doorknob canvas autoclose in Chrome! My answer was developed/tested in this browser. \$\endgroup\$
    – Florent
    Commented Feb 14, 2014 at 7:57
  • 1
    \$\begingroup\$ Upvote for the second one, with the drips sinking into the ground/puddle. \$\endgroup\$ Commented Feb 16, 2014 at 7:58

JS + jQuery (172-20-50 = 102)

Copy/Paste that line in the browser console (generally press F12 key) :


Animated red hearts rain for Valentine's day !

enter image description here

  • 1
    \$\begingroup\$ well, it's not realistic. Hearts are coming from the top of the screen and stick to random positions of the page. That does not really match the point of view condition. \$\endgroup\$
    – user16229
    Commented Feb 14, 2014 at 10:39
  • 10
    \$\begingroup\$ AUGGGGHH! How do I stop it?! \$\endgroup\$ Commented Feb 14, 2014 at 15:54
  • 1
    \$\begingroup\$ @user2509848 But is there any other way? \$\endgroup\$ Commented Feb 14, 2014 at 16:54
  • 3
    \$\begingroup\$ @TheGuywithTheHat, reload the page \$\endgroup\$
    – Michael M.
    Commented Feb 14, 2014 at 18:42
  • 19
    \$\begingroup\$ Brilliant! I think this captures the heart of the question. \$\endgroup\$
    – andrewb
    Commented Feb 14, 2014 at 23:17

APL, 105 chars/bytes* – 20 – 50 = 35 score

e¨'36m' '?25l' '2J'
e⍵';'c'H',' .∘⍟'[⍺]}¨⍳t
∇0⌈⍵-1}0⍴⍨t←24 80

*: Most APL implementations support some form of (legacy) single-byte charset, that maps APL symbols to the upper 128 byte values. Therefore, for the purpose of golfing, a program that only uses ASCII characters and APL symbols can be scored as chars = bytes.

I tested it on Nick's latest apl.js on Node.js in an OS X terminal. But I haven't used anything specific to his dialect, so it should work on any modern APL that can be run on an ANSI terminal and supports d-funs {...}, strand assignment (a b)←..., and commute , such as Dyalog for Linux or for Raspberry PI (with ⎕IO←0)

The in line 1 is a literal escape character (which is 1 byte). You can input it using Ctrl-V Esc in a Linux terminal or in Vim, or supposedly something like Alt-027 in Windows. Also, I couldn't find a reliable way to discover the terminal size, so you might want to edit the number of rows and columns at the end of the last line.

I defend the 50 bonus by the fact that each raindrop goes through the following shapes: ⍟∘. which give the impression of a slight downwards wind, given that the scene is being looked at from above. In fact, looking at the gif below, you should get the impression that each drop is gently moving downwards and to the left, before disappearing on the ground.

Ungolfed version:

e←{⍞←∊"␛["⍵}                  # utility to print escape sequence
e¨'36m' '?25l' '2J'            # set cyan, hide the cursor and clear screen
{                              # repeat (⍵=current board of raindrops)
  ⍵←3⌊⍵+3×0=?t⍴50              #   add some new drops (=3) in random places
  ⍵{                           #   print the drops (⍺=drop value, ⍵=coords)
    (r c)←⍕¨⍵+1                #     convert the coordinates to string
    e r';'c'H',' .∘⍟'[⍺]       #     print or clear the drop
  }¨⍳t                         #   ..
  ∇0⌈⍵-1                       #   remove 1 from every drop and repeat
}0⍴⍨t←24 80                    # ..starting with an empty board


enter image description here

APL, different style

Out of competition.

m←×/t←1+(ζη)←2×(βγ)←24 80
e←{⍞←∊(⎕UCS 27)'['⍵}
e¨'2J' '36m' '?25l'
' 'p(~⍵)∧0,⍵[1+⍳ζ;⍳η]⍪0

Here my aim was to give the impression of raindrops falling with a slant and accumulating on the ground, while trying to keep the number of visible drops (either falling or splattered) constant on average. The trick was to create a number of new falling drops / at every cycle and having the falling drops "wipe out" any splattered ones they travel across.

The result is strangely reminiscent of the Matrix code.

(the jerk every 5s is the gif looping)

enter image description here

  • \$\begingroup\$ This is nice, but I don't think the ESC character is being printed right. i.sstatic.net/vLERQ.png I tried pasting the code with gedit too, didn't work. \$\endgroup\$
    – Riking
    Commented Feb 15, 2014 at 2:11
  • \$\begingroup\$ You got your score wrong. The question says "bytes", not "chars". \$\endgroup\$
    – jazzpi
    Commented Feb 15, 2014 at 9:37
  • 1
    \$\begingroup\$ @Riking I edited that part. If you try it again it should work. \$\endgroup\$
    – Tobia
    Commented Feb 15, 2014 at 12:44
  • \$\begingroup\$ @Tobia Show me a picture of you sitting at your IBM 5100, and I'll buy the chars = bytes argument. \$\endgroup\$
    – primo
    Commented Feb 15, 2014 at 14:26
  • 4
    \$\begingroup\$ @primo imageshack.com/a/img811/314/86dt.jpg \$\endgroup\$
    – Tobia
    Commented Feb 15, 2014 at 17:25


134 - 20 = 114


n = 99; m = Array[0 &, {n, n}]; r := RandomInteger[{1, n}, {2}]
Table[ArrayPlot[m = ReplacePart[m, r ->  1], ColorRules -> {1 -> Blue}], {k, 250}];
Export["d.gif", d]



The raindrop shape is made via a revolution plot around the z axis.

Initially, rain is generated for a region that extends well above the display region. The appearance of falling rain is achieved by shifting the Viewpoint upwards along the z-axis. (It is more efficient than recalculating the position of each raindrop.)


r = RandomInteger; z = Table[{r@30, r@30, r@160}, {100}];
w = RevolutionPlot3D[{.7 Sin[x] Cos[x], 0,   1.4 Sin[x] }, {x, 0, -Pi/2}, 
PerformanceGoal -> "Speed"][[1]];
c = Map[Translate[w, #] &, z]; 
p = Table[Graphics3D[c, PlotRange -> {k, k + 50}], {k, 1, 100}]
Export["p.gif", p]

With Wind

There is considerable overhead to making the rain fall with wind. But I'm including here anyway.

The blue floor pretty much keeps {x,y} view region confined to the area of interest. There are some glitches, but, oh well,

r = RandomInteger;
z = Table[{r@120, r@30, r@180}, {800}];
w = RevolutionPlot3D[{.7 Sin[x] Cos[x], 0,   1.4 Sin[x] }, {x, 
     0, -Pi/2}, PerformanceGoal -> "Speed"][[1]];
c = Map[Translate[w, #] &, z];
g[k_, z1_, w_, c1_] :=
  z2 = Cases[z, {x_, _, _} /; 0 + k < x < 30 + k];
  c = Map[Translate[w, #] &, z2];
  Graphics3D[{Polygon[{{0 + k, 0, 1 + k}, {30 + k, 0, 1 + k}, {30 + k,
        30, 1 + k}, {0 + k, 30, 1 + k}}], c}, 
   PlotRange -> {k, k + 50}]]

p = Table[g[k, z, w, c], {k, 1, 100, 1}];
Export["p.gif", p]

with wind

From Directly Above

The closest raindrops are clipped but I'll overlook that.

from above 3D

ImageSize-> 350,Sphere/@Cases[pos,{_,_,z1_}/;lowZ<z1<hiZ-2]},PlotRange->{lowZ,hiZ}, 
ViewPoint-> {0,0,1},ImagePadding->5]]
  • \$\begingroup\$ Shift it to the side in under 50 characters and you lower your score. :) \$\endgroup\$ Commented Feb 14, 2014 at 18:47
  • 1
    \$\begingroup\$ I love this one \$\endgroup\$
    – user16229
    Commented Feb 15, 2014 at 16:37
  • \$\begingroup\$ +1 for the last one, with the correct camera angle BUT you forgot that the camera blocks some of the rain.... ;) \$\endgroup\$ Commented Feb 16, 2014 at 7:59
  • \$\begingroup\$ @GreenAsJade, The clipping for the 3D (from above) viewpoint is now fixed. \$\endgroup\$
    – DavidC
    Commented Feb 17, 2014 at 16:54
  • \$\begingroup\$ Sweet, but I was being more frivolous than you thought. I was meaning that there is a physical camera looking down at this, so it should be blocking some of the raindrops :%) \$\endgroup\$ Commented Feb 18, 2014 at 0:06

HTML / JavaScript, 156 123 (143 - 20)

<body bgcolor=0 onload="t=c.getContext('2d');t.fillStyle='#07d';setInterval('n=Math.random()*4e4;t.fillRect(n%270,n/150,1,1)',1)"><canvas id=c>

Annotated version:

<body bgcolor="#000">
<canvas id="c"></canvas>
  onload = function() {
    // Retrieve the rendering context
    // Set rain color
    // Render whenever it is possible
    setInterval(function() {
      // Generate a number between 0 and 40,000
      // 40,000 ~= 270 * 150
      // Draw a raindrop.
      // Since x and y are not rounded, the raindrop looks blurry!
    }, 1);

Smalltalk (Smalltalk/X)

with random wind ;-)

|BG CLR N1 H W v WIND drops gen newDrops draw remove move buffer|

BG := Color black.
CLR := Color blue lightened.
H := 100.
W := 100.
N1 := 10.
WIND := 0.
drops := OrderedCollection new.

gen := [:n | ((1 to:n) collect:[:i | Random nextIntegerBetween:1 and:W] as:Set) collect:[:x | x@0]].
newDrops := [drops addAll:(gen value:N1)].
draw := [buffer fill:BG; paint:CLR. drops do:[:d | buffer displayPoint:d]].
remove := [drops := drops reject:[:d | d y > H]].
move := [:wind | drops := drops collect:[:d| (d x + wind)\\W @ (d y + 1)]].
v := View new openAndWait.
buffer := Form extent:(v extent) depth:24 onDevice:v device.

    [v shown] whileTrue:[
        draw value.
        v displayForm:buffer.
        move value:WIND.
        remove value.
        newDrops value.
        WIND := (WIND+(Random nextBetween:-1 and:1)) clampBetween:-5 and:5.
        Delay waitForSeconds:0.1.
] fork.

output in view: enter image description here

  • 6
    \$\begingroup\$ It does not qualify since it's a side view of the rain falling, and not the rain hitting the ground. Still a nice wind effect. \$\endgroup\$
    – user16229
    Commented Feb 14, 2014 at 10:11

Processing, 94 - 20 = 74

void setup(){background(0);fill(0,0,255);}
void draw(){ellipse(random(0,99),random(0,99),3,3);}

(New line added for readability.)

Click here for an online demo.

  • 1
    \$\begingroup\$ Processing is really good for problems like these. \$\endgroup\$
    – cjfaure
    Commented Feb 13, 2014 at 21:01
  • \$\begingroup\$ Cannot view it in Firefox, default security settings block the Java applet and it doesn't tell me how to override. AFAIK there is a Processing.js port to JavaScript, if you could convert it to JS and post a link I'd be thankful. \$\endgroup\$
    – marczellm
    Commented Feb 14, 2014 at 17:06
  • \$\begingroup\$ @marczellm I'm using Firefox 27.0 on Ubuntu and it works fine. Are you sure there are no prompts asking you whether to allow or block the plugin? I will take a look at a JS version as well. \$\endgroup\$
    – user12205
    Commented Feb 14, 2014 at 17:11
  • \$\begingroup\$ @ace After I tell all promps to "allow", a security message still blocks it. Thanks for the JS version. \$\endgroup\$
    – marczellm
    Commented Feb 14, 2014 at 17:21
  • 1
    \$\begingroup\$ @marczellm added the javascript version into the answer, enjoy :) and just a blind guess, maybe your current java plugin version is outdated and has known security issues \$\endgroup\$
    – user12205
    Commented Feb 14, 2014 at 17:21


while true;do echo " / / / / /";echo "/ / / / / ";done

I'm not sure this should be a code golf because there isn't a strict requirement on what the "rain" must look like.

EDIT: If you want it to look like the camera is pointing straight down use this:

while true;do echo " . . . . .";echo ". . . . . ";done
  • 7
    \$\begingroup\$ "The camera is fixed : you are above looking straight to the ground." This appears to be viewing the rain from the side? \$\endgroup\$ Commented Feb 13, 2014 at 21:25
  • 2
    \$\begingroup\$ Save 9 characters: while echo \ / / / / /;do echo / / / / /;done (or a few more with a recursive function but that'll quickly blow up the stack). @undergroundmonorail Strong wind, diagonal relative to the camera. \$\endgroup\$ Commented Feb 14, 2014 at 4:27
  • \$\begingroup\$ @Gilles In that case, we can do while echo -e '\e[0;34m / / / / /';do echo / / / / /;done and get it down to -13 with bonuses :) \$\endgroup\$ Commented Feb 14, 2014 at 5:19
  • 4
    \$\begingroup\$ that's defintely not looking like rain :D \$\endgroup\$
    – Kiwy
    Commented Feb 14, 2014 at 9:14
  • 5
    \$\begingroup\$ I don't really think this should be considered as an answer. In short: It's not realistic. Detailed argument: If I interpreted the question correctly, the rain should fall randomly (or at least pseudo-randomly) and, over a long period of time, the distribution should be similar per unit area. (This is how rain works, right?) However in this answer, it is guaranteed that there will be no rain drops next to any rain drop, so if we take the unit area to be the area of one character, we see that the distribution is uneven. \$\endgroup\$
    – user12205
    Commented Feb 14, 2014 at 17:07

Python 2.7: 195 - 20 = 175

I'm sure there's more that can be done here, but this is what I've got for now:

import os,time
from random import*
l=[i[:]for i in[[' ']*100]*50]
while 1:
 print'\033[94m\n'.join(''.join(r)for r in l)

I'll post a gif of the output when I remember how to do that.

This works on linux. Replacing 'clear' with 'cls' makes it work on windows, but then ANSI colours don't work and I lose the bonus.

I have a 2D array of one-character strings, initialized to . Every 0.05 seconds, one of them is chosen at random set to ., and the screen is redrawn.

from random import* saves two characters over import os,time,random and using random.randint() twice, though I'm not convinced that's the best way to choose a cell anyway. I wanted to use random.choice() but I couldn't think of a way around immutable strings that wouldn't waste more characters than it saved.

  • 3
    \$\begingroup\$ l=[i[:]for i in[[' ']*100]*50], as per stackoverflow.com/a/6688361/1114687. 198 - 20 = 178 \$\endgroup\$
    – n.st
    Commented Feb 14, 2014 at 2:10
  • \$\begingroup\$ Oh, wow, I've never seen that before. If I'm reading it correctly, the slice notation does nothing except ensure that it's a unique list and not another reference to the same one, correct? That's really cool! Thank you! \$\endgroup\$ Commented Feb 14, 2014 at 5:09
  • \$\begingroup\$ I originally tried l=[[' ']*100]*50, but that just creates 50 references to the same 100-element list, so I searched for the shortest possible way to circumvent that and found the Stack Overflow answer linked above. \$\endgroup\$
    – n.st
    Commented Feb 14, 2014 at 18:10

132 + 27 - 20 - 50 = 89

Javascript (132)


CSS (27)


Demo: http://jsfiddle.net/kelunik/5WC87/4/embedded/result/

  • \$\begingroup\$ It's from side view, it does not qualify for the moment. \$\endgroup\$
    – user16229
    Commented Feb 14, 2014 at 16:53
  • \$\begingroup\$ @BenH You're right, missed that point, new version is in my answer now. \$\endgroup\$
    – kelunik
    Commented Feb 14, 2014 at 17:07
  • \$\begingroup\$ seems like nothing happens when trying your code in firefox console :/ \$\endgroup\$
    – user16229
    Commented Feb 14, 2014 at 17:49
  • \$\begingroup\$ @BenH That's why there's a jsfiddle-demo. \$\endgroup\$
    – kelunik
    Commented Feb 14, 2014 at 17:54

Processing, 62 - 20 = 42

void draw(){stroke(0,0,214);point(random(0,99),random(0,99));}

Generates blue pixels on a white background. Demonstration in a very similar language here: https://www.khanacademy.org/cs/rain2/6172053633761280

  • \$\begingroup\$ Obligatory +1 for extreme terseness. \$\endgroup\$
    – primo
    Commented Feb 17, 2014 at 13:54

Processing.js, 86 - 20 = 66

...but it also slowly fades out (the ground absorbs the rain, naturally). Points for that?

g=99;r=random;void draw(){fill(0,9);rect(0,0,g,g);fill(0,g,r(g));rect(r(g),r(g),2,2);}

Bonus features include varying between greenish and blueish (it's clearly dirty 'city' rain).

Also, I was very pleased that I got to use a JavaScript hack in here; Note that, because this is processing.js, you can throw in things like the typeless declaration of g=99, or the alias of r for random (cross-language alias!).

Any other ideas to minify?

Readable version:

g = 99;
r = random;                  // Javascript trickery
void draw() {
    fill(0, 9);
    rect(0, 0, g, g);        // Fade the background
    fill(0, r(g), r);
    rect(r(g), r(g), 2, 2);  // Add a new drop

The whole thing can be viewed here.

...plus another version without fade: 58 - 20 = 38

If you don't like fading and don't mind grey dirt:

r=random;void draw(){fill(0,0,255);rect(r(99),r(99),2,2);}

Tcl/Tk, 139 - 20 = 119

Reusing my own answer http://codegolf.stackexchange.com/a/143018/29325

Must be run in the interactive shell

gri [can .c -w 40 -he 40]
set x 0
wh 1 {.c cr o $x [set y [exp int(rand()*40)]] $x [set x $y] -f #[form %06x [exp int(rand()*255**3)]]

Unfortunately, converting expr int(rand()* into a proc makes the script have one byte more!

enter image description here

To stop, one just needs to click the ineffable "X" button.