#include <mazegameD2state01.h>
#include <mazematrixD2createmaze.h>
#include <stringconvert.h>
#include <stringtagparser.h>

void mazegameD2state01::game01default()
{
  m=8;
  n=12;

  path.clear();

  gamestart=0;
  gamefinish=0;

  randomize=true;

  proper=true;
  deletewall=0.025; // 2.5%
}


mazegameD2state01::mazegameD2state01()
  : m(mz.dim[0]), n(mz.dim[1]) 
{
  game01default();
}


void mazegameD2state01::game01()
{
  assert(m!=0);
  assert(n!=0);

  uint mn=m*n;
  assert(mn!=0);
  if (mn==0)
    return;

  if (randomize)
    srand( (unsigned)time( NULL ) );
  
  gamestart = gamefinish = 0;
  for ( ; gamestart==gamefinish; )
  {
    gamestart = 1+(rand()%mn);
    gamefinish = 1+(rand()%mn);
  }

  path.clear();
  path.push_back(gamestart);

  mz.dimset(m,n);
  mazematrixD2createmaze<uint> mc(mz);
  mc.buildpropermaze(); 

  if (proper==false)
    mc.impropermaze01(deletewall);

  assert(valid());
}

boolc mazegameD2state01::valid() const
{
//cout << SHOW(m) << endl;
//cout << SHOW(mz.dim[0]) << endl;

//cout << SHOW(gamestart) << " " << SHOW(gamefinish) << " " << SHOW(mz.dim[2]) << endl;

  assertreturnfalse(mz.valid());
  //assertreturnfalse(m==mz.dim[0]);
  //assertreturnfalse(n==mz.dim[1]);
  assertreturnfalse(!((gamestart==0)||(gamestart>mz.dim[2])));
  assertreturnfalse(!((gamefinish==0)||(gamefinish>mz.dim[2])));

  return true;
}

stringc mazegameD2state01::settings() const
{
  string options="";
  string s;

  options += ( "m=" + stringconvert::tostring(m) + " " );
  options += ( "n=" + stringconvert::tostring(n) + " " );
  options += ( "gamestart=" + stringconvert::tostring(gamestart) + " " );
  options += ( "gamefinish=" + stringconvert::tostring(gamefinish) + " " );
  options += ( "randomize=" + stringconvert::tostring(randomize) + " " );
  options += ( "proper=" + stringconvert::tostring(proper) + " " );
  options += ( "deletewall=" + stringconvert::tostring(deletewall) + " " );

  return options;
}

uintc mazegameD2state01::currentpos() const
{
  assert(path.empty()==false);
  return path[path.size()-1];
}

boolc mazegameD2state01::currentmove(uintc dir)
{
  assert(dir<4);

  bool res=false;
  uint k2;

  k2 = mz.vi[currentpos()].ni[dir];
  if (k2!=0)
    res=true;

//  mz.move(res,k2,dir,currentpos());

  if (res==false)
    return false;

  if (path.size()>1)
  {
    if (path[path.size()-2]==k2)
    {
      path.pop_back(); 
      return true;
    }
  }

  path.push_back(k2);
  return true;
}

mazegameD2state01::operator stringc () const
{
  string s1;
  s1 += "<mazegameD2state01>\n";

  s1 += stringtag(gamestart,"gamestart");
  s1 += stringtag(gamefinish,"gamefinish");
  s1 += stringtag(path.size(),"pathsize");
  s1 += "<path>\n";
  for (uint i=0; i<path.size(); ++i)
  {
    s1 += stringto(path[i]);
    s1 += " ";
  }
  s1 += "\n</path>\n";
  s1 += stringtag(randomize,"randomize");
  s1 += stringtag(proper,"proper");
  s1 += stringtag(deletewall,"deletewall");

  s1 += (stringc)mz;
  s1 += "</mazegameD2state01>\n";

  return s1;
}


void mazegameD2state01::serializeInverse(stringc & str)
{
  string s2(stringtagparser(str).data("mazegameD2state01"));
  stringfrom(gamestart,stringtagparser(s2).data("gamestart"));
  stringfrom(gamefinish,stringtagparser(s2).data("gamefinish"));
  stringfrom(randomize,stringtagparser(s2).data("randomize"));
  stringfrom(proper,stringtagparser(s2).data("proper"));
  stringfrom(deletewall,stringtagparser(s2).data("deletewall"));
  
  path.clear();
  uint n;
  stringfrom(n,stringtagparser(s2).data("pathsize"));
  {
    uint k;
    stringstream ss(stringtagparser(s2).data("path"));
    for (uint i=0; i<n; ++i)
    {
      ss >> k;
      path.push_back(k); 
    }
  }

  mz.serializeInverse(s2);
}



