Diffusion-limited aggregation code

This code generates this picture http://allrgb.com/dla which uses each 2^24 color once and only once.
DLA rule is tweaked a bit to generate nice picture.

Save as dla.cc , just compile it cc dla.cc, and run "a.out Number.of.Seeds"

// Bits per plane. Must be even and <=8, namely either 2, 4, 6, 8

//Uncomment these for 4096x4096
//#define CBIT 8
//Addressing scheme 4 is fastest for CBIT=8
//#define ADR_SCHEME4

// Use these for 512x512 test
#define CBIT 6
//Addressing scheme 0 is fastest for CBIT=6
#define ADR_SCHEME0

/////////////////////////////////////////////////////
// no need to edit below
#define CADR_SCHEME0

// Misc. consts
#define VMAX (1<<CBIT)
#define CBMASK (VMAX-1)

#define LBIT (CBIT+CBIT/2)
#define L (1<<LBIT)
#define L2 (L*L)
#define L2MASK (L2-1)
#define LMASK (L-1)
#define LMASKY (L2MASK ^ LMASK)

// Manage list of unused colors
int nemp_c;
int emp_c[L2];
void init_emp()
{
    int i;
    for(i=0;i<L2;i++)
    {
	emp_c[i]=i;
    }
    nemp_c=L2;
}

//Address conversion
// x, y ->3char
#define BTMOV(x, mask, sh) (((x)&mask)<<sh)
#define BTMOV2(x, mask, sh) (((x)&mask)>>sh)
// c00000 c0000 c000 c00  c0   c
//  8421 8421   8421 8421 8421 8421
//  yyxx yyxx   yyxx yyxx yyxx yyxx

#ifdef ADR_SCHEME0
#define XY2ADR(x,y) ((x)|((y)*L))
#define ADR2XY(a,x,y) { x=a&(L-1);y=a/L;}
#endif

// 4bit
#ifdef ADR_SCHEME4
#define XY2ADR(x,y) (\
    BTMOV(x,0xf,  0) | BTMOV(y,0xf,  4) | \
    BTMOV(x,0xf0, 4) | BTMOV(y,0xf0, 8) | \
    BTMOV(x,0xf00,8) | BTMOV(y,0xf00,12))
#define ADR2XY(a,x,y) {\
    x=BTMOV2((a),0x0f,0)  |BTMOV2((a),0xf00,4)  |BTMOV2((a),0xf0000,8);\
    y=BTMOV2((a),0xf0,4)  |BTMOV2((a),0xf000,8) |BTMOV2((a),0xf00000,12);}
#endif

// 3bit
#ifdef ADR_SCHEME3
#define XY2ADR(x,y) (\
    BTMOV(x,07,  0)  | BTMOV(y,07, 3)  |\
    BTMOV(x,070, 3)  | BTMOV(y,070,6)  |\
    BTMOV(x,0700,6)  | BTMOV(y,0700,9) |\
    BTMOV(x,07000,9) | BTMOV(y,07000,12))
#define ADR2XY(a,x,y) {\
    x=BTMOV2((a),07,0)  |BTMOV2((a),0700,3)   |BTMOV2((a),070000,6)  |BTMOV2((a),07000000,9);\
    y=BTMOV2((a),070,3) |BTMOV2((a),07000,6)  |BTMOV2((a),0700000,9) |BTMOV2((a),070000000,12);}
#endif

// 2bit
#ifdef ADR_SCHEME2
#define XY2ADR(x,y) (\
    BTMOV(x,0x3, 0) | BTMOV(y,0x3, 2) | BTMOV(x,0xc,2) | BTMOV(y,0xc,4) |\
    BTMOV(x,0x30,4) | BTMOV(y,0x30,6) | BTMOV(x,0xc0,6)|BTMOV(y,0xc0,8) |\
    BTMOV(x,0x300,8) | BTMOV(y,0x300,10) | BTMOV(x,0xc00,10)|BTMOV(y,0xc00,12) )
