home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d188 / fastgro.lha / FastGro / FastGro.c < prev    next >
C/C++ Source or Header  |  1989-02-26  |  11KB  |  386 lines

  1. /* FastGro 1.0   - a simulation of Diffusion-Limited Aggregation
  2.  
  3.     Copyright (c) 1989  Doug Houck (03-Feb-89)
  4.  
  5.     This program has been placed in the PUBLIC DOMAIN, so anyone,
  6.     anywhere can do anything they want with it.
  7.  
  8.     This was compiled with the Aztec C compiler, version 3.6a, using
  9.     the large data, large code, small integer model. "cc +d +d ..."
  10.     and linked with "ln FastGro.o Wander.o -lml -lcl"
  11. */
  12.  
  13. #include <exec/types.h>
  14. #include <intuition/intuition.h>
  15. #include <functions.h>            /* learn about system */
  16.  
  17. #define RANDOMS        50437        /* how many random #s to generate */
  18. #define STARTING_POINTS    200        /* points around circle for starting */
  19.  
  20. #define ffp long            /* Motorola Fast Floating Point */
  21. extern ffp
  22.     ran(),                /* use manx random # generator */
  23.     SPFlt(), SPFix(), SPMul(), SPDiv(),
  24.     SPSin(), SPCos(), SPAdd(), SPSub();
  25.  
  26. struct Screen *hires_screen    = NULL;
  27. struct Window *hires_window    = NULL;
  28. struct RastPort *hires_rp    = NULL;
  29. struct MsgPort *window_port    = NULL;
  30.  
  31. long MathBase            = NULL,    /* library bases */
  32.     MathTransBase        = NULL,
  33.     IntuitionBase        = NULL,
  34.     GfxBase            = NULL;
  35.  
  36. int    rows, columns,            /* size of screen in pixels */
  37.     maxrow, maxcolumn,
  38.     columnsdiv8;             /* in bytes */
  39.     
  40. long radius, color_iterations,
  41.     points, points_to_go;        /* parameters for drawing */
  42.  
  43.  
  44. char *row[550];                /* pointers to rows */
  45. char *row_memory = NULL;        /*   in row memory */
  46. char *border[550];            /* pointers to rows */
  47. char *border_memory = NULL;        /*   in border memory */
  48. long optimizer_memory;            /* how much space used */
  49.  
  50. char *randoms = NULL;            /* pointer to random array */
  51. char *next_random;            /* index into randoms */
  52.  
  53. struct start_t                /* cache starting points */
  54. {  int x, y;
  55. };
  56. struct start_t start[STARTING_POINTS];
  57.  
  58. struct NewScreen new_hires_screen =
  59. {  0,0,
  60.    640, STDSCREENHEIGHT,        /* size from Workbench screen */    
  61.    4,          /* 16 colors */
  62.    2,1,        /* pens */
  63.    HIRES | LACE,
  64.    CUSTOMSCREEN | SHOWTITLE | SCREENQUIET | SCREENBEHIND,
  65.    NULL,
  66.    NULL,
  67.    NULL,
  68.    NULL
  69. };
  70.  
  71.  
  72. struct NewWindow new_hires_window =
  73. {  0,0,        /* coords */
  74.    640,400,
  75.    0,1,      /* pens */
  76.    MOUSEBUTTONS,
  77.    BACKDROP  |  BORDERLESS,
  78.    NULL,
  79.    NULL,
  80.    NULL,           /* title */
  81.    NULL,           /* screen */
  82.    NULL,           /* bitmap */
  83.    0,0,0,0,        /* min, max */
  84.    CUSTOMSCREEN
  85. };
  86.  
  87.  
  88. initialize(argc, argv)        /* open libraries, allocate memory... */
  89.    int argc;
  90.    char **argv;
  91. {
  92.    IntuitionBase = (long)OpenLibrary( "intuition.library",33L);
  93.    if (!IntuitionBase)
  94.    {  ReportProblem("I Really Needed Kickstart/Workbench 1.2");
  95.       return(0);
  96.    }
  97.  
  98.    GfxBase = (long)OpenLibrary( "graphics.library",33L);
  99.    if (!GfxBase)
  100.    {  ReportProblem("can't open graphics.library");
  101.       return(FALSE);
  102.    }
  103.  
  104.    MathBase = (long)OpenLibrary( "mathffp.library",33L);
  105.    if (!MathBase)
  106.    {  ReportProblem("can't open mathffp.library");
  107.       return(FALSE);
  108.    }
  109.  
  110.    MathTransBase = (long)OpenLibrary( "mathtrans.library",33L);
  111.    if (!MathTransBase)
  112.    {  ReportProblem("Would kinda liketa have 'mathtrans.library' 1.2, mebbee?");
  113.       return(FALSE);
  114.    }
  115.  
  116.    rows = DisplayRows()<<1;        /* get # of rows in WB screen */
  117.    maxrow = rows-1;
  118.    columns = DisplayColumns()<<1;    /* get # of columns in WB screen */
  119.    columnsdiv8 = (columns+7)>>3;
  120.    maxcolumn = columns-1;  
  121.    optimizer_memory = rows * columnsdiv8; /* space arrays will use */
  122.  
  123. /* ------------------------------- display screen ---------------------- */
  124.    new_hires_screen.Height = rows;
  125.    new_hires_screen.Width = columns;
  126.  
  127.    hires_screen = OpenScreen( &new_hires_screen );
  128.    if (!hires_screen)
  129.    {  ReportProblem("No Memory for HiRes Screen.  Sorry!");
  130.       return(0);
  131.    }
  132.  
  133.    new_hires_window.Screen = hires_screen;
  134.    new_hires_window.Width = hires_screen->Width;
  135.    new_hires_window.Height = hires_screen->Height;
  136.    hires_window = OpenWindow( &new_hires_window );
  137.    if (!hires_window )
  138.    {  ReportProblem("Can't open hires window");
  139.       return(0);
  140.    }
  141.    hires_rp = hires_window->RPort;
  142.    window_port = hires_window->UserPort;
  143.  
  144.    {  long red, green, blue;        /* set up colors */
  145.       green = 12;
  146.       for( red = 0, blue = 15;
  147.            red <= 15;
  148.            red++, blue--
  149.          )
  150.          SetRGB4( &hires_screen->ViewPort, red, red, green, blue );
  151.       SetRGB4( &hires_screen->ViewPort, 0L, 0L, 0L, 0L );
  152.    }
  153.  
  154. /* ---------------------- allocate optimizing arrays --------------------- */
  155.  
  156.    row_memory = (char*)AllocMem( optimizer_memory, 0L );
  157.    border_memory = (char*)AllocMem( optimizer_memory, 0L );
  158.    if (!row_memory || !border_memory)
  159.    {  ReportProblem("No Memory For Auxiliary Arrays");
  160.       return(FALSE);
  161.    }
  162.  
  163.    {  int i = 0;            /* init row pointers into arrays */
  164.       char *row_ptr = row_memory;
  165.       char *border_ptr = border_memory;
  166.  
  167.       for( i=0; i < rows; i++ )
  168.       {  row[i]    = row_ptr;
  169.          border[i] = border_ptr;
  170.          row_ptr    += columnsdiv8;
  171.          border_ptr += columnsdiv8;
  172.       }
  173.    }
  174.  
  175.    randoms = (char*)AllocMem( (long)RANDOMS, 0L );
  176.    if (!randoms)
  177.    {  ReportProblem( "no random array");
  178.       return(0);
  179.    }
  180.    {  long counter = RANDOMS-1;        /* init random array */
  181.       register char *ptr = randoms;
  182.       long scaler;
  183.       scaler = SPFlt( 254L );
  184.       while(--counter)
  185.         *ptr++ = SPFix( SPMul(ran(), scaler ) )+ 1;
  186.       *ptr = 0;                /* 0 marks the end */
  187.       next_random = randoms;
  188.    }
  189.  
  190.    radius = 70;
  191.    color_iterations = 100;
  192.    points = 5000;
  193.  
  194.    return( TRUE );
  195. }
  196.  
  197. wrapup()    /* clean up, close libraries, deallocate, wipe nose, etc */
  198. {
  199.    if (randoms)          FreeMem       ( randoms,       (long)RANDOMS    );
  200.    if (row_memory)    FreeMem       ( row_memory,    optimizer_memory );    
  201.    if (border_memory) FreeMem       ( border_memory, optimizer_memory );
  202.    if (hires_window)  CloseWindow   ( hires_window  );
  203.    if (hires_screen)  CloseScreen   ( hires_screen  );
  204.    if (IntuitionBase) CloseLibrary  ( IntuitionBase );
  205.    if (GfxBase)       CloseLibrary  ( GfxBase       );
  206.    if (MathTransBase) CloseLibrary  ( MathTransBase );
  207.    if (MathBase)      CloseLibrary  ( MathBase      );
  208.  
  209.   exit( 0 );
  210. }
  211.  
  212. ReportProblem( text )
  213.    char *text;
  214. {  char answer[64];
  215.    printf("Had a slight problem...\n\n");
  216.    printf("    %s\n\n", text);
  217.    printf("Press <RETURN> to abort.  ");
  218.    gets( answer );
  219. }
  220.  
  221. mark_perimeter( x, y )    /* mark perimeter around a pixel */
  222.    int x, y;
  223. {  setbit( row, x, y );
  224.  
  225.    if (y>0)          setbit( row, x  , y-1 );    /* careful of edges... */
  226.    if (y<maxrow)     setbit( row, x  , y+1 );
  227.  
  228.    if (x>0)
  229.    {  if (y>0)       setbit( row, x-1, y-1 );
  230.                      setbit( row, x-1, y   );
  231.       if (y<maxrow)  setbit( row, x-1, y+1 );
  232.    }
  233.    if (x<maxcolumn)
  234.    {  if (y>0)       setbit( row, x+1, y-1 );
  235.                      setbit( row, x+1, y   );
  236.       if (y<maxrow)  setbit( row, x+1, y+1 );
  237.    }
  238. }
  239.  
  240. set_up_optimizing( radius )
  241.    long radius;
  242. {  int x, y;
  243.    long midx, midy;
  244.    int steps, s, thick;
  245.    ffp theta, stepsize, radi;
  246.  
  247.    midx = columns / 2;
  248.    midy = rows / 2;
  249.  
  250.    for(y = 0; y<rows; y++)        /* clear everything first */
  251.       for(x=0; x<columnsdiv8; x++)
  252.       {  row[y][x] = 0;
  253.          border[y][x] = 0;
  254.       }
  255.  
  256.    steps = radius * 12;        /* mark border of circle */
  257.    stepsize = SPDiv( SPFlt((long)steps),    /* 2 pi / steps */
  258.     SPDiv( SPFlt(1000L), SPFlt( 6283L) ) );
  259.    radi = SPFlt( radius );
  260.  
  261.    for(thick = 0; thick<4; thick++ )        /* make sure no leaks */
  262.    {  for( theta = 0, s = steps;
  263.            s;
  264.            s--, theta = SPAdd(theta, stepsize ) )
  265.       {  x = midx + SPFix(SPMul( SPCos(theta), radi ));
  266.          y = midy + SPFix(SPMul( SPSin(theta), radi ));
  267.          setbit( row, x, y );
  268.          setbit( border, x, y );
  269.       }
  270.       radi = SPSub( SPDiv( SPFlt(3L),SPFlt(1L)), radi );
  271.    }
  272.                 /* set up starting points */
  273.  
  274.    steps = STARTING_POINTS;
  275.    stepsize = SPDiv( SPFlt((long)steps),SPDiv( SPFlt(1000L), SPFlt( 6283L) ) );
  276.    radi = SPFlt( radius - 3L );
  277.  
  278.    for( theta = 0, steps = 0;
  279.         steps < STARTING_POINTS;
  280.         steps++, theta = SPAdd(theta, stepsize )
  281.       )
  282.    {  start[steps].x = midx + SPFix(SPMul( SPCos(theta), radi ));
  283.       start[steps].y = midy + SPFix(SPMul( SPSin(theta), radi ));
  284.    }
  285. }
  286.  
  287. draw_fractal()
  288. {  long max_radius, color_counter, color;
  289.    int x,y;
  290.    ffp start_scale;
  291.    int start_location;
  292.    struct IntuiMessage *im;
  293.    char answer[64];
  294.  
  295.    max_radius = rows/2 - 2;
  296.    start_scale = SPFlt( (long)STARTING_POINTS );
  297.  
  298.    printf("\n\nRadius (10..%ld) [%ld] ",max_radius, radius); /* get parms */
  299.    gets( answer );
  300.    if (answer[0])
  301.    {  sscanf(answer, "%ld", &radius );
  302.       if (radius < 10) radius = 10;
  303.       if (radius > max_radius) radius = max_radius;
  304.    }
  305.  
  306.    printf("Particles (1..1000000) [%ld] ",points);
  307.    gets( answer );
  308.    if (answer[0])
  309.       sscanf(answer, "%ld", &points );
  310.    points_to_go = points;   
  311.  
  312.    printf("Change Color After (1..1000000) [%ld] ",color_iterations);
  313.    gets( answer );
  314.    if (answer[0])
  315.       sscanf( answer, "%ld", &color_iterations );
  316.    color = 1;
  317.    color_counter = color_iterations;
  318.  
  319.    printf("To abort drawing, click anywhere on drawing.\n");
  320.    printf("Setting up...\n");
  321.  
  322.    set_up_optimizing( radius);
  323.  
  324.    x = columns / 2;            /* seed the center */
  325.    y = rows / 2;
  326.    mark_perimeter(x,y);
  327.    WritePixel( hires_rp, (long)x, (long)y );
  328.  
  329.    SetAPen( hires_rp, 1L );        /* erase window */
  330.    SetDrMd( hires_rp, JAM2 );
  331.    SetRast( hires_rp, 0L );
  332.  
  333.    ScreenToFront( hires_screen );
  334.  
  335.                     /* clean out port */
  336.    while( im = (struct IntuiMessage*)GetMsg( window_port) )
  337.       ReplyMsg( im );
  338.  
  339.    while(!IsMessageWaiting(window_port) && (points_to_go> 0 ))
  340.    {  start_location = SPFix(SPMul( ran(), start_scale ));
  341.       x = start[start_location].x;
  342.       y = start[start_location].y;
  343.  
  344.       wander_asm( &x, &y );        /* do the time-consuming stuff */
  345.  
  346.       if (!checkbit( border, x, y ) )    /* not a border hit? OK! */
  347.       {  mark_perimeter(x,y);
  348.          WritePixel( hires_rp, (long)x, (long)y );
  349.          points_to_go--;
  350.          if( !(--color_counter) )
  351.          {  color_counter = color_iterations;
  352.             color++;
  353.             if (color > 15) color = 1;
  354.             SetAPen( hires_rp, color );
  355.          }
  356.       }
  357.    }
  358.  
  359.    ScreenToBack( hires_screen);
  360. }
  361.  
  362. main( argc, argv )
  363.    int argc;
  364.    char **argv;
  365. {  char answer[32];
  366.  
  367.    printf("Welcome to FastGro, a fractal program by Doug Houck,\n");
  368.    printf("simulating Diffusion-Limited Aggregation.  The purpose\n");
  369.    printf("of this program is to demonstrate how selected\n");
  370.    printf("optimizations can improve the speed of a program by\n");
  371.    printf("an order of magnitude.  Meanwhile, I'm setting up...\n");
  372.  
  373.    if (!initialize( argc, argv ))
  374.       wrapup();
  375.  
  376.    do
  377.    {  draw_fractal();
  378.       printf("More? (Y/N) [Yes] ");
  379.       gets( answer );
  380.    }
  381.    while ( ! ((answer[0]=='N') || (answer[0]=='n')) );
  382.  
  383.    wrapup();
  384. }
  385.  
  386.