
// option.cpp

// includes

#include <cstdlib>

#include "option.h"
#include "protocol.h"
#include "util.h"
#include "FruitConfiguration.h"

// types

struct option_t
{
   const char*  var;
   bool         declare;
   const char*  init;
   const char*  type;
   const char*  extra;
   const char*  val;
};

// variables

static option_t Option[] = 
{
  { "Hash", true, "16", "spin", "min 4 max 1024", NULL },

// kh 10.04.07 Thomas Gaksch
  // JAS
  // search X seconds for the best move, equal to "go movetime"
  { "Search Time",  true, "0",   "spin",  "min 0 max 3600", NULL },
  // search X plies deep, equal to "go depth"
  { "Search Depth",  true, "0",   "spin",  "min 0 max 20", NULL },
  // JAS end

  { "Ponder", true, "false", "check", "", NULL },

  { "OwnBook",  true, "true",           "check",  "", NULL },

// kh 10.04.07 Thomas Gaksch
//{ "BookFile", true, "book_small.bin", "string", "", NULL },
  { "BookFile", true, "performance.bin", "string", "", NULL },


// kh 10.04.07 Thomas Gaksch
	{ "Bitbases Path", true, "c:/egbb/", "string", "", NULL },

// kh 02.06.08 Thomas Gaksch 14b5c
	{ "Bitbases Cache Size", true, "16", "spin", "min 16 max 1024", NULL },
//{ "Bitbases Cache Size", true, "32", "spin", "min 16 max 1024", NULL },

  { "MultiPV", true, "1", "spin",  "min 1 max 10", NULL },

// kh 10.04.07 start Thomas Gaksch
  { "NullMove Pruning",       true, "Always", "combo", "var Always var Fail High var Never", NULL },
  { "NullMove Reduction",     true, "3",         "spin",  "min 1 max 4", NULL },
  { "Verification Search",    true, "Always",   "combo", "var Always var Endgame var Never", NULL },
// kh 10.04.07 end Thomas Gaksch

  { "Verification Reduction", true, "5",         "spin",  "min 1 max 6", NULL },

  { "History Pruning",     true, "true", "check", "", NULL },

// kh 02.06.08 Thomas Gaksch 14b5c
  { "History Threshold",   true, "70",   "spin",  "min 0 max 100", NULL },

// kh 10.04.07 Thomas Gaksch
  { "Futility Pruning", true, "true", "check", "", NULL },

  { "Futility Margin",  true, "100",   "spin",  "min 0 max 500", NULL },

// kh 02.06.08 Thomas Gaksch 14b5c
  { "Extended Futility Margin",  true, "300",   "spin",  "min 0 max 900", NULL },

// kh 10.04.07 Thomas Gaksch
  { "Delta Pruning", true, "true", "check", "", NULL },

  { "Delta Margin",  true, "50",    "spin",  "min 0 max 500", NULL },

  { "Quiescence Check Plies", true, "1", "spin", "min 0 max 2", NULL },

  { "Material",        true, "100", "spin", "min 0 max 400", NULL },
  { "Piece Activity",  true, "100", "spin", "min 0 max 400", NULL },
	{ "Piece Square Activity",  true, "100", "spin", "min 0 max 400", NULL }, // kh 10.04.07 Thomas Gaksch
  { "King Safety",     true, "100", "spin", "min 0 max 400", NULL },
  { "Pawn Structure",  true, "100", "spin", "min 0 max 400", NULL },
  { "Passed Pawns",    true, "100", "spin", "min 0 max 400", NULL },

// kh 10.04.07 Thomas Gaksch
  { "Toga Lazy Eval", true, "true", "check", "", NULL },
  { "Toga Lazy Eval Margin",  true, "200",    "spin",  "min 0 max 900", NULL },

// kh 02.06.08 Thomas Gaksch 14b5c
  { "Toga Exchange Bonus",  false, "20",    "spin",  "min 0 max 100", NULL }, 

// kh 02.06.08 Thomas Gaksch 14b5c
  { "Toga King Safety", true, "false", "check", "", NULL },

// kh 02.06.08 Thomas Gaksch 14b5c
  { "Toga King Safety Margin",   true, "1700",    "spin",  "min 500 max 3000", NULL },

// kh 02.06.08 Thomas Gaksch 14b5c
  { "Toga Extended History Pruning", true, "false", "check", "", NULL },

// kh 02.06.08 Thomas Gaksch 14b5c
  { "Toga History Threshold",   false, "40",   "spin",  "min 0 max 100", NULL },


// kh 09.02.08 YBWC specific options
  {OPT_NAME_FRUIT_DEBUG_LEVEL,                            true,         "0",   "spin",    "min 0 max 999", NULL},

  {OPT_NAME_LOG_TO_COMMON_FILE,                           true,     "false",  "check",                 "", NULL},
  {OPT_NAME_LOG_TO_FILE,                                  true,     "false",  "check",                 "", NULL},
  {OPT_NAME_LOG_TO_STDOUT,                               false,     "false",  "check",                 "", NULL},

  {OPT_NAME_MAX_BUFFERED_REQUEST_COUNT,                  false,        "32",   "spin",    "min 0 max 999", NULL},
  {OPT_NAME_MAX_BUFFERED_RESULT_COUNT,                   false,        "32",   "spin",    "min 0 max 999", NULL},

  {OPT_NAME_REQUEST_FOR_WORK_WAIT_COUNTER_LIMIT,         false,      "1000",   "spin",  "min 0 max 99999", NULL},
  {OPT_NAME_REQUEST_FOR_WORK_WAIT_COUNTER_TO_DOUBLE,     false,        "10",   "spin",   "min 1 max 9999", NULL},
  {OPT_NAME_REQUEST_FOR_WORK_REPEAT_BLOCK_FACTOR,        false,         "2",   "spin",    "min 1 max 999", NULL},

  {OPT_NAME_SEND_ADDITIONAL_UCI_INFO,                    false,     "false",  "check",                 "", NULL},

  {OPT_NAME_DEBUG_WAIT_FOR_SLAVE_RATE,                   false,         "0",   "spin", "min 0 max 999999", NULL},
  {OPT_NAME_DEBUG_WAIT_FOR_WORK_RATE,                    false,         "0",   "spin", "min 0 max 999999", NULL},
  {OPT_NAME_DEBUG_AT_WORK_RATE,                          false,         "0",   "spin", "min 0 max 999999", NULL},
  {OPT_NAME_DEBUG_AWAITING_RESULT_RATE,                  false,         "0",   "spin", "min 0 max 999999", NULL},

  {OPT_NAME_FORCE_REPRODUCIBLE_EVALUATION,               false,     "false",  "check",                 "", NULL},

  {OPT_NAME_ONLY_DISTRIBUTE_WORK_OF_ROOT_MASTER,          true,     "false",  "check",                 "", NULL},
  {OPT_NAME_SUPPRESS_DISTRIBUTION_OF_ROOT_MOVES,          true,     "false",  "check",                 "", NULL},
  {OPT_NAME_SUPPRESS_DISTRIBUTION_OF_FULL_SEARCH_MOVES,   true,     "false",  "check",                 "", NULL},
  {OPT_NAME_ALLOW_DISTRIBUTION_OF_LAST_MOVE_IN_LIST,      true,      "true",  "check",                 "", NULL},

  {OPT_NAME_REVERSE_SEARCH_STACK_DISTRIBUTION_ORDER,     false,     "false",  "check",                 "", NULL},

  {OPT_NAME_UPDATE_SEARCH_WINDOWS,                        true,      "true",  "check",                 "", NULL},
  {OPT_NAME_DIRECT_UPDATE_SEARCH_WINDOWS,                 true,      "true",  "check",                 "", NULL},

  {OPT_NAME_MINIMUM_ALPHA_IMPROVEMENT_FOR_RERUN_SEARCH,   true,         "0",   "spin",  "min 0 max 99999", NULL},
  {OPT_NAME_MAXIMUM_MOVES_COMPLETED_FOR_RERUN_SEARCH,     true,         "2",   "spin",    "min 0 max 256", NULL},
  {OPT_NAME_MAXIMUM_PERCENT_COMPLETED_FOR_RERUN_SEARCH,   true,         "0",   "spin",    "min 0 max 100", NULL},
  {OPT_NAME_MAXIMUM_ALPHA_IMPROVEMENT_CHECK_COMPLETED,    true,        "50",   "spin",  "min 0 max 99999", NULL},

// kh 25.03.08 setoption at runtime is not yet supported for transposition table broadcast
  {OPT_NAME_BROADCAST_TRANSPOSITION_TABLE,               false,      "true",  "check",                 "", NULL},
  {OPT_NAME_BROADCAST_TRANSPOSITION_TABLE_CHUNK_SIZE,     true,        "64",   "spin",    "min 1 max 256", NULL},

  {OPT_NAME_MINIMUM_TRANS_DEPTH_FOR_BROADCAST,            true,         "4",   "spin",    "min 0 max 256", NULL},

// kh 25.03.08 setoption at runtime is not yet supported for shared memory transposition table access
  {OPT_NAME_USE_SHARED_MEMORY_TRANSPOSITION_TABLE,       false,      "true",  "check",                 "", NULL},

// kh 25.03.08 setoption at runtime is not yet supported for shared memory history table access
  {OPT_NAME_USE_SHARED_MEMORY_HISTORY_TABLE,             false,     "false",  "check",                 "", NULL},
  {OPT_NAME_SYNCHRONIZE_HISTORY_TABLE_ACCESS,            false,     "false",  "check",                 "", NULL},

// kh 25.03.08 setoption at runtime is not yet supported for history table broadcast
  {OPT_NAME_BROADCAST_HISTORY_TABLE,                     false,     "false",  "check",                 "", NULL},
  {OPT_NAME_HISTORY_TABLE_UPDATES_TO_TRIGGER_BROADCAST,  false,       "100",  "spin",    "min 1 max 4096", NULL},
  {OPT_NAME_HIST_TOT_TABLE_UPDATES_TO_TRIGGER_BROADCAST, false,       "100",  "spin",    "min 1 max 4096", NULL},

  {OPT_NAME_TRANSMIT_KILLER_TABLE,                       false,      "true",  "check",                 "", NULL},

  {OPT_NAME_TRANSMIT_HISTORY_TABLE,                      false,      "true",  "check",                 "", NULL},
  {OPT_NAME_TRANSMIT_HIST_TOT_TABLE,                     false,      "true",  "check",                 "", NULL},

  {OPT_NAME_USE_HISTORY_PRUNING,                          true,      "true",  "check",                 "", NULL},

  {OPT_NAME_USE_IID,                                     false,      "true",  "check",                 "", NULL},
  {OPT_NAME_USE_TRANSPOSITION_TABLE,                     false,      "true",  "check",                 "", NULL},

  {OPT_NAME_CHECK_NB,                                    false,     "10000",   "spin", "min 1 max 999999", NULL},
  {OPT_NAME_CHECK_INC,                                   false,     "10000",   "spin", "min 1 max 999999", NULL},

  {OPT_NAME_CHECK_NB_MPI_POLL,                           false,       "100",   "spin", "min 1 max 999999", NULL},
  {OPT_NAME_CHECK_INC_MPI_POLL,                          false,       "100",   "spin", "min 1 max 999999", NULL},

  {OPT_NAME_CLEANUP_ACTIONS_INTERVAL,                    false,      "2000",   "spin", "min 1 max 999999", NULL},

  {OPT_NAME_TIMER_ACTIONS_INTERVAL_01,                   false,      "3000",   "spin", "min 1 max 999999", NULL},

  {OPT_NAME_SEND_KEEP_ALIVE_CHARS,                       false,     "false",  "check",                 "", NULL},

//kh 01.02.07 negative values are used as relative IID start depth for sub problems
  {OPT_NAME_SLAVE_START_IID_DEPTH,                        true,       "256",   "spin", "min -256 max 256", NULL},

  {OPT_NAME_SLAVE_IID_DEPTH_SKIP_TO_MAX,                  true,         "1",   "spin",    "min 1 max 256", NULL},

// kh 12.02.08 use standard uci options now
/*
  {OPT_NAME_HASH_TABLE_SIZE_MB,                           true,        "16",   "spin",   "min 4 max 1024", NULL},
*/

  {OPT_NAME_MINIMUM_BROTHERS_FINISHED_ROOT,               true,         "1",   "spin",    "min 0 max 256", NULL},
  {OPT_NAME_MINIMUM_BROTHERS_FINISHED,                    true,         "1",   "spin",    "min 0 max 256", NULL},
  {OPT_NAME_BROTHERS_FINISHED_TYPE_CUT_OFFSET,           false,         "0",   "spin",    "min 0 max 256", NULL},
  {OPT_NAME_BROTHERS_FINISHED_TYPE_ALL_OFFSET,           false,         "0",   "spin",    "min 0 max 256", NULL},
  {OPT_NAME_BROTHERS_FINISHED_TYPE_PV_OFFSET,            false,         "0",   "spin",    "min 0 max 256", NULL},

  {OPT_NAME_MINIMUM_REMOTE_SEARCH_DEPTH_SAME_NODE,        true,         "4",   "spin",    "min 1 max 256", NULL},
  {OPT_NAME_MINIMUM_REMOTE_SEARCH_DEPTH,                  true,         "4",   "spin",    "min 1 max 256", NULL},
  {OPT_NAME_MAXIMUM_REMOTE_SEARCH_DEPTH,                  true,       "256",   "spin",    "min 1 max 256", NULL},

  {OPT_NAME_MINIMUM_REMOTE_SEARCH_HEIGHT,                false,         "0",   "spin",    "min 0 max 256", NULL},
  {OPT_NAME_MAXIMUM_REMOTE_SEARCH_HEIGHT,                false,       "256",   "spin",    "min 1 max 256", NULL},

  {OPT_NAME_USE_MULTI_STEP_STACK_SEARCH,                 false,     "false",  "check",                 "", NULL},
  {OPT_NAME_MINIMUM_BROTHERS_FINISHED_ROOT_FIRST_STEP,   false,         "8",   "spin",    "min 0 max 256", NULL},
  {OPT_NAME_MINIMUM_BROTHERS_FINISHED_FIRST_STEP,        false,         "8",   "spin",    "min 0 max 256", NULL},

  {OPT_NAME_USE_SYNCHRONIZED_STACK_STOP_ENTRY,           false,     "false",  "check",                 "", NULL},

  {OPT_NAME_ADJUST_PROCESS_PRIORITY,                     false,      "true",  "check",                 "", NULL},

  {OPT_NAME_USE_EVENT,                                   false,      "true",  "check",                 "", NULL},

  {NULL, false, NULL, NULL, NULL, NULL,},
};