#define ADR2XY(a,x,y) {\
    x=BTMOV2(a,0x03,0)  |BTMOV2(a,0x30,2)   |BTMOV2(a,0x300,4)|\
      BTMOV2(a,0x3000,6)|BTMOV2(a,0x30000,8)|BTMOV2(a,0x300000,10);\
    y=BTMOV2(a,0x0c,2)  |BTMOV2(a,0xc0,4)   |BTMOV2(a,0xc00,6)|\
      BTMOV2(a,0xc000,8)|BTMOV2(a,0xc0000,10)|BTMOV2(a,0xc00000,12);}
#endif
//////////////////////////////////////////////////////////
#ifdef CADR_SCHEME4
#define rgb2idx(r,g,b) (\
	 BTMOV(r,0x0f,0) | BTMOV(g,0x0f,4)  | BTMOV(b, 0x0f,8) |\
	 BTMOV(r,0xf0,8) | BTMOV(g,0xf0,12) | BTMOV(b, 0xf0,16) \
	)
#endif

#ifdef CADR_SCHEME0
#define rgb2idx(r,g,b) ((r)|((g)<<CBIT)|((b)<<(CBIT*2)))
#define IDX2RGB(c,r,g,b) {r=(c)&CBMASK; g=((c)>>CBIT)&CBMASK;b=((c)>>(CBIT*2))&CBMASK;}
#endif
/////////////////////////////////////////////////////
// global variables block
typedef unsigned char rgbtype;
// main color data
rgbtype colr[L2],colg[L2], colb[L2];
rgbtype *col3[3]={colr, colg, colb};


#include <math.h>
#include <string.h>

#include <stdio.h>
#include <stdlib.h>

#include <sys/time.h>
// for timing
int getmsec()
{
    static int sec0=0,usec0=0;
    struct timeval tv;
    struct timezone tz;
    gettimeofday(&tv,&tz);
    return tv.tv_sec*1000+tv.tv_usec/1000;
    //int res=(tv.tv_sec-sec0)*1000000+(tv.tv_usec-usec0);
    //sec0=tv.tv_sec;
    //usec0=tv.tv_usec;
    //return res;
}
////////////

// DLA var
unsigned char solid[L2];
int cidx[L2];
char cidx0[L2];
int dwid;

void place_solid(int x,int y, int r, int g, int b, int sol)
{
    int x1=(x-1)&LMASK;
    int x2=(x+1)&LMASK;
    int y1=(y-1)&LMASK;
    int y2=(y+1)&LMASK;

    int ad=XY2ADR(x,y);
    int c=rgb2idx(r,g,b);
    cidx[c]=ad;
    cidx0[c]=1;
    solid[ad]=1;
    colr[ad]=r;
    colg[ad]=g;
    colb[ad]=b;

    ad=XY2ADR(x1,y);if(solid[ad]==0)solid[ad]=sol;
    ad=XY2ADR(x2,y);if(solid[ad]==0)solid[ad]=sol;
    ad=XY2ADR(x,y1);if(solid[ad]==0)solid[ad]=sol;
    ad=XY2ADR(x,y2);if(solid[ad]==0)solid[ad]=sol;
}

int init_misc(int nc, double rt)
{
    if(nc!=1)dwid = L;
    else dwid=64;
    if(dwid>L)dwid=L;
    int i;

    int maxv=(int)(VMAX*rt);
    int res=0;

    for(i=0;i<L2;i++)
    {
	solid[i]=0;
	cidx[i]=-1;
	cidx0[i]=0;
	int r,g,b;
	IDX2RGB(i,r,g,b);
	int max=r;
	int min=r;
	if(max<g)max=g;
	if(max<b)max=b;
	if(min>g)min=g;
	if(min>b)min=b;
	// reserve low-satulation colors
	int sat=max-min;
	if (sat < maxv) 
	{
	    cidx[i]=-2;
	    cidx0[i]=1;
	    res++;
	}
    }

    //place random seeds
    for(i=0;i<nc;i++)
    {
	int x=(rand()>>4)&LMASK;
	int y=(rand()>>4)&LMASK;
	if(nc==1)
	{
	    x=y=L/2;
	}
	int c;
	while(1)
	{
	    c=(rand()>>4)&L2MASK;
	    if(cidx0[c]== 0)break;
	}
	printf("#Init Place %d\n",i);
	int r,g,b;
	IDX2RGB(c,r,g,b);
	place_solid(x,y, r,g,b,2);
    }
    return res;
}

