EUREKA!

After searching the books I have and not finding quite what I
thought I would, I decided to experiment.  After looking at
the picture again it seemed that standard DLA would not do.
I think I could modify a DLA program to produce something like
that and I'm sure it could also be done with some percolation
model, but the algorithm I found is probably the simplest.
Actually I found two methods that produce the same result.
The second one is simpler and faster but doesn't keep
a record of the whole picture.

I started coding in C, but soon realized that recompiling
ever time I made a little change would soon take all the
fun out. So here they are in BASIC for the QBasic interpreter.

#1: Drop particles straight down at random x values from higher than the
    highest part of the aggregate, looking at the 3 sites below, sticking
    when one of them is filled.

#2: Just keep track of y for the highest particle at each x value, look
    for the maximum of the values at x-1, x, x+1 for random x, use that
    plus one as y for the new particle.

The third program is for comparison.

RANDOMIZE TIMER
SCREEN 12: WINDOW (-320, 239)-(319, -240): CLS
w = 120: h = 120: d = 1: m = 14: p = 1
DIM s(w + 1, h + 1)
FOR x = 0 TO w
   FOR y = 0 TO h
      s(x, y) = 0
   NEXT y
NEXT x
WHILE d <= h
   x = INT(RND * (w - 1)) + 1
   y = d
   c = 0
   WHILE y <> 0 AND c = 0
      IF p = 1 THEN PSET (x, y), 15
      c = s(x, y - 1)
      IF c = 0 THEN c = s(x - 1, y - 1)
      IF c = 0 THEN c = s(x + 1, y - 1)
      IF INT(RND * 2) = 1 AND s(x + 1, y - 1) <> 0 THEN c = s(x + 1, y - 1)
      IF p = 1 THEN PSET (x, y), 0
      IF c = 0 THEN y = y - 1
   WEND
   IF c = 0 THEN c = (x MOD m) + 1
   s(x, y) = c
   PSET (x, y), c
   IF y = d - 1 THEN d = d + 1
WEND



RANDOMIZE TIMER
SCREEN 12: WINDOW (0, 479)-(639, 0): CLS
w = 640: h = 480: d = 1: m = 14
DIM s(w + 1), c(w + 1)
FOR x = 0 TO w
   s(x) = 0
   c(x) = 0
NEXT x
WHILE d <= h
   x = INT(RND * (w - 1)) + 1
   f = x
   IF s(f) < s(x - 1) THEN f = x - 1
   IF s(f) < s(x + 1) THEN f = x + 1
   IF INT(RND * 2) = 1 AND s(f) = s(x + 1) THEN f = x + 1
   s(x) = s(f)
   c(x) = c(f)
   IF c(x) = 0 THEN c(x) = (x MOD m) + 1
   PSET (x, s(x)), c(x)
   s(x) = s(x) + 1
   IF s(x) = d THEN d = d + 1
WEND



SCREEN 12
RANDOMIZE TIMER
PRINT "initializing"
w = 100: h = 100: m = 14: n = INT(w * h / 4)
DIM r(n), s(w + 1), c(w + 1), i(w + 1, h + 1)
FOR t = 0 TO n
   IF t MOD 100 = 0 THEN PRINT ".";
   r(t) = INT(RND * (w - 1)) + 1
NEXT t
FOR x = 0 TO w
   PRINT ".";
   s(x) = 0
   c(x) = 0
   FOR y = 0 TO h
      i(x, y) = 0
   NEXT y
NEXT x
CLS
WINDOW (-320 + w + 10, 239)-(319 + w + 10, -240)
d = 1: t = 0: p = 1
LOCATE 1, 1: PRINT TIME$
WHILE d <= h AND t < n
   x = r(t): t = t + 1: LOCATE 2, 1: PRINT t
   y = d
   c = 0
   WHILE y <> 0 AND c = 0
      IF p = 1 THEN PSET (x, y), 15
      c = i(x, y - 1)
      IF c = 0 THEN c = i(x - 1, y - 1)
      IF c = 0 THEN c = i(x + 1, y - 1)
      IF i(x + 1, y - 1) <> 0 AND r(t) MOD 2 = 1 THEN c = i(x + 1, y - 1)
      IF p = 1 THEN PSET (x, y), 0
      IF c = 0 THEN y = y - 1
   WEND
   IF c = 0 THEN c = (x MOD m) + 1
   i(x, y) = c
   PSET (x, y), c
   IF y = d - 1 THEN d = d + 1: PSET (-5, d), 15
WEND
WINDOW (-320, 239)-(319, -240)
d = 1: t = 0
LOCATE 3, 1: PRINT TIME$
WHILE d <= h AND t < n
   x = r(t): t = t + 1: LOCATE 4, 1: PRINT t
   f = x
   IF s(f) < s(x - 1) THEN f = x - 1
   IF s(f) < s(x + 1) THEN f = x + 1
   IF s(f) = s(x + 1) AND r(t) MOD 2 = 1 THEN f = x + 1
   s(x) = s(f)
   c(x) = c(f)
   IF c(x) = 0 THEN c(x) = (x MOD m) + 1
   PSET (x, s(x)), c(x)
   s(x) = s(x) + 1
   IF s(x) = d THEN d = d + 1: PSET (-5, d), 15
