home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 57
/
Amiga_Dream_57.iso
/
Amiga
/
Jeux
/
Reflexion
/
Crafty-15.19.lha
/
crafty-15.19
/
src
/
time.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-09-13
|
15KB
|
339 lines
#include <stdio.h>
#include <stdlib.h>
#include "chess.h"
#include "data.h"
/* last modified 09/27/96 */
/*
********************************************************************************
* *
* TimeAdjust() is called to adjust timing variables after each program move *
* is made. it simply increments the number of moves made, decrements the *
* amount of time used, and then makes any necessary adjustments based on the *
* time controls. *
* next search. *
* *
********************************************************************************
*/
void TimeAdjust(int time_used, PLAYER player)
{
/*
----------------------------------------------------------
| |
| decrement the number of moves remaining to the next |
| time control. then subtract the time the program took |
| to choose its move from the time remaining. |
| |
----------------------------------------------------------
*/
if (player == crafty) {
tc_moves_remaining--;
tc_time_remaining-=(tc_time_remaining > time_used) ?
time_used : tc_time_remaining;
if (!tc_moves_remaining) {
if (tc_sudden_death == 2) tc_sudden_death=1;
tc_moves_remaining+=tc_secondary_moves;
tc_time_remaining+=tc_secondary_time;
tc_time_remaining_opponent+=tc_secondary_time;
Print(4095,"time control reached\n");
}
if (tc_increment) tc_time_remaining+=tc_increment;
}
else {
tc_time_remaining_opponent-=(tc_time_remaining_opponent > time_used) ?
time_used : tc_time_remaining_opponent;
if (tc_increment) tc_time_remaining_opponent+=tc_increment;
}
}
/* last modified 06/15/98 */
/*
********************************************************************************
* *
* TimeCheck() is used to determine when the search should stop. it uses *
* several conditions to make this determination: (1) the search time has *
* exceeded the time per move limit; (2) the value at the root of the tree *
* has not dropped to low. (3) if the root move was flagged as "easy" and *
* no move has replaced it as best, the search can actually be stopped early *
* to save some time on the clock. if (2) is true, then the time is extended *
* based on how far the root value has dropped in an effort to avoid whatever *
* is being lost. *
* *
********************************************************************************
*/
int TimeCheck(int abort)
{
int time_used;
int value, last_value, searched;
int *i, ndone;
TREE *tree=local[0];
/*
----------------------------------------------------------
| |
| first, check to see if we are searching the first move |
| at this depth. if so, and we run out of time, we can |
| abort the search rather than waiting to complete this |
| ply=1 move to see if it's better. |
| |
----------------------------------------------------------
*/
if (tree->last[0]==(tree->last[1]-1) && !booking && !annotate_mode &&
!pondering && iteration_depth>4) return(1);
ndone=0;
for (i=tree->last[0];i<tree->last[1];i++)
if (tree->searched_this_root_move[i-tree->last[0]]) ndone++;
if (ndone == 1) abort=1;
if (iteration_depth <= 2) return(0);
/*
----------------------------------------------------------
| |
| now, check to see if we need to "burp" the time to |
| let the operator know the search is progressing and |
| how much time has been used so far. |
| |
----------------------------------------------------------
*/
time_used=(ReadClock(time_type)-start_time);
if (tree->nodes_searched>noise_level && (display_options&32) && time_used>burp) {
#if defined(SMP)
Lock(lock_io);
#endif
#if defined(MACOS)
printf(" %2i %s\n",iteration_depth,DisplayTime(time_used));
#else
printf(" %2i %s\r",iteration_depth,DisplayTime(time_used));
#endif
burp=(time_used/1500)*1500+1500;
fflush(stdout);
#if defined(SMP)
UnLock(lock_io);
#endif
}
if (pondering || analyze_mode) return(0);
if (time_used > absolute_time_limit) return(1);
if (easy_move && !search_time_limit) {
if (time_limit>100 && time_used<time_limit/3) return (0);
}
else if (time_used < time_limit) return(0);
if (search_time_limit) return(1);
/*
----------------------------------------------------------
| |
| ok. we have used "time_limit" at this point. now the |
| question is, can we stop the search? |
| |
| first, make sure that we have actually found a score |
| at the root of the tree. if not, we can safely stop |
| searching without wasting any more time. |
| |
----------------------------------------------------------
*/
if ((root_value == root_alpha) && !search_failed_low) {
searched=0;
for (i=tree->last[0];i<tree->last[1];i++)
if (tree->searched_this_root_move[i-tree->last[0]]) searched++;
if (searched == 1) return(1);
}
/*
----------------------------------------------------------
| |
| we have a score at the root of the tree, if the |
| evaluation is not significantly worse than the last |
| evaluation (from the previous iteration...) then we |
| safely stop the search. note also that if the current |
| evaluation is quite a bit worse, but we are still way |
| ahead, we can still avoid using extra time. |
| |
----------------------------------------------------------
*/
value=root_value;
last_value=last_search_value;
if ((value>=last_value-33 && !search_failed_low) ||
(value>350 && value >= last_value-67)) {
if (time_used > time_limit*2) return(1);
else return(abort);
}
/*
----------------------------------------------------------
| |
| we are in trouble at the root. depending on how much |
| the score has dropped, increase the search time limit |
| to try and correct the problem. for a positional drop |
| we can double the search time (this is for a serious |
| drop, of course). |
| |
----------------------------------------------------------
*/
if (time_used < time_limit*2.5 && time_used+500<tc_time_remaining) return(0);
if ((value >= last_value-67 && !search_failed_low) ||
value>550) return(abort);
/*
----------------------------------------------------------
| |
| we are in really serious trouble at the root, losing |
| material. increase the time limit to 6X the original |
| target, as losing material is tantamount to losing the |
| game anyway. |
| |
----------------------------------------------------------
*/
if (time_used < time_limit*6 && time_used+500<tc_time_remaining) return(0);
return(1);
}
/* last modified 10/17/97 */
/*
********************************************************************************
* *
* TimeSet() is called to set the two variables "time_limit" and *
* "absolute_time_limit" which controls the amount of time taken by the *
* iterated search. it simply takes the timing controls as set by the user *
* and uses these values to calculate how much time should be spent on the *
* next search. *
* *
********************************************************************************
*/
void TimeSet(int search_type)
{
float behind[6] = {32.0, 16.0, 8.0, 4.0, 2.0, 1.5};
int reduce[6] = {96, 48, 24, 12, 6, 3};
int i;
int surplus, average;
int simple_average;
surplus=0;
average=0;
/*
----------------------------------------------------------
| |
| check to see if we are in a sudden-death type of time |
| control. if so, we have a fixed amount of time |
| remaining. set the search time accordingly and exit. |
| |
----------------------------------------------------------
*/
if (tc_sudden_death == 1) {
if (tc_increment) {
time_limit=(tc_time_remaining-tc_operator_time*tc_moves_remaining)/30+
tc_increment;
if (tc_time_remaining < 3000) time_limit=tc_increment;
if (tc_time_remaining < 1500) time_limit=tc_increment/2;
absolute_time_limit=tc_time_remaining/2;
}
else {
time_limit=tc_time_remaining/35;
absolute_time_limit=Min(time_limit*6,tc_time_remaining/2);
}
}
/*
----------------------------------------------------------
| |
| we are not in a sudden_death situation. we now have |
| two choices: if the program has saved enough time to |
| meet the surplus requirement, then we simply divide |
| the time left evenly among the moves left. if we |
| haven't yet saved up a cushion so that "fail-lows" |
| have extra time to find a solution, we simply take the |
| number of moves divided into the total time less the |
| necessary operator time as the target. |
| |
----------------------------------------------------------
*/
else {
if (move_number <= tc_moves)
simple_average=(tc_time-(tc_operator_time*tc_moves_remaining))/tc_moves;
else
simple_average=(tc_secondary_time-(tc_operator_time*tc_moves_remaining))/
tc_secondary_moves;
surplus=Max(tc_time_remaining-(tc_operator_time*tc_moves_remaining)-
simple_average*tc_moves_remaining,0);
average=(tc_time_remaining-(tc_operator_time*tc_moves_remaining)+
tc_moves_remaining*tc_increment)
/tc_moves_remaining;
if (surplus < tc_safety_margin)
time_limit = (average<simple_average) ? average : simple_average;
else
time_limit=(average<2.0*simple_average) ? average : 2.0*simple_average;
}
if (surplus < 0) surplus=0;
if (tc_increment>200 && moves_out_of_book<2) time_limit*=1.2;
if (time_limit <= 0) time_limit=5;
absolute_time_limit=time_limit+surplus/2+((tc_time_remaining-
tc_operator_time*tc_moves_remaining)/4);
if (absolute_time_limit > 6*time_limit) absolute_time_limit=6*time_limit;
if (absolute_time_limit > tc_time_remaining/2)
absolute_time_limit=tc_time_remaining/2;
/*
new option 'usage' increases and decrease the time factors)
*/
if (usage_level) time_limit*=1.0+usage_level/100.0;
/*
----------------------------------------------------------
| |
| this code is used to handle the case where someone is |
| trying to "blitz" crafty by reaching a position where |
| things are locked up, and then just shuffling pieces |
| back and forth. when crafty reaches the point where it |
| has less than 3/4 of the time the opponent has, it |
| starts decreasing the target time. at 1/2, it |
| decreases it further. |
| |
----------------------------------------------------------
*/
if (mode!=tournament_mode && !tc_increment) {
for (i=0;i<6;i++) {
if ((float)tc_time_remaining*behind[i] <
(float)tc_time_remaining_opponent) {
time_limit=time_limit/reduce[i];
Print(128,"crafty is behind %4.1f on time, reducing by 1/%d.\n",
behind[i],reduce[i]);
break;
}
}
if (tc_increment==0 && tc_time_remaining_opponent>tc_time_remaining) {
if (tc_time_remaining < 3000) time_limit/=2;
if (tc_time_remaining < 2000) time_limit/=2;
if (tc_time_remaining < 1000) time_limit=1;
}
}
/*
----------------------------------------------------------
| |
| if the operator has set an absolute search time limit |
| already, then we simply copy this value and return. |
| |
----------------------------------------------------------
*/
if (search_time_limit) {
time_limit=search_time_limit;
absolute_time_limit=time_limit;
}
if (search_type==puzzle || booking) {
time_limit/=10;
absolute_time_limit=time_limit*3;
}
if (!tc_sudden_death && !search_time_limit && time_limit>3*tc_time/tc_moves)
time_limit=3*tc_time/tc_moves;
if (search_type != puzzle) {
if (!tc_sudden_death)
Print(128," time surplus %s ",DisplayTime(surplus));
else
Print(128," ");
Print(128,"time limit %s", DisplayTimeWhisper(time_limit));
Print(128," (%s)", DisplayTimeWhisper(absolute_time_limit));
if (usage_level != 0.0) {
Print(128,"/");
Print(128,"(%d)",usage_level);
}
if (easy_move) Print(128," [easy move]");
Print(128,"\n");
}
if (time_limit <= 1) {
time_limit= 1;
usage_level=0;
}
}