Home * Engines * CPW-Engine * Chronos

 
 
#include "stdafx.h"
 
enum etask {
    TASK_NOTHING,
    TASK_SEARCH,
    TASK_PONDER
} extern task;
 
stime chronos;
 
extern sSearchDriver sd;
 
extern bool time_over;
 
#define TIMEBUFFER 500
#define MOVESTOGO 24
 
 
#if defined(_MSC_VER) || defined(_WINDOWS_)
    #include <Windows.h>
 
    unsigned int gettime() {
        FILETIME ft;
        GetSystemTimeAsFileTime(&ft);    
        return (unsigned int) ((((U64)ft.dwHighDateTime << 32) | ft.dwLowDateTime) / 10000);
    }
#else
    #include <sys/time.h>
 
    unsigned int gettime() {
        timeval t;
        gettimeofday(&t, 0);
        return t.tv_usec;
    }
#endif
 
 
void time_uci_go(char * command) {
 
    time_over = false;
    task = TASK_SEARCH;
 
    chronos.flags = 0;
 
    if (strstr(command, "infinite")) {chronos.flags |= FINFINITE;}
    if (strstr(command, "ponder")) {chronos.flags |= FINFINITE; task = TASK_PONDER;}
 
    //not implemented (do an infinite search instead)
    if (strstr(command, "searchmoves")) {chronos.flags |= FINFINITE;}
 
    if (strstr(command, "wtime")) {chronos.flags |= FTIME; sscanf(strstr(command, "wtime"), "wtime %d", &chronos.time[WHITE]);}
    if (strstr(command, "btime")) {chronos.flags |= FTIME; sscanf(strstr(command, "btime"), "%*s %d", &chronos.time[BLACK]);}
    if (strstr(command, "winc")) {chronos.flags |= FINC; sscanf(strstr(command, "winc"), "%*s %d", &chronos.inc[WHITE]);}
    if (strstr(command, "binc")) {chronos.flags |= FINC; sscanf(strstr(command, "binc"), "%*s %d", &chronos.inc[BLACK]);}
    if (strstr(command, "movestogo")) {chronos.flags |= FMOVESTOGO; sscanf(strstr(command, "movestogo"), "%*s %d", &chronos.movestogo);}
    if (strstr(command, "depth")) {chronos.flags |= FDEPTH; sscanf(strstr(command, "depth"), "%*s %d", &chronos.depth);}
    if (strstr(command, "nodes")) {chronos.flags |= FNODES; sscanf(strstr(command, "nodes"), "%*s %d", &chronos.nodes);}
 
    //not implemented (do an infinite search instead)
    if (strstr(command, "mate")) {chronos.flags |= FMATE; chronos.flags |= FINFINITE; sscanf(strstr(command, "mate"), "%*s %d", &chronos.mate);}
 
    if (strstr(command, "movetime")) {chronos.flags |= FMOVETIME; sscanf(strstr(command, "movetime"), "%*s %d", &chronos.movetime);}
 
    if (chronos.flags == 0) chronos.flags |= FINFINITE;
}
 
int time_uci_ponderhit() {
    if (task != TASK_PONDER) return 0;
 
    /* switch from pondering mode to normal search */
    chronos.flags &= ~FINFINITE;
    sd.starttime = gettime();
    task = TASK_SEARCH;
 
    return 0;
}
 
void time_xboard_go() {
 
    time_over = false;
    task = TASK_SEARCH;
 
    if (!chronos.flags) chronos.flags = FINFINITE;
}
 
void time_nothing_go() {
 
    time_over = false;
    task = TASK_SEARCH;
}
 
void time_calc_movetime() {
 
    /* no movetime to be calculated in these search types */
 
    if (chronos.flags & (FINFINITE | FDEPTH | FNODES)) return;
 
    /* if the movetime is given */
 
    if (chronos.flags & FMOVETIME) {
        if (chronos.movetime > TIMEBUFFER) {
            sd.movetime = chronos.movetime - TIMEBUFFER;
        } else {
            sd.movetime = -1;
        }
        return;
    }
 
    /* in any other case we are given an ordinary timecontrol 
       (time + opt. movestogo + opt. incremental) 
 
        we take the total time left (chronos.time[sd.myside]), divide it
        by the number of moves that are still to play (chronos.movestogo)
        and we have the allowed time per move.
        If we are given an incremental time control, we consider this 
        here as well.
 
        In case we are not told how many moves we are supposed to play
        with the time left, we assume a constant. This results in a 
        slower play in the beginning and more rapid towards the end.
 
        as a little buffer we always assume that there are more moves
        to be played than we actually have to. This should avoid loosing on time.
    */
 
    sd.movetime = 0;
    int movestogo = MOVESTOGO;
    if (chronos.flags & FMOVESTOGO) movestogo = chronos.movestogo + 2;
 
    if ( chronos.time[sd.myside] < 0 ) chronos.time[sd.myside] = 0;
    if ( chronos.inc[sd.myside]  < 0 ) chronos.inc[sd.myside]  = 0;
 
    if ( chronos.flags & FTIME) sd.movetime += chronos.time[sd.myside] / movestogo;
    if ( chronos.flags & FINC ) sd.movetime += chronos.inc[sd.myside];
 
    if (sd.movetime > TIMEBUFFER) 
        sd.movetime -= TIMEBUFFER;
    else
        sd.movetime = -1;
 
    return;
 
}
 