// dump color to a file
void dump(int idx, rgbtype *rr, rgbtype *gg, rgbtype *bb)
{
    bool do_stuff = true;

    if (do_stuff)
    {
	//init_cidx();
	char fn[128];
	sprintf(fn, "%04d.ppm",idx);
	FILE *fp;
	unsigned char *pbuf = (unsigned char *)malloc(L2*3);
	fp=fopen(fn,"w");
	if (fp==NULL)
	{
	    printf("cannot open %s for dump\n",fn);
	    exit(1);
	}
	int i;
	int vv = 255/(VMAX-1);
	printf("#Dump %s, color scale *%d Size %f Mb\n",fn, vv, L2*3e-6);
	int x,y;
	for(i=0;i<L2;i++)
	{
	    ADR2XY(i, x, y);
	    int ad= (x+y*L)*3;
	    pbuf[ad+0] = vv*rr[i];
	    pbuf[ad+1] = vv*gg[i];
	    pbuf[ad+2] = vv*bb[i];
	}
	fprintf(fp, "P6\n%d %d\n255\n", L,L);
	fwrite(pbuf,1,L2*3,fp);
	fclose(fp);
	free(pbuf);
    }
}

void dump_small(int idx, rgbtype *rr, rgbtype *gg, rgbtype *bb)
{
    bool do_stuff = true;
    if (do_stuff)
    {
	char fn[128];
	sprintf(fn, "ppms/%04d.ppm",idx);
	FILE *fp;

	int l00=720;
	if (l00>L)l00=480;
	if (l00>L)l00=320;
	if (l00>L)return;
	unsigned char *pbuf = (unsigned char *)malloc(l00*l00*3);
	int *ibuf = (int *)malloc(l00*l00*3*4);
	int *ibuf2 = (int *)malloc(l00*l00*4);
	int i;
	for(i=0;i<l00*l00;i++)
	{
	    ibuf2[i]=0;
	    ibuf[i*3+0]=0;
	    ibuf[i*3+1]=0;
	    ibuf[i*3+2]=0;
	}

	fp=fopen(fn,"w");
	if (fp==NULL)
	{
	    printf("cannot open %s for dump\n",fn);
	    exit(1);
	}
	int vv = 255/(VMAX-1);
	printf("#Dump %s, color scale *%d Size %f Mb\n",fn, vv, l00*l00*3e-6);

	//Calc
	for(i=0;i<L2;i++)
	{
	    int x,y;
	    ADR2XY(i,x,y);
	    int x2 = x*l00/L;
	    int y2 = y*l00/L;
	    int ad = x2+y2*l00;
	    ibuf2[ad]++;
	    ibuf[ad*3+0] += vv*rr[i];
	    ibuf[ad*3+1] += vv*gg[i];
	    ibuf[ad*3+2] += vv*bb[i];
	}
	for(i=0;i<l00*l00;i++)
	{
	    pbuf[i*3+0] = ibuf[i*3+0]/ibuf2[i];
	    pbuf[i*3+1] = ibuf[i*3+1]/ibuf2[i];
	    pbuf[i*3+2] = ibuf[i*3+2]/ibuf2[i];
	}

	fprintf(fp, "P6\n%d %d\n255\n", l00,l00);
	fwrite(pbuf,1,l00*l00*3,fp);
	fclose(fp);
	free(pbuf);
	free(ibuf);
	free(ibuf2);
    }
}

