
// protocol.cpp

// includes

#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include "board.h"
#include "book.h"
#include "eval.h"
#include "fen.h"
#include "material.h"
#include "move.h"
#include "move_do.h"
#include "move_legal.h"
#include "option.h"
#include "pawn.h"
#include "posix.h"
#include "protocol.h"
#include "pst.h"
#include "search.h"
#include "trans.h"
#include "util.h"

// kh 10.04.07 Thomas Gaksch
#include "sort.h"
#include "probe.h"

#include "pv.h"

#include "value.h"

#include "CommPrinter.h"
#include "YBWCManager.h"
extern YBWCManager* g_pYBWCManagerInstance;

// constants

static const double NormalRatio = 1.0;
static const double PonderRatio = 1.25;

// variables

static bool Init;

static bool Searching; // search in progress?
static bool Infinite; // infinite or ponder mode?
static bool Delay; // postpone "bestmove" in infinite/ponder mode?

static char * dirptr = "C:/egbb"; // kh 10.04.07 Thomas Gaksch

// prototypes

static void init              ();

static void loop_step         ();

static void parse_go          (char string[]);

// kh 10.08.06
static void parse_remote      (char string[]);

static void parse_position    (char string[]);

static void parse_setoption   (char string[]);

static void send_best_move    ();

static bool string_equal      (const char s1[], const char s2[]);
static bool string_start_with (const char s1[], const char s2[]);

// functions

// kh 10.04.07 Thomas Gaksch
void book_parameter() {

    // UCI options

	book_close();
	if (option_get_bool("OwnBook")) {
         book_open(option_get_string("BookFile"));
	}
}

// loop()