WEND
LOCATE 5, 1: PRINT TIME$


Some books that briefly mention aggregation or percolation and have
a picture or two of generated clusters:

1. FractalVision
   Dick Oliver

2. The Science of Fractal Images
   Heinz-Otto Peitgen & Dietmar Saupe  Editors

3. Islands of Truth
   Ivars Peterson

4. The Mathematical Tourist
   Ivars Peterson

5. Fractals, Chaos, Power Laws
   Manfred Schroeder

6. Does God Play Dice?
   Ian Stewart

7. Cellular Automata Machines
   Tommaso Toffoli & Norman Margolus



Books with the most about aggregation and percolation:

8. Fractals
   Jens Feder

9. Fractal Growth Phenomena (Second Edition)
   Tamas Vicsek

Number 8 is the book that inspired me a few years ago to write a program
I called RFCGDLAS. (which obviously stands for Random Fractal Cluster
Generating Diffusion Limited Aggregation Simulation ;-)

Number 9 is the book that prompted me on Friday to try ballistic aggregation.

And finally, after I wrote my ballistic aggregation programs, I looked
through my Algorithm magazines and found an ad in November 1990 issue:

------------------------------------------------------------------------
Generate your own fractals using BALLISTIC           \\\\\\\\\\\\\\\\\
AGGREGATION TECHNIQUES.  Beautiful                   \  small and    \
fractals resemble coral, bushes, trees and           \  blocky black \
mountains.  In color on EGA or VGA.  Many            \  and white    \
hours of fun and education.  Menus and Help          \  graphic here \
plus hot keys provide ease of use.  Introductory     \               \
offer: $25.00                                        \               \
Contact:   FRACTAL RECREATIONS                       \\\\\\\\\\\\\\\\\
           21 Wichard Blvd.
           Commack, NY 11725-1706                 (516) 543-3850
------------------------------------------------------------------------

Although the picture is small and not colored, this is probably what
I remember seeing that I thought was in a book!  Or maybe it was
something in Science News.......
The world may never know.


PS:

Here's the C++ for the graphics if you want it ...

#include "Xwin.h"
#include <stdlib.h>

main()
{
   const int w = 640, h = 480;
   short int f, x, d = 1, m = 14, s[w+1], c[w+1];
   cout << "rand seed: ";
   cin >> f;
   srand(f);
   Xwin ba("Ballistic Aggregation", w, h, 1);
   ba.clear();
   for(x = 0; x <= w; x++)
      s[x] = c[x] = 0;
   while(d <= h)
   {
      x = rand()%(w-1) + 1;
      f = x;
      if(s[f] < s[x-1])
         f = x - 1;
      if(s[f] < s[x+1])
         f = x + 1;
      if(s[f] == s[x+1] && rand()/2%2)
         f = x + 1;
      s[x] = s[f];
      c[x] = c[f];
      if(!c[x])
         c[x] = x%m + 1;
      switch(c[x])
      {
         case 1: ba.change_color("gold"); break;
         case 2: ba.change_color("orange"); break;
         case 3: ba.change_color("yellow"); break;
         case 4: ba.change_color("deep pink"); break;
         case 5: ba.change_color("red"); break;
         case 6: ba.change_color("magenta"); break;
         case 7: ba.change_color("cyan"); break;
         case 8: ba.change_color("blue"); break;
         case 9: ba.change_color("coral"); break;
         case 10: ba.change_color("orchid"); break;
         case 11: ba.change_color("aquamarine"); break;
         case 12: ba.change_color("maroon"); break;
         case 13: ba.change_color("cornflower blue"); break;
         case 14: ba.change_color("violet red"); break;
//  alternative palette
//         case 1: ba.change_color("slate blue"); break;
//         case 2: ba.change_color("sky blue"); break;
//         case 3: ba.change_color("turquoise"); break;
//         case 4: ba.change_color("cyan"); break;
//         case 5: ba.change_color("aquamarine"); break;
//         case 6: ba.change_color("sea green"); break;
//         case 7: ba.change_color("cornflower blue"); break;
//         case 8: ba.change_color("purple"); break;
//         case 9: ba.change_color("lime green"); break;
//         case 10: ba.change_color("orchid"); break;
//         case 11: ba.change_color("medium aquamarine"); break;
//         case 12: ba.change_color("medium sea green"); break;
//         case 13: ba.change_color("steel blue"); break;
//         case 14: ba.change_color("violet red"); break;
      }
      ba.draw_block(x, s[x]);
      if(++s[x] == d)
         d++;
      if(!(d%5))
         Xwin::flush();
   }
   Xwin::flush();
   Xwin::wait_for_button_press();
}