// resume from an image file
//  or import smaller size image and expand, add lower bit data
void load_ppm(char *fn)
{
    char buf[128];
    FILE *fp=fopen(fn, "r");
    if (fp==NULL)
    {
	printf("# cannot open file %s\n",fn);
	exit(1);
    }
    int ll;
    fgets(buf,99,fp);
    fgets(buf,99,fp);
    sscanf(buf, "%d", &ll);
    fgets(buf,99,fp);
    printf("#Loading %s L=%d\n",fn, ll);

    if (ll==L)
    {
	//resume
	printf("  #Same size data\n");
	unsigned char *pbuf = (unsigned char *)malloc(L2*3);
	fread(pbuf,1,L2*3,fp);
	fclose(fp);
	int vv = 255/(VMAX-1);
	printf("  # read complete, color scale /%d\n", vv);
	int i;
	int ad,x,y;
	for(i=0;i<L2;i++)
	{
	    x=i&(L-1);
	    y=i/L;
	    ad = XY2ADR(x,y);
	    unsigned char *c = &pbuf[i*3];
	    colr[ad] = c[0]/vv;
	    colg[ad] = c[1]/vv;
	    colb[ad] = c[2]/vv;
	}
	free(pbuf);
	return;
    }
    if (ll*ll==L)
    {
	// self-similar
	printf("  # sqrt(L) size data\n");
	unsigned char *pbuf = (unsigned char *)malloc(ll*ll*3);
	fread(pbuf,1,ll*ll*3,fp);
	fclose(fp);

	int v2 = (1<<(CBIT/2));
	int vv = 255/(v2-1);
	printf("  # read complete, color scale /%d\n", vv);

	int x,y;

	//block
	for(x=0;x<ll;x++){
	    for(y=0;y<ll;y++){
		int ad1 = (x+y*ll)*3;
		int r1=(pbuf[ad1 +0]/vv)<<(CBIT/2);
		int g1=(pbuf[ad1 +1]/vv)<<(CBIT/2);
		int b1=(pbuf[ad1 +2]/vv)<<(CBIT/2);

		int xx,yy;
		for(xx=0;xx<ll;xx++){
		    for(yy=0;yy<ll;yy++){
			int x2=xx;
			int y2=yy;
			if (x&1) x2=ll-1-xx;
			if (y&1) y2=ll-1-yy;
			int ad0 = (x2+y2*ll)*3;

			int r=pbuf[ad0 +0]/vv +r1;
			int g=pbuf[ad0 +1]/vv +g1;
			int b=pbuf[ad0 +2]/vv +b1;
			int ad1 = (x*ll+xx)+(y*ll+yy)*L;
			colr[ad1] = r;
			colg[ad1] = g;
			colb[ad1] = b;
		    }}
	    }}
	free(pbuf);
	return;
    }

    if (ll==L/8)
    {
	// expand CBIT-2 image
	printf("  # 1/8 size data\n");
	unsigned char *pbuf = (unsigned char *)malloc(L2*3/64);
	fread(pbuf,1,L2*3/64,fp);
	fclose(fp);

	int ofs[8][8][3];
	int x,y;
	int vv = 255/((VMAX/4)-1);
	printf("  # read complete, vv=%d\n",vv);

	// 8x8 optimum solution
	int ofsR[8][8];
	int ofsG[8][8];
	int ofsRy[8]={1,0,0,1,2,3,3,2};
	int ofsGx[8]={0,0,1,2,3,3,2,1};
	int ofsB[8][8]=
	{
	    {2,3,3,3,3,2,2,2},
	    {2,3,3,3,3,1,1,1},
	    {0,1,2,2,2,0,0,0},
	    {0,1,1,1,1,0,0,0},
	    {0,1,1,1,1,0,0,0},
	    {0,2,2,2,1,0,0,0},
	    {1,3,3,3,3,2,1,1},
	    {2,3,3,3,3,2,2,2}
	};

	// fine bit part
	for(x=0;x<8;x++){
	    for(y=0;y<8;y++){
		ofs[x][y][0] = x/2;
		ofs[x][y][1] = y/2;
		ofs[x][y][2] = (x&1) + (y&1)*2;
		ofsR[y][x]=ofsRy[y];
		ofsG[y][x]=ofsGx[x];
	    }}

	// repeat small image
	//block
	for(x=0;x<8;x++){
	    for(y=0;y<8;y++){
		int r0 =ofsR[x][y];
		int g0 =ofsG[x][y];
		int b0 =ofsB[x][y];
		int xx,yy;
		for(xx=0;xx<L/8;xx++){
		    for(yy=0;yy<L/8;yy++){
			int ad0 = (xx+yy*(L/8))*3;

			int r=(pbuf[ad0 +0]/vv)*4 +r0;
			int g=(pbuf[ad0 +1]/vv)*4 +g0;
			int b=(pbuf[ad0 +2]/vv)*4 +b0;
			int x0=x+xx*8;
			int y0=y+yy*8;

			int adr=XY2ADR(x0,y0);
			colr[adr]=r;
			colg[adr]=g;
			colb[adr]=b;
		    }}
	    }}

	free(pbuf);
	return;
    }
    printf("#Couldn't load %s\n",fn);
    exit(1);
}

