//------------------ CellUtility Class -------------------//

import java.awt.*;
import java.applet.*;
import java.io.*;
import java.lang.String;
import java.util.Random;
import java.util.Date;

public class myCellUtility
{

    public int randomise(Random nrand,int range)
	 {
	    if(range==0) return 0;
		return( java.lang.Math.abs(nrand.nextInt()) % range);
	 }


public void DomyGetCellLoc(int id,myCell gCell[],myPoint dstP)
{
   gCell[id].DoGetLoc(dstP);
}

public boolean hidalihasi(myPoint p0)
{
   if(p0.h==0) {
      if(p0.v>=4 && p0.v<11) return false;
      if(p0.v>=19 && p0.v<26) return false;
       return true;
   }
  
   if(p0.v<4 || p0.v>=26 ){
           if(p0.h==1) return true;
    }
    
    return false;
}

public  boolean migihasi(myPoint p0)
{
  if(p0.v>=11 && p0.v<19){ if(p0.h==52) return true;}
  
   switch(p0.v){
   
        case 0: case 29: if(p0.h==17 || p0.h==18) return true; break;
        case 1: case 28: if(p0.h==23 || p0.h==24) return true; break;
        case 2: case 27: if(p0.h==29 || p0.h==30) return true; break;
        case 3: case 26: if(p0.h==35 || p0.h==36) return true; break;
         
    }
  
    return false;
    
}

public boolean uehasi(myPoint p0)
{
  if(p0.v==0) return true;
  
   switch(p0.v){
      case 1: if(p0.h==1 || p0.h==17) return true; break;
      case 2: if(p0.h==1 || p0.h==23) return true; break;
      case 3: if(p0.h==1 || p0.h==29) return true; break;
      case 4: if(p0.h==1 || p0.h==35) return true; break;
   }
  
   return false;

}

public boolean sitahasi(myPoint p0)
{
  if(p0.v==29) return true;
  
  switch(p0.v){
      case 29: if(p0.h==1 || p0.h==17) return true; break;
      case 28: if(p0.h==1 || p0.h==23) return true; break;
      case 27: if(p0.h==1 || p0.h==29) return true; break;
      case 26: if(p0.h==1 || p0.h==35) return true; break;
   }
   
  return false;

}


public int DoGetCellDistW(myPoint p0)
{
 int x0=0;
 
    switch(p0.v){
     
      case 0:  case 29: x0=17; break;
      case 1:  case 28: x0=14; break;
      case 2:  case 27: x0=11; break;
      case 3:  case 26: x0=8;  break;
      case 4:  case 25: x0=7;  break;
      case 5:  case 24: x0=6;  break;
      case 6:  case 23: x0=5;  break;
      case 7:  case 22: x0=4;  break;
      case 8:  case 21: x0=3;  break;
      case 9:  case 20: x0=2;  break;
      case 10: case 19: x0=1;  break;
      
      case 11: case 12: case 13: case 14:
      case 15: case 16: case 17: case 18:
              x0=0; break;
      
   }
    x0 +=p0.h;
    
   return x0;
    
}


public int DoGetCellDistW2(myPoint p0)
{
 int x0=0;
 
    switch(p0.v){
     
      case 0:  case 29: x0=0; break;
      case 1:  case 28: x0=3; break;
      case 2:  case 27: x0=6; break;
      case 3:  case 26: x0=9;  break;
      case 4:  case 25: x0=10;  break;
      case 5:  case 24: x0=11;  break;
      case 6:  case 23: x0=12;  break;
      case 7:  case 22: x0=13;  break;
      case 8:  case 21: x0=14;  break;
      case 9:  case 20: x0=15;  break;
      case 10: case 19: x0=16;  break;
      
      case 11: case 12: case 13: case 14:
      case 15: case 16: case 17: case 18:
              x0=17; break;
      
   }
   
   x0 +=p0.h;
    
   return x0;
    
}

public int DoGetCellDistW3(myPoint p0)
{
 int x0=0;
 
    switch(p0.v){
     
      case 0:  case 29: x0=0; break;
      case 1:  case 28: x0=3; break;
      case 2:  case 27: x0=6; break;
      case 3:  case 26: x0=9;  break;
      case 4:  case 25: x0=10;  break;
      case 5:  case 24: x0=11;  break;
      case 6:  case 23: x0=12;  break;
      case 7:  case 22: x0=13;  break;
      case 8:  case 21: x0=14;  break;
      case 9:  case 20: x0=15;  break;
      case 10: case 19: x0=16;  break;
      
      case 11: case 12: case 13: case 14:
      case 15: case 16: case 17: case 18:
              x0=17; break;
      
   }
   
  // x0 +=p0.h;
    
   return x0;
    
}

public int DoGetRightEndIndex(myPoint P0)
{

   switch(P0.v){
     case 0: case 29: return 18;
     case 1: case 28: return 24;
     case 2: case 27: return 30;
     case 3: case 26: return 36;
     case 4: case 25: return 38;
     case 5: case 24: return 40;
     case 6: case 23: return 42;
     case 7: case 22: return 44;
     case 8: case 21: return 46;
     case 9: case 20: return 48;
     case 10: case 19: return 50;
     default: return 52;
   }

}

public boolean DoGetUpOrDown(myPoint P0)
{
 int   sx,s0,ss;
 boolean up;
 
     sx=DoGetCellDistW(P0);
    
     s0= sx & 0x0001;
     if(s0==1) up=true;
     else up=false;
     
     ss=P0.v; ss=ss & 0x0001;   if(ss==1) up=!up; 
       
     return up;
 }
 
public boolean  HIDALIHASI(myPoint P0)
{
  if(P0.h==0) return true;
  
  return false;

}

boolean  MIGIHASI(myPoint P0)
{
 int sx;

  sx=DoGetRightEndIndex(P0);
  
  if(P0.h==sx) return true;
  
   return false;
  
}

public boolean     DoCheckExistNotMeAround(int ID,int myID,int DST[],myCell gCell[])
{
 int i,id;
 
     for(i=0;i<3;i++){
          if(!gCell[ID].DoGetOpen(i)) continue;
        
           id=gCell[ID].DoGetDoorNBID(i,0);
           if(gCell[id].DoCheckExistNotMe(myID)) {
              DST[0]=id;
              return true;
           }
      }
     
     return false;
          
}

public int   DoGetRandomCellNotMe(int ID,int myID,myCell gCell[],Random nrand)
{
 int i,num=0,id,ss[];
 
   ss=new int[3];
 
  for(i=0;i<3;i++){
     if(!gCell[ID].DoGetOpen(i)) continue;
     id=gCell[ID].DoGetDoorNBID(i,0);
     if(gCell[id].DoCheckExistNotMe(myID)) { ss[num]=id; num ++; }
   }
   
   if(num==0) return -1;
   if(num==1) return ss[0];
   
    id=randomise(nrand,num);
    
    return ss[id];

}

//------------------------------------------------//
public boolean     DoCheckExistNotMeAndMe(int ID,int myID,int DST[],myCell gCell[])
{
 int i,id;
 
     for(i=0;i<3;i++){
          if(!gCell[ID].DoGetOpen(i)) continue;
        
           id=gCell[ID].DoGetDoorNBID(i,0);
           if(gCell[id].DoCheckExistNotMeAndMe(myID)) {
              DST[0]=id;
              return true;
           }
      }
     
     return false;
          
}

public int    GT_DoGetMoveDir(int cellid,int myID,myCell gCell[],Random nrand)
{
 int i,num=0,id,s0,dstCell,DST[];
 
      DST=new int[3];
 
      s0=gCell[cellid].DoGetPieceNum();
      if(s0==2){ num=1; DST[0]=cellid;}
     
      for(i=0;i<3;i++){
      
         if(!gCell[cellid].DoGetOpen(i)) continue;
   
         id =gCell[cellid].DoGetDoorNBID(i,0);
         
       //  if(gCell[id]->DoGetLeftOrRightEnd()) continue; ///
              
         if(gCell[id].DoCheckExistNotMe(myID)){
            DST[num]=id;
            num++;
         }
      }
      
    if(num==0) return -1;
    
     dstCell=DST[randomise(nrand,num)];
 
     return dstCell;

}

public boolean  CL_DoCheckIfEdge(myPoint p0)
{
 
     if(p0.h<=1) return true;
     if(p0.h>=DoGetRightEndIndex(p0)-1) return true;
 
     if(HIDALIHASI(p0)) return true;
     if(MIGIHASI(p0))   return true;
     if(uehasi(p0))     return true;
     if(sitahasi(p0))   return true;
     
     if(p0.v>=1 && p0.v<4){
         if(p0.h<=3 || p0.h>=DoGetRightEndIndex(p0)-3) return true; 
     }
      
     if(p0.v>=26 && p0.v<29){
         if(p0.h<=3 || p0.h>=DoGetRightEndIndex(p0)-3) return true; 
     }
    
    return false;
}


public int  CL_DoGetCellidFromType(myPoint P0,myPoint P1,int srcID,myCell gCell[])
{
 int x0,x1,s0,dstID;
 myPoint p0=new myPoint(),p1=new myPoint();
 
      gCell[srcID].DoGetLoc(p0);
      
      p1.v=p0.v + P1.v - P0.v;
      if(p1.v<0 || p1.v>29) return -1;
  
      x0=DoGetCellDistW3(p0);
      x1=DoGetCellDistW3(p1);
      
      p1.h=p0.h + P1.h - P0.h + (x1 - x0);
      
      if(p1.h<0) return -1;
      s0=DoGetRightEndIndex(p1);
      if(p1.h>s0) return -1;
      
     // dstID=DoGetCellIDbymyPoint(p1);
      dstID=DoGetCellIDbyPoint(p1);

      return dstID;
}

public int CL_DoGetOpenDirectionNum(int ID,int DST[],myCell gCell[])
{
 int i,num=0,id,val,s0,s1;
 
   for(i=0;i<3;i++){
     if(!gCell[ID].DoGetOpen(i)) continue;
      
      id =gCell[ID].DoGetDoorNBID(i,0);
      val=gCell[ID].DoGetDoorNBID(i,1);
     
      s0=gCell[id].DoGetPieceID(val,0);
      s1=gCell[id].DoGetPieceID(val,1);
      if(s0==-1 || s1==-1){  DST[num]=id; num ++;}
    }
   
   return num;
}

public int CL_DoGetOpenDirectionNotThis(int ID,int thisID,myCell gCell[])
{
 int i,id,val,s0,s1;
 
    for(i=0;i<3;i++){
      if(!gCell[ID].DoGetOpen(i)) continue;
     
      id=gCell[ID].DoGetDoorNBID(i,0);
      val=gCell[ID].DoGetDoorNBID(i,1);
   
      s0=gCell[id].DoGetPieceID(val,0);
      s1=gCell[id].DoGetPieceID(val,1);
      if(s0==-1 || s1==-1){   if(id!=thisID) return i;  }
    }
   
    return -1;
}

public int CL_DoGetExistEmptyDirectionNum(int ID,int val,myCell gCell[])
{
 int s0,s1;
 
   if(!gCell[ID].DoCheckIfExistEmpty()) return 1;
 
   if(gCell[ID].DoGetLeftOrRightEnd()){
        s0=gCell[ID].DoGetDoorNBID(val,0);
       if(gCell[s0].DoGetLeftOrRightEnd()) return 1;
       else  return 2;
   }else {
      s0=gCell[ID].DoGetPieceID(val,0);
      s1=gCell[ID].DoGetPieceID(val,1);
      if(s0==-1 && s1==-1) return 2;
      else return 1;
   }

}

public boolean CL_DoCheckIfExistEmptyToThisDirection(int src,int dst,myCell gCell[])
{
 int i,id,s0,s1;
 
   if(!gCell[src].DoCheckIfExistEmpty()) return false;
 
   for(i=0;i<3;i++){
   
        id=gCell[src].DoGetDoorNBID(i,0);
        if(id==dst){
             s0=gCell[src].DoGetPieceID(i,0);
             s1=gCell[src].DoGetPieceID(i,1);
             
             if(s0==-1 || s1==-1) return true;
             else return false;
        }
    }
  
    return false;
}


public int  PC_DoGetEdgeCellID(int index)
{
 
     switch(index){
      case 0:  return  1;   
      case 1:  return  0;    
        
      case 2:  return  20;   
      case 3:  return  19;  
        
      case 4:  return  45;   
      case 5:  return  44;   
        
      case 6:  return  76;   
      case 7:  return  75;   
        
      case 8:    return  112;  
      case 9:    return  151;  
      case 10:   return  192;  
      case 11:   return  235;  
      case 12:   return  280;  
      case 13:   return  327;  
      case 14:   return  376;  
        
      case 15:  return  427;  
      case 16:  return  480;  
      case 17:  return  533;   
      case 18:  return  586;  
      case 19:  return  639;  
      case 20:  return  692;  
      case 21:  return  745;   
      case 22:  return  798;   
    
      case 23:  return  851;   
      case 24:  return  902;   
      case 25:  return  951;   
      case 26:  return  998;   
      case 27:  return  1043;  
      case 28:  return  1086;  
      case 29:  return  1127;  
      
      case 30:  return  1166;  
      case 31:  return  1167;  
        
      case 32:  return  1203;   
      case 33:  return  1204;  
        
      case 34:  return  1234;  
      case 35:  return  1235;  
        
      case 36:  return  1259;   
      case 37:  return  1260;  
        
      case 38:  return  1262;   
      case 39:  return  1264;  
      case 40:  return  1266;  
      case 41:  return  1268;  
      case 42:  return  1270;  
      case 43:  return  1272;   
      case 44:  return  1274;   
         
      case 45:  return  1276;   
      case 46:  return  1277;  
        
      case 47:  return  1257;  
      case 48:  return  1258;   
        
      case 49:  return  1232;  
      case 50:  return  1233;  
        
      case 51:  return  1201;  
      case 52:  return  1202; 
     
      case 53:  return  1165;  
      case 54:  return  1126;  
      case 55:  return  1085;   
      case 56:  return  1042;  
      case 57:  return   997;  
      case 58:  return   950;  
      case 59:  return   901;  
        
      case 60:  return   850;  
      case 61:  return   797;  
      case 62:  return   744;  
      case 63:  return   691;  
      case 64:  return   638;  
      case 65:  return   585;  
      case 66:  return   532;  
      case 67:  return   479;  
        
      case 68:  return   426;   
      case 69:  return   375;   
      case 70:  return   326;  
      case 71:  return   279;  
      case 72:  return   234;  
      case 73:  return   191;  
      case 74:  return   150;   
     
      case 75:  return   111;  
      case 76:  return   110;   
        
      case 77:  return   74;  
      case 78:  return   73;  
        
      case 79:  return   43;  
      case 80:  return   42;  
        
      case 81:  return   18;  
      case 82:  return   17;   
        
      case 83:  return   15;  
      case 84:  return   13; 
      case 85:  return   11;  
      case 86:  return    9;  
      case 87:  return    7; 
      case 88:  return    5;  
      case 89:  return    3;  
         
   }
   
 
   return 0;

}

public int PC_DoGetEdgeCellID2(int index)
{
 
     switch(index){
        case 1:    return 0;
        case 0:    return 1;
        
        case 20:   return 2;
        case 19:   return 3;
        
        case 45:   return 4;
        case 44:   return 5;
        
        case 76:   return 6;
        case 75:   return 7;
        
        case 112:  return  8;
        case 151:  return  9;
        case 192:  return 10;
        case 235:  return 11;
        case 280:  return 12;
        case 327:  return 13;
        case 376:  return 14;
        
        case 427:  return 15;
        case 480:  return 16;
        case 533:  return 17;
        case 586:  return 18;
        case 639:  return 19;
        case 692:  return 20;
        case 745:  return 21;
        case 798:  return 22;
    
        case 851:   return 23;
        case 902:   return 24;
        case 951:   return 25;
        case 998:   return 26;
        case 1043:  return 27;
        case 1086:  return 28;
        case 1127:  return 29;
      
        case 1166:  return 30;
        case 1167:  return 31;
        
        case 1203:  return 32;
        case 1204:  return 33;
        
        case 1234:  return 34;
        case 1235:  return 35;
        
        case 1259:  return 36;
        case 1260:  return 37;
        
        case 1262:  return 38;
        case 1264:  return 39;
        case 1266:  return 40;
        case 1268:  return 41;
        case 1270:  return 42;
        case 1272:  return 43;
        case 1274:  return 44;
         
        case 1276:  return 45;
        case 1277:  return 46;
        
        case 1257:  return 47;
        case 1258:  return 48;
        
        case 1232:  return 49;
        case 1233:  return 50;
        
        case 1201:  return 51;
        case 1202:  return 52;
     
        case 1165:  return 53;
        case 1126:  return 54;
        case 1085:  return 55;
        case 1042:  return 56;
        case  997:  return 57;
        case  950:  return 58;
        case  901:  return 59;
        
        case  850:  return 60;
        case  797:  return 61;
        case  744:  return 62;
        case  691:  return 63;
        case  638:  return 64;
        case  585:  return 65;
        case  532:  return 66;
        case  479:  return 67;
        
        case  426:  return 68;
        case  375:  return 69;
        case  326:  return 70;
        case  279:  return 71;
        case  234:  return 72;
        case  191:  return 73;
        case  150:  return 74;
     
        case  111:  return 75;
        case  110:  return 76;
        
        case  74:  return 77;
        case  73:  return 78;
        
        case  43:  return 79;
        case  42:  return 80;
        
        case  18:  return 81;
        case  17:  return 82;
        
        case  15:  return 83;
        case  13:  return 84;
        case  11:  return 85;
        case   9:  return 86;
        case   7:  return 87;
        case   5:  return 88;
        case   3:  return 89;
         
   }
   

   return 0;

}

public int   DoGetCellIDbyPoint(myPoint srcP)
{
 int dst=0;
 
   switch(srcP.v){
   
   case 0:  dst=srcP.h;       break;  
   case 1:  dst=srcP.h +  19; break;  
   case 2:  dst=srcP.h +  44; break;     
   case 3:  dst=srcP.h +  75; break;    
   case 4:  dst=srcP.h + 112; break;    
   case 5:  dst=srcP.h + 151; break;  
   case 6:  dst=srcP.h + 192; break;   
   case 7:  dst=srcP.h + 235; break;   
   case 8:  dst=srcP.h + 280; break;   
   case 9:  dst=srcP.h + 327; break;  
   case 10: dst=srcP.h + 376; break;  
   case 11: dst=srcP.h + 427; break;  
   case 12: dst=srcP.h + 480; break;  
   case 13: dst=srcP.h + 533; break; 
   case 14: dst=srcP.h + 586; break;  
   case 15: dst=srcP.h + 639; break;   
   case 16: dst=srcP.h + 692; break;   
   case 17: dst=srcP.h + 745; break;  
   case 18: dst=srcP.h + 798; break;   
   case 19: dst=srcP.h + 851; break; 
   case 20: dst=srcP.h + 902; break;  
   case 21: dst=srcP.h + 951; break;   
   case 22: dst=srcP.h + 998; break;  
   case 23: dst=srcP.h + 1043; break;  
   case 24: dst=srcP.h + 1086; break;    
   case 25: dst=srcP.h + 1127; break;  
   case 26: dst=srcP.h + 1166; break;  
   case 27: dst=srcP.h + 1203; break;  
   case 28: dst=srcP.h + 1234; break;  
   case 29: dst=srcP.h + 1259; break;  
 }
 
  return dst;
}



public int PC_DoGetNextEdgeCell(int  preID,myCell gCell[],myPiece gPiece[])
{
 int    i,j,s0,num=0,ss[],id;
 boolean  exist;
 
   ss=new int[12];
 
 
   for(i=0;i<12;i++){
       s0=gPiece[preID].DoGetCellID(i);
       
       if(!gCell[s0].DoGetIfEdge()) continue;
       
       exist=false;
       if(num>0){
         for(j=0;j=90) s0=0;
     
     id=PC_DoGetEdgeCellID(s0);
     return id;

}

private  int  doGetMaxID(int SS[],int Num)
{
 int i,id,s0,s1;

     if(Num==1) return SS[0];
     
     id=SS[0];
     s0=PC_DoGetEdgeCellID2(SS[0]);
   
     for(i=1;i< Num;i++){
        s1=PC_DoGetEdgeCellID2(SS[i]);
       if(docheckifbigger(s1,s0)){ id=SS[i]; s0=s1;}
     }
     return id;
}
private boolean docheckifbigger(int S1,int S0)
{
 int n0,n1;
 
  
   if(S1> S0){
      n0=S1 - S0;
      n1=S0 + 90 - S1;
      
      if(n0< n1) return true;
      else return false;
   }else {
   
     n0=S0 - S1;
     n1=S1 + 90 - S0;
     
     if(n0> n1) return true;
     else return false;
   
   }

 }

}