/* evolve a maze level */ #include #include #include /* Maze states */ enum { U = 1, R = 1<<1, B = 1<<2, L = 1<<3, E = 1<<4, T = 1<<5, M = 1<<6, }; enum { MX = 6, MY = 6, }; typedef struct { Point t; /* theseus */ Point m; /* minotaur */ Point e; /* exit */ uint b[MX][MY]; uint i; uint s; /* score */ } Level; Level l; uint maxmoves = 30; char moves[1024]; void start(void) { l.s = 0; l.e = Pt(0, 0); /* choose which side the exit is on, clockwise rotation */ switch(nrand(4)) { case 0: /* top */ l.e = Pt(nrand(MX), 0); break; case 1: /* right */ l.e = Pt(MX-1, nrand(MY)); break; case 2: /* bottom */ l.e = Pt(nrand(MX), MY-1); break; case 3: /* left */ l.e = Pt(0, nrand(MY)); break; } /* find a place for theseus, not on the exit, please */ l.t = Pt(nrand(MX), nrand(MY)); while(eqpt(l.t, l.e)) l.t = Pt(nrand(MX), nrand(MY)); /* the minotaur should not share the same initial square as theseus */ l.m = Pt(nrand(MX), nrand(MY)); while(eqpt(l.t, l.m)) l.m = Pt(nrand(MX), nrand(MY)); } void addwall(Point p) { if((l.b[p.x][p.y] & (0xF)) == 0xF) return; switch(nrand(4)) { case 0: /* top */ l.b[p.x][p.y] |= U; if(p.y != 0) l.b[p.x][p.y-1] |= B; break; case 1: l.b[p.x][p.y] |= R; if(p.x != MX-1) l.b[p.x+1][p.y] |= L; break; case 2: l.b[p.x][p.y] |= B; if(p.y != MY-1) l.b[p.x][p.y+1] |= U; break; case 3: l.b[p.x][p.y] |= L; if(p.x != 0) l.b[p.x-1][p.y] |= R; break; } } void remwall(Point p) { int i; if(l.b[p.x][p.y] == 0) return; do { i = nrand(4); } while(l.b[p.x][p.y] & (1<m; t = lvl->t; while(moves < 2) { o = m; /* first move horizontally, then vertically */ if((t.x > m.x) && !(lvl->b[m.x][m.y] & R)) m.x++; else if((t.x < m.x) && !(lvl->b[m.x][m.y] & L)) m.x--; else if((t.y > m.y) && !(lvl->b[m.x][m.y] & B)) m.y++; else if((t.y < m.y) && !(lvl->b[m.x][m.y] & U)) m.y--; moves++; lvl->m = m; if(eqpt(m, o)) { return; } if(eqpt(m, t)) break; } } int solve(Level lvl) { Level m; if(lvl.s > maxmoves) return 0; movem(&lvl); if(eqpt(lvl.t, lvl.m)) return 0; if(eqpt(lvl.t, lvl.e)) { l.s = lvl.s; return 1; } m = lvl; m.s++; if((m.t.y != 0) && !(m.b[m.t.x][m.t.y] & U)) { m.t.y--; moves[m.s] = 'U'; if(solve(m)) return 1; } if((m.t.x != MX-1) && !(m.b[m.t.x][m.t.y] & R)) { m.t.x++; moves[m.s] = 'R'; if(solve(m)) return 1; } if((m.t.y != MY-1) && !(m.b[m.t.x][m.t.y] & B)) { m.t.y++; moves[m.s] = 'B'; if(solve(m)) return 1; } if((m.t.x != 0) && !(m.b[m.t.x][m.t.y] & L)) { m.t.x--; moves[m.s] = 'L'; if(solve(m)) return 1; } return 0; } void printout(void) { int x, y; uint b; print("/* score: %ud */\n", l.s); print("/* solution: "); for(x = 0; x <= l.s; x++) print("%c", moves[x]); print(" */\n"); print("{\n"); for(y = 0; y < MY; y++) { print("\t"); for(x = 0; x < MX; x++) { b = l.b[x][y]; print("0"); if(eqpt(l.e, Pt(x, y))) print("+E"); if(eqpt(l.m, Pt(x, y))) print("+M"); if(eqpt(l.t, Pt(x, y))) print("+T"); if(b & U) print("+U"); if(b & R) print("+R"); if(b & L) print("+L"); if(b & B) print("+B"); print(",\t\t"); } print("\n"); } print("},\n"); } void main(int argc, char *argv[]) { int tries = 1000; if(argc == 2) maxmoves = (uint)atoi(argv[1]); else if(argc > 2) { print("usage: %s [maxmoves] -- default is %d\n", argv[0], maxmoves); exits("usage"); } if(maxmoves > 1024) maxmoves = 1024; srand(time(0)); start(); while(tries--) { evolve(); if(solve(l)) { printout(); tries = 1000; } start(); } }