int ncol;
#define RTMAX 128
int rt[RTMAX],gt[RTMAX],bt[RTMAX];

void reg_col_aux(int r, int g, int b)
{
    int oo=r|g|b;
    if (oo&(~CBMASK)) return;
    if(cidx0[rgb2idx(r,g,b)]== 0)
    {
	rt[ncol]=r;
	gt[ncol]=g;
	bt[ncol]=b;
	ncol++;
    }
}
void reg_col(int ad, int flag)
{
    if(solid[ad]!=1)return;
    int r=colr[ad];
    int g=colg[ad];
    int b=colb[ad];

    if(flag==1)
    {
    reg_col_aux(r-1,g,b);
    reg_col_aux(r+1,g,b);
    reg_col_aux(r,g-1,b);
    reg_col_aux(r,g+1,b);
    reg_col_aux(r,g,b-1);
    reg_col_aux(r,g,b+1);
    }
    if(flag==2)
    {
    reg_col_aux(r-1,g-1,b);
    reg_col_aux(r-1,g+1,b);
    reg_col_aux(r+1,g-1,b);
    reg_col_aux(r+1,g+1,b);
    reg_col_aux(r,g-1,b-1);
    reg_col_aux(r,g-1,b+1);
    reg_col_aux(r,g+1,b-1);
    reg_col_aux(r,g+1,b+1);
    reg_col_aux(r-1,g,b-1);
    reg_col_aux(r-1,g,b+1);
    reg_col_aux(r+1,g,b-1);
    reg_col_aux(r+1,g,b+1);
    }
    if(flag==3)
    {
        reg_col_aux(r-1,g-1,b-1);
        reg_col_aux(r-1,g-1,b+1);
        reg_col_aux(r-1,g+1,b-1);
        reg_col_aux(r-1,g+1,b+1);
        reg_col_aux(r+1,g-1,b-1);
        reg_col_aux(r+1,g-1,b+1);
        reg_col_aux(r+1,g+1,b-1);
        reg_col_aux(r+1,g+1,b+1);
    }
    if(flag==4)
    {
        reg_col_aux(r-2,g,b);
        reg_col_aux(r+2,g,b);
        reg_col_aux(r,g-2,b);
        reg_col_aux(r,g+2,b);
        reg_col_aux(r,g,b+2);
        reg_col_aux(r,g,b-2);
    }
}

void reg_col0(int xx, int yy)
{
    ncol=0;
	int x1=(xx-1)&LMASK;
	int x2=(xx+1)&LMASK;
	int y1=(yy-1)&LMASK;
	int y2=(yy+1)&LMASK;
	int ad1=XY2ADR(x1,yy);
	int ad2=XY2ADR(x2,yy);
	int ad3=XY2ADR(xx,y1);
	int ad4=XY2ADR(xx,y2);

	reg_col(ad1,1);
	reg_col(ad2,1);
	reg_col(ad3,1);
	reg_col(ad4,1);
	if(ncol!=0)return;
	reg_col(ad1,2);
	reg_col(ad2,2);
	reg_col(ad3,2);
	reg_col(ad4,2);
	if(ncol!=0)return;
	reg_col(ad1,3);
	reg_col(ad2,3);
	reg_col(ad3,3);
	reg_col(ad4,3);
	if(ncol!=0)return;
	reg_col(ad1,4);
	reg_col(ad2,4);
	reg_col(ad3,4);
	reg_col(ad4,4);
}