void loop() 
{
  int   nResult;
  char  sMemo[65536];

// init (to help debugging)

  Init      = false;

  Searching = false;
  Infinite  = false;
  Delay     = false;

  search_clear();

// kh 04.08.06 the "all time minimum" seems to be more interesting, so the initialization 
// was disabled in search_clear(...
// the absolute value of this minimum represents the maximum number of nodes searched in a row 
// without servicing any messages in between
  SearchInfo->check_nb_mpi_poll_min = 1; // kh 04.08.06 any value > 0 is sufficient

  board_from_fen(SearchInput->board, StartFen);

// loop

  g_pYBWCManagerInstance->nState = YBWC_MANAGER_STATE_IDLE;

// kh 19.09.06 never necessary here
  ASSERT(g_pYBWCManagerInstance->pHeadDelayedRequest == NULL);
//YBWCManager_DispatchDelayedRequests(g_pYBWCManagerInstance);

  if(g_pYBWCManagerInstance->bRootMaster)
  {

// kh 14.02.08 support immediate "go depth..." command after start of ClusterToga (without "UCI", "isready" etc.) 
    strcpy(sMemo, "position startpos");

// kh 10.08.06
    nResult = YBWCManager_HookPosition(g_pYBWCManagerInstance, sMemo);

    if(nResult == MPI_SUCCESS)
    {
    }
    else
    {
      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR loop_step(... failed at YBWCManager_HookPosition(..., errorcode = %d\n", nResult);
      }
    }

    while(/*true && */ !g_pYBWCManagerInstance->bFatalError) 
    {
      YBWCManager_ServiceMessages(g_pYBWCManagerInstance);

      if(input_available() || g_pYBWCManagerInstance->pAutoTester->bAutoTest)
      {
        loop_step();
      }
      else
      {

// kh 03.08.06 avoid heavy "busy waiting" if the root master is idle and waiting for a command via stdin
        CountdownTimer_WaitAndRestart(g_pYBWCManagerInstance->pCountdownTimerForRootMasterIdle);
      }
    } // while(true)
  } // if(g_pYBWCManagerInstance->bRootMaster)
  else
  {

// kh 09.08.06 for non root master implicitly perform the loop_step() actions for "uci"  
    ASSERT(!Searching);
    ASSERT(!Delay);

    option_list();

// kh 09.08.06 for non root master implicitly perform the loop_step() actions for "isready"  
    init();

// kh 19.09.06 a three way handshake is used for a proper shutdown
// step 1: root master invitates for logoff
// step 2: root master waits until all non root master have send the log off acknowledge result
// step 3: root master requests all non root master to shutdown
    while(g_pYBWCManagerInstance->nState != YBWC_MANAGER_STATE_SHUTDOWN)
    {
      YBWCManager_ServiceMessages(g_pYBWCManagerInstance);

      YBWCManager_CheckSendRequestForWork(g_pYBWCManagerInstance);

// kh 03.08.06 avoid heavy "busy waiting" if a non root master is "non searching" and servicing messages
// but this may be replaced for fastest message handling (a non root master should have 
// nothing else to compute anyway)
      if(g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
      {

// kh 16.11.06 very fast message handling (a processor should have nothing else to compute anyway)
        CountdownTimer_WaitAndRestart(g_pYBWCManagerInstance->pCountdownTimerForNonRootMasterIdle);

      }
    } // while(true) 
  } // !if(g_pYBWCManagerInstance->bRootMaster)
}

// init()

static void init() 
{
  if(!Init) 
  {
    // late initialisation

    Init                               = true;
    g_pYBWCManagerInstance->bFruitInit = TRUE;

// kh 10.04.07 start Thomas Gaksch
	  book_parameter();
      
	  //SearchInput->multipv = option_get_int("MultiPV");
// kh 10.04.07 end Thomas Gaksch


// kh 15.12.06 non root master trans_alloc are handled when receiving 
// the machine info (i.e. the node names at the moment)
// race conditions are quite possible at the moment (a non root master - on the same node as 
// the root master - calls trans_alloc before the root master)

// the g_pYBWCManagerInstance->bHashTableMaster property is not used at the moment anyway, so this is no problem
// (the first process on a node "wins" an creates the shared memory table)
// doing trans_alloc for the root_master will work too, if the 
// g_pYBWCManagerInstance->bHashTableMaster property would be used 
     
    if(g_pYBWCManagerInstance->bRootMaster)
    {
      trans_alloc(Trans);

      history_alloc(&gpHistory); // kh 08.02.07
    }

    pawn_init();
    pawn_alloc();

    material_init();
    material_alloc();

    pst_init();
    eval_init();

    if(g_pYBWCManagerInstance->bRootMaster)
    {
  		sort_init(); // kh 10.04.07 Thomas Gaksch
    }
  }
}

// kh 04.08.06 avoid memory leaks
void finalize()
{
  if(Init) 
  {
    Init = false;

    material_free();

    pawn_free();

// kh 26.02.07 moved to the YBWCManager_Finalize(... for the correct handling of the (potential) shared memory tables
/*
    trans_free(Trans);

    history_free(gpHistory); // kh 08.02.07
*/

  }

  option_finalize();
}

// event()

void event() 
{
  if(g_pYBWCManagerInstance->bRootMaster)
  {
    if(g_pYBWCManagerInstance->bEventActive)
    {
      // kh 31.07.06 avoid reentrant problems
    }
    else
    {
      g_pYBWCManagerInstance->bEventActive = TRUE;
      while(!SearchInfo->stop && input_available()) 
      {
        loop_step();
      }
      g_pYBWCManagerInstance->bEventActive = FALSE;
    }
  }
}

// loop_step()

static void loop_step() 
{
  int           nResult;
  int           nExitResult;

  char          string[65536];
  char          sMemo [65536];
  char*         pString;

  nExitResult = EXIT_FAILURE;

   // read a line

  if(    g_pYBWCManagerInstance->pAutoTester->bAutoTest
      && !g_pYBWCManagerInstance->bEventActive)
  {
    pString = AutoTester_GetNextUCIString(g_pYBWCManagerInstance->pAutoTester);
    if(pString)
    {
      strcpy(string, pString);
    }
    else
    {
      strcpy(string, "quit"); // kh 31.07.06 defensive
    }
  }
  else
  {
    get(string, 65536);

// kh 10.04.07 Thomas Gaksch
/*	FILE *fp;
   fp=fopen("toga.log","a+");
   fprintf(fp,"%s\n",string);
   fclose(fp); */


// kh 03.01.07 for debug purposes only
// YBWCManager_Printf(g_pYBWCManagerInstance, "string received <%s>\n", string);
  }

   // parse

  if(false) 
  {
  } 
  else if(string_start_with(string, "debug ")) 
  {
      // dummy
  } 
  else if(string_start_with(string, "go ")) 
  {
    if(!Searching && !Delay) 
    {

      nResult = YBWCManager_HookGo(g_pYBWCManagerInstance);

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR loop_step(... failed at YBWCManager_HookGo(..., errorcode = %d\n", nResult);
        }
      }

      init();
      parse_go(string);
    } 
    else 
    {
      ASSERT(false);
    }
  } 

// kh 10.08.06
  else if(string_start_with(string, "remote ")) 
  {
    if(!Searching && !Delay) 
    {
      init();
      parse_remote(string);
    } 
    else 
    {
      ASSERT(false);
    }
  } 
  else if (string_equal(string, "isready")) 
  {

    if(!Searching && !Delay) 
    {
      init();
    }

    send("readyok"); // no need to wait when searching (dixit SMK)

  } 
  else if (string_equal(string, "ponderhit")) 
  {
    if(Searching) 
    {
      ASSERT(Infinite);

      SearchInput->infinite = false;
      Infinite              = false;

    } 
    else if(Delay) 
    {
      send_best_move();
      Delay = false;
    } 
    else 
    {
      ASSERT(false);
    }

  } 
  else if(string_start_with(string, "position ")) 
  {
    if(!Searching && !Delay) 
    {
      init();

      strcpy(sMemo, string);
      parse_position(string); // kh 26.09.06 string is "dirty" modified if "fen ... moves ..." is present

// kh 10.08.06
      nResult = YBWCManager_HookPosition(g_pYBWCManagerInstance, sMemo);

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR loop_step(... failed at YBWCManager_HookPosition(..., errorcode = %d\n", nResult);
        }
      }
    } 
    else 
    {
      ASSERT(false);
    }
  } 
  else if(string_equal(string, "quit"))
  {
    nExitResult = EXIT_SUCCESS; // kh 21.07.06 force to success at the moment

    YBWCManager_Printf(YBWCManager_Instance(), "finalizing environment via \"quit\"\n");

    ASSERT(!Searching);
    ASSERT(!Delay);

    ASSERT(YBWCManager_Instance()->nState == YBWC_MANAGER_STATE_IDLE);
// kh 20.09.06 if the root master is (unexpected) not already idle some kind of a forced stopping at first 
// could be implemented here as a future expansion
// the non root master still should shutdown correctly, because all searching will be stopped first 
// (in YBWCManager_Destruct(... ) with the special three way handshake used for the shutdown 

    YBWCManager_SaveLogSettings(YBWCManager_Instance(), LogSettings_Instance());
    YBWCManager_Destruct(YBWCManager_Instance());

    nResult = MPIWrapper_Finalize(MPIWrapper_Instance());
    if(nResult == MPI_SUCCESS)
    {
    }
    else
    {

  // kh 05.07.06 pFruitConfiguration is no longer accessible here
  //  if(YBWCManager_Instance()->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_LoadLogSettings(YBWCManager_Instance(), LogSettings_Instance());
        YBWCManager_Printf(YBWCManager_Instance(), "ERROR MPI finalize failed, errorcode = %d\n", nResult);
        YBWCManager_Destruct(YBWCManager_Instance());
      }
    }

    MPIWrapper_Destruct(MPIWrapper_Instance());

    YBWCManager_LoadLogSettings(YBWCManager_Instance(), LogSettings_Instance());
    YBWCManager_Printf(YBWCManager_Instance(), "done\n", nResult);

    finalize();

    YBWCManager_Destruct(YBWCManager_Instance());
    CommPrinter_Destruct(CommPrinter_Instance());
    LogSettings_Destruct(LogSettings_Instance());

    exit(nExitResult);
  } 
  else if(string_start_with(string, "setoption ")) 
  {
    if(!Searching && !Delay) 
    {

// kh 13.02.08 shared memory is potentially allocated already for the non root master
// force allocation in the root master
      init(); 

      parse_setoption(string);

// kh 10.04.07 Thomas Gaksch
		  pawn_parameter();
		  material_parameter();
		  book_parameter();
		  pst_init();
		  eval_parameter();

    } 
    else 
    {
      ASSERT(false);
    }
  } 
  else if(string_equal(string, "stop")) 
  {
    g_pYBWCManagerInstance->pAutoTester->bAutoTest = FALSE;

    if(Searching) 
    {
      SearchInfo->stop  = true;
      Infinite          = false;
    } 
    else if(Delay) 
    {
      send_best_move();
      Delay = false;
    }

// kh 05.09.06
    nResult = YBWCManager_HookStop(g_pYBWCManagerInstance);

    if(nResult == MPI_SUCCESS)
    {
    }
    else
    {
      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR loop_step(... failed at YBWCManager_HookStop(..., errorcode = %d\n", nResult);
      }
    }
  } 
  else if(string_equal(string, "uci")) 
  {

    ASSERT(!Searching);
    ASSERT(!Delay);

    send("id name " PROGRAM_NAME " " PROGRAM_VERSION);
    send("id author " PROGRAM_AUTHOR);

    option_list();

    send("uciok");


// kh 10.08.06 defensive, uci triggers implicitly ucinewgame for non root master
    nResult = YBWCManager_HookNewGame(g_pYBWCManagerInstance, YBWC_MANAGER_NON_ROOT_MASTER_SYNC_NEW_GAME_TIMEOUT);

    if(nResult == MPI_SUCCESS)
    {
    }
    else
    {
      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR loop_step(... failed at YBWCManager_HookNewGame(..., errorcode = %d\n", nResult);
      }
    }
  } 
  else if(string_equal(string, "ucinewgame")) 
  {
    if(!Searching && !Delay && Init) 
    {
      trans_clear(Trans);

// kh 10.08.06
      nResult = YBWCManager_HookNewGame(g_pYBWCManagerInstance, YBWC_MANAGER_NON_ROOT_MASTER_SYNC_NEW_GAME_TIMEOUT);

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR loop_step(... failed at YBWCManager_HookNewGame(..., errorcode = %d\n", nResult);
        }
      }
    } 
    else 
    {
      ASSERT(false);
    }
  }
}

// parse_go()

static void parse_go(char string[]) 
{
  const char* ptr;

  bool    infinite;
  bool    ponder;

  int     depth;
  int     mate;
  int     movestogo;

  sint64  nodes;

  double  binc;
  double  btime;
  double  movetime;
  double  winc;
  double  wtime;

  double  time;
  double  inc;

  double  time_max;
  double  alloc;

  int nResult;

  // init

  infinite  = false;
  ponder    = false;

  depth     = -1;
  mate      = -1;
  movestogo = -1;

  nodes     = -1;

  binc      = -1.0;
  btime     = -1.0;
  movetime  = -1.0;
  winc      = -1.0;
  wtime     = -1.0;

  // parse

  ptr = strtok(string," "); // skip "go"

  for (ptr = strtok(NULL," "); ptr != NULL; ptr = strtok(NULL," ")) {

     if (false) {

     } else if (string_equal(ptr,"binc")) {

        ptr = strtok(NULL," ");
        if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

        binc = double(atoi(ptr)) / 1000.0;
        ASSERT(binc>=0.0);

     } else if (string_equal(ptr,"btime")) {

        ptr = strtok(NULL," ");
        if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

        btime = double(atoi(ptr)) / 1000.0;
        ASSERT(btime>=0.0);

     } else if (string_equal(ptr,"depth")) {

        ptr = strtok(NULL," ");
        if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

        depth = atoi(ptr);
        ASSERT(depth>=0);

     } else if (string_equal(ptr,"infinite")) {

        infinite = true;

     } else if (string_equal(ptr,"mate")) {

        ptr = strtok(NULL," ");
        if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

        mate = atoi(ptr);
        ASSERT(mate>=0);

     } else if (string_equal(ptr,"movestogo")) {

        ptr = strtok(NULL," ");
        if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

        movestogo = atoi(ptr);
        ASSERT(movestogo>=0);

     } else if (string_equal(ptr,"movetime")) {

        ptr = strtok(NULL," ");
        if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

        movetime = double(atoi(ptr)) / 1000.0;
        ASSERT(movetime>=0.0);

     } else if (string_equal(ptr,"nodes")) {

        ptr = strtok(NULL," ");
        if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

        nodes = my_atoll(ptr);
        ASSERT(nodes>=0);

     } else if (string_equal(ptr,"ponder")) {

        ponder = true;

     } else if (string_equal(ptr,"searchmoves")) {

        // dummy

     } else if (string_equal(ptr,"winc")) {

        ptr = strtok(NULL," ");
        if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

        winc = double(atoi(ptr)) / 1000.0;
        ASSERT(winc>=0.0);

     } else if (string_equal(ptr,"wtime")) {

        ptr = strtok(NULL," ");
        if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

        wtime = double(atoi(ptr)) / 1000.0;
        ASSERT(wtime>=0.0);
     }
  }

  // init

  search_clear();

  // depth limit

// kh 10.04.07 Thomas Gaksch
   // JAS
   int option_depth = 0;
   option_depth = option_get_int("Search Depth");
   if (option_depth > 0) {
   	  depth = option_depth;
   }
   // JAS end

  if (depth >= 0) {
     SearchInput->depth_is_limited = true;
     SearchInput->depth_limit = depth;
  } else if (mate >= 0) {
     SearchInput->depth_is_limited = true;
     SearchInput->depth_limit = mate * 2 - 1; // HACK: move -> ply
  }

  // time limit

  if (COLOUR_IS_WHITE(SearchInput->board->turn)) {
     time = wtime;
     inc = winc;
  } else {
     time = btime;
     inc = binc;
  }

// kh 10.04.07 Thomas Gaksch
  if (movestogo <= 0 || movestogo > 30) movestogo = 30; // HACK was 30
//if (movestogo <= 0 || movestogo > 30) movestogo = 30; // HACK

  if (inc < 0.0) inc = 0.0;

// kh 10.04.07 Thomas Gaksch
   // JAS
   int option_movetime = 0;
   option_movetime = option_get_int("Search Time");
   if (option_movetime > 0) {
   	  movetime = option_movetime;
   }
   // JAS end

  if (movetime >= 0.0) {

     // fixed time

     SearchInput->time_is_limited = true;
     SearchInput->time_limit_1 = movetime * 5.0; // HACK to avoid early exit
     SearchInput->time_limit_2 = movetime;

  } else if (time >= 0.0) {

     // dynamic allocation

     time_max = time * 0.95 - 1.0;
     if (time_max < 0.0) time_max = 0.0;

     SearchInput->time_is_limited = true;

     alloc = (time_max + inc * double(movestogo-1)) / double(movestogo);
     alloc *= (option_get_bool("Ponder") ? PonderRatio : NormalRatio);
     if (alloc > time_max) alloc = time_max;
     SearchInput->time_limit_1 = alloc;

     alloc = (time_max + inc * double(movestogo-1)) * 0.5;
     if (alloc < SearchInput->time_limit_1) alloc = SearchInput->time_limit_1;
     if (alloc > time_max) alloc = time_max;
     SearchInput->time_limit_2 = alloc;
  }

  if(infinite || ponder) 
  {
    SearchInput->infinite = true;
  }

  // search

  ASSERT(!Searching);
  ASSERT(!Delay);

  Searching  = true;

  ASSERT(g_pYBWCManagerInstance->bRootMaster);
  g_pYBWCManagerInstance->nState = YBWC_MANAGER_STATE_SEARCHING; 

  Infinite   = infinite || ponder;
  Delay      = false;

  search();

  g_pYBWCManagerInstance->bPostSearchActive = TRUE;

  search_update_current();

  ASSERT(Searching);
  ASSERT(!Delay);

// kh 20.09.06 update to the comment from 03.08.06 below:
// no searching slaves have to be stopped here (but there may be slaves, that have not handled the 
// stop request yet (queued by the (mpi) system))
// there are 2 cases:
// a) if the search of the root master was stopped via "long jump" used by fruit (e.g. 
//    to handle the uci "stop" command an associated Stack_Stop(... has been executed
// b) the search of the root master was not stopped via the "long jump" and has simply terminated the 
//    first/main recursive call
//    this case implicates that there will not be any slave searching (the stack will be "clear")
// kh 03.08.06 here is the appropriate place to send REQUEST_TYPE_ROOT_MASTER_STOP_SEARCH

  Searching  = false;

  Delay      = Infinite;

  if(!Delay) 
  {
    send_best_move();
  }

  ASSERT(g_pYBWCManagerInstance->bRootMaster);
	sort_init(); // kh 10.04.07 Thomas Gaksch
  
// kh 20.09.06 the broadcast of the idle invitation here may be suppressed as 
// a future expansion for a better performance
// it is used for debugging purposes at the moment 
  nResult = YBWCManager_HookSearchTerminated(g_pYBWCManagerInstance);

  if(nResult == MPI_SUCCESS)
  {
  }
  else
  {
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR parse_go(... failed at YBWCManager_HookSearchTerminated(..., errorcode = %d\n", nResult);
    }
  }

  ASSERT(!g_pYBWCManagerInstance->bStoppingActive);
  g_pYBWCManagerInstance->bPostSearchActive = FALSE;
  g_pYBWCManagerInstance->nState            = YBWC_MANAGER_STATE_IDLE; 

// kh 13.09.06 never necessary for the root master
  ASSERT(g_pYBWCManagerInstance->pHeadDelayedRequest == NULL);
//YBWCManager_DispatchDelayedRequests(g_pYBWCManagerInstance);
}

// parse_remote()

// kh 10.08.06
static void parse_remote(char string[]) 
{
  char* ptr;
  int   nProcessorId;
  int   nResult;

  // init

  // parse

  ptr = strtok(string, " "); // skip "remote"

  ptr = strtok(NULL,   " ");
  if(ptr == NULL) 
  {
    my_fatal("parse_remote(): missing processor argument\n");
  }

  nProcessorId = atoi(ptr);

  ASSERT(g_pYBWCManagerInstance->nSize > 1);
//ASSERT((nProcessorId > 0) && (nProcessorId < g_pYBWCManagerInstance->nSize));

  if(nProcessorId >= g_pYBWCManagerInstance->nSize)
  {
    nProcessorId = g_pYBWCManagerInstance->nSize - 1;
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, "WARNING parse_remote(... failed (nProcessorId >= g_pYBWCManagerInstance->nSize), now set to %d\n", nProcessorId);
    }
  }

  if(nProcessorId < 1)
  {
    nProcessorId = 1;
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, "WARNING parse_remote(... failed (nProcessorId < 1), now set to 1\n");
    }
  }

  ptr = strtok(NULL, "");

  // search

  ASSERT(!Searching);
  ASSERT(!Delay);

  Searching  = true;

  ASSERT(g_pYBWCManagerInstance->bRootMaster);

  ASSERT(!g_pYBWCManagerInstance->bStoppingActive);
  g_pYBWCManagerInstance->nState = YBWC_MANAGER_STATE_SEARCHING_REMOTE; 

  Delay      = false;

// kh 05.09.06 do some initialization for variables/structures not necessarily received (pv clear etc.) 
// as the remote search result
  search_clear();

//search();

//search_update_current();

// kh 10.08.06
  nResult = YBWCManager_HookRemoteTest(g_pYBWCManagerInstance, nProcessorId, ptr);

  if(nResult == MPI_SUCCESS)
  {
  }
  else
  {
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR loop_step(... failed at YBWCManager_HookPosition(..., errorcode = %d\n", nResult);
    }
  }

  ASSERT(Searching);
  ASSERT(!Delay);
}

// parse_position()

static void parse_position(char string[]) 
{
  const char* fen;
  char*       moves;
  const char* ptr;
  char        move_string[256];
  int         move;
  undo_t      undo[1];

  // init

  fen    = strstr(string, "fen ");
  moves  = strstr(string, "moves ");

  // start position

  if(fen != NULL) // "fen" present
  {
    if(moves != NULL) // "moves" present
    {
      ASSERT(moves > fen);
      moves[-1] = '\0'; // dirty, but so is UCI
    }

    board_from_fen(SearchInput->board, fen + 4); // CHANGE ME
  } 
  else 
  {
     // HACK: assumes startpos
    board_from_fen(SearchInput->board, StartFen);
  }

  // moves
  if(moves != NULL) // "moves" present
  {
    ptr = moves + 6;
    while(*ptr != '\0') 
    {
      move_string[0] = *ptr++;
      move_string[1] = *ptr++;
      move_string[2] = *ptr++;
      move_string[3] = *ptr++;

      if(*ptr == '\0' || *ptr == ' ') 
      {
        move_string[4] = '\0';
      } 
      else // promote
      {
        move_string[4] = *ptr++;
        move_string[5] = '\0';
      }

      move = move_from_string(move_string, SearchInput->board);

      move_do(SearchInput->board, move, undo);

      while(*ptr == ' ') 
      {
        ptr++;
      }
    }
  }
}

// parse_setoption()

static void parse_setoption(char string[]) 
{
  const char* name;
  char*       value;

// kh 10.04.07 Thomas Gaksch
	uint32      egbb_cache_size;
	char*       egbb_path;

  int         nResult;

   // init

  name  = strstr(string, "name ");
  value = strstr(string, "value ");

  if(name == NULL || value == NULL || name >= value) 
  {
    return; // ignore buttons
  }

  value[-1] = '\0'; // HACK
  name  += 5;
  value += 6;

  // update

  option_set(name, value);

  FruitConfiguration_UpdateOptions(g_pYBWCManagerInstance->pFruitConfiguration);
  FruitConfiguration_Dump(g_pYBWCManagerInstance->pFruitConfiguration);

// kh 10.04.07 start Thomas Gaksch
	// update bitbases if needed

	if(my_string_equal(name, "Bitbases Path") || my_string_equal(name, "Bitbases Cache Size"))
  {
		egbb_cache_size = (option_get_int("Bitbases Cache Size") * 1024 * 1024);
		egbb_path = (char *) option_get_string("Bitbases Path"); 

#if defined(_WIN32) || defined(_WIN64)

 		egbb_is_loaded = (LoadEgbbLibrary(egbb_path,egbb_cache_size) != 0);


#else // assume POSIX

    egbb_is_loaded = false;

#endif

		if(!egbb_is_loaded)
    {
			printf("EgbbProbe not Loaded!\n");
    }
	}
// kh 10.04.07 end Thomas Gaksch

  // update transposition-table size if needed

  if(Init && my_string_equal(name, "Hash")) // Init => already allocated
  {
    g_pYBWCManagerInstance->bResizeHashTableActive = TRUE;

    ASSERT(!Searching);

    if(option_get_int("Hash") >= 4) 
    {

// kh 08.02.08 g_pYBWCManagerInstance->pHashTableTransmitBuffer->pBroadcastRequestBuffer is created lazy 
// when the first entry is added
// with he optimized version writing direct to the mpi packed buffer structures the count has already 
// been "prefilled" as nChunkSizeForFlush 
// therefore a HashTableBuffer_FlushWithBroadcast(... is not allowed here (probably containing 
// not exactly nChunkSizeForFlush buffered hash table entries)
// the hash table on all processors will be resized (and cleared) anyway
/*
      if(g_pYBWCManagerInstance->pHashTableTransmitBuffer->pBroadcastRequestBuffer == NULL)
      {
      }
      else
      {

// kh 05.02.08 all buffered hash table info is flushed synchronized (see non root master handling) 
// to keep a stable clear hash table after resizing is finished
        HashTableBuffer_FlushWithBroadcast(g_pYBWCManagerInstance->pHashTableTransmitBuffer);
      }
*/

// kh 08.02.08 now simply discard the buffered entries
      HashTableBuffer_Discard(g_pYBWCManagerInstance->pHashTableTransmitBuffer);

// kh 05.02.08 not necessary here, sync is implicit for the root master
//    YBWCManager_WaitForSyncAfterBroadcast(g_pYBWCManagerInstance, YBWC_MANAGER_SYNC_AFTER_BROADCAST_TIMEOUT);

      nResult = YBWCManager_HookSetOption(g_pYBWCManagerInstance, 
                                          YBWC_MANAGER_NON_ROOT_MASTER_SYNC_SET_OPTION_TIMEOUT,
                                          UCI_OPTION_NAME_HASH_STEP_1_DETACH,
                                          "");

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR parse_setoption(... failed at YBWCManager_HookSetOption(..., errorcode = %d\n", nResult);
        }
      }

      YBWCManager_DetachSharedMem(g_pYBWCManagerInstance, SHARED_MEMORY_KEY_TRANSPOSITION_TABLE);

      nResult = YBWCManager_HookSetOption(g_pYBWCManagerInstance, 
                                          YBWC_MANAGER_NON_ROOT_MASTER_SYNC_SET_OPTION_TIMEOUT,
                                          UCI_OPTION_NAME_HASH_STEP_2_DELETE,
                                          "");

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR parse_setoption(... failed at YBWCManager_HookSetOption(..., errorcode = %d\n", nResult);
        }
      }

      YBWCManager_DeleteSharedMem(g_pYBWCManagerInstance, SHARED_MEMORY_KEY_TRANSPOSITION_TABLE);

      g_pYBWCManagerInstance->hMapSharedTranspositionTable  = NULL;
      g_pYBWCManagerInstance->pSharedTranspositionTable     = NULL;

      trans_free(Trans);
      trans_alloc(Trans);

      nResult = YBWCManager_HookSetOption(g_pYBWCManagerInstance, 
                                          YBWC_MANAGER_NON_ROOT_MASTER_SYNC_SET_OPTION_TIMEOUT,
                                          UCI_OPTION_NAME_HASH_STEP_3_INIT,
                                          (char*)option_get_string("Hash"));

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR parse_setoption(... failed at YBWCManager_HookSetOption(..., errorcode = %d\n", nResult);
        }
      }

    } // if(option_get_int("Hash") >= 4) 

    g_pYBWCManagerInstance->bResizeHashTableActive = FALSE;
  } // if(Init && my_string_equal(name,"Hash"))

  nResult = YBWCManager_HookSetOption(g_pYBWCManagerInstance, 
                                      YBWC_MANAGER_NON_ROOT_MASTER_SYNC_SET_OPTION_TIMEOUT,
                                      (char*)name,
                                      value);

  if(nResult == MPI_SUCCESS)
  {
  }
  else
  {
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR parse_setoption(... failed at YBWCManager_HookSetOption(..., errorcode = %d\n", nResult);
    }
  }
}

// send_best_move()

static void send_best_move() {

   double time, speed, cpu;
   sint64 node_nb;
   char move_string[256];
   char ponder_string[256];
   int move;
   mv_t * pv;

   // info

   // HACK: should be in search.cpp

   time = SearchCurrent->time;
   speed = SearchCurrent->speed;
   cpu = SearchCurrent->cpu;
   node_nb = SearchCurrent->node_nb;

   send("info time %.0f nodes " S64_FORMAT " nps %.0f cpuload %.0f",time*1000.0,node_nb,speed,cpu*1000.0);

   trans_stats(Trans);
   // pawn_stats();
   // material_stats();

   // best move

// kh 10.04.07 start Thomas Gaksch
   move = SearchBest[0].move;
   pv   = SearchBest[0].pv;

/*
   move = SearchBest->move;
   pv   = SearchBest->pv;
*/
// kh 10.04.07 end Thomas Gaksch

   move_to_string(move,move_string,256);

   if (pv[0] == move && move_is_ok(pv[1])) {
      move_to_string(pv[1],ponder_string,256);
      send("bestmove %s ponder %s",move_string,ponder_string);
   } else {
      send("bestmove %s",move_string);
   }
}

// get()

void get(char string[], int size) 
{
  int           nResult;
  int           nExitResult;

  nExitResult = EXIT_SUCCESS; // kh 21.07.06 force to success at the moment

  ASSERT(string != NULL);
  ASSERT(size >= 65536);

  if(!my_file_read_line(stdin, string, size)) 
  { // EOF

    YBWCManager_Printf(YBWCManager_Instance(), "finalizing environment via !my_file_read_line(...\n");

    YBWCManager_SaveLogSettings(YBWCManager_Instance(), LogSettings_Instance());
    YBWCManager_Destruct(YBWCManager_Instance());

    nResult = MPIWrapper_Finalize(MPIWrapper_Instance());
    if(nResult == MPI_SUCCESS)
    {
    }
    else
    {

// kh 05.07.06 pFruitConfiguration is no longer accessible here
//    if(YBWCManager_Instance()->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_LoadLogSettings(YBWCManager_Instance(), LogSettings_Instance());
        YBWCManager_Printf(YBWCManager_Instance(), "ERROR MPI finalize failed, errorcode = %d\n", nResult);
        YBWCManager_Destruct(YBWCManager_Instance());
      }
    }

    MPIWrapper_Destruct(MPIWrapper_Instance());

    YBWCManager_LoadLogSettings(YBWCManager_Instance(), LogSettings_Instance());
    YBWCManager_Printf(YBWCManager_Instance(), "done\n", nResult);

    finalize();

    YBWCManager_Destruct(YBWCManager_Instance());
    CommPrinter_Destruct(CommPrinter_Instance());
    LogSettings_Destruct(LogSettings_Instance());

    exit(nExitResult);
  }
}

// send()

void send(const char format[], ...) 
{
  va_list arg_list;
  char    string[4096];

  if(g_pYBWCManagerInstance->bRootMaster)
  {
    ASSERT(format != NULL);

    va_start(arg_list, format);
    vsprintf(string, format, arg_list);
    va_end(arg_list);

// kh 22.09.06 fprintf(stdout, ... must not be used in combination with the mpi environment
// it was observed that when using fprintf(stdout, ... e.g. two different output lines of two different 
// processors can get "merged" within the same "physical" output line (e.g. in the protocol window of Arena)
// that can cause problems for the gui which may not correctly detect the uci commands from the engine
// e.g. when something like "bestm<some protocol output of a non root master>ove e2e4\n" is received by the gui
//  fprintf(stdout, "%s\n", string);
// (see also comment from 22.09.06 for YBWCManager_Printf(... in YBWCManager.cpp)
    printf("%s\n", string);

// kh 21.09.06
    fflush(stdout);
  }
}

// string_equal()

static bool string_equal(const char s1[], const char s2[]) 
{
  ASSERT(s1 != NULL);
  ASSERT(s2 != NULL);

  return strcmp(s1, s2) == 0;
}

// string_start_with()

static bool string_start_with(const char s1[], const char s2[]) 
{
  ASSERT(s1 != NULL);
  ASSERT(s2 != NULL);

  return strstr(s1, s2) == s1;
}

// kh 10.08.06 use fruit functions
void fruit_actions_for_sync_position_received(char string[])
{
  int  i;

  init();
  parse_position(string);
  g_pYBWCManagerInstance->bSyncPositionHistoryTableFirst = TRUE; // kh 08.02.07 used to clear the history table once

/*
  if(g_pYBWCManagerInstance->pFruitConfiguration->bUseSharedMemoryHistoryTable)
  {
*/
// kh 08.02.07 as a future expansion this could be done more synchronized, e.g. waiting first for all non root master
// acknowledging their fruit_actions_for_sync_position_received (analogous to acknowledging 
// their fruit_actions_for_new_game_received) 
// the hashtablemasters of all non root master can clear the table once in fruit_actions_for_sync_position_received 
// and when all acks are received the root master can clear the history table (he is implicit the hashtable master)
// at the moment "in the startup phase" (e.g. after a uci go from the gui) the history table will be cleared a little bit
// too often and some useful information already contained in the table will be cleared also

    g_pYBWCManagerInstance->bSyncPositionHistoryTableFirst = FALSE;

    if(g_pYBWCManagerInstance->pFruitConfiguration->bSynchronizeHistoryTableAccess)
    {
      CriticalSection_Enter(g_pYBWCManagerInstance->pCriticalSectionHistoryTable);
    }

    for(i = 0; i < HistorySize; i++) 
    {
      gpHistory->History[i] = 0;
    }

    for(i = 0; i < HistorySize; i++) 
    {
      gpHistory->HistHit[i] = 1;
      gpHistory->HistTot[i] = 1;
    }

    g_pYBWCManagerInstance->bHistoryTableInitialized = TRUE;

    if(g_pYBWCManagerInstance->pFruitConfiguration->bSynchronizeHistoryTableAccess)
    {
      CriticalSection_Leave(g_pYBWCManagerInstance->pCriticalSectionHistoryTable);
    }
/*
  }
*/

// kh 10.04.07 sort_init(... is now done e.g. at the end of parse_go(... after send_best_move(... for the 
// root master (and not any longer in search(...) 
// this seems to be an appropriate place to do it for the non root master
	sort_init(); 
}

void fruit_actions_for_new_game_received()
{
  if(!Searching && !Delay && Init) 
  {
    trans_clear(Trans);
  } 
  else 
  {
    ASSERT(false);
  }
}

void fruit_actions_for_set_option_received(char* szOptionName, char* szOptionValue)
{
  const char* name;
  char*       value;

// kh 10.04.07 Thomas Gaksch
	uint32      egbb_cache_size;
	char*       egbb_path;

   // init

// kh 07.02.08 set option is also used to resize the hash table for the non root master
// in a synchronized manner. the root master will perform 3 steps: detach, delete and init
  if(strcmp(szOptionName, UCI_OPTION_NAME_HASH_STEP_1_DETACH) == 0)
  {
    g_pYBWCManagerInstance->bResizeHashTableActive = TRUE;

    ASSERT(!Searching);

// kh 08.02.08 g_pYBWCManagerInstance->pHashTableTransmitBuffer->pBroadcastRequestBuffer is created lazy 
// when the first entry is added
// with he optimized version writing direct to the mpi packed buffer structures the count has already 
// been "prefilled" as nChunkSizeForFlush 
// therefore a HashTableBuffer_FlushWithBroadcast(... is not allowed here (probably containing 
// not exactly nChunkSizeForFlush buffered hash table entries
// the hash table on all processors will be resized (and cleared) anyway
/*
    if(g_pYBWCManagerInstance->pHashTableTransmitBuffer->pBroadcastRequestBuffer == NULL)
    {
    }
    else
    {

// kh 05.02.08 all buffered hash table info is flushed synchronized (see non root master handling) 
// to keep a stable clear hash table after resizing is finished
      HashTableBuffer_FlushWithBroadcast(g_pYBWCManagerInstance->pHashTableTransmitBuffer);
    }
*/

// kh 08.02.08 now simply discard the buffered entries
    HashTableBuffer_Discard(g_pYBWCManagerInstance->pHashTableTransmitBuffer);

    YBWCManager_WaitForSyncAfterBroadcast(g_pYBWCManagerInstance, YBWC_MANAGER_SYNC_AFTER_BROADCAST_TIMEOUT);

    YBWCManager_DetachSharedMem(g_pYBWCManagerInstance, SHARED_MEMORY_KEY_TRANSPOSITION_TABLE);
  }
  else if(strcmp(szOptionName, UCI_OPTION_NAME_HASH_STEP_2_DELETE) == 0)
  {
    YBWCManager_DeleteSharedMem(g_pYBWCManagerInstance, SHARED_MEMORY_KEY_TRANSPOSITION_TABLE);
    g_pYBWCManagerInstance->hMapSharedTranspositionTable  = NULL;
    g_pYBWCManagerInstance->pSharedTranspositionTable     = NULL;
  }
  else if(strcmp(szOptionName, UCI_OPTION_NAME_HASH_STEP_3_INIT) == 0)
  {
    option_set("Hash", szOptionValue);

    FruitConfiguration_UpdateOptions(g_pYBWCManagerInstance->pFruitConfiguration); // kh 13.02.08 defensive

    trans_free(Trans);
    trans_alloc(Trans);

    g_pYBWCManagerInstance->bResizeHashTableActive = FALSE;
  }
  else if(my_string_equal(szOptionName, "Hash"))
  {
    // kh 07.02.08 already handled in 3 steps (see above), ignore here
  }
  else
  {
    name  = szOptionName;
    value = szOptionValue;

// kh 07.02.08 update
    option_set(name, value);

    FruitConfiguration_UpdateOptions(g_pYBWCManagerInstance->pFruitConfiguration);

// kh 10.04.07 start Thomas Gaksch
	  // update bitbases if needed

	  if(my_string_equal(name, "Bitbases Path") || my_string_equal(name, "Bitbases Cache Size"))
    {
		  egbb_cache_size = (option_get_int("Bitbases Cache Size") * 1024 * 1024);
		  egbb_path = (char *) option_get_string("Bitbases Path"); 

#if defined(_WIN32) || defined(_WIN64)

 		  egbb_is_loaded = (LoadEgbbLibrary(egbb_path,egbb_cache_size) != 0);

#else // assume POSIX

      egbb_is_loaded = false;

#endif

		  if(!egbb_is_loaded)
      {
			  printf("EgbbProbe not Loaded!\n");
      }
	  }
// kh 10.04.07 end Thomas Gaksch

    else if(my_string_equal(name, OPT_NAME_ADJUST_PROCESS_PRIORITY))
    {
      YBWCManager_AdjustProcessPriority(g_pYBWCManagerInstance);
    }

    pawn_parameter(); 
    material_parameter();
    book_parameter();
    pst_init();
    eval_parameter();
  }
}

void fruit_actions_for_stop_remote_received()
{
  if(Searching) 
  {
    SearchInfo->stop  = true;
    Infinite          = false;
  } 
  else if(Delay) 
  {

// kh 05.09.06
    ASSERT(false);
/*
    send_best_move();
    Delay = false;
*/
  }
  else
  {

// kh 05.09.06
    ASSERT(false)
  }
}

// send_best_move()

void fruit_actions_for_stop_received()
{
//longjmp(SearchInfo->buf, 1); // kh 16.03.07 for a temp test only

  ASSERT(!g_pYBWCManagerInstance->bStoppingActive);
  g_pYBWCManagerInstance->bStoppingActive = TRUE;

  if(Searching) 
  {
    SearchInfo->stop  = true;
    Infinite          = false;
  } 
  else if(Delay) 
  {

// kh 16.03.07
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR fruit_actions_for_stop_received(... failed,  unexpected state <Delay>");
    }

// kh 05.09.06
    ASSERT(false);

/*
    send_best_move();
    Delay = false;
*/

  }
  else
  {

// kh 16.03.07
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, "INFO fruit_actions_for_stop_received(... slave stopped while transmitting result back to master");
    }

// kh 19.03.07 slave stopped while transmitting result back to master
    ASSERT(g_pYBWCManagerInstance->bPostSearchActive);
// kh 05.09.06
//  ASSERT(false)
    
// kh 19.03.07 this is really important, otherwise the next stop request was formerly ignored
// (now handled additionally devensive in fruit_work_available_parse_go(... , see comment from 19.03.07)
    g_pYBWCManagerInstance->bStoppingActive = FALSE;
  }
}

