#include <iostream.h>
#include "tangle.h"
#include "CDiction.h"


//global variables
CDiction* Dict;
CMap TheMap[8][8];
int size,minlength;
char outword[17], step;
ofstream outfile;

CLink::CLink(){
 for(x=0;x<size;x++)
  for(y=0;y<size;y++) beenthere[x][y]=0;
 x=128;y=0;next=NULL;
}

CLink::CLink(char* input){
 for(x=0;x<size;x++)
  for(y=0;y<size;y++) beenthere[x][y]=input[x*size+y];
   x=128;y=0;next=NULL;
}

CLink::~CLink(){
 if(next) delete next;
}

void CLink::Output(){
 cout<<x<<'_'<<y<<' ';
 if(next) next->Output();
}

CMap::CMap(){
 for(int x=0; x<8; x++) pointers[x]=0;
 letter=0;
}

CMap::~CMap(){
}

CLink* CLink::MakeChain(char target){
CLink *head,*traverse,*lag;
short count,dx,dy;
 head = new CLink;
 traverse = head;
 for(count=0;count<8;count++){
  dx=0; dy=0;
  if(TheMap[x][y].pointers[count]==target){
   //cout<<'^'<<(char)(target+96);
   switch(count){
    case 0: dy=-1; break;
    case 1: dx=1, dy=-1; break;
    case 2: dx=1; break;
    case 3: dx=1, dy=1; break;
    case 4: dy=1; break;
    case 5: dx=-1, dy=1; break;
    case 6: dx=-1; break;
    case 7: dx=-1, dy=-1; break;
   }
   if(beenthere[x+dx][y+dy]==0){
    traverse->next = new CLink();
    lag=traverse;
    for(char a=0;a<size;a++)
     for(char b=0;b<size;b++)
      traverse->beenthere[a][b]=beenthere[a][b];
    traverse->x=x+dx;
    traverse->y=y+dy;
    traverse->beenthere[x+dx][y+dy]=1;
    traverse=traverse->next;
   }
  }
 }
 delete traverse;
 if(head==traverse){
  if(next) head=next->MakeChain(target);
  else head=NULL;
 }
 else{
  if(next) lag->next=next->MakeChain(target);
  else lag->next=NULL;
 }
 return(head);
}

void Seek(CLink* input, unsigned long int pos, short istrailer, short arewords, short ispointer){
 CLink *head[16],*outhead=NULL;
 char temp;
 unsigned long int header;
 short dx,dy,a=0,b=1;
 
 if(input){
  header=31;
  head[0]=input;
  temp=step;

  if(istrailer){
   for(a=1;a<16;a++) head[a]=NULL;
   //cout<<'*';
   for(a=0;(header&31)&&head[a];a++){
    
    if(a%6==0){
     if(header){
      header=Dict->index[pos];
      pos++;
     }
    }
    
    head[a+1]=head[a]->MakeChain(header&31);
    if(head[a+1]==NULL){
     for(b=1;b<a+1;b++) delete head[b];
    }
    else{
     //cout<<(char)((header&31)+96)<<' ';
     outword[step]=(header&31)+96;
     step++;
     header>>5;
    }
   }
  }
  if(head[a]){
   //head[a]->Output();
   if(ispointer){
    for(int count=0; b;count++){
     b=Dict->index[pos+count]&1024;
     outhead=head[a]->MakeChain(Dict->index[count+pos]&31);
     //cout<<(count+pos)<<'('<<(char)((Dict->index[count+pos]&31)+96)<<')';
     if(outhead){
      outword[step]=(Dict->index[count+pos]&31)+96;
      step++;
      outword[step]='\0';
      //cout<<outword<<":";
      Seek(outhead,Dict->index[count+pos]>>13,Dict->index[count+pos]&2048,Dict->index[count+pos]&32,Dict->index[count+pos]&4096);
      delete outhead;
      step--;
      outword[step]='\0';
      //cout<<'\n';
     }
    }
   }
   for(a=0;a<minlength&&b;a++) b=outword[a];
   if(arewords&&b) outfile<<outword<<'\n';
  }
  step=temp;
  outword[step]='\0';
 }
}

