import vrml.*;
import vrml.node.*;
import vrml.field.*;

import java.util.*;

public class body extends Script {
   
   SFRotation headRot,foot11Rot,foot12Rot,foot21Rot,foot22Rot,hand11Rot,hand12Rot,hand21Rot,hand22Rot,bodyRot,bodyTurn;
   SFVec3f bodyTrans;
   float foot11,foot12,foot21,foot22,hand11,hand12,hand21,hand22,head;
   float x,y,z,X;
   float startPos;
   float turn;
   float rot;
   int count;
   int status ;
   Random randGen;
   
   public void initialize() {
      foot11Rot = (SFRotation)getEventOut("foot_L1_rotation");
      foot12Rot = (SFRotation)getEventOut("foot_L2_rotation");
      
      foot21Rot = (SFRotation)getEventOut("foot_R1_rotation");
      foot22Rot = (SFRotation)getEventOut("foot_R2_rotation");
      
      
      
      hand11Rot = (SFRotation)getEventOut("hand_L1_rotation");
      hand12Rot = (SFRotation)getEventOut("hand_L2_rotation");
      
      hand21Rot = (SFRotation)getEventOut("hand_R1_rotation");
      hand22Rot = (SFRotation)getEventOut("hand_R2_rotation");
      
      headRot = (SFRotation)getEventOut("head_rotation");
      bodyRot = (SFRotation)getEventOut("body_rotation");
      bodyTurn = (SFRotation)getEventOut("turn");
      bodyTrans = (SFVec3f)getEventOut("body_translation");
      
      x=-9;
      z=0;
      turn=1.5708f;
      X=0;
      count=0;
      status=1;
      
      }
   
   
   void update() {
      float temp[]=new float[4];
      temp[0]=1;temp[1]=0;temp[2]=0;
      
      temp[3]=foot11;
      foot11Rot.setValue(temp);
      temp[3]=foot21;
      foot21Rot.setValue(temp);
      
      temp[3]=foot12;
      foot12Rot.setValue(temp);
      temp[3]=foot22;
      foot22Rot.setValue(temp);
      
      temp[3]=hand11;
      hand11Rot.setValue(temp);
      temp[3]=hand21;
      hand21Rot.setValue(temp);
      
      temp[3]=hand12;
      hand12Rot.setValue(temp);
      temp[3]=hand22;
      hand22Rot.setValue(temp);
      
      temp[3]=rot;
      bodyRot.setValue(temp);
      
      
      
      
      temp[3]=head;
      temp[1]=1;
      temp[0]=0;
      headRot.setValue(temp);
      temp[3]=turn;
      bodyTurn.setValue(temp);
      
      temp[0]=x+(float) (Math.sin(turn)*X);
      temp[1]=y;
      temp[2]=z+(float)(Math.cos(turn)*X);
      bodyTrans.setValue(temp);
      randGen = new Random();
      }
   
   
   
   boolean startWalking() {
      float angle=0.4f;
      foot11=count*angle/10;
      foot21=-count*angle/10;
      hand11=-count*angle/10;
      hand21=count*angle/10;
      hand12=-count*0.6f/10;
      head=count*0.5f/10;
      
      
      y=(float)(2.8f*Math.cos(foot11)-2.8f);
      X+=2.8f*Math.sin(angle)/10;
      
      if (count>=10) {
         count=0;
         
         return false;
         }
      else {
         count++;
         return true;
         }
      }
   
   boolean stopWalking() {
      float angle=0.4f;
      int c=10-count;
      foot11=c*angle/10;
      foot21=-c*angle/10;
      hand11=-c*angle/10;
      hand21=c*angle/10;
      hand12=-c*0.6f/10;
      head=c*0.5f/10;
      
      
      y=(float)(2.8f*Math.cos(foot11)-2.8f);
      X+=2.8f*Math.sin(angle)/10;
      
      if (count>=10) {
         y=0;
         count=0;
         return false;
         }
      else {
         count++;
         return true;
         }
      }
   
   double sqr(double x) {
      return x*x;
      }
   
