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 >
C/C++ Source or Header  |  1998-09-13  |  15KB  |  339 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "chess.h"
  4. #include "data.h"
  5.  
  6. /* last modified 09/27/96 */
  7. /*
  8. ********************************************************************************
  9. *                                                                              *
  10. *   TimeAdjust() is called to adjust timing variables after each program move  *
  11. *   is made.  it simply increments the number of moves made, decrements the    *
  12. *   amount of time used, and then makes any necessary adjustments based on the *
  13. *   time controls.                                                             *
  14. *   next search.                                                               *
  15. *                                                                              *
  16. ********************************************************************************
  17. */
  18. void TimeAdjust(int time_used, PLAYER player)
  19. {
  20. /*
  21.  ----------------------------------------------------------
  22. |                                                          |
  23. |   decrement the number of moves remaining to the next    |
  24. |   time control.  then subtract the time the program took |
  25. |   to choose its move from the time remaining.            |
  26. |                                                          |
  27.  ----------------------------------------------------------
  28. */
  29.   
  30.   if (player == crafty) {
  31.     tc_moves_remaining--;
  32.     tc_time_remaining-=(tc_time_remaining > time_used) ? 
  33.                        time_used : tc_time_remaining;
  34.     if (!tc_moves_remaining) {
  35.       if (tc_sudden_death == 2) tc_sudden_death=1;
  36.       tc_moves_remaining+=tc_secondary_moves;
  37.       tc_time_remaining+=tc_secondary_time;
  38.       tc_time_remaining_opponent+=tc_secondary_time;
  39.       Print(4095,"time control reached\n");
  40.     }
  41.     if (tc_increment) tc_time_remaining+=tc_increment;
  42.   }
  43.   else {
  44.     tc_time_remaining_opponent-=(tc_time_remaining_opponent > time_used) ? 
  45.                                 time_used : tc_time_remaining_opponent;
  46.     if (tc_increment) tc_time_remaining_opponent+=tc_increment;
  47.   }
  48. }
  49.  
  50. /* last modified 06/15/98 */
  51. /*
  52. ********************************************************************************
  53. *                                                                              *
  54. *   TimeCheck() is used to determine when the search should stop.  it uses     *
  55. *   several conditions to make this determination:  (1) the search time has    *
  56. *   exceeded the time per move limit;  (2) the value at the root of the tree   *
  57. *   has not dropped to low.  (3) if the root move was flagged as "easy" and    *
  58. *   no move has replaced it as best, the search can actually be stopped early  *
  59. *   to save some time on the clock.  if (2) is true, then the time is extended *
  60. *   based on how far the root value has dropped in an effort to avoid whatever *
  61. *   is being lost.                                                             *
  62. *                                                                              *
  63. ********************************************************************************
  64. */
  65. int TimeCheck(int abort)
  66. {
  67.   int time_used;
  68.   int value, last_value, searched;
  69.   int *i, ndone;
  70.   TREE *tree=local[0];
  71. /*
  72.  ----------------------------------------------------------
  73. |                                                          |
  74. |   first, check to see if we are searching the first move |
  75. |   at this depth.  if so, and we run out of time, we can  |
  76. |   abort the search rather than waiting to complete this  |
  77. |   ply=1 move to see if it's better.                      |
  78. |                                                          |
  79.  ----------------------------------------------------------
  80. */
  81.   if (tree->last[0]==(tree->last[1]-1) && !booking && !annotate_mode &&
  82.       !pondering && iteration_depth>4) return(1);
  83.   ndone=0;
  84.   for (i=tree->last[0];i<tree->last[1];i++)
  85.     if (tree->searched_this_root_move[i-tree->last[0]]) ndone++;
  86.   if (ndone == 1) abort=1;
  87.   if (iteration_depth <= 2) return(0);
  88. /*
  89.  ----------------------------------------------------------
  90. |                                                          |
  91. |   now, check to see if we need to "burp" the time to     |
  92. |   let the operator know the search is progressing and    |
  93. |   how much time has been used so far.                    |
  94. |                                                          |
  95.  ----------------------------------------------------------
  96. */
  97.   time_used=(ReadClock(time_type)-start_time);
  98.   if (tree->nodes_searched>noise_level && (display_options&32) && time_used>burp) {
  99. #if defined(SMP)
  100.     Lock(lock_io);
  101. #endif
  102. #if defined(MACOS)
  103.     printf("               %2i   %s\n",iteration_depth,DisplayTime(time_used));
  104. #else
  105.     printf("               %2i   %s\r",iteration_depth,DisplayTime(time_used));
  106. #endif
  107.     burp=(time_used/1500)*1500+1500;
  108.     fflush(stdout);
  109. #if defined(SMP)
  110.     UnLock(lock_io);
  111. #endif
  112.   }
  113.   if (pondering || analyze_mode) return(0);
  114.   if (time_used > absolute_time_limit) return(1);
  115.   if (easy_move && !search_time_limit) {
  116.     if (time_limit>100 && time_used<time_limit/3) return (0);
  117.   }
  118.   else if (time_used < time_limit) return(0);
  119.   if (search_time_limit) return(1);
  120. /*
  121.  ----------------------------------------------------------
  122. |                                                          |
  123. |   ok.  we have used "time_limit" at this point.  now the |
  124. |   question is, can we stop the search?                   |
  125. |                                                          |
  126. |   first, make sure that we have actually found a score   |
  127. |   at the root of the tree.  if not, we can safely stop   |
  128. |   searching without wasting any more time.               |
  129. |                                                          |
  130.  ----------------------------------------------------------
  131. */
  132.   if ((root_value == root_alpha) && !search_failed_low) {
  133.     searched=0;
  134.     for (i=tree->last[0];i<tree->last[1];i++)
  135.       if (tree->searched_this_root_move[i-tree->last[0]]) searched++;
  136.     if (searched == 1) return(1);
  137.   }
  138. /*
  139.  ----------------------------------------------------------
  140. |                                                          |
  141. |   we have a score at the root of the tree, if the        |
  142. |   evaluation is not significantly worse than the last    |
  143. |   evaluation (from the previous iteration...) then we    |
  144. |   safely stop the search.  note also that if the current |
  145. |   evaluation is quite a bit worse, but we are still way  |
  146. |   ahead, we can still avoid using extra time.            |
  147. |                                                          |
  148.  ----------------------------------------------------------
  149. */
  150.   value=root_value;
  151.   last_value=last_search_value;
  152.   if ((value>=last_value-33 && !search_failed_low) ||
  153.       (value>350 && value >= last_value-67)) {
  154.     if (time_used > time_limit*2) return(1);
  155.     else return(abort);
  156.   }
  157. /*
  158.  ----------------------------------------------------------
  159. |                                                          |
  160. |   we are in trouble at the root.  depending on how much  |
  161. |   the score has dropped, increase the search time limit  |
  162. |   to try and correct the problem.  for a positional drop |
  163. |   we can double the search time (this is for a serious   |
  164. |   drop, of course).                                      |
  165. |                                                          |
  166.  ----------------------------------------------------------
  167. */
  168.   if (time_used < time_limit*2.5 && time_used+500<tc_time_remaining) return(0);
  169.   if ((value >= last_value-67 && !search_failed_low) ||
  170.       value>550) return(abort);
  171. /*
  172.  ----------------------------------------------------------
  173. |                                                          |
  174. |   we are in really serious trouble at the root, losing   |
  175. |   material.  increase the time limit to 6X the original  |
  176. |   target, as losing material is tantamount to losing the |
  177. |   game anyway.                                           |
  178. |                                                          |
  179.  ----------------------------------------------------------
  180. */
  181.   if (time_used < time_limit*6 && time_used+500<tc_time_remaining) return(0);
  182.   return(1);
  183. }
  184.  
  185. /* last modified 10/17/97 */
  186. /*
  187. ********************************************************************************
  188. *                                                                              *
  189. *   TimeSet() is called to set the two variables "time_limit" and              *
  190. *   "absolute_time_limit" which controls the amount of time taken by the       *
  191. *   iterated search.  it simply takes the timing controls as set by the user   *
  192. *   and uses these values to calculate how much time should be spent on the    *
  193. *   next search.                                                               *
  194. *                                                                              *
  195. ********************************************************************************
  196. */
  197. void TimeSet(int search_type)
  198. {
  199.   float behind[6] = {32.0, 16.0, 8.0, 4.0, 2.0, 1.5};
  200.   int reduce[6] = {96, 48, 24, 12, 6, 3};
  201.   int i;
  202.   int surplus, average;
  203.   int simple_average;
  204.  
  205.   surplus=0;
  206.   average=0;
  207. /*
  208.  ----------------------------------------------------------
  209. |                                                          |
  210. |   check to see if we are in a sudden-death type of time  |
  211. |   control.  if so, we have a fixed amount of time        |
  212. |   remaining.  set the search time accordingly and exit.  |
  213. |                                                          |
  214.  ----------------------------------------------------------
  215. */
  216.   if (tc_sudden_death == 1) {
  217.     if (tc_increment) {
  218.       time_limit=(tc_time_remaining-tc_operator_time*tc_moves_remaining)/30+
  219.                  tc_increment;
  220.       if (tc_time_remaining < 3000) time_limit=tc_increment;
  221.       if (tc_time_remaining < 1500) time_limit=tc_increment/2;
  222.       absolute_time_limit=tc_time_remaining/2;
  223.     }
  224.     else {
  225.       time_limit=tc_time_remaining/35;
  226.       absolute_time_limit=Min(time_limit*6,tc_time_remaining/2);
  227.     }
  228.   }
  229. /*
  230.  ----------------------------------------------------------
  231. |                                                          |
  232. |   we are not in a sudden_death situation.  we now have   |
  233. |   two choices:  if the program has saved enough time to  |
  234. |   meet the surplus requirement, then we simply divide    |
  235. |   the time left evenly among the moves left.  if we      |
  236. |   haven't yet saved up a cushion so that "fail-lows"     |
  237. |   have extra time to find a solution, we simply take the |
  238. |   number of moves divided into the total time less the   |
  239. |   necessary operator time as the target.                 |
  240. |                                                          |
  241.  ----------------------------------------------------------
  242. */
  243.   else {
  244.     if (move_number <= tc_moves)
  245.       simple_average=(tc_time-(tc_operator_time*tc_moves_remaining))/tc_moves;
  246.     else
  247.       simple_average=(tc_secondary_time-(tc_operator_time*tc_moves_remaining))/
  248.                      tc_secondary_moves;
  249.     surplus=Max(tc_time_remaining-(tc_operator_time*tc_moves_remaining)-
  250.                  simple_average*tc_moves_remaining,0);
  251.     average=(tc_time_remaining-(tc_operator_time*tc_moves_remaining)+
  252.             tc_moves_remaining*tc_increment)
  253.             /tc_moves_remaining;
  254.     if (surplus < tc_safety_margin) 
  255.       time_limit = (average<simple_average) ? average : simple_average;
  256.     else
  257.       time_limit=(average<2.0*simple_average) ? average : 2.0*simple_average;
  258.   }
  259.   if (surplus < 0) surplus=0;
  260.   if (tc_increment>200 && moves_out_of_book<2) time_limit*=1.2;
  261.   if (time_limit <= 0) time_limit=5;
  262.   absolute_time_limit=time_limit+surplus/2+((tc_time_remaining-
  263.                       tc_operator_time*tc_moves_remaining)/4);
  264.   if (absolute_time_limit > 6*time_limit) absolute_time_limit=6*time_limit;
  265.   if (absolute_time_limit > tc_time_remaining/2)
  266.     absolute_time_limit=tc_time_remaining/2;
  267. /*
  268.    new option 'usage' increases and decrease the time factors)
  269. */
  270.   if (usage_level)  time_limit*=1.0+usage_level/100.0;
  271. /*
  272.  ----------------------------------------------------------
  273. |                                                          |
  274. |  this code is used to handle the case where someone is   |
  275. |  trying to "blitz" crafty by reaching a position where   |
  276. |  things are locked up, and then just shuffling pieces    |
  277. |  back and forth.  when crafty reaches the point where it |
  278. |  has less than 3/4 of the time the opponent has, it      |
  279. |  starts decreasing the target time.  at 1/2, it          |
  280. |  decreases it further.                                   |
  281. |                                                          |
  282.  ----------------------------------------------------------
  283. */
  284.   if (mode!=tournament_mode && !tc_increment) {
  285.     for (i=0;i<6;i++) {
  286.       if ((float)tc_time_remaining*behind[i] <
  287.           (float)tc_time_remaining_opponent) {
  288.         time_limit=time_limit/reduce[i];
  289.         Print(128,"crafty is behind %4.1f on time, reducing by 1/%d.\n",
  290.                behind[i],reduce[i]);
  291.         break;
  292.       }
  293.     }
  294.     if (tc_increment==0 && tc_time_remaining_opponent>tc_time_remaining) {
  295.       if (tc_time_remaining < 3000) time_limit/=2;
  296.       if (tc_time_remaining < 2000) time_limit/=2;
  297.       if (tc_time_remaining < 1000) time_limit=1;
  298.     }
  299.   }
  300. /*
  301.  ----------------------------------------------------------
  302. |                                                          |
  303. |   if the operator has set an absolute search time limit  |
  304. |   already, then we simply copy this value and return.    |
  305. |                                                          |
  306.  ----------------------------------------------------------
  307. */
  308.   if (search_time_limit) {
  309.     time_limit=search_time_limit;
  310.     absolute_time_limit=time_limit;
  311.   }
  312.   if (search_type==puzzle || booking) {
  313.     time_limit/=10;
  314.     absolute_time_limit=time_limit*3;
  315.   }
  316.  
  317.   if (!tc_sudden_death && !search_time_limit && time_limit>3*tc_time/tc_moves)
  318.     time_limit=3*tc_time/tc_moves;
  319.   if (search_type != puzzle) {
  320.     if (!tc_sudden_death)
  321.       Print(128,"              time surplus %s  ",DisplayTime(surplus));
  322.     else
  323.       Print(128,"              ");
  324.     Print(128,"time limit %s", DisplayTimeWhisper(time_limit));
  325.     Print(128," (%s)", DisplayTimeWhisper(absolute_time_limit));
  326.     if (usage_level != 0.0) {
  327.       Print(128,"/");
  328.       Print(128,"(%d)",usage_level);
  329.     }
  330.     if (easy_move) Print(128," [easy move]");
  331.     Print(128,"\n");
  332.   }
  333.   if (time_limit <= 1) {
  334.     time_limit= 1;
  335.     usage_level=0;
  336.   }
  337.  
  338. }
  339.