int place_one()
{
    static int avmin=0;
    int ox=L/2- dwid/2;
    int oy=L/2- dwid/2;

    int x=0;
    int y=0;
    if(dwid==L)
    {
	x=(rand()>>4)&(L-1);
	y=(rand()>>4)&(L-1);
    }

    const int dx[4]={-1,1,0,0};
    const int dy[4]={0,0,-1,1};
    int cnt=0;
#define CMAX 10000

#define RSHIFT 8
    while(1)
    {
	int r1=rand()>>RSHIFT;
	int r2=RAND_MAX>>RSHIFT;
	while(1)
	{
	    int xx=ox+x;
	    int yy=oy+y;
	    int ad=XY2ADR(xx,yy);
	    if(solid[ad]==2)break;

	    if((r2&3)!=3)
	    {
	        r1=rand()>>RSHIFT;
	        r2=RAND_MAX>>RSHIFT;
	    }

	    int rnd=r1&3;
	    r1>>=2;
	    r2>>=2;

	    x =(x+dx[rnd])&(dwid-1);
	    y =(y+dy[rnd])&(dwid-1);
	}

	ncol=0;
	int xx=ox+x;
	int yy=oy+y;

	reg_col0(xx,yy);
	if(ncol!=0)break;

	cnt++;
	if(cnt==CMAX) break;

	if (1){
	    int rnd=(rand()>>10)&3;
	    x =(x+dx[rnd])&(dwid-1);
	    y =(y+dy[rnd])&(dwid-1);
	    //printf("Fail %d\n",cnt);
	}
    }

    if(ncol==0)
    {
	//Check avail colors
	int ncol=0;
	int i;
	for(i=0;i<L2;i++)
	{
	    if (solid[i]!=2)continue;
	    int xx,yy;
	    ADR2XY(i,xx,yy);
	    reg_col0(xx,yy);
	    if(ncol!=0)
	    {
		int cc=(rand()>>4)%ncol;
		place_solid(xx,yy, rt[cc],gt[cc],bt[cc],2);
		return 0;
	    }
	}//i
	return 1;
    }
    else
    {
	int cc=(rand()>>4)%ncol;
	place_solid(ox+x,oy+y, rt[cc],gt[cc],bt[cc],2);
    }
    int wx=abs(x-dwid/2);
    int wy=abs(y-dwid/2);
    if((wx>dwid/2-2 || wy>dwid/2-2) && (dwid!=L))
    {
	dwid*=2;
	printf("Now wid=%d\n",dwid);
	dump(2, colr,colg,colb);
    }
    return 0;
}