   boolean Walking() {
      float angle=0.4f;
      if (count<20) {
         foot21+=angle/10;
         hand11+=angle/10;
         hand21-=angle/10;
         hand12+=0.6f/20;
         hand22-=0.6f/20;
         head-=0.5f/10;
         
         if (count<10) {
            foot11-=(angle+0.2f)/10;
            foot12+=(1f)/10;     
            }
         else {
            foot11-=(angle-0.2f)/10;
            foot12-=(1f)/10;  
            }
         y=(float)(2.8f*Math.cos(foot11)-2.8f);
         }
      else if (count<40) {
         foot11+=angle/10;
         hand21+=angle/10;
         hand11-=angle/10;
         hand22+=0.6f/20;
         hand12-=0.6f/20;
         head+=0.5f/10;
         if (count<30) {
            foot21-=(angle+0.2f)/10;
            foot22+=(1f)/10;  
            }
         else {
            foot21-=(angle-0.2f)/10;
            foot22-=(1f)/10;  
            }
         y=(float)(2.8f*Math.cos(foot21)-2.8f);
         }
      else {
         count=0;

         X+=2.8f*Math.sin(angle)/10;
         
         if (sqr(x+Math.sin(turn)*(X+6))+sqr(z+Math.cos(turn)*(X+6))
            <sqr(10)) return true;
         else return false;
         
         }
      
      
      
      X+=2.8f*Math.sin(angle)/10;
      count++;
      return true;
      
      }
   boolean Rolling() {
      
      
      if (count<10) {
         hand21=hand11=count*0.5f/5;   
         startPos=X;
         }
      else if (count<25){
         hand21=hand11=(-(count-10)*(1.3f+3.1416f)/15)+0.5f;
         rot=-(count-10)*1.2f/14;
         foot11=foot21=-rot;
         y=(float)(1.1*Math.cos(rot)-1.1);
         X=startPos+(1.1f*(float)Math.sin(rot));
         }
      else if (count<40){
         rot=-(count-25)*(3.1416f-1.2f)/15-1.2f;
         hand21=hand11=(count-25)*(0.8f)/15-0.8f-3.1416f;
         foot11=foot21=-(count-25)*(1.2f)/15+1.2f;
         }
      else if (count<60) {
         rot=-(count-40)*(3.1416f)/19+3.1614f;
         hand11=hand21=(count-40)*(3.1416f)/19-3.1614f;
         if (count<50)
            foot11=foot21=-(count-40)*(1f)/9;
         else 
            foot11=foot21=+(count-50)*(1f)/9-1f;
         }
      
      else {
         count=0;
         y=0;
         rot=0;
         if (X<-2.5) return false;
         };
      if ((count>=25) && (count<60)){
         X-=7f/(60-25);
         if (count<40) y-=((float)(1.1*Math.cos(-1.2)-1.1)+1f)/15;
         else y+=1f/20;
         }
      
      count++;
      return true;
      }
   
   boolean Turning1() {
      x=x+(float) (Math.sin(turn)*X);
      z=z+(float)(Math.cos(turn)*X);
      X=(float)Math.sqrt(x*x+z*z);
      
      if (Math.abs(z) <0.001) {
         if (x>0) turn=(float) Math.PI/2;
         else turn= (float) -Math.PI/2;
         }
      else if (z>0) turn= (float) Math.atan(x/z);
      else turn=  (float) (Math.PI+Math.atan(x/z));
      x=0;
      z=0;
      return false;
      }
   
   boolean Turning2() {
      x=x+(float) (Math.sin(turn)*X);
      z=z+(float)(Math.cos(turn)*X);
      X=0;
      turn+= (randGen.nextFloat()-2)*0.5f;
      return false;
      }
   
   void set_fraction(){
      switch (status) {
         
      case 1:if (!startWalking()) status=2; break;
      case 2:if (!Walking()) status=3; break;
      case 3:if (!stopWalking()) status=4; break;
      case 4:if (!Turning1()) status=5;break;
      case 5:if (!Rolling()) status=6; break;
      case 6:if (!Turning2()) status=1;break;
         };
      
      update();
      }  
   
   public void processEvent(Event e) {
      
      String EventName = e.getName();
      
      if (EventName.equals("set_fraction")) {
         set_fraction();
         }  
      }
   }