/* Recursive drawing of Koch curves.  */

#include <fork.h>
#include <assert.h>
#include <io.h>
#include <stdlib.h>
#include <math.h>
#include <graphic.h>

#define PIXELS 252      /*extents of generated X-Bitmap picture*/

sh double factor = 0.5;
sh int MAXLEVEL = 5;

/* output routines: */

async void seq_koch ( pr int startx, pr int starty, 
                      pr int stopx, pr int stopy, pr int level )
{
 if (level >= MAXLEVEL) {   /*reach the limit of recursion*/
    seq_line( startx, starty, stopx, stopy, 0xc0c0c0, 1 );
    return;
 } /* else: another recursion step */
 else {
   pr int *x, *y;
   pr int dx, dy;
   pr int i;
   seq_line( startx, starty, stopx, stopy, 0xc0c000+(level+2)*0x10, 1 );
   x = (int *) shmalloc(5 * sizeof(int));
   y = (int *) shmalloc(5 * sizeof(int));
   dx = stopx - startx;
   dy = stopy - starty;
   /* linear interpolation: */
   x[0] = startx;
   y[0] = starty;
   x[1] = startx + (dx/3); 
   y[1] = starty + (dy/3);
   x[2] = startx + dx/2 - (int)(factor * (float)dy);
   y[2] = starty + dy/2 + (int)(factor * (float)dx);
   x[3] = startx + (2*dx/3); 
   y[3] = starty + (2*dy/3);
   x[4] = stopx;
   y[4] = stopy;
   for (i=0; i<4; i++)
     seq_koch( x[i], y[i], x[i+1], y[i+1], level + 1 );
 }
}


sync void koch (  sh int startx, sh int starty, 
                  sh int stopx, sh int stopy,    sh int level )
{
 sh int p;
 if (level >= MAXLEVEL) {   /*reach the limit of recursion*/
    line( startx, starty, stopx, stopy, 0xc0c0c0 , 1 );
    return;
 } /* else: another recursion step */
 line( startx, starty, stopx, stopy, (level+1)*0x10, 1 );
 p = groupsize();
 if (p<4)
   seq  seq_koch( startx, starty, stopx, stopy, level );
 else {
   sh int *x, *y;
   sh int dx, dy;
   pr int j;
   x = (int *) shalloc(5 * sizeof(int));
   y = (int *) shalloc(5 * sizeof(int));
   dx = stopx - startx;
   dy = stopy - starty;
   /* linear interpolation: */
   x[0] = startx;
   y[0] = starty;
   x[1] = startx + (dx/3); 
   y[1] = starty + (dy/3);
   x[2] = startx + dx/2 - (int)(factor * (float)dy);
   y[2] = starty + dy/2 + (int)(factor * (float)dx);
   x[3] = startx + (2*dx/3); 
   y[3] = starty + (2*dy/3);
   x[4] = stopx;
   y[4] = stopy;
   fork ( 4; @=$%4; $=$/4 )
      koch( x[@], y[@], x[@+1], y[@+1], level + 1 );
 }
}
 


void main( void )
{
 if (__PROC_NR__==0) printf("Clearing picture ...\n");
 start {
    init_pict( PIXELS+1, PIXELS+1 );
    clear_pixels( 0 );
    seq {
       printf("Enter MAXLEVEL = ");
       scanf("%d", &MAXLEVEL );
       printf("Enter factor = ");
       scanf("%f", &factor );
       printf("\nGenerating Koch curve (%f) of level %d...\n", factor, MAXLEVEL);
    }
    koch ( 1, PIXELS/4, PIXELS-1, PIXELS/4, 1 );
    write_pixmap( "KOCH" );
 }
 exit(0);
}
