int nrot[7];
int bs_wid[7][4];
int bs_ofs[7][4][4];
int bs_hei[7][4][4];
int bs_min[7][4];
int bs_pos[7][4][4];
void init_bs_aux(int blk, int rot, int o1, int o2, int o3, int o4, int h1, int h2, int h3, int h4)
{
bs_ofs[blk][rot][0]=o1;
bs_ofs[blk][rot][1]=o2;
bs_ofs[blk][rot][2]=o3;
bs_ofs[blk][rot][3]=o4;
bs_hei[blk][rot][0]=h1;
bs_hei[blk][rot][1]=h2;
bs_hei[blk][rot][2]=h3;
bs_hei[blk][rot][3]=h4;
int x,y;
int ymin=99;
int np=0;
for(x=0;x<4;x++)
{
for(y=0;y<bs_hei[blk][rot][x];y++)
{
bs_pos[blk][rot][np] = x*10+(bs_ofs[blk][rot][x]+y);
np++;
}
if(bs_hei[blk][rot][x]!=0) bs_wid[blk][rot]=x+1;
if(bs_ofs[blk][rot][x] < ymin)
{
ymin=bs_ofs[blk][rot][x];
bs_min[blk][rot]=x;
}
}
}
int cmp_int(const void *i, const void *j)
{
int *pi = (int *)i;
int *pj = (int *)j;
return -pj[0]+pi[0];
}
void init_bs()
{
int rot,x;
nrot[0]=1;
init_bs_aux(0, 0, 0,0,0,0, 2,2,0,0);
nrot[1]=2;
init_bs_aux(1, 0, 0,0,0,0, 4,0,0,0);
init_bs_aux(1, 1, 0,0,0,0, 1,1,1,1);
nrot[2]=4;
init_bs_aux(2, 0, 2,0,0,0, 1,3,0,0);
init_bs_aux(2, 1, 0,1,1,0, 2,1,1,0);
init_bs_aux(2, 2, 0,0,0,0, 3,1,0,0);
init_bs_aux(2, 3, 0,0,0,0, 1,1,2,0);
nrot[3]=4;
init_bs_aux(3, 0, 0,2,0,0, 3,1,0,0);
init_bs_aux(3, 1, 1,1,0,0, 1,1,2,0);
init_bs_aux(3, 2, 0,0,0,0, 1,3,0,0);
init_bs_aux(3, 3, 0,0,0,0, 2,1,1,0);
nrot[4]=2;
init_bs_aux(4, 0, 1,0,0,0, 1,2,1,0);
init_bs_aux(4, 1, 0,1,0,0, 2,2,0,0);
nrot[5]=2;
init_bs_aux(5, 0, 0,0,1,0, 1,2,1,0);
init_bs_aux(5, 1, 1,0,0,0, 2,2,0,0);
nrot[6]=4;
init_bs_aux(6, 0, 1,0,1,0, 1,2,1,0);
init_bs_aux(6, 1, 0,0,0,0, 1,2,1,0);
init_bs_aux(6, 2, 1,0,0,0, 1,3,0,0);
init_bs_aux(6, 3, 1,1,0,0, 3,1,0,0);
}
#define CBIT 8
#define ADR_SCHEME4
#define CADR_SCHEME
#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)
#define BTMOV(x, mask, sh) (((x)&mask)<<sh)
#define BTMOV2(x, mask, sh) (((x)&mask)>>sh)
#ifdef ADR_SCHEME0
#define XY2ADR(x,y) ((x)|((y)*L))
#define ADR2XY(a,x,y) { x=a&(L-1);y=a/L;}
#endif
#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
#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
#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 idx2egb(c,r,g,b) {r=(c)&CBMASK; g=((c)>>CBIT)&CBMASK;b=((c)>>(CBIT*2))&CBMASK;}
#endif
typedef unsigned char rgbtype;
rgbtype colr[L2],colg[L2], colb[L2];
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void dump(int idx, rgbtype *rr, rgbtype *gg, rgbtype *bb)
{
bool do_stuff = true;
if (do_stuff)
{
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);
}
}
#define CBOX 4
#define LBOX 4
#define CBOX3 (CBOX*CBOX*CBOX)
#define LBOX2 (LBOX*LBOX)
int ctabr[CBOX3];
int ctabg[CBOX3];
int ctabb[CBOX3];
#define MCOL (256/CBOX)
#define NCOL (MCOL*MCOL*MCOL)
int blkcolr[7][NCOL];
int blkcolg[7][NCOL];
int blkcolb[7][NCOL];
int blkcolA[7][NCOL];
int blkcoli[7][NCOL];
int blkcol_used[7];
int blk2col[7]={7,2,3,4,1,6,5};
#define BW (L/LBOX)
int hei[BW];
int lock[BW];
int lockx;
int blk_idx(int r, int g, int b, int *lv)
{
int bit;
int l=0;
for(bit=MCOL;bit!=0;bit>>=1)
{
int c=0;
if(r&bit)c+=2;
if(g&bit)c+=4;
if(b&bit)c+=1;
if(c!=0)
{
*lv=bit;
return c;
}
l++;
}
*lv=1;
return 7;
}
void init_cused()
{
int i;
for(i=0;i<7;i++) blkcol_used[i]=0;
int mm,r,g,b,c;
for(mm=0;mm<=MCOL*3;mm++)
{
for(r=0;r<=mm;r++)
{
if(r>=MCOL)continue;
for(g=0;g<=mm-r;g++)
{
if(g>=MCOL)continue;
b=mm-r-g;
if(b>=MCOL || b<0)continue;
int lv;
int blk = blk_idx(r,g,b, &lv)-1;
int ix=blkcol_used[blk];
if(ix>=NCOL)
{
printf("#error blkcol small %d/%d\n",ix,NCOL);
exit(1);
}
blkcolr[blk][ix]=r*CBOX;
blkcolg[blk][ix]=g*CBOX;
blkcolb[blk][ix]=b*CBOX;
blkcolA[blk][ix]=lv;
blkcol_used[blk]++;
}
}
}
int sbuf[NCOL*2];
for(i=0;i<7;i++)
{
printf("#Block %d ncol %d\n", i, blkcol_used[i]);
int b0=0,g0=0,r0=0;
if((i+1)&1)b0=1;
if((i+1)&2)r0=1;
if((i+1)&4)g0=1;
int j;
for(j=0;j<blkcol_used[i];j++)
{
int a=blkcolA[i][j];
int r=blkcolr[i][j];
int g=blkcolg[i][j];
int b=blkcolb[i][j];
if(r+g+b==0)
{
sbuf[j*2]=0;sbuf[j*2+1]=j;
continue;
}
r-=r0*a;
g-=g0*a;
b-=b0*a;
if(r<0 || g<0 || b<0)
{
printf(" %d %d %d b %d rgb0 %d %d %d\n",blkcolr[i][j],blkcolg[i][j],blkcolb[i][j],a,r0,g0,b0);
exit(1);
}
int hue=0;
int max=r, min=r;
if(r+g+b==0)
{
sbuf[j*2]=0;sbuf[j*2+1]=j;
continue;
}
if(r>=g && g>=b)
{
hue = (int)(60* g/r);
}
if(g>=r && r>=b)
{
hue =60 + (int)(60*(g-r)/g);
}
if(g>=b && b>=r)
{
hue = 120+(int)(60* b/g);
}
if(b>=g && g>=r)
{
hue =180 + (int)(60*(b-g)/b);
}
if(b>=r && r>=g)
{
hue = 240+(int)(60* r/b);
}
if(r>=b && b>=g)
{
hue =300 + (int)(60*(r-b)/r);
}
sbuf[j*2]=hue + a*360;sbuf[j*2+1]=j;
}
qsort(sbuf, blkcol_used[i], sizeof(int)*2, cmp_int);
for(j=0;j<blkcol_used[i];j++)
blkcoli[i][j] = sbuf[j*2+1];
}
}
void init_config()
{
int i;
for(i=0;i<BW;i++)hei[i]=lock[i]=0;
lockx=0;
}
void init_pal()
{
int nc=0;
int mm;
for(mm=0;mm<=CBOX*3;mm++)
{
int r,g,b;
for(r=0;r<=mm;r++)
{
if(r>=CBOX)continue;
for(g=0;g<=mm-r;g++)
{
if(g>=CBOX)continue;
b=mm-r-g;
if(b>=CBOX || b<0)continue;
ctabr[nc]=r;
ctabg[nc]=g;
ctabb[nc]=b;
printf("#%d %d %d %d\n",nc, r,g,b);
nc++;
}
}
}
if(nc!=CBOX3)
{
printf("Error ctab\n");
exit(1);
}
}
void draw1(int r1, int g1, int b1, int x, int y, int blk, int rot)
{
int nlig=CBOX3-1;
int ndark=0;
int wid=2;
int xx,yy;
int bx0[4],by0[4];
int np;
for(np=0;np<4;np++)
{
int bb =bs_pos[blk][rot][np];
int bx=bb/10;
int by=bb%10;
bx0[np]=bx+x;
by0[np]=by+y;
}
#if 1
for(yy=0;yy<wid;yy++){
for(xx=yy;xx<LBOX-yy;xx++){
for(np=0;np<4;np++)
{
int x0=bx0[np]*LBOX+xx;
int y0=L-1-by0[np]*LBOX-(LBOX-1-yy);
int ad=XY2ADR(x0,y0);
colr[ad]=r1+ctabr[nlig];
colg[ad]=g1+ctabg[nlig];
colb[ad]=b1+ctabb[nlig];
nlig--;
y0=L-1-by0[np]*LBOX-yy;
ad=XY2ADR(x0,y0);
colr[ad]=r1+ctabr[ndark];
colg[ad]=g1+ctabg[ndark];
colb[ad]=b1+ctabb[ndark];
ndark++;
}
}}
for(xx=0;xx<wid;xx++){
for(yy=xx+1;yy<LBOX-xx-1;yy++){
for(np=0;np<4;np++)
{
int x0=bx0[np]*LBOX+xx;
int y0=L-1-by0[np]*LBOX-(LBOX-1-yy);
int ad=XY2ADR(x0,y0);
colr[ad]=r1+ctabr[nlig];
colg[ad]=g1+ctabg[nlig];
colb[ad]=b1+ctabb[nlig];
nlig--;
x0=bx0[np]*LBOX+(LBOX-1-xx);
y0=L-1-by0[np]*LBOX-yy;
ad=XY2ADR(x0,y0);
colr[ad]=r1+ctabr[ndark];
colg[ad]=g1+ctabg[ndark];
colb[ad]=b1+ctabb[ndark];
ndark++;
}
}}
#endif
for(yy=wid;yy<LBOX-wid;yy++){
for(xx=wid;xx<LBOX-wid;xx++){
for(np=0;np<4;np++)
{
int x0=bx0[np]*LBOX+xx;
int y0=L-1-by0[np]*LBOX-yy;
int ad=XY2ADR(x0,y0);
colr[ad]=r1+ctabr[ndark];
colg[ad]=g1+ctabg[ndark];
colb[ad]=b1+ctabb[ndark];
ndark++;
}
}}
if(ndark!=nlig+1)
{
printf("#error ndark=%d %d\n",ndark,nlig);
exit(1);
}
}
int place(int blk)
{
int hmin=BW*100;
int x,mx;
int mcnt=1;
for(x=0;x<BW;x++)
{
if((hei[x]<=hmin) && (lock[x]==0) && hei[x]!=BW)
{
if (hei[x]==hmin)
{
int r=(rand()>>8)%mcnt;
if(r!=0)continue;
mcnt++;
}
else mcnt=1;
hmin=hei[x];
mx=x;
}
}
int rot;
int cnt;
if(hmin>=BW *50/64)
{
mx=(rand()>>8)%BW;
}
hmin=hei[mx];
for(cnt=0;cnt<100;cnt++)
{
rot=(rand()>>8)%nrot[blk];
int ok=1;
int x;
for(x=0;x<bs_wid[blk][rot];x++)
{
int xx=mx-bs_min[blk][rot] +x;
if(xx>=BW || (xx<0))
{
ok=0;
break;
}
if(lock[xx] != 0)
{
ok=0;
break;
}
if (hei[xx] != hmin +bs_ofs[blk][rot][x] )ok=0;
if (hmin +bs_ofs[blk][rot][x] + bs_hei[blk][rot][x]>BW)ok=0;
int mg=0;
#if 1
if (hei[xx] < BW*52/64)mg=3;
else
#endif
if (hei[xx] < BW*56/64)mg=2;
else
if (hei[xx] < BW*60/64)mg=1;
if(x==0 && xx!=0)
{
if(hei[xx-1] < hei[xx]+bs_hei[blk][rot][x] -mg)ok=0;
}
else if(x!=0)
{
if(bs_ofs[blk][rot][x-1]+bs_hei[blk][rot][x-1] < bs_ofs[blk][rot][x]+bs_hei[blk][rot][x] -mg)ok=0;
}
if(ok==0)break;
}
if (ok==1)
{
int cblk=blk2col[blk]-1;
int cnt=0;
while(1)
{
if(blkcol_used[cblk]!=0)break;
cblk=(rand()>>8)%7;
cnt++;
if(cnt==1000)exit(1);
}
int ix=blkcol_used[cblk]-1;
int ix0 =blkcoli[cblk][ix];
int r= blkcolr[cblk][ix0];
int g= blkcolg[cblk][ix0];
int b= blkcolb[cblk][ix0];
blkcol_used[cblk]--;
draw1(r,g,b, mx-bs_min[blk][rot], hmin, blk, rot);
for(x=0;x<bs_wid[blk][rot];x++)
{
int xx=mx-bs_min[blk][rot] +x;
hei[xx]+= bs_hei[blk][rot][x];
}
return 1;
}
mx=(rand()>>8)%BW;
hmin=hei[mx];
}
return 0;
}
int main(int argc, char **argv)
{
srand(atoi(argv[1]));
int i;
init_bs();
init_pal();
init_config();
init_cused();
for(i=0;i<L2;i++)
{
int x,y,a2;
ADR2XY(i,x,y);
a2=XY2ADR(x,y);
if(i!=a2)exit(1);
}
int npl=0;
int cnt=0;
while(1)
{
int blk=(rand()>>8)%7;
npl+=place(blk);
if(npl==(int)(BW*BW/4 ))break;
cnt++;
if(cnt==BW*BW*10)break;
}
printf("Left %d\n", BW*BW/4-npl);
dump(6, colr,colg,colb);
}