//
 From Borg to Borges: A 3D labyrinth - Ken Perlin

import render.*;
import java.awt.*;

public class Borg extends RenderApplet
{
   public void initialize() {
      setBgColor(0,0,.2);                                     // INIT BACKGROUND, LIGHT, MATERIAL
      addLight(1,1,1, 1,1,1);
      world.setMaterial((new Material().setColor(.6,.6,.6, 0,0,0,20, .4,.4,.4)));
      buildMaze();
   }
   void buildMaze() {
      if (world.child != null) world.child[0] = null;         // IF OLD MAZE EXISTS, DELETE IT
      Geometry maze = world.add();                            // ADD A NEW MAZE TO THE WORLD

      int walls[] = RandomPermutation.generate(3*n*n*n,seed); // ALL CELL PATHS, IN RANDOM ORDER

      UnionFind set = new UnionFind(n * n * n);               // ADD PATHS BETW UNCONNECTED CELLS
      for (int m = 0 ; m < walls.length ; m++) {
         int c = walls[m], a = c/3, i = a % n, j = (a / n) % n, k = a / n / n;
         int u = c%3==0 ? 1 : 0, v = c%3==1 ? 1 : 0, w = c%3==2 ? 1 : 0, b = a + u + n*(v + n*w);
         if (i < n-u && j < n-v && k < n-w && set.find(a) != set.find(b)) {
            set.union(a,b);
            push();
               scale(2.5/n, 2.5/n, 2.5/n);
               translate(2*i - n+1 + u, 2*j - n+1 + v, 2*k - n+1 + w);
               scale(u + 1./r, v + 1./r, w + 1./r);
               transform(maze.add().cube());
            pop();
         }
      }
   }
   public boolean keyUp(Event e, int key) {                   // HOT KEY OPTIONS.
      if (key == 1002) { setFOV(.2); }
      if (key == 1003) { setFOV(1.); }
      if (key == 1004) { if (n < 30) { n++; buildMaze(); } }
      if (key == 1005) { if (n >  2) { n--; buildMaze(); } }
      if (key == 1006) { r = 20; buildMaze(); }
      if (key == 1007) { r =  2; buildMaze(); }
      if (key >= '0' && key <= '9') { seed = key - '0'; buildMaze(); }
      damage();
      return super.keyUp(e, key);
   }
   int n = 4, seed = 0, r = 20;
}