bool time_stop_root() {
 
    if (time_over) return 1;
 
    /* in the root function we check at the beginning of every iteration, 
       whether we should start calculating another cycle.
    */
 
    /* first check for any new commands (e.g. the stop command, 
        which would set task to TASK_NOTHING)
    */
    com();
    if (task == TASK_NOTHING) return 1;
 
    /* in case we are supposed to search to a certain depth, nodes count, 
        fixed time or infinite, check whether we have finished the task.
    */
 
    if ( chronos.flags & FINFINITE ) return 0;
    if ( chronos.flags & FDEPTH    ) return (sd.depth > chronos.depth);
    if ( chronos.flags & FNODES    ) return (sd.nodes > chronos.nodes);
    if ( chronos.flags & FMOVETIME ) return ((int)(gettime() - sd.starttime) > sd.movetime);
 
    /* none of the other types of search-duration controls were triggered.
        This means we are given an ordinary timecontrol.
 
        Now we ask the question, whether it is worth to search another 
        ply, risk running out of time and having to abort  the search
        or if we should just stop the search now and save the time for
        another move.
 
        based on some tests in average positions (where the hash isn't full yet,
        there are not too many captures - resulting in a longer quiescence search)
        the time for searching a ply is about the duration of the search
        of the previous plies.
 
        So:
        timeused = (gettime() - sd.starttime);
        predictedtime = timeused;
        timeleft = movetime - timeused;
 
        if (predictedtime > timeleft) we stop the search now
 
 
        Simplifying the equations:
        (predictedtime > timeleft)
        ( timeused > (movetime - timeused) )
        ( (timeused * 2) > movetime )
 
    */
 
    return (((int)(gettime() - sd.starttime) * 2) > sd.movetime);
 
}
 
bool time_stop() {
 
    /* time_stop() function is similar to time_stop_root(), only that
        this function is not called every time we reach another ply,
        but every couple thousand nodes. This function is very time
        consuming, so calling it too often will slow down the search.
        Calling it to seldom results in a slower response to input 
        through the console and it might overlook the running out of 
        time in faster games.
    */
 
    if (sd.depth <= 1) return 0;
 
    /* the first few lines are the same as in time_stop_root().
        for more comments see that function
    */
 
    com();
    if (task == TASK_NOTHING) return 1;
 
    if (chronos.flags & FINFINITE) return 0;
    if (chronos.flags & FDEPTH   ) return (sd.depth > chronos.depth);
    if (chronos.flags & FNODES   ) return (sd.nodes > chronos.nodes);
    if (chronos.flags & FMOVETIME) return ((int)(gettime() - sd.starttime) > chronos.movetime );
 
    /* again we are not doing one of the easier to manage time controls
 
        other than the function before we are now already in the middle of
        a search. Actually if our prediction was right, we wouldn't have 
        entered this ply if we weren't able to finish it.
 
        so ( (gettime() - sd.starttime) < movetime ) should always be given.
 
        Anyway there are some situations where our prediction method fails.
        The problem is that should we return true here and stop the search
        a lot of information gathered gets useless, as the different lines
        searched are not verfied.
 
        if possible give in such cases a little overdraft and hope that
        the misprediction was only small
    */
 
    if ((int)(gettime() - sd.starttime) > sd.movetime) {
 
        int movestogo = MOVESTOGO;
        if ( chronos.flags & FMOVESTOGO ) movestogo = chronos.movestogo;
 
        if ( ( movestogo > 5 ) && 
             ( (int)(gettime() - sd.starttime) < (sd.movetime * 2) ) && 
             ( sd.movetime > 5000) ) {
            return 0;
        } else {
            return 1;
        }
 
    }
 
    return 0;
 
}
 
 
 
 

What links here?


Up one Level