void fruit_actions_for_update_search_window_received(int nAlphaImproved, int nBetaImproved)
{
  int                   nAlphaDiff;

  bool                  bSuppressRerun;

  int                   i;
  int                   nCompleted;
  int                   nPercentCompleted;

  char                  sTmpMoveString[256];

  StackEntry*           pStackEntryTmp;

  StackEntry*           pStackEntryPrev;

  bool                  bBreak;

  ASSERT(g_pYBWCManagerInstance->pWorkAvailableResult != NULL);

  if(g_pYBWCManagerInstance->pFruitConfiguration->bDirectUpdateSearchWindows)
  {
    if(nAlphaImproved > g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha) // kh 20.12.06 defensive
    {
      g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha = nAlphaImproved;

      g_pYBWCManagerInstance->pWorkAvailableResult->bAlphaBoundIsEstimated = FALSE;

      if(g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha >= g_pYBWCManagerInstance->pWorkAvailableResult->nBeta) // kh 22.05.08 potentially adjust "null window" 
      {
        g_pYBWCManagerInstance->pWorkAvailableResult->nBeta = g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha + 1;
      }

    }
    if(nBetaImproved < g_pYBWCManagerInstance->pWorkAvailableResult->nBeta) // kh 20.12.06 defensive
    {
      g_pYBWCManagerInstance->pWorkAvailableResult->nBeta = nBetaImproved;

      if(g_pYBWCManagerInstance->pWorkAvailableResult->nBeta <= g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha) // kh 22.05.08 potentially adjust "null window" 
      {
        g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha = g_pYBWCManagerInstance->pWorkAvailableResult->nBeta - 1;
      }
    }

    if(g_Stack.nCount > 0)
    {
      bBreak = true;
      pStackEntryPrev = &g_Stack.stackEntry[0];

      if(nAlphaImproved > pStackEntryPrev->parameters.fullRootPar.alpha)
      {
        pStackEntryPrev->parameters.fullRootPar.alpha     = nAlphaImproved;
        pStackEntryPrev->localData.fullRootDat.old_alpha  = pStackEntryPrev->parameters.fullRootPar.alpha;

        if(pStackEntryPrev->parameters.fullRootPar.alpha >= pStackEntryPrev->parameters.fullRootPar.beta) // kh 22.05.08 potentially adjust "null window" 
        {
          pStackEntryPrev->parameters.fullRootPar.beta = pStackEntryPrev->parameters.fullRootPar.alpha + 1;
        }

        bBreak = false;
      }

      if(nBetaImproved < pStackEntryPrev->parameters.fullRootPar.beta)
      {
        pStackEntryPrev->parameters.fullRootPar.beta     = nBetaImproved;

        if(pStackEntryPrev->parameters.fullRootPar.beta <= pStackEntryPrev->parameters.fullRootPar.alpha) // kh 22.05.08 potentially adjust "null window" 
        {
          pStackEntryPrev->parameters.fullRootPar.alpha = pStackEntryPrev->parameters.fullRootPar.beta - 1;
        }

        bBreak = false;
      }

      if(bBreak)
      {
      }
      else
      {
        Stack_UpdateSearchWindow(pStackEntryPrev, 1);
      }
    } // if(g_Stack.nCount > 0)
  } // if(g_pYBWCManagerInstance->pFruitConfiguration->bDirectUpdateSearchWindows)
  else
  {
    ASSERT(nAlphaImproved > g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha)

    if(g_pYBWCManagerInstance->bStoppingActive)
    {

// kh 20.12.06
      if(g_pYBWCManagerInstance->bRerunSearch)
      {

// kh 10.11.06 possible in rare cases, if a further update search window request is dispatched
//      while the actual search is still stopping by a former update search window request
        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, 
                            "WARNING fruit_actions_for_update_search_window_received(... alpha is improved (now %d) while the actual search has not even stopped for the previous alpha improvement (%d) (start beta %d)\n",
                            nAlphaImproved,
                            g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha,
                            g_pYBWCManagerInstance->pWorkAvailableResult->nBeta);
        }

// kh 20.12.06 just update the alpha value without stopping before
        if(nAlphaImproved > g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha) // kh 20.12.06 defensive
        {

// kh 15.02.07 if the limit was reached before, the limit (transitively) reached here and it is 
// not necessary to recheck it here
          g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha = nAlphaImproved;
        }
      }
      else
      {

// kh 20.12.06 a real stop (i.e. cutoff message) is processed, so reset the rerun flag
        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, 
                            "WARNING fruit_actions_for_update_search_window_received(... but a cutoff message is processed at the moment, rerun is cancelled\n");
        }

        ASSERT(!g_pYBWCManagerInstance->bRerunSearch); 
        g_pYBWCManagerInstance->bRerunSearch = FALSE; // kh 15.02.07 is already implicitly false, see above