int  main(int argc, char **argv)
{


    int i;
    //test address
    for(i=0;i<L2;i++)
    {
	int x,y,a2;
	ADR2XY(i,x,y);
	a2=XY2ADR(x,y);
	if(i!=a2)exit(1);
    }

    int ni=atoi(argv[1]);
    if(ni==0)
    {
	printf("Usage: a.out N.of.Seeds\n");
	exit(1);
    }

    init_emp();
    int np=init_misc(ni,0.5);

#if 1
    // Do DLA
    int t0=getmsec();
    for(i=0;i<L2-ni - np;i++)
    {
	int ii=place_one();
	if(i%1000==0)
	{
	    int tt=getmsec();
	    printf("%d/%d %d %d sec\n",i,L2, i*100/(L2-ni-np), tt-t0);
	    if(tt-t0>1000*60)
	    {
	       dump(4, colr,colg,colb); //exit(1);
	       t0=tt;
	    }
	    int j;
	}
	if(ii!=0)break;
    }//loop
#endif


    printf("Place %d Reserve %d\n",ni,np);

    //reorder avail col
    int nc=0;
    int mm;
    for(mm=0;mm<=VMAX*3;mm++)
    {
	int r,g,b;
#if 1
	for(r=0;r<=mm;r++){
	    if(r>=VMAX)continue;
	for(g=0;g<=mm-r;g++){
	    if(g>=VMAX)continue;
	    b=mm-r-g;
	    if(b>=VMAX)continue;
	    int c=rgb2idx(r,g,b);
	    if(cidx[c] < 0)
	    emp_c[nc++]=c;
	}}
#else
	//V
	for(g=0;g<=mm;g++)
	for(b=0;b<=mm;b++)
	    emp_c[nc++]=rgb2idx(mm,g,b);

	for(r=0;r<=mm-1;r++)
	for(b=0;b<=mm;b++)
	    emp_c[nc++]=rgb2idx(r,mm,b);

	for(r=0;r<=mm-1;r++)
	for(g=0;g<=mm-1;g++)
	    emp_c[nc++]=rgb2idx(r,g,mm);
#endif
    }
    printf("Reserve %d\n",nc);

    char *revflag = (char *)malloc(L2);
    //revert
    for(i=0;i<L2;i++)
    {
	revflag[i]=0;
	if(cidx[i]==-2)cidx[i]=-1;
    }

    for(i=0;i<L2;i++)
    {
	if(cidx[i]>=0)
	{
	int r,g,b;
	  IDX2RGB(i,r,g,b);
	  int ad=cidx[i];
	  revflag[ad]=1;
	  colr[ad]=CBMASK-colr[ad];
	  colg[ad]=CBMASK-colg[ad];
	  colb[ad]=CBMASK-colb[ad];
	}
    }

    int th= (int)(RAND_MAX*0.0);

    ///////////////////////////////////
    //Fill

    nc=0;
    int fl0=2;
    int cnt=0;
    int done=0;
    // Fill
    while(1)
    {
	cnt++;
	if(cnt==10)break;
	if(cnt%1000==0) dump(4, colr,colg,colb);

	int nfil=0;
	int fl2=fl0+1;
	if(fl2==256)fl2=2;
	//printf("fl=%d fl2=%d\n",fl0,fl2);

	int skip=0;
	for(i=0;i<L2;i++)
	{
	    if(solid[i]!=fl0)continue;
#if 0
	    if(rand()<th) {solid[i]=fl2; nfil++;continue;}
	    ncol=0;
	    int  xx,yy;
	    ADR2XY(i,xx,yy);
	    reg_col0(xx,yy);
	    if(ncol==0) {skip++; continue;}
	    nfil++;
	    int cc=(rand()>>4)%ncol;
	    place_solid(xx,yy, rt[cc],gt[cc],bt[cc],fl2);
#else
	    int c=emp_c[nc];nc++;
	    int r,g,b;
	    IDX2RGB(c,r,g,b);
	    int x,y;
	    ADR2XY(i,x,y);
	    place_solid(x,y, r,g,b, fl2);
	    nfil++;
#endif
	}//i
	//printf("%d placed 1\n",nfil);
	if(skip==0)
	{
	    fl0=fl2;
	    if(nfil==0)
	    {
		done=1;
		break;
	    }
	    continue;
	}

	nfil=0;
	for(i=0;i<L2;i++)
	{
	    if(solid[i]!=fl0)continue;
	    while(cidx[emp_c[nc]]>=0)nc++;
	    int r,g,b;
	    IDX2RGB(emp_c[nc],r,g,b);
	    int x,y;
	    ADR2XY(i,x,y);
	    place_solid(x,y, r,g,b, fl2);
	    nfil++;
	}
	printf("%d/%d placed 2\n",nfil,skip);

	if(nfil==0)
	{
	    done=1;
	    break;
	}
	fl0=fl2;
    }//

    if(done==0)
    {
	for(i=0;i<L2;i++)
	{
	    if(solid[i]==1)continue;
	    int c=emp_c[nc];nc++;
	    int r,g,b;
	    IDX2RGB(c,r,g,b);
	    int x,y;
	    ADR2XY(i,x,y);
	    place_solid(x,y, r,g,b, 2);
	}//i
    }


    //revert
    for(i=0;i<L2;i++)
    {
	if(revflag[i]==1)
	{
	    int r,g,b;
	    colr[i]=CBMASK-colr[i];
	    colg[i]=CBMASK-colg[i];
	    colb[i]=CBMASK-colb[i];
	}
    }

    dump(4, colr,colg,colb);

}