// EXchess source code, (c) Daniel C. Homan  1997-2011
// Released under the GNU public license, see file license.txt
 

#include <cstdlib>
using namespace std;


#include "define.h"
#include "chess.h"
#include "const.h"

game_rec::game_rec() {

	book = 1;
	both = 0;
	mttc = 0;
	omttc = 0;
	inc = 0;
	base = 5.0;
	timeleft[0] = 500.0;
	timeleft[1] = 500.0;
        learn_bk = 0;
        td_learning = 0;
	knowledge_scale = 100;

	/* tree search parameters */
	ts.ponder = 0;
	ts.last_ponder = 0;
	ts.ponder_time = 0;
	ts.ponder_time_double = 0;
	ts.root_tb_score = -1;
        ts.last_depth = 1;
	ts.fail = 0;
        ts.analysis_mode = 0;
        ts.tsuite = 0;
        ts.no_book = 0;
	ts.max_search_depth = MAXD;
	ts.max_search_time = MAXT; 

	ts.link_nodes(this);                // link nodes in tree search     
	setboard(i_pos, 'w', "KQkq", "-");  // set up the board

}


// This function sets up the board from EPD format

void game_rec::setboard(const char inboard[256], const char ms, const char castle[5], const char ep[3])
{
  int rx = 0, ry = 7, i;  // control variables

  // no book learning yet
  learn_count = 0; learned = 0;

  // game is not over
  over = 0; 

  // reset time control variables
  mttc = omttc;
  timeleft[0] = base*100.0;
  timeleft[1] = base*100.0;

  // Side to move
  if (ms == 'b') { T = 2; p_side = 0; pos.wtm = 0; }
  else { T = 1; p_side = 1; pos.wtm = 1; }

  // Other game parameters
  pos.fifty = 0; pos.last.t = NOMOVE;

  // initializing castling status
  pos.castle = 0;
  for(i = 0; i < 4; i++)  {
   switch (castle[i]) {
    case 'K':
     pos.castle = pos.castle^1; break;
    case 'Q':
     pos.castle = pos.castle^2; break;
    case 'k':
     pos.castle = pos.castle^4; break;
    case 'q':
     pos.castle = pos.castle^8; break;
   }
  }

  // en-passant
  if(ep[0] != '-') {
    int ex, ey;
    ex = int(ep[0])-97;
    ey = atoi(&ep[1])-1;
    pos.ep = SQR(ex,ey);
    //cout << "ep square is " << ex << " " << ey << " " << pos.ep << "\n";
  }
  else pos.ep = 0;

  // clear the board
  for(int ci = 0; ci < 64; ci++) { pos.sq[ci] = empty; }

  // Setting up the board
  for (int ri = 0; ri < 256; ri++)
  {
    switch (inboard[ri])
    {
      case '/': ry--; rx = 0; break;
      case '1': pos.sq[SQR(rx,ry)] = empty; rx++; break;
      case '2': for(i=1;i<=2;i++) { pos.sq[SQR(rx,ry)] = empty; rx++; } break;
      case '3': for(i=1;i<=3;i++) { pos.sq[SQR(rx,ry)] = empty; rx++; } break;
      case '4': for(i=1;i<=4;i++) { pos.sq[SQR(rx,ry)] = empty; rx++; } break;
      case '5': for(i=1;i<=5;i++) { pos.sq[SQR(rx,ry)] = empty; rx++; } break;
      case '6': for(i=1;i<=6;i++) { pos.sq[SQR(rx,ry)] = empty; rx++; } break;
      case '7': for(i=1;i<=7;i++) { pos.sq[SQR(rx,ry)] = empty; rx++; } break;
      case '8': for(i=1;i<=8;i++) { pos.sq[SQR(rx,ry)] = empty; rx++; } break;
      case 'p': pos.sq[SQR(rx,ry)].side = 0;
           pos.sq[SQR(rx,ry)].type = PAWN; rx++; break;
      case 'n': pos.sq[SQR(rx,ry)].side = 0;
           pos.sq[SQR(rx,ry)].type = KNIGHT; rx++; break;
      case 'b': pos.sq[SQR(rx,ry)].side = 0;
           pos.sq[SQR(rx,ry)].type = BISHOP; rx++; break;
      case 'r': pos.sq[SQR(rx,ry)].side = 0;
           pos.sq[SQR(rx,ry)].type = ROOK; rx++; break;
      case 'q': pos.sq[SQR(rx,ry)].side = 0;
           pos.sq[SQR(rx,ry)].type = QUEEN; rx++; break;
      case 'k': pos.sq[SQR(rx,ry)].side = 0;
           pos.sq[SQR(rx,ry)].type = KING; rx++; break;
      case 'P': pos.sq[SQR(rx,ry)].side = 1;
           pos.sq[SQR(rx,ry)].type = PAWN; rx++; break;
      case 'N': pos.sq[SQR(rx,ry)].side = 1;
           pos.sq[SQR(rx,ry)].type = KNIGHT; rx++; break;
      case 'B': pos.sq[SQR(rx,ry)].side = 1;
           pos.sq[SQR(rx,ry)].type = BISHOP; rx++; break;
      case 'R': pos.sq[SQR(rx,ry)].side = 1;
           pos.sq[SQR(rx,ry)].type = ROOK; rx++; break;
      case 'Q': pos.sq[SQR(rx,ry)].side = 1;
           pos.sq[SQR(rx,ry)].type = QUEEN; rx++; break;
      case 'K': pos.sq[SQR(rx,ry)].side = 1;
           pos.sq[SQR(rx,ry)].type = KING; rx++; break;
    }
   if(ry <= 0 && rx >= 8) break;
   if(inboard[ri] == '\0') break;
  }

  // generate the hash_code for this position
  //  -- this also updates the piece lists and piece counts and game stage
  pos.gen_code();

  // set some final parameters
  pos.has_castled[0] = 0;
  pos.has_castled[1] = 0;
  pos.in_check();
  plist[T-1] = pos.hcode;
  reset = pos;

}

//--------------------------------------------------------
//  Function to link nodes in tree search data structure
//--------------------------------------------------------
void tree_search::link_nodes(game_rec *gr) {

  /* setup linked list of nodes for search */
  for(int iply = 0; iply <= MAXD; iply++) {
     n[iply].ply=iply;
     n[iply].ts = &(gr->ts);
     n[iply].gr = gr; 
     if(!iply) n[iply].prev = 0;
     else n[iply].prev = &n[iply-1];
     if(iply == MAXD) n[iply].next = 0;
     else n[iply].next = &n[iply+1];  
  }

}