// kh 14.02.07 do not longer update the alpha value (of the pseude root only, does not matter anyway), here
// this is defensive only (see also comment from 15.02.07 below with the 40, 80, 110 centipawns example)
/*
// kh 20.12.06 just update the alpha value (defensive)
        if(nAlphaImproved > g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha) // kh 20.12.06 defensive
        {
          g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha = nAlphaImproved;
        }
*/
      }
    } // if(g_pYBWCManagerInstance->bStoppingActive)
    else
    {
      bSuppressRerun = false;
      if(nAlphaImproved > g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha) // kh 20.12.06 defensive
      {
        nAlphaDiff = nAlphaImproved - g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha;

        if(nAlphaDiff >= g_pYBWCManagerInstance->pFruitConfiguration->nMinimumAlphaImprovementForRerunSearch)
        {

// kh 13.03.07 estimate the total progress of this search by the progress of the level next to the root level
          if(0 < g_pYBWCManagerInstance->pStack->nCount) // kh 26.10.06 check potential access to the root level
          {
            pStackEntryTmp = Stack_PeekAt(/* g_pYBWCManagerInstance->pStack, */ 0);

            ASSERT(pStackEntryTmp->nCallType == CALL_TYPE_FULL_ROOT);

            if(pStackEntryTmp->nCallType == CALL_TYPE_FULL_ROOT)
            {
/*
              pFullRootPar = &pStackEntryTmp->parameters.fullRootPar;
*/
//            pFullRootDat = &pStackEntryTmp->localData.fullRootDat;
              if(g_pYBWCManagerInstance->pWorkAvailableResult->nDepth == pStackEntryTmp->parameters.fullRootPar.depth) // kh 13.03.07 check for final iteration
              {
                if(1 < g_pYBWCManagerInstance->pStack->nCount) // kh 26.10.06 check potential access to stack level 1
                {
                  pStackEntryTmp = Stack_PeekAt(/* g_pYBWCManagerInstance->pStack, */ 1);

                  nCompleted = 0;
                  for(i = 0; i < pStackEntryTmp->nMoveListTotalCount; i++)
                  {
                    if(pStackEntryTmp->CompletedList[i])
                    {
                      nCompleted++;
                    }
                  }

                  if(g_pYBWCManagerInstance->pFruitConfiguration->nMaximumMovesCompletedForRerunSearch > 0)
                  {
                    if(nCompleted >= g_pYBWCManagerInstance->pFruitConfiguration->nMaximumMovesCompletedForRerunSearch)
                    {
                      bSuppressRerun = true;

// kh 17.03.07 try to adjust the window for the actual search a little bit 
                      if(nAlphaImproved > pStackEntryTmp->parameters.fullRootPar.alpha) // kh 17.03.07 defensive
                      {
                        pStackEntryTmp->parameters.fullRootPar.alpha = nAlphaImproved;
                      }
                      else
                      {
                        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
                        {
                          YBWCManager_Printf(g_pYBWCManagerInstance, 
                                            "ERROR update window message received new alpha %d expected > actual alpha %d at the root (beta %d)\n",
                                            nAlphaImproved,
                                            pStackEntryTmp->parameters.fullRootPar.alpha,
                                            pStackEntryTmp->parameters.fullRootPar.beta);
                        }
                      }

                      ASSERT(pStackEntryTmp->nCallType == CALL_TYPE_FULL_SEARCH);

// kh 17.03.07 does not work (beta < alpha was observed)
/*
                      if(pStackEntryTmp->nCallType == CALL_TYPE_FULL_SEARCH)
                      {
/*
                        pFullSearchPar = &pStackEntryTmp->parameters.fullSearchPar;
* /
//                      pFullSearchDat = &pStackEntryTmp->localData.fullSearchDat;

                        if(-nAlphaImproved < pStackEntryTmp->parameters.fullSearchPar.beta) // kh 17.03.07 assignment to pStackEntryTmp->parameters.fullSearchPar.beta exist in fullSearch(...
                        {
                          if(pStackEntryTmp->nReturnPosition == RETURN_POSITION_FULL_ROOT_02)
                          {
                          }
                          else
                          {
                            pStackEntryTmp->parameters.fullSearchPar.beta = -nAlphaImproved; 
/*
                            if(pStackEntryTmp->nReturnPosition == RETURN_POSITION_FULL_ROOT_02) // kh 17.03.07 will not help any more
                            {
                              pStackEntryTmp->parameters.fullSearchPar.alpha = -nAlphaImproved - 1;
                            }
* /
                          }
                        }
                        else
                        {
                          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
                          {
                            YBWCManager_Printf(g_pYBWCManagerInstance, 
                                              "INFO update window message received new beta %d < actual beta %d at level 1\n",
                                              -nAlphaImproved,
                                              pStackEntryTmp->parameters.fullSearchPar.beta);
                          }
                        }
                      }
*/

                      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
                      {
                        YBWCManager_Printf(g_pYBWCManagerInstance, 
                                          "INFO update window message received -> no rerun -> already %d moves (actual/max %d/%d) completed\n",
                                          nCompleted,
                                          pStackEntryTmp->nMoveListTotalCount,
                                          pStackEntryTmp->nMoveListTotalCountMax);
                      }
                    }
                  }

                  if(bSuppressRerun)
                  {
                  }
                  else
                  {
                    if(g_pYBWCManagerInstance->pFruitConfiguration->nMaximumPercentCompletedForRerunSearch > 0)
                    {
                      if(pStackEntryTmp->nMoveListTotalCountMax > 0)
                      {
                        ASSERT(nCompleted <= pStackEntryTmp->nMoveListTotalCountMax);
                        nPercentCompleted = (nCompleted * 100) / pStackEntryTmp->nMoveListTotalCountMax;
                        if(nPercentCompleted >= g_pYBWCManagerInstance->pFruitConfiguration->nMaximumPercentCompletedForRerunSearch)
                        {
                          bSuppressRerun = true;

// kh 17.03.07 try to adjust the window for the actual search a little bit 
                          if(nAlphaImproved > pStackEntryTmp->parameters.fullRootPar.alpha) // kh 17.03.07 defensive
                          {
                            pStackEntryTmp->parameters.fullRootPar.alpha = nAlphaImproved;
                          }
                          else
                          {
                            if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
                            {
                              YBWCManager_Printf(g_pYBWCManagerInstance,
                                                "ERROR update window message received new alpha %d expected > actual alpha %d at the root (beta %d)\n",
                                                nAlphaImproved,
                                                pStackEntryTmp->parameters.fullRootPar.alpha,
                                                pStackEntryTmp->parameters.fullRootPar.beta);
                            }
                          }

                          ASSERT(pStackEntryTmp->nCallType == CALL_TYPE_FULL_SEARCH);

// kh 17.03.07 does not work (beta < alpha was observed)
/*
                          if(pStackEntryTmp->nCallType == CALL_TYPE_FULL_SEARCH)
                          {
/*
                            pFullSearchPar = &pStackEntryTmp->parameters.fullSearchPar;
* /
//                          pFullSearchDat = &pStackEntryTmp->localData.fullSearchDat;

                            if(-nAlphaImproved < pStackEntryTmp->parameters.fullSearchPar.beta) // kh 17.03.07 assignment to pStackEntryTmp->parameters.fullSearchPar.beta exist in fullSearch(...
                            {
                              if(pStackEntryTmp->nReturnPosition == RETURN_POSITION_FULL_ROOT_02)
                              {
                              }
                              else
                              {
                                pStackEntryTmp->parameters.fullSearchPar.beta = -nAlphaImproved; 
/*
                                if(pStackEntryTmp->nReturnPosition == RETURN_POSITION_FULL_ROOT_02) // kh 17.03.07 will not help any more
                                {
                                  pStackEntryTmp->parameters.fullSearchPar.alpha = -nAlphaImproved - 1;
                                }
* /
                              }
                            }
                            else
                            {
                              if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
                              {
                                YBWCManager_Printf(g_pYBWCManagerInstance, 
                                                  "INFO update window message received new beta %d < actual beta %d at level 1\n",
                                                  -nAlphaImproved,
                                                  pStackEntryTmp->parameters.fullSearchPar.beta);
                              }
                            }
                          }
*/

                          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
                          {
                            YBWCManager_Printf(g_pYBWCManagerInstance, 
                                              "INFO update window message received -> no rerun -> already %d%%/%d moves (actual/max %d/%d) completed\n",
                                              nPercentCompleted,
                                              nCompleted,
                                              pStackEntryTmp->nMoveListTotalCount,
                                              pStackEntryTmp->nMoveListTotalCountMax);
                          }
                        }
                      }
                    }
                  }

                } // if(1 < g_pYBWCManagerInstance->pStack->nCount)
              }
              else
              {
                if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
                {
                  YBWCManager_Printf(g_pYBWCManagerInstance, 
                                    "INFO update window message received, rerun allowed for actual iteration depth %d, final iteration depth %d not even reached \n",
                                    pStackEntryTmp->parameters.fullRootPar.depth,
                                    g_pYBWCManagerInstance->pWorkAvailableResult->nDepth);

                }
              } // !if(1 < g_pYBWCManagerInstance->pStack->nCount)
            } // if(pStackEntryTmp->nCallType == CALL_TYPE_FULL_ROOT)
          } // if(0 < g_pYBWCManagerInstance->pStack->nCount) 

// kh 14.03.07 now implemented (see above):
// kh 15.02.07 this could further fine tuned here e.g. with a parameter specifying a search progress limit
// and when beyond that threshold the rerun is suppressed (for a simple way to do that, an absolute limit of totally
// completed moves in (relative) height 1 could be used, as a more sophisticated solution the move list 
// of (relative) height 1 could be expanded here on demand and a relative percent value of completed moves 
// could be used (but for the sophisticated solution there will be a tradeoff because of the 
// fruit specific lazy move list generation)

          if(bSuppressRerun)
          {
            if(    (g_pYBWCManagerInstance->pFruitConfiguration->nMaximumAlphaImprovementCheckCompleted > 0)
                && (nAlphaDiff >= g_pYBWCManagerInstance->pFruitConfiguration->nMaximumAlphaImprovementCheckCompleted))
            {

              if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
              {
                YBWCManager_Printf(g_pYBWCManagerInstance, 
                                  "INFO rerun -> reenabled, alpha improved from %d to %d (diff = %d) (max. diff to suppress a rerun is %d) (start beta %d)\n",
                                  g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha,
                                  nAlphaImproved,
                                  nAlphaDiff,
                                  g_pYBWCManagerInstance->pFruitConfiguration->nMaximumAlphaImprovementCheckCompleted,
                                  g_pYBWCManagerInstance->pWorkAvailableResult->nBeta);
              }

              bSuppressRerun = false; // kh 15.03.07 forced reenable of the rerun for "high" improvemnents
              g_pYBWCManagerInstance->nTotalForcedWindowUpdateRerunCount++;

            }
          }
          
          if(bSuppressRerun)
          {
          }
          else
          {
            if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
            {
              move_to_string(g_pYBWCManagerInstance->pWorkAvailableResult->nMove, sTmpMoveString, 256);
              YBWCManager_Printf(g_pYBWCManagerInstance, 
                                "INFO alpha update at work for %d/%d StackIndex %d Move %d %s (%d) WorkId " S64_FORMAT " height/depth %d/%d nodes " S64_FORMAT " local " S64_FORMAT ", improved from %d to %d (diff %d) (minimum needed %d) (start beta %d)\n",
                                g_pYBWCManagerInstance->nMasterId,
                                g_pYBWCManagerInstance->pWorkAvailableResult->nSourceId,
                                g_pYBWCManagerInstance->pWorkAvailableResult->nStackIndex,
                                g_pYBWCManagerInstance->pWorkAvailableResult->nMoveListIndex + 1,
                                sTmpMoveString,
                                g_pYBWCManagerInstance->pWorkAvailableResult->nMove, 
                                g_pYBWCManagerInstance->pWorkAvailableResult->nWorkId,
                                g_pYBWCManagerInstance->pWorkAvailableResult->nHeight,
                                g_pYBWCManagerInstance->pWorkAvailableResult->nDepth,
                                SearchCurrent->node_nb,
                                SearchCurrent->node_local_nb,
                                g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha,
                                nAlphaImproved,
                                nAlphaDiff,
                                g_pYBWCManagerInstance->pFruitConfiguration->nMinimumAlphaImprovementForRerunSearch,
                                g_pYBWCManagerInstance->pWorkAvailableResult->nBeta);

              g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha = nAlphaImproved;
              g_pYBWCManagerInstance->bRerunSearch                 = TRUE;

              fruit_actions_for_stop_received();
            }
          }

        } // if(nAlphaDiff >= g_pYBWCManagerInstance->pFruitConfiguration->nMinimumAlphaImprovementForRerunSearch)
        else
        {

// kh 15.02.07 do not update the alpha value (of the pseude root only, does not matter anyway), 
// to be able to detect potentially a satisfiable improvement in the future (i.e. avoid not detecting
// reaching the limit of 50 centipawns of an alpha improvement, if the first actual alpha 
// value is e.g. 40 and then 2 update reqeust are received with new alpha values of e.g. 80 and 110
// updatating from 40 to 80 would suppress the detection of reaching the limit (110-40 > 50), because
// 110-80 <(=) 50)
//        g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha = nAlphaImproved;

// kh 18.03.07 update the value anyway to support a potential IID search
// to handle that even better an additional nIIDAlpha could be used which is set initialized immediately 
// before the call to search(... (where the IID is handled) with the value from g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha
// (the next next statement has to be disabled with a comment again)
// this way an alpha improvement without a rerun is stable for the IID and receiving several small window updates in row 
// are also detected if the nMinimumAlphaImprovementForRerunSearch threshold is reached
          g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha = nAlphaImproved;

          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
          {
            YBWCManager_Printf(g_pYBWCManagerInstance, 
                              "INFO update window message received, rerun avoided for alpha improved from %d to %d (diff = %d) (but minimum needed is %d) (start beta %d)\n",
                              g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha,
                              nAlphaImproved,
                              nAlphaDiff,
                              g_pYBWCManagerInstance->pFruitConfiguration->nMinimumAlphaImprovementForRerunSearch,
                              g_pYBWCManagerInstance->pWorkAvailableResult->nBeta);
          }

// kh 19.03.07 try at least to adjust the window for the actual search a little bit 
          if(0 < g_pYBWCManagerInstance->pStack->nCount) // kh 26.10.06 check potential access to the root level
          {
            pStackEntryTmp = Stack_PeekAt(/* g_pYBWCManagerInstance->pStack, */ 0);

            ASSERT(pStackEntryTmp->nCallType == CALL_TYPE_FULL_ROOT);

            if(pStackEntryTmp->nCallType == CALL_TYPE_FULL_ROOT)
            {
/*
              pFullRootPar = &pStackEntryTmp->parameters.fullRootPar;
*/
//            pFullRootDat = &pStackEntryTmp->localData.fullRootDat;

              if(nAlphaImproved > pStackEntryTmp->parameters.fullRootPar.alpha) // kh 17.03.07 defensive
              {
                if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
                {
                  YBWCManager_Printf(g_pYBWCManagerInstance, 
                                    "INFO actual root alpha improved without rerun from %d to %d (beta %d)\n",
                                    pStackEntryTmp->parameters.fullRootPar.alpha,
                                    nAlphaImproved,
                                    pStackEntryTmp->parameters.fullRootPar.beta);
                }
                pStackEntryTmp->parameters.fullRootPar.alpha = nAlphaImproved;
              }
              else
              {
                if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
                {
                  YBWCManager_Printf(g_pYBWCManagerInstance, 
                                    "ERROR update window message received new alpha %d expected > actual alpha %d at the root (beta %d)\n",
                                    nAlphaImproved,
                                    pStackEntryTmp->parameters.fullRootPar.alpha,
                                    pStackEntryTmp->parameters.fullRootPar.beta);
                }
              }
            }
          }
        } // !if(nAlphaDiff >= g_pYBWCManagerInstance->pFruitConfiguration->nMinimumAlphaImprovementForRerunSearch)
      } // if(nAlphaImproved > g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha)
    } // !if(g_pYBWCManagerInstance->bStoppingActive)

