This code was written with the _ALPHA_ version of Processing
and it may not run correctly with the current vesion.


// ALPHABOT
// by Nikita Pashenkov
//
// Created:                  Oct 2000
// Ported to Processing:     Dec 2002
  

float rotX, rotY;
int POS_NUM = 19;

float preset_a[] = {0, 30, 0, 0, 0, 60, 30, 0, 0, 0, 0, -90, 0, 0, 0, 0, 0, 0, 0};
float preset_b[] = {0, 0, 0, 0, 0, -10, -20, -90, -100, -110, 80, 100, 110, 0, 0, 0, 0, 0, 0};
float preset_c[] = {10, 20, 90, 0, 0, 0, -20, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0};
float preset_d[] = {0, 0, 80, 120, 0, 0, 0, 0, 0, 0, 80, 120, 0, 0, 0, 0, 0, 0, 0};
float preset_e[] = {0, 0, 0, 270, 0, 0, 0, -90, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0};
float preset_f[] = {0, 0, 0, 270, 0, 0, 0, -90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
float preset_g[] = {10, 20, 90, 0, 0, 0, -20, 0, 0, 0, 90, 100, 0, 0, 0, 0, 0, 0, 0};
float preset_h[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -90, 0, 0, -90, 0, 0, 150, 0};
float preset_i[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 0, 0};
float preset_j[] = {-20, -25, 0, 0, 0, 0, 20, 0, 0, 0, -90, -120, 0, 0, 0, 0, 110, 0, 0};
float preset_k[] = {0, 0, 0, -60, -150, -10, -90, 0, 0, 0, 0, 0, 0, -130, 0, 0, 0, 0, 0};
float preset_l[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0};
float preset_m[] = {0, 0, 40, 160, 0, 0, 0, 40, 160, 0, 0, 0, 0, 0, 0, 0, -50, 200, 0};
float preset_n[] = {0, 0, 30, 180, 180, 0, 0, 0, 180, 180, 0, 0, 0, -30, 180, 180, 0, 160, 0};
float preset_o[] = {0, 0, 90, 0, 0, 0, 0, 90, 0, 0, 90, 0, 0, -90, 0, 0, 0, 150, 0};
float preset_p[] = {0, 0, 90, 90, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
float preset_q[] = {0, 0, 90, 0, 0, 0, 0, 90, 0, 0, 90, -165, 0, -90, 0, 0, 0, 150, 0};
float preset_r[] = {0, 0, 90, 90, 125, -10, -90, 0, 0, 0, 0, 0, 0, -130, 0, 0, 0, 0, 0};
float preset_s[] = {0, -90, 0, 0, 0, 90, 90, 0, 0, 0, -90, 0, 0, 0, 0, 0, 125, 0, 0};
float preset_t[] = {0, 0, 90, 0, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 75, 0, 0};
float preset_u[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, -90, 0, 0, 0, 150, 0};
float preset_v[] = {20, 20, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 140, 0};
float preset_w[] = {20, 20, 0, 0, 0, 0, 15, 0, 0, 0, 50, 140, 0, -50, 140, 0, 0, 210, 0};
float preset_x[] = {-30, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -135, 30};
float preset_y[] = {0, 30, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 0, 0};
float preset_z[] = {-20, 0, 0, 0, 0, 0, 0, 70, 0, 0, 70, 0, 0, 0, 0, 0, 0, 0, 0};
// preset_*[0]        // angle: part 1 bottom
// preset_*[1]        // angle: part 1 middle 
// preset_*[2]        // angle: part 1 top 1st degree
// preset_*[3]        // angle: part 1 top 2nd degree
// preset_*[4]        // angle: part 1 top 3rd degree
// preset_*[5]        // angle: part 2 top
// preset_*[6]        // angle: part 2 middle
// preset_*[7]        // angle: part 2 top 1st degree
// preset_*[8]        // angle: part 2 top 2nd degree
// preset_*[9]        // angle: part 2 top 3rd degree
// preset_*[10]       // angle: part 1 bottom 1st degree
// preset_*[11]       // angle: part 1 bottom 2nd degree
// preset_*[12]       // angle: part 1 bottom 3rd degree
// preset_*[13]       // angle: part 2 bottom 1st degree
// preset_*[14]       // angle: part 2 bottom 2nd degree
// preset_*[15]       // angle: part 2 bottom 3rd degree
// preset_*[16]       // distance: part 1 starting distance
// preset_*[17]       // distance: part 2 starting distance
// preset_*[18]       // distance: part 2 'x' special case


float pos_preset[];
float pos_current[];


void setup()
{
  size(400, 400);
  background(255);

  rotX = 0;
  rotY = 0;

  lights();
  //noStroke();

  pos_preset = new float[POS_NUM];
  pos_current = new float[POS_NUM];
  
  for(int i=0; i<POS_NUM; i++)
    pos_preset[i] = preset_a[i]; 
}


void mouseDragged()
{
  rotX += mouseX - pmouseX;
  rotY += mouseY - pmouseY;
}


void keyPressed() 
{
  if(key == 'a' || key == 'A') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_a[i]; 
       
  else if(key == 'b' || key == 'B') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_b[i];  
      
  else if(key == 'c' || key == 'C') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_c[i];  
      
  else if(key == 'd' || key == 'D') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_d[i];  
      
  else if(key == 'e' || key == 'E') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_e[i];  
      
  else if(key == 'f' || key == 'F') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_f[i];  
      
  else if(key == 'g' || key == 'G') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_g[i];  
      
  else if(key == 'h' || key == 'H') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_h[i];  
      
  else if(key == 'i' || key == 'I') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_i[i];  
      
  else if(key == 'j' || key == 'J') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_j[i];  
      
  else if(key == 'k' || key == 'K') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_k[i];
        
  else if(key == 'l' || key == 'L') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_l[i];  
      
  else if(key == 'm' || key == 'M') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_m[i];  
      
  else if(key == 'n' || key == 'N') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_n[i];  
      
  else if(key == 'o' || key == 'O') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_o[i];  
      
  else if(key == 'p' || key == 'P') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_p[i];  
      
  else if(key == 'q' || key == 'Q') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_q[i];  
      
  else if(key == 'r' || key == 'R') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_r[i];  
      
  else if(key == 's' || key == 'S') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_s[i];  
      
  else if(key == 't' || key == 'T') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_t[i];  
      
  else if(key == 'u' || key == 'U') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_u[i];  
      
  else if(key == 'v' || key == 'V') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_v[i]; 
       
  else if(key == 'w' || key == 'W') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_w[i];  
    
  else if(key == 'x' || key == 'X') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_x[i];  
      
  else if(key == 'y' || key == 'Y') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_y[i];  

  else if(key == 'z' || key == 'Z') 
    for(int i=0; i<POS_NUM; i++)
      pos_preset[i] = preset_z[i];  
}


void loop()
{
  translate(200, 200, 75);
  scale(.65);

  rotateZ(-PI/2);                                          
  rotateX(0.9*PI);  
  rotateX(-rotX*0.005);
  translate(0, 0, -75);

  fill(102, 153, 102);
  draw_bot();
  fold_bot();
  //delay(10);
}


void draw_bot()
{
  boolean flip = true;

  translate(-150, 50-pos_current[16], 0);               // initial parts translate
  rotateZ(pos_current[0]*PI/180);                       // initial parts angle
  draw_part(160, 40, 70, !flip);

  push();
    translate(10, 0, 10);  
    rotateZ(-pos_current[10]*PI/180);                   // part 1 bottom 1st degree
    draw_part(140, 35, 50, flip);

    translate(110, 12, 10);
    rotateZ(PI-pos_current[11]*PI/180);                 // part 1 bottom 2nd degree
    draw_part(122.5, 30.625, 30, flip);

    translate(95, 5, 10);
    rotateZ(PI-pos_current[12]*PI/180);                 // part 1 bottom 3rd degree
    draw_part(107, 26.8, 10, flip);
  pop();

  translate(150, 0, 0);
  rotateZ(-pos_current[1]*PI/180);                      // part 1 bend
  translate(150, 0, 70);
  rotateY(180*PI/180);
  draw_part(160, 40, 70, !flip);

  push();                                               // part 1
    translate(10, 0, 10);
    rotateZ(-pos_current[2]*PI/180);                    // part 1 top 1st degree
    draw_part(140, 35, 50, flip);

    translate(110, 12, 10);
    rotateZ(PI-pos_current[3]*PI/180);                  // part 1 top 2nd degree
    draw_part(122.5, 30.625, 30, flip);

    translate(94, 5, 10);
    rotateZ(PI-pos_current[4]*PI/180);                  // part 1 top 3rd degree
    draw_part(107, 26.8, 10, flip);
  pop();
  
  rotateX(180*PI/180);                                  // flip part
  rotateZ(pos_current[18]*PI/180);                      // part 2 starting distance
  translate(0, pos_current[17], 0);                     // 'x' special case
  rotateZ(pos_current[5]*PI/180);                       // angle between parts
  draw_part(160, 40, 70, !flip);

  push();                                               // part 2
    translate(10, 0, 10);
    rotateZ(-pos_current[7]*PI/180);                    // part 2 top 1st degree
    draw_part(140, 35, 50, flip);

    translate(110, 12, 10);
    rotateZ(PI-pos_current[8]*PI/180);                  // part 2 top 2nd degree
    draw_part(122.5, 30.625, 30, flip);

    translate(96, 5, 10);
    rotateZ(PI-pos_current[9]*PI/180);                  // part 2 top 3rd degree
    draw_part(107, 26.8, 10, flip);
  pop();

  translate(150, 0, 0);
  rotateZ(-pos_current[6]*PI/180);                      // part 2 bend
  translate(150, 0, 70);
  rotateY(PI);
  draw_part(160, 40, 70, !flip);

  push();            
    translate(10, 0, 10);
    rotateZ(pos_current[13]*PI/180);                    // part 2 bottom 1st degree
    draw_part(140, 35, 50, flip);

    translate(110, 12, 10);
    rotate(PI-pos_current[14]*PI/180);                  // part 2 bottom 2nd degree
    draw_part(122.5, 30.625, 30, flip);

    translate(94, 5, 10);
    rotate(PI-pos_current[15]*PI/180);                  // part 2 bottom 3rd degree
    draw_part(107, 26.8, 10, flip);
  pop();
}


void draw_part(float x, float y, float z, boolean flip)
{
  push();
    translate(-10, -20, 0);
    draw_part_h(0, x, 0, y, 0, 10);

    if(z > 10)                                          // if larger than smallest part 
    {
      if(flip)
        draw_part_v2(0, x, 0, y, 0, z);
      else
        draw_part_v1(0, x, 0, y, 0, z);
      draw_part_h(0, x, 0, y, z-10, z);
    }
  pop();
 }


void draw_part_v1(float x0, float x1, float y0, float y1, float z0, float z1)
{
  float dx = x1 - x0;
  float dy = y1 - y0;

  beginShape(QUADS);
    vertex(dx*0.375,  dy*1.5,      z0+10);
    vertex(dx*0.75,   dy*1.5,      z0+10);
    vertex(dx*0.75,   dy*1.5,      z1-10);
    vertex(dx*0.375,  dy*1.5,      z1-10);
    
    vertex(dx*0.75,   dy*1.5,      z0+10);
    vertex(dx*0.75,   dy*1.5-10,   z0+10);
    vertex(dx*0.75,   dy*1.5-10,   z1-10);
    vertex(dx*0.75,   dy*1.5,      z1-10);
    
    vertex(dx*0.75,   dy*1.5-10,   z0+10);
    vertex(dx*0.375,  dy*1.5-10,   z0+10);
    vertex(dx*0.375,  dy*1.5-10,   z1-10);
    vertex(dx*0.75,   dy*1.5-10,   z1-10);
    
    vertex(dx*0.25,   dy*1.33,     z0+10);
    vertex(dx*0.375,  dy*1.5,      z0+10);
    vertex(dx*0.375,  dy*1.5,      z1-10);
    vertex(dx*0.25,   dy*1.33,     z1-10);
    
    vertex(dx*0.25,   dy*1.33,     z0+10);
    vertex(dx*0.25,   dy*1.33-10,  z0+10);
    vertex(dx*0.25,   dy*1.33-10,  z1-10);
    vertex(dx*0.25,   dy*1.33,     z1-10);
    
    vertex(dx*0.25,   dy*1.33-10,  z0+10);
    vertex(dx*0.375,  dy*1.5-10,   z0+10);
    vertex(dx*0.375,  dy*1.5-10,   z1-10);
    vertex(dx*0.25,   dy*1.33-10,  z1-10);
  endShape();  
}


void draw_part_v2(float x0, float x1, float y0, float y1, float z0, float z1)
{
  float dx = x1 - x0;
  float dy = y1 - y0;
  
  beginShape(QUADS);
    vertex(dx*2/8,     y0,         z0+10);
    vertex(dx*5/8,     y0,         z0+10);
    vertex(dx*5/8,     y0,         z1-10);
    vertex(dx*2/8,     y0,         z1-10);
    
    vertex(dx*5/8,     y0,         z0+10);
    vertex(dx*6/8,     dy/6,       z0+10);
    vertex(dx*6/8,     dy/6,       z1-10);
    vertex(dx*5/8,     y0,         z1-10);
    
    vertex(dx*6/8,     dy/6,       z0+10);
    vertex(dx*6/8,     dy/6+10,    z0+10);
    vertex(dx*6/8,     dy/6+10,    z1-10);
    vertex(dx*6/8,     dy/6,       z1-10);
    
    vertex(dx*5/8,     y0+10,      z0+10);
    vertex(dx*6/8,     dy/6+10,    z0+10);
    vertex(dx*6/8,     dy/6+10,    z1-10);
    vertex(dx*5/8,     y0+10,      z1-10);
      
    vertex(dx*2/8,     y0+10,      z0+10);
    vertex(dx*5/8,     y0+10,      z0+10);
    vertex(dx*5/8,     y0+10,      z1-10);
    vertex(dx*2/8,     y0+10,      z1-10);
    
    vertex(dx*2/8,     y0,         z0+10);
    vertex(dx*2/8,     y0+10,      z0+10);
    vertex(dx*2/8,     y0+10,      z1-10);
    vertex(dx*2/8,     y0,         z1-10);
  endShape();  
}


void draw_part_h(float x0, float x1, float y0, float y1, float z0, float z1)
{
  float dx = x1 - x0;
  float dy = y1 - y0;
  
  beginShape(POLYGON);
    vertex(x0,         y0,         z0);
    vertex(dx*0.625,   y0,         z0);
    vertex(x1,         dy*0.5,     z0);
    vertex(x1,         dy*1.5,     z0);
    vertex(dx*0.375,   dy*1.5,     z0);
    vertex(x0,         y1,         z0);
  endShape();
    
  beginShape(POLYGON);
    vertex(x0,         y0,         z1);
    vertex(dx*0.625,   y0,         z1);
    vertex(x1,         dy*0.5,     z1);
    vertex(x1,         dy*1.5,     z1);
    vertex(dx*0.375,   dy*1.5,     z1);
    vertex(x0,         y1,         z1);
  endShape();
    
  beginShape(QUADS);
    vertex(x0,        y0,          z0);
    vertex(x0,         dy,         z0);
    vertex(x0,         dy,         z1);
    vertex(x0,         y0,         z1);
      
    vertex(x0,         dy,         z0);
    vertex(dx*0.375,   dy*1.5,     z0);
    vertex(dx*0.375,   dy*1.5,     z1);
    vertex(x0,         dy,         z1);
      
    vertex(dx*0.375,   dy*1.5,     z0);
    vertex(dx,         dy*1.5,     z0);
    vertex(dx,         dy*1.5,     z1);
    vertex(dx*0.375,   dy*1.5,     z1);
      
    vertex(dx,         dy*1.5,     z0);
    vertex(dx,         dy*0.5,     z0);
    vertex(dx,         dy*0.5,     z1);
    vertex(dx,         dy*1.5,     z1);
      
    vertex(dx,         dy*0.5,     z0);
    vertex(dx*5/8,     y0,         z0);
    vertex(dx*5/8,     y0,         z1);
    vertex(dx,         dy*0.5,     z1);
      
    vertex(dx*5/8,     y0,         z0);
    vertex(x0,         y0,         z0);
    vertex(x0,         y0,         z1);
    vertex(dx*5/8,     y0,         z1);
  endShape();  
}


void fold_bot()
{
  for(int i=0; i<POS_NUM; i++)
  {
    if(pos_current[i] < pos_preset[i])      
      pos_current[i]++;
    else if(pos_current[i] > pos_preset[i])  
      pos_current[i]--;
  }
}