// prototypes

static option_t * option_find (const char var[]);

// functions

// option_init()

void option_init() 
{
  option_t* opt;

  for(opt = &Option[0]; opt->var != NULL; opt++) 
  {
    option_set(opt->var, opt->init);
  }
}

// kh 04.08.06 avoid memory leaks
void option_finalize() 
{
  option_t* opt;

  for(opt = &Option[0]; opt->var != NULL; opt++) 
  {
    if(opt->val)
    {
      my_free((void*)opt->val);
    }
  }
}

// option_list()

void option_list() 
{
   option_t * opt;

   for(opt = &Option[0]; opt->var != NULL; opt++) 
   {
      if(opt->declare) 
      {
         if(opt->extra != NULL && *opt->extra != '\0') 
         {
            send("option name %s type %s default %s %s",opt->var,opt->type,opt->val,opt->extra);
         } 
         else 
         {
            send("option name %s type %s default %s",opt->var,opt->type,opt->val);
         }
      }
   }
}

// option_set()

bool option_set(const char var[], const char val[]) 
{
   option_t * opt;

   ASSERT(var != NULL);
   ASSERT(val != NULL);

   opt = option_find(var);
   if(opt == NULL) 
   {
     return false;
   }

   my_string_set(&opt->val, val);

   return true;
}

// option_get()

const char * option_get(const char var[]) {

   option_t * opt;

   ASSERT(var!=NULL);

   opt = option_find(var);
   if (opt == NULL) my_fatal("option_get(): unknown option \"%s\"\n",var);

   return opt->val;
}

// option_get_bool()

bool option_get_bool(const char var[]) {

   const char * val;

   val = option_get(var);

   if (false) {
   } else if (my_string_equal(val,"true") || my_string_equal(val,"yes") || my_string_equal(val,"1")) {
      return true;
   } else if (my_string_equal(val,"false") || my_string_equal(val,"no") || my_string_equal(val,"0")) {
      return false;
   }

   ASSERT(false);

   return false;
}

// option_get_int()

int option_get_int(const char var[]) {

   const char * val;

   val = option_get(var);

   return atoi(val);
}

// option_get_string()

const char * option_get_string(const char var[]) {

   const char * val;

   val = option_get(var);

   return val;
}

// option_find()

static option_t * option_find(const char var[]) {

   option_t * opt;

   ASSERT(var!=NULL);

   for (opt = &Option[0]; opt->var != NULL; opt++) {
      if (my_string_equal(opt->var,var)) return opt;
   }

   return NULL;
}

// end of option.cpp