// kh 20.12.06 avoid rerun if there was a real stop received in between
/*
    g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha = nAlphaImproved;
    g_pYBWCManagerInstance->bRerunSearch = TRUE;
*/

    if(    value_is_ok(g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha)
        && value_is_ok(g_pYBWCManagerInstance->pWorkAvailableResult->nBeta)
        && (g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha < g_pYBWCManagerInstance->pWorkAvailableResult->nBeta))
    {    
    }
    else
    {
      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, 
                          "ERROR in pWorkAvailableResult alpha beta range %d .. %d\n",
                          g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha,
                          g_pYBWCManagerInstance->pWorkAvailableResult->nBeta);
      }
    }

    if(g_pYBWCManagerInstance->pStack->nCount > 0) // kh 23.03.07 check potential access to the root level
    {
      pStackEntryTmp = Stack_PeekAt(/* g_pYBWCManagerInstance->pStack, */ 0);

      ASSERT(pStackEntryTmp->nCallType == CALL_TYPE_FULL_ROOT);

      if(pStackEntryTmp->nCallType == CALL_TYPE_FULL_ROOT)
      {
/*
        pFullRootPar = &pStackEntryTmp->parameters.fullRootPar;
*/
//      pFullRootDat = &pStackEntryTmp->localData.fullRootDat;

        if(    value_is_ok(pStackEntryTmp->parameters.fullRootPar.alpha)
            && value_is_ok(pStackEntryTmp->parameters.fullRootPar.beta)
            && (pStackEntryTmp->parameters.fullRootPar.alpha < pStackEntryTmp->parameters.fullRootPar.beta))
        {    
        }
        else
        {
          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(g_pYBWCManagerInstance, 
                              "ERROR in pStackEntryTmp->parameters.fullRootPar alpha beta range %d .. %d\n",
                              pStackEntryTmp->parameters.fullRootPar.alpha,
                              pStackEntryTmp->parameters.fullRootPar.beta);
          }
        }
      }
    }
  } // !if(g_pYBWCManagerInstance->pFruitConfiguration->bDirectUpdateSearchWindows)
}