void OutWords(){
 CLink *head,*traverse,*lag;
 int pos=0;
 for(char count=1;count<27;count++){
  head = new CLink;
  traverse = head;
  for(int x=0; x<size; x++){
   for(int y=0; y<size; y++){
    if(TheMap[x][y].letter==count){
     lag=traverse;
     traverse->next = new CLink;
     traverse->x=x;
     traverse->y=y;
     traverse->beenthere[x][y]=1;
     traverse=traverse->next;
    }
   }
  }
  
  if (head!=traverse){
   delete lag->next;
   lag->next=NULL;
  }
  else{
   delete head;
   head=NULL;
  }
  
  if(head){
   pos=0;
   outword[0]=count+96;
   //cout<<'\n';
   step=1;
   while(((Dict->index[Dict->start+pos]&31)<count)
    &&(Dict->index[Dict->start+pos]&1024)) pos++;
   
   if((Dict->index[pos+Dict->start]&31)==count)
    Seek(head,Dict->index[Dict->start+pos]>>13,
          Dict->index[Dict->start+pos]&2048,
           Dict->index[Dict->start+pos]&32,
            Dict->index[Dict->start+pos]&4096);
   delete head;
  }
 }
}

void Process(char* input){
int left, top, right, y,bottom,x; 
 for(x=0; x<size; x++)
  for(y=0; y<size; y++)
   TheMap[x][y].letter=input[x*size+y]-96;
 right=1;
 left=0;
 for(x=0;x<size;x++){
  if(x==(size-1)) right=0;
  top=0;
  bottom=1;
  for(y=0;y<size;y++){
   if(y==(size-1)) bottom=0;
   if(left){
    TheMap[x][y].pointers[6]=TheMap[x-1][y].letter;
   }
   if(right){
    TheMap[x][y].pointers[2]=TheMap[x+1][y].letter;
   }
   if(top){
    TheMap[x][y].pointers[0]=TheMap[x][y-1].letter;
   }
   if(bottom){
    TheMap[x][y].pointers[4]=TheMap[x][y+1].letter;
   }
   if(left&&top){
    TheMap[x][y].pointers[7]=TheMap[x-1][y-1].letter;
   }
   if(left&&bottom){
    TheMap[x][y].pointers[5]=TheMap[x-1][y+1].letter;
   }
   if(right&&top){
    TheMap[x][y].pointers[1]=TheMap[x+1][y-1].letter;
   }
   if(right&&bottom){
    TheMap[x][y].pointers[3]=TheMap[x+1][y+1].letter;
   }
   top=1;
  }
  left=1;
 }
}

void main(){
char input[65],choice,q=1,filename[20]="output.txt\0";
 for(size=0;size<17;size++) outword[size]='\0';
 ifstream words("input.dic",ios::in);
 Dict= new CDiction(&words);
 words.close();
 size=5;
 minlength=4;
 cout<<"--------------TangleWord Trainer v0.8--------------\n";
 cout<<"\n\nInput is assumed to come from input.dic\n";
 do{
  cout<<"Setup is\n -Board Length:"<<size<<"\n -Minimum Word Length:"<<minlength<<"\n";
  cout<<" -Output goes to "<<filename<<'\n';
  cout<<"(1) : Set Board Length\n";
  cout<<"(2) : Set Minimum Word Length\n";
  cout<<"(3) : Set output file\n";
  cout<<"(4) : Find Words on Board (enter '1' to stop input)\n";
  cout<<"Other Key Quits Program\n";
  cout<<"Enter selection:";
  cin>>choice;
  switch(choice){
   case '1' : cin>>size;break;
   case '2' : cin>>minlength;break;
   case '4' : do{
                cin>>input;
                if(input[0]=='1') break;
				outfile.open(filename,ios::out);
                Process(input);
                OutWords();
                outfile.close();
              }while(1==1);
              break;
   case '3' : cin>>filename;break;
   default : q=0; break;
  }
 }while(q);
 delete Dict;
}
