#include "includes.h" #include "knightcap.h" #define GAME_MOVES 120 #define MORE_MOVES 15 #define SAFETY_TIME 5 #define MULT_HIGH 6 #define MULT_LOW 3 #define MULT_MAX 10 #define MIN_MOVE_TIME 0.1 #define LAG_TIME 0.1 extern struct state *state; extern int mulling; static float move_start_time, wallstart, cpustart; static float timer_limit; static time_t move_start_time_t; static enum {IDLE, STARTED, EXPIRED} timer_state; float timer_elapsed(void) { if (timer_state == IDLE) return 0; return gettime() - move_start_time; } float cpu_percent(void) { float cpu = cputime() - cpustart; float wall = walltime() - wallstart; return 100.0*(cpu/wall); } time_t timer_start_time(void) { return move_start_time_t; } void timer_start(int player) { timer_state = STARTED; wallstart = walltime(); cpustart = cputime(); move_start_time = gettime(); move_start_time_t = time(NULL); timer_limit = state->move_time; } int timer_extend(void) { float extension; timer_state = STARTED; extension = state->move_time/3; if (state->time_limit - (timer_elapsed()+SAFETY_TIME) < extension) extension = state->time_limit - (timer_elapsed()+SAFETY_TIME); if (extension <= 0) return 0; timer_limit += extension; return 1; } void timer_estimate(int secs, int opp_secs, int increment) { int n; float safety = SAFETY_TIME+increment; state->time_limit = secs; if (secs <= 0) { state->move_time = 0; return; } /* guess how long the game will be */ n = (GAME_MOVES - state->position.move_num); if (n < MORE_MOVES) n = MORE_MOVES; if (secs > 120) n /= (4+increment/3); else if (secs > 30) n /= (2+increment/3); state->move_time = increment + (secs-safety)/n - LAG_TIME; if (state->move_time < MIN_MOVE_TIME) state->move_time = MIN_MOVE_TIME; if (state->move_time > secs/2) state->move_time = secs/2; if (increment == 0 && secs < opp_secs) { state->move_time /= 2; if (secs < opp_secs/2) state->move_time /= 2; if (secs < opp_secs/4) state->move_time /= 2; } if (!state->ics_robot) lprintf(0,"move_time=%2.1f\n", state->move_time); } int timer_expired(void) { if (timer_state == IDLE) return 0; if (timer_state == STARTED) { if (timer_elapsed() > timer_limit) timer_state = EXPIRED; } return (timer_state == EXPIRED); } void timer_reset(void) { } void timer_off(void) { timer_state = IDLE; } int timer_terminate(int depth, int player, int force) { float elapsed = timer_elapsed(); float available = state->move_time; if (force) return 1; if (timer_state == IDLE) return 0; if (!mulling && elapsed < available * 0.7) return 0; if (mulling && elapsed < available) return 0; return 1; } float cputime(void) { struct rusage ru; getrusage(RUSAGE_SELF, &ru); return ru.ru_utime.tv_sec + 1.0e-6*ru.ru_utime.tv_usec; } float walltime(void) { static struct timeval tv0; struct timeval tv; static int initialised; if (!initialised) { initialised = 1; gettimeofday(&tv0, NULL); } gettimeofday(&tv, NULL); return (tv.tv_sec - tv0.tv_sec) + 1.0e-6*(tv.tv_usec - tv0.tv_usec); } float gettime(void) { #if WALL_CLOCK return walltime(); #else return cputime(); #endif }