// send_best_move()

static void fruit_send_remote_test_best_move_result()
{
  int               nResult;
  ProcessorHandler* pProcessorHandler;
  Result*           pResult;

  BOOL              bPonderMoveOk;

  int               nPVLength;

  mv_t * pv;

  pv   = SearchBest[0].pv;

// kh 05.09.06 bPonderMoveOk is not really used
  bPonderMoveOk = (    (SearchBest[0].pv[0] == SearchBest[0].move) 
                    && move_is_ok(SearchBest[0].pv[1]));

  pProcessorHandler = g_pYBWCManagerInstance->processorHandlerPool[0];
  pResult           = ProcessorHandler_CreateResult(pProcessorHandler);

  nPVLength = 0;
  while(*pv++ != MoveNone) 
  {
    nPVLength++;
  }

  nResult           = Result_InitNonRootMasterRemoteTest(pResult,
                                                         SearchBest[0].move,
                                                         SearchBest[0].value,
                                                         SearchBest[0].flags,
                                                         SearchBest[0].depth,
                                                         SearchCurrent->max_depth,
                                                         nPVLength,
                                                         SearchBest[0].pv,
                                                         bPonderMoveOk,
                                                         SearchCurrent->time,
                                                         SearchCurrent->speed,
                                                         SearchCurrent->cpu,
                                                         SearchCurrent->node_nb);

  if(nResult == MPI_SUCCESS)
  {
    nResult = Result_Send(pResult);
    if(nResult == MPI_SUCCESS)
    {
    }
    else
    {
      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR fruit_send_remote_test_best_move_result(... failed at Result_Send(..., errorcode = %d\n", nResult);
      }
    }
  }
  else
  {
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR fruit_send_remote_test_best_move_result(... failed at Result_InitNonRootMasterRemoteTest(..., errorcode = %d\n", nResult);
    }
  }
}

static void fruit_remote_test_parse_go(char string[]) 
{
  const char * ptr;
  bool infinite, ponder;
  int depth, mate, movestogo;
  sint64 nodes;
  double binc, btime, movetime, winc, wtime;
  double time, inc;
  double time_max, alloc;

  // init

  infinite = false;
  ponder = false;

  depth = -1;
  mate = -1;
  movestogo = -1;

  nodes = -1;

  binc = -1.0;
  btime = -1.0;
  movetime = -1.0;
  winc = -1.0;
  wtime = -1.0;

  // parse

// kh 10.08.06 no need to skip "go" or "remote n" respectively, use string initially
// ptr = strtok(string, " "); // skip "go"

  for(ptr = strtok(string, " "); ptr != NULL; ptr = strtok(NULL, " ")) 
  {
    if(false) 
    {
    } 
    else if(string_equal(ptr, "binc")) 
    {
      ptr = strtok(NULL, " ");
      if(ptr == NULL) 
      {
        my_fatal("parse_go(): missing argument\n");
      }

      binc = double(atoi(ptr)) / 1000.0;
      ASSERT(binc >= 0.0);
    } 
    else if(string_equal(ptr, "btime")) 
    {
      ptr = strtok(NULL, " ");
      if(ptr == NULL) 
      {
        my_fatal("parse_go(): missing argument\n");
      }

      btime = double(atoi(ptr)) / 1000.0;
      ASSERT(btime >= 0.0);
    } 
    else if(string_equal(ptr, "depth")) 
    {
      ptr = strtok(NULL, " ");
      if(ptr == NULL) 
      {
        my_fatal("parse_go(): missing argument\n");
      }
      depth = atoi(ptr);
      ASSERT(depth >= 0);
    } 
    else if(string_equal(ptr, "infinite")) 
    {
      infinite = true;
    } 
    else if(string_equal(ptr, "mate")) 
    {
      ptr = strtok(NULL, " ");
      if(ptr == NULL) 
      {
        my_fatal("parse_go(): missing argument\n");
      }
      mate = atoi(ptr);
      ASSERT(mate >= 0);
    } 
    else if(string_equal(ptr, "movestogo")) 
    {
      ptr = strtok(NULL, " ");
      if(ptr == NULL) 
      {
        my_fatal("parse_go(): missing argument\n");
      }

      movestogo = atoi(ptr);
      ASSERT(movestogo >= 0);
    } 
    else if(string_equal(ptr, "movetime")) 
    {
      ptr = strtok(NULL, " ");
      if(ptr == NULL) 
      {
        my_fatal("parse_go(): missing argument\n");
      }

      movetime = double(atoi(ptr)) / 1000.0;
      ASSERT(movetime >= 0.0);
    } 
    else if(string_equal(ptr, "nodes")) 
    {
      ptr = strtok(NULL, " ");
      if (ptr == NULL) 
      {
        my_fatal("parse_go(): missing argument\n");
      }
      nodes = my_atoll(ptr);
      ASSERT(nodes >= 0);
    } 
    else if(string_equal(ptr, "ponder")) 
    {
      ponder = true;
    } 
    else if(string_equal(ptr, "searchmoves")) 
    {
       // dummy
    } 
    else if(string_equal(ptr, "winc")) 
    {
      ptr = strtok(NULL, " ");
      if(ptr == NULL) 
      {
        my_fatal("parse_go(): missing argument\n");
      }
      winc = double(atoi(ptr)) / 1000.0;
      ASSERT(winc >= 0.0);
    } 
    else if(string_equal(ptr, "wtime")) 
    {
      ptr = strtok(NULL, " ");
      if(ptr == NULL) 
      {
        my_fatal("parse_go(): missing argument\n");
      }
      wtime = double(atoi(ptr)) / 1000.0;
      ASSERT(wtime >= 0.0);
    }
  }

  // init

  search_clear();

  // depth limit

// kh 10.04.07 Thomas Gaksch
   // JAS
   int option_depth = 0;
   option_depth = option_get_int("Search Depth");
   if (option_depth > 0) {
   	  depth = option_depth;
   }
   // JAS end

  if(depth >= 0) 
  {
    SearchInput->depth_is_limited  = true;
    SearchInput->depth_limit       = depth;
  } 
  else if(mate >= 0) 
  {
    SearchInput->depth_is_limited = true;
    SearchInput->depth_limit      = mate * 2 - 1; // HACK: move -> ply
  }

  // time limit

  if(COLOUR_IS_WHITE(SearchInput->board->turn)) 
  {
    time  = wtime;
    inc   = winc;
  } 
  else 
  {
    time  = btime;
    inc   = binc;
  }

// kh 10.04.07 Thomas Gaksch
  if(movestogo <= 0 || movestogo > 30) // HACK was 30
//if(movestogo <= 0 || movestogo > 30) 
  {
    movestogo = 30; // HACK
  }

  if(inc < 0.0) 
  {
    inc = 0.0;
  }

  if(movetime >= 0.0) 
  {
     // fixed time

    SearchInput->time_is_limited = true;
    SearchInput->time_limit_1    = movetime * 5.0; // HACK to avoid early exit
    SearchInput->time_limit_2    = movetime;
  } 
  else if(time >= 0.0) 
  {
     // dynamic allocation

    time_max = time * 0.95 - 1.0;
    if(time_max < 0.0) 
    {
      time_max = 0.0;
    }

    SearchInput->time_is_limited = true;

    alloc = (time_max + inc * double(movestogo-1)) / double(movestogo);
    alloc *= (option_get_bool("Ponder") ? PonderRatio : NormalRatio);
    if(alloc > time_max) 
    {
      alloc = time_max;
    }
    SearchInput->time_limit_1 = alloc;

    alloc = (time_max + inc * double(movestogo-1)) * 0.5;
    if(alloc < SearchInput->time_limit_1) 
    {
      alloc = SearchInput->time_limit_1;
    }
    if(alloc > time_max) 
    {
      alloc = time_max;
    }
    SearchInput->time_limit_2 = alloc;
  }

  if(infinite || ponder) 
  {
    SearchInput->infinite = true;
  }

  // search

  ASSERT(!Searching);
  ASSERT(!Delay);

  Searching  = true;

  ASSERT(!g_pYBWCManagerInstance->bRootMaster);
  ASSERT(!g_pYBWCManagerInstance->bStoppingActive);
  g_pYBWCManagerInstance->nState = YBWC_MANAGER_STATE_SEARCHING;

  Infinite   = infinite || ponder;
  Delay      = false;

  search();

  g_pYBWCManagerInstance->bPostSearchActive = TRUE;

  search_update_current();

  ASSERT(Searching);
  ASSERT(!Delay);

  Searching  = false;

  Delay      = Infinite;

// kh 10.08.06

//if(!Delay) 
  {
    fruit_send_remote_test_best_move_result();
  }

  g_pYBWCManagerInstance->bStoppingActive   = FALSE;

  g_pYBWCManagerInstance->bPostSearchActive = FALSE;
  g_pYBWCManagerInstance->nState            = YBWC_MANAGER_STATE_IDLE; 

  YBWCManager_DispatchDelayedRequests(g_pYBWCManagerInstance);
}

// fruit_actions_for_remote_test_received()

// kh 10.08.06
void fruit_actions_for_remote_test_received(char string[])
{
  if(!Searching && !Delay) 
  {
    init();
    fruit_remote_test_parse_go(string);
  } 
  else 
  {
    ASSERT(false);
  }
}

void fruit_actions_for_remote_test_result_received(Result* pResult)
{
  SearchBest[0].move        = pResult->nBestMove;
  SearchBest[0].value       = pResult->nBestValue;
  SearchBest[0].flags       = pResult->nFlags; 
  SearchBest[0].depth       = pResult->nDepth;

  pv_copy(SearchBest[0].pv, pResult->PV);

  SearchCurrent->max_depth  = pResult->nMaxDepth,

  SearchCurrent->time       = pResult->dTime,
  SearchCurrent->speed      = pResult->dSpeed,
  SearchCurrent->cpu        = pResult->dCPU,
  SearchCurrent->node_nb    = pResult->nNodes;

//search_update_current();

  search_update_best();

  ASSERT(Searching);
  ASSERT(!Delay);

  Searching  = false;

  Delay      = Infinite;

  if(!Delay) 
  {
    send_best_move();
  }

	ASSERT(g_pYBWCManagerInstance->bRootMaster);
  sort_init(); // kh 10.04.07 Thomas Gaksch

  ASSERT(g_pYBWCManagerInstance->bRootMaster);

  ASSERT(!g_pYBWCManagerInstance->bStoppingActive);

  g_pYBWCManagerInstance->nRemoteTestProcessorId = -1;
  g_pYBWCManagerInstance->nState                 = YBWC_MANAGER_STATE_IDLE; 

// kh 13.09.06 never necessary for the root master
  ASSERT(g_pYBWCManagerInstance->pHeadDelayedRequest == NULL);
//YBWCManager_DispatchDelayedRequests(g_pYBWCManagerInstance);
}

void fruit_work_available_do_moves_ahead(Result* pResult, undo_t UndoBuffer[])
{
  int i;
  int nMove;

  for(i = 0; i < pResult->nMoveAheadListCount; i++)
  {
    nMove = pResult->MoveAheadList[i];

    switch(nMove)
    {
    case MoveNone:
      break;

    case MoveNull:
      move_do_null(SearchInput->board, &UndoBuffer[i]);
      break;

    default:
      move_do(SearchInput->board, nMove, &UndoBuffer[i]);
      break;
    }
  }
}

void fruit_work_available_undo_moves_ahead(Result* pResult, undo_t UndoBuffer[])
{
  int i;
  int nMove;

  for(i = pResult->nMoveAheadListCount - 1; i >= 0; i--)
  {
    nMove = pResult->MoveAheadList[i];

    switch(nMove)
    {
    case MoveNone:
      break;

    case MoveNull:
      move_undo_null(SearchInput->board, &UndoBuffer[i]);
      break;

    default:
      move_undo(SearchInput->board, nMove, &UndoBuffer[i]);
      break;
    }
  }
}

static void fruit_send_work_available_best_move_result()
{
  int               nResult;
  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  BOOL              bPonderMoveOk;

  int               nPVLength;

  mv_t * pv;

  pv   = SearchBest[0].pv;

// kh 05.09.06 bPonderMoveOk is not really used
  bPonderMoveOk = (   (SearchBest[0].pv[0] == SearchBest[0].move) 
                    && move_is_ok(SearchBest[0].pv[1]));

  pProcessorHandler = g_pYBWCManagerInstance->processorHandlerPool[g_pYBWCManagerInstance->pWorkAvailableResult->nSourceId];
  pRequest          = ProcessorHandler_CreateRequest(pProcessorHandler);

  nPVLength = 0;
  while(*pv++ != MoveNone) 
  {
    nPVLength++;
  }

  nResult           = Request_InitSlaveProcessSearchResult(pRequest,

// kh 11.10.06 transmit stack access key information back to the master, which may have 
// completed/aborted the search in between (so this result has to be ignored by the master)
                                                           g_pYBWCManagerInstance->pWorkAvailableResult->nWorkId,
                                                           g_pYBWCManagerInstance->pWorkAvailableResult->nStackIndex,
                                                           g_pYBWCManagerInstance->pWorkAvailableResult->nMoveListIndex,

                                                           SearchBest[0].move,
                                                           SearchBest[0].value,
                                                           SearchBest[0].flags,
                                                           SearchBest[0].depth,
                                                           SearchCurrent->max_depth,
                                                           nPVLength,
                                                           SearchBest[0].pv,
                                                           bPonderMoveOk,
                                                           SearchCurrent->time,
                                                           SearchCurrent->speed,
                                                           SearchCurrent->cpu,
                                                           SearchCurrent->node_nb,
                                                           Trans->used);

  if(nResult == MPI_SUCCESS)
  {
    g_pYBWCManagerInstance->nNodesSinceSendResult = SearchCurrent->node_nb;

// kh 04.04.08 subjob results are potentially received during Request_Send(... 
    nResult = Request_Send(pRequest);

    g_pYBWCManagerInstance->nNodesSinceSendResult = SearchCurrent->node_nb - g_pYBWCManagerInstance->nNodesSinceSendResult;

    if(nResult == MPI_SUCCESS)
    {
    }
    else
    {
      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR fruit_send_work_available_best_move_result(... failed at Request_Send(..., errorcode = %d\n", nResult);
      }
    }
  }
  else
  {
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR fruit_send_work_available_best_move_result(... failed at Request_InitNonRootMasterRemoteTest(..., errorcode = %d\n", nResult);
    }
  }
}

static void fruit_work_available_parse_go(Result* pResult) 
{
//const char* ptr;
  bool        infinite;
  bool        ponder;
  int         depth;
  int         mate;
  int         movestogo;
  sint64      nodes;

  double      binc;
  double      btime;
  double      movetime;
  double      winc; 
  double      wtime;

  double      time;
  double      inc;

  double      time_max;
  double      alloc;

  bool        bResultNeededByMaster;

  sint64      nTotalNodesRerunOverhead;

  StackEntry* pStackEntry;

  int         nCallIndex;

  // init

  undo_t  UndoBuffer[MAX_MOVES];

  g_pYBWCManagerInstance->nTotalWorkStartedCount++;

  g_pYBWCManagerInstance->nRerunSearchCounter = 0;

  g_pYBWCManagerInstance->bRealStopReceived       = FALSE; // kh 21.03.07 for debug purposes only
  g_pYBWCManagerInstance->nNodesSinceStopReceive  = 0;

// kh 15.12.06 $$$ debug only
  if(false &&  g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
  {
    YBWCManager_Printf(g_pYBWCManagerInstance, "start fruit_work_available_parse_go\n");
    YBWCManager_Printf(g_pYBWCManagerInstance, "  master is = <%d>\n", pResult->nSourceId);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  nSyncPositionId = <%d>\n", pResult->nSyncPositionId);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  nWorkId = <" F12INT64d ">\n", pResult->nWorkId);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  nStackIndex = <%d>\n", pResult->nStackIndex);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  nMoveListIndex = <%d>\n", pResult->nMoveListIndex);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  nCallType = <%d>\n", pResult->nCallType);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  nMove = <%d>\n", pResult->nMove);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  nDepth = <%d>\n", pResult->nDepth);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  nNewDepth = <%d>\n", pResult->nNewDepth);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  nHeight = <%d>\n", pResult->nHeight);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  bInPV= <%d>\n", pResult->bInPV);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  nPlayedNb = <%d>\n", pResult->nPlayedNb);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  nHistoryValue = <%d>\n", pResult->nHistoryValue);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  nAlpha = <%d>\n", pResult->nAlpha);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  nBeta = <%d>\n", pResult->nBeta);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  nMoveAheadListCount = <%d>\n", pResult->nMoveAheadListCount);
  }

  fruit_work_available_do_moves_ahead(pResult, UndoBuffer);

  g_pYBWCManagerInstance->pWorkAvailableResult  = pResult; // kh 11.10.06 for global convenient access

  bResultNeededByMaster                = false;

  nTotalNodesRerunOverhead             = 0;

  g_pYBWCManagerInstance->bRerunSearch = TRUE;
  while(g_pYBWCManagerInstance->bRerunSearch)
  {
    if(g_pYBWCManagerInstance->nRerunSearchCounter > 0)
    {

// kh 13.03.07 rerun overhead is defined here as the sum of all nodes caused by update window reruns 
// but  without the final (re)run (see also search_clear(... )
      nTotalNodesRerunOverhead = SearchCurrent->node_nb; 
    }

    if(g_pYBWCManagerInstance->nRerunSearchCounter > g_pYBWCManagerInstance->nRerunSearchCounterMax)
    {
      g_pYBWCManagerInstance->nRerunSearchCounterMax = g_pYBWCManagerInstance->nRerunSearchCounter;

// kh 27.05.07
      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance,
                           "WARNING fruit_actions_for_work_available_received(... nRerunSearchCounterMax = %d, improved alpha = %d) \n", 
                           g_pYBWCManagerInstance->nRerunSearchCounterMax,
                           g_pYBWCManagerInstance->pWorkAvailableResult->nAlpha);
      }
    } // if(g_pYBWCManagerInstance->nRerunSearchCounter > g_pYBWCManagerInstance->nRerunSearchCounterMax)
    
