=
if (p==q || p>q+8) {
fprintf(stderr,"Piece name is nonexistent or too long: %s",
buf);
exit(-7);
}
for (j=q;j=0 && y>=0 && z>=0 && occupied[x][y][z]) {
fprintf(stderr,"Piece name conflicts with board position: %s",
buf);
exit(-333);
}
}
@ It's a good idea to ``normalize'' the typical cells of a piece,
by making the |xmin|, |ymin|, |zmin| fields of |newbox| all zero.
@=
xyz0=(newbox.xmin<<16)+(newbox.ymin<<8)+newbox.zmin;
if (xyz0) {
for (p=newbox.list;p;p=elt[p].link) elt[p].xyz-=xyz0;
newbox.xmax-=newbox.xmin,newbox.ymax-=newbox.ymin,newbox.zmax-=newbox.zmin;
newbox.xmin=newbox.ymin=newbox.zmin=0;
}
@*Transformations. Now we get to the interesting part of this program,
as we try to find all of the base placements that are obtainable from
a given set of typical cells.
The method is a simple application of breadth-first search:
Starting at the newly created base, we make sure that
every elementary transformation of every known placement is also known.
This procedure requires a simple subroutine to check whether or not
two placements are equal. We can assume that both placements are normalized,
and that both have the same size. Equality testing is easy because
the lists have been sorted.
@=
int equality(int b) { /* return 1 if |base[b]| matches |newbox| */
register int p,q;
for (p=base[b].list,q=newbox.list; p; p=elt[p].link,q=elt[q].link)
if (elt[p].xyz!=elt[q].xyz) return 0;
return 1;
}
@ Just two elementary transformations suffice to generate them all.
@=
j=basecount,k=basecount+1; /* bases |j| thru |k-1| have been checked */
while (j;
for (i=basecount;i;
for (i=basecount;imaxbases) {
fprintf(stderr,"Overflow! Recompile me by making maxbases bigger than %d.\n",
basecount+23);
exit(-669);
}
@ The first elementary transformation replaces $(x,y,z)$ by $(y,-x,z)$.
It corresponds to 90-degree rotation about a vertical axis.
@=
newbox.size=newbox.list=0;
newbox.xmax=base[j].ymax, t=newbox.ymax=base[j].xmax, newbox.zmax=base[j].zmax;
for (p=base[j].list;p;p=elt[p].link) {
x=elt[p].xyz>>16, y=(elt[p].xyz>>8)&0xff, z=elt[p].xyz&0xff;
insert(y,t-x,z);
}
@ The other elementary transformation replaces $(x,y,z)$ by $(y,z,x)$.
It corresponds to 120-degree rotation about a major diagonal.
@=
newbox.size=newbox.list=0;
newbox.xmax=base[j].ymax, newbox.ymax=base[j].zmax, newbox.zmax=base[j].xmax;
for (p=base[j].list;p;p=elt[p].link) {
x=elt[p].xyz>>16, y=(elt[p].xyz>>8)&0xff, z=elt[p].xyz&0xff;
insert(y,z,x);
}
@*Finishing up. In previous parts of this program, I've terminated
abruptly when finding malformed input.
But when everything on |stdin| passes muster,
I'm ready to publish all the information that has been gathered.
@