1 /* Sorry, BSD for alloca(). */
10 #define HTAB_SIZE 56783
12 /* #define STSTEP 100 */
14 /* #define BENCHMARK */
17 #define SaXYL(x,y) ((x)+(y)*5)
18 #define SaLX(l) ((l)%5)
19 #define SaLY(l) ((l)/5)
20 #define SaLXY(l,x,y) do { (x)=SaLX((l)); (y)=SaLY((l)); } while (0)
22 unsigned total=0,solutions=0;
34 struct st *nexttogo,*nextinchain,*ost;
36 } *togo,**togop=&togo,*togonow,*htab[HTAB_SIZE];
39 static void chk(void *p)
42 fprintf(stderr,"Virtual memory exhausted!\n");
45 #define chknew(a) chk((a)=malloc(sizeof(*(a))))
47 static unsigned hash(const char *st)
57 static struct st **findhash(const char *st,unsigned hval)
60 for (r=&htab[hval];*r;r=&(*r)->nextinchain)
61 if (!memcmp((*r)->data,st,20)) break;
65 static void dumpst(const char *st)
70 printf(" | %.5s |\n",st+SaXYL(0,yi));
74 static void addstate(const char *st,struct st *ost)
76 struct st *now,**nowp;
80 if (*(nowp=findhash(st,hval))) return;
87 chk(now=malloc(sizeof(*now)));
88 *togop=now;togop=&now->nexttogo; now->nexttogo=NULL;
89 now->nextinchain=NULL; *nowp=now;
90 memcpy(now->data,st,20);
95 static char isdest(const char *st)
97 return (st[SaXYL(3,1)]=='A' && st[SaXYL(4,1)]=='B'
98 &&st[SaXYL(3,2)]=='C' && st[SaXYL(4,2)]=='D');
101 static void trymoves(struct st *sts)
105 int blk[2],bli,oi,nbp;
106 static const char offs[4][2]={{0,-1},{+1,0},{0,+1},{-1,0}};
107 char bx,by,nbx,nby,gx=0,gy=0,gxs=0,gys=0,sx,sy,xi,yi;
111 printf("Entered trymoves()\n");
121 for (o=sts;o;o=o->ost) {
122 chk(b=alloca(sizeof(*b)));
133 printf("*** GOAL: level=%d\n",level);
138 printf("> /-------\\ forwardtrace: level=%d\n",lev++);
139 dumpst(back->st->data);
144 blk[0]=((char *)memchr(st ,'+',20 ))-((char *)st); assert(blk[0]<20);
145 blk[1]=((char *)memchr(st+(blk[0]+1),'+',20-(blk[0]+1)))-((char *)st); assert(blk[1]<20);
146 assert(!memchr(st+(blk[1]+1),'+',20-(blk[1]+1)));
147 for (bli=0;bli<2;bli++) {
148 SaLXY(blk[bli],bx,by);
149 for (oi=0;oi<4;oi++) {
150 nbx=bx+(sx=offs[oi][0]);
151 nby=by+(sy=offs[oi][1]);
152 if (nbx<0 || nbx>=5 || nby<0 || nby>=4) {
156 #define CHKPOS(xs,ys,dx,dy) do { char nxb=nbx-dx,nyb=nby-dy; \
157 if (nxb<0 || nxb+xs>5 || nyb<0 || nyb+ys>5) goto failed; \
158 for (xi=0;xi<(xs);xi++) for (yi=0;yi<(ys);yi++) { \
159 if (xi-sx>=0&&xi-sx<xs&&yi-sy>=0&&yi-sy<ys) continue; \
160 if (st[SaXYL(bx-dx+xi,by-dy+yi) ]!='+') goto failed; \
162 gx=nbx-dx; gy=nby-dy; gxs=xs; gys=ys; \
167 case '{': CHKPOS(2,1, 0, 0); break;
168 case '}': CHKPOS(2,1,+1, 0); break;
169 case '^': CHKPOS(1,2, 0, 0); break;
170 case 'v': CHKPOS(1,2, 0,+1); break;
171 case '#': CHKPOS(1,1, 0, 0); break;
172 case 'A': CHKPOS(2,2, 0, 0); break;
173 case 'B': CHKPOS(2,2,+1, 0); break;
174 case 'C': CHKPOS(2,2, 0,+1); break;
175 case 'D': CHKPOS(2,2,+1,+1); break;
176 case '+': goto failed;
182 for (yi=gy;yi<gy+gys;yi++) memset(nst+SaXYL(gx,yi),'+',gxs);
183 for (yi=gy;yi<gy+gys;yi++) memcpy(nst+SaXYL(gx-sx,yi-sy),st+SaXYL(gx,yi),gxs);
186 printf("Moving: g=(%d,%d)[%d,%d] by (%d,%d)\n",gx,gy,gxs,gys,-sx,-sy);
194 static void swtogo(void)
213 while ((now=togonow)) {
214 togonow=now->nexttogo;
219 if (!(gone%STSTEP)) printf("%5u+%5u=%5u\n",gone,total-gone,total);
221 if (++ststep==STSTEP || !togo) {
222 printf("%5u+%5u=%5u, level=%3d\n",gone,total-gone,total,level);
230 printf("total=%u, maxlevel=%d, solutions=%d\n",total,level,solutions);
232 return(EXIT_SUCCESS);