// kh 10.11.06 may be set asynchronously to TRUE when an update search window request is dispatched
    g_pYBWCManagerInstance->bRerunSearch = FALSE; 

    infinite  = false;
    ponder    = false;

    depth     = -1;
    mate      = -1;
    movestogo = -1;

    nodes     = -1;

    binc      = -1.0;
    btime     = -1.0;
    movetime  = -1.0;
    winc      = -1.0;
    wtime     = -1.0;

  // kh 06.09.06 "parse"

    depth = pResult->nDepth;
    ASSERT(depth >= 0);

    // init

    search_clear();

    // depth limit

// kh 10.04.07 Thomas Gaksch
   // JAS
   int option_depth = 0;
   option_depth = option_get_int("Search Depth");
   if (option_depth > 0) {
   	  depth = option_depth;
   }
   // JAS end

    if(depth >= 0) 
    {
      SearchInput->depth_is_limited  = true;
      SearchInput->depth_limit       = depth;
    } 
    else if(mate >= 0) 
    {
      SearchInput->depth_is_limited = true;
      SearchInput->depth_limit      = mate * 2 - 1; // HACK: move -> ply
    }

    // time limit

    if(COLOUR_IS_WHITE(SearchInput->board->turn)) 
    {
      time  = wtime;
      inc   = winc;
    } 
    else 
    {
      time  = btime;
      inc   = binc;
    }

// kh 10.04.07 Thomas Gaksch
  if(movestogo <= 0 || movestogo > 30) // HACK was 30
//if(movestogo <= 0 || movestogo > 30) 
    {
      movestogo = 30; // HACK
    }

    if(inc < 0.0) 
    {
      inc = 0.0;
    }

    if(movetime >= 0.0) 
    {
      // fixed time

      SearchInput->time_is_limited = true;
      SearchInput->time_limit_1    = movetime * 5.0; // HACK to avoid early exit
      SearchInput->time_limit_2    = movetime;
    } 
    else if(time >= 0.0) 
    {
      // dynamic allocation

      time_max = time * 0.95 - 1.0;
      if(time_max < 0.0) 
      {
        time_max = 0.0;
      }

      SearchInput->time_is_limited = true;

      alloc = (time_max + inc * double(movestogo-1)) / double(movestogo);
      alloc *= (option_get_bool("Ponder") ? PonderRatio : NormalRatio);
      if(alloc > time_max) 
      {
        alloc = time_max;
      }
      SearchInput->time_limit_1 = alloc;

      alloc = (time_max + inc * double(movestogo-1)) * 0.5;
      if(alloc < SearchInput->time_limit_1) 
      {
        alloc = SearchInput->time_limit_1;
      }
      if(alloc > time_max) 
      {
        alloc = time_max;
      }
      SearchInput->time_limit_2 = alloc;
    }

    if(infinite || ponder) 
    {
      SearchInput->infinite = true;
    }

    // search

    ASSERT(!Searching);
    ASSERT(!Delay);

    Searching  = true;

    ASSERT(!g_pYBWCManagerInstance->bRootMaster);

    ASSERT(!g_pYBWCManagerInstance->bStoppingActive);

    if(g_pYBWCManagerInstance->bStoppingActive)
    {
      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR fruit_work_available_parse_go(... stopping is active on entry (set defensive to false now)\n");
      }

      g_pYBWCManagerInstance->bStoppingActive = FALSE; // kh 19.03.07 defensive, but there exist a real problem
    }

//  g_pYBWCManagerInstance->pWorkAvailableResult          = pResult; // kh 11.10.06 for global convenient access
    g_pYBWCManagerInstance->nState                        = YBWC_MANAGER_STATE_SEARCHING; 
    g_pYBWCManagerInstance->bSearchingSubproblem          = TRUE;


// kh 14.03.07 prepare max number of moves buffering for level 1 to estimate the percentage of search completion
// used in combination with pFruitConfiguration->nMaximumPercentCompletedForRerunSearch  to avoid the handling
// of update window messages if the search is already nearly completed with the actual window (i.e. alpha value)
//  g_pYBWCManagerInstance->nLevel1MoveListTotalCountMax  = 0;
    pStackEntry = &g_pYBWCManagerInstance->pStack->stackEntry[1]; // kh 14.03.07 this access is a little bit quick and dirty
    pStackEntry->nMoveListTotalCountMax = 0;

    Infinite   = infinite || ponder;
    Delay      = false;

    search();

    search_update_current();

    ASSERT(Searching);
    ASSERT(!Delay);

    Searching  = false;

    Delay      = Infinite;

    if(g_pYBWCManagerInstance->bRealStopReceived)
    {
      ASSERT(!g_pYBWCManagerInstance->bRerunSearch);

      if(g_pYBWCManagerInstance->bRerunSearch)
      {
        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR fruit_work_available_parse_go(... rerun is active after receiving a real stop request from the master (set defensive to false now)\n");
        }

        g_pYBWCManagerInstance->bRerunSearch = FALSE; // kh 21.03.07 defensive, but there exist a real problem

      }
    }

    bResultNeededByMaster = false; // kh 22.12.06 defensive
    if(g_pYBWCManagerInstance->bRerunSearch || g_pYBWCManagerInstance->bStoppingActive)
    {
    }
    else
    {
      bResultNeededByMaster = true;
      g_pYBWCManagerInstance->nTotalWorkFinishedCount++;
    }

    g_pYBWCManagerInstance->bStoppingActive = FALSE;

    g_pYBWCManagerInstance->nRerunSearchCounter++;
  } // while(g_pYBWCManagerInstance->bRerunSearch)

  g_pYBWCManagerInstance->bRealStopReceived = FALSE; // kh 21.03.07 for debug purposes only

  nCallIndex = Stack_CallPositionToIndex(/* g_pYBWCManagerInstance->pStack, */
                                         g_pYBWCManagerInstance->pWorkAvailableResult->nReturnPosition);

  g_pYBWCManagerInstance->CallPositionStatistics[nCallIndex].nTotalCalls++;

  g_pYBWCManagerInstance->CallPositionStatistics[nCallIndex].nTotalNodes += SearchCurrent->node_nb;

  g_pYBWCManagerInstance->nTotalNodesRerunOverhead += nTotalNodesRerunOverhead;

  g_pYBWCManagerInstance->CallPositionStatistics[nCallIndex].nTotalNodesRerunOverhead += nTotalNodesRerunOverhead;


  if(bResultNeededByMaster)
  {
  }
  else
  {
    g_pYBWCManagerInstance->nTotalNodesAbortOverhead += SearchCurrent->node_nb;

    g_pYBWCManagerInstance->CallPositionStatistics[nCallIndex].nTotalNodesAbortOverhead += SearchCurrent->node_nb;
  }

  g_pYBWCManagerInstance->bPostSearchActive = TRUE;

  if(g_pYBWCManagerInstance->nNodesSinceStopReceive > 0)
  {
    g_pYBWCManagerInstance->nNodesSinceStopReceive = SearchCurrent->node_local_nb - g_pYBWCManagerInstance->nNodesSinceStopReceive;
    if(g_pYBWCManagerInstance->nNodesSinceStopReceive > g_pYBWCManagerInstance->nNodesSinceStopReceiveMax)
    {
      g_pYBWCManagerInstance->nNodesSinceStopReceiveMax = g_pYBWCManagerInstance->nNodesSinceStopReceive;

      if(false && /* tuning */ g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, 
                           "max nodes after stop reveived = " S64_FORMAT "\n", 
                           g_pYBWCManagerInstance->nNodesSinceStopReceiveMax);
      }
    }
  }

// kh 10.08.06

// kh 15.12.06 $$$ debug only
  if(false &&  g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
  {
    YBWCManager_Printf(g_pYBWCManagerInstance, "end (1) fruit_work_available_parse_go\n");
//  YBWCManager_Printf(g_pYBWCManagerInstance, "  result nSyncPositionId = <%d>\n", pResult->nSyncPositionId);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  result nWorkId = <" F12INT64d ">\n", g_pYBWCManagerInstance->pWorkAvailableResult->nWorkId);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  result nStackIndex = <%d>\n", g_pYBWCManagerInstance->pWorkAvailableResult->nStackIndex);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  result nMoveListIndex = <%d>\n", g_pYBWCManagerInstance->pWorkAvailableResult->nMoveListIndex);
//  YBWCManager_Printf(g_pYBWCManagerInstance, "  nCallType = <%d>\n", pResult->nCallType);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  result SearchBest[0].move = <%d>\n", SearchBest[0].move);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  result SearchBest[0].value = <%d>\n", SearchBest[0].value);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  result nDepth = <%d>\n", SearchBest[0].depth);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  result SearchBest[0].depth = <%d>\n", SearchBest[0].depth);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  result SearchCurrent->max_depth = <%d>\n", SearchCurrent->max_depth);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  result SearchCurrent->time = <%9.2f>\n", SearchCurrent->time);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  result SearchCurrent->speed = <%9.2f>\n", SearchCurrent->speed);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  result SearchCurrent->cpu = <%7.2f>\n", SearchCurrent->cpu);
    YBWCManager_Printf(g_pYBWCManagerInstance, "  result SearchCurrent->node_nb = <" S64_FORMAT ">\n", SearchCurrent->node_nb);
  }

  g_pYBWCManagerInstance->nNodesSinceSendResult = 0;

//if(!Delay) 
  {
// kh 22.12.06 tuning send result anyway (does not need much bandwidth and seems to be more defensive)
    if(true || bResultNeededByMaster)
    {

// kh 27.02.07 MoveNone was observed during debug if the slave search was aborted before even really started
// now retransmit the original move forced back to the master 
      if(SearchBest[0].move == MoveNone) // kh 27.02.07 observed SearchBest[0].move
      {

        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, "INFO slave search cancelled even before really started (the result is not available but not needed anyway)\n");
        }

        SearchBest[0].move = g_pYBWCManagerInstance->pWorkAvailableResult->nMove; 
      }

      fruit_send_work_available_best_move_result();
    }
    else
    {
      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, "end (1b) slave send result suppressed, result is not really needed by master\n");
      }
    }
  }

// kh 04.04.08 favor "gross" node counting (see also comment from 04.04.08 for search_clear(... in search.cpp)
  SearchCurrent->node_nb  = g_pYBWCManagerInstance->nNodesSinceSendResult;
  SearchCurrent->time     = 0.0;
  SearchCurrent->speed    = 0.0;
  SearchCurrent->cpu      = 0.0;
 
  fruit_work_available_undo_moves_ahead(pResult, UndoBuffer);

//g_pYBWCManagerInstance->bStoppingActive       = FALSE;
  g_pYBWCManagerInstance->bSearchingSubproblem  = FALSE;
  g_pYBWCManagerInstance->nMasterId             = -1;
  g_pYBWCManagerInstance->bPostSearchActive     = FALSE;
  g_pYBWCManagerInstance->nState                = YBWC_MANAGER_STATE_SUPPORT_SEARCH; 
  g_pYBWCManagerInstance->pWorkAvailableResult  = NULL;

  YBWCManager_DispatchDelayedRequests(g_pYBWCManagerInstance);

// kh 15.12.06 $$$ debug only
  if(false && g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
  {
    YBWCManager_Printf(g_pYBWCManagerInstance, "end (2) fruit_work_available_parse_go\n");
  }
}

// fruit_work_available_parse_go()

void fruit_actions_for_work_available_received(Result* pResult)
{
  if(!Searching && !Delay) 
  {
    init();

// kh 06.09.06 the "info for go" is extracted from pResult
    fruit_work_available_parse_go(pResult); 
  } 
  else 
  {
    ASSERT(false);
  }
}
// end of protocol.cpp
