7b4db9468d0c29abe121b1edd126a4e56d89d411
[gnushogi.git] / src / tcontrl.c
1 /*
2  * tcontrl.c - C source for GNU SHOGI
3  *
4  * Copyright (c) 1993, 1994, 1995 Matthias Mutz
5  *
6  * GNU SHOGI is based on GNU CHESS
7  *
8  * Copyright (c) 1988,1989,1990 John Stanback
9  * Copyright (c) 1992 Free Software Foundation
10  *
11  * This file is part of GNU SHOGI.
12  *
13  * GNU Shogi is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 1, or (at your option)
16  * any later version.
17  *
18  * GNU Shogi is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with GNU Shogi; see the file COPYING.  If not, write to
25  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26  */
27  
28 #include "gnushogi.h" 
29
30 #ifdef DEBUG
31 #include <assert.h>
32 #else
33 #include <assert.h>
34 #endif
35
36 #define ALTERNATIVE_TC
37
38 #if !defined OLDTIME && defined HASGETTIMEOFDAY
39 double pow();
40 #endif
41
42
43 /*
44  * In a networked enviroment gnuchess might be compiled on different hosts
45  * with different random number generators, that is not acceptable if they
46  * are going to share the same transposition table.
47  */
48
49 static unsigned long int next = 1;
50
51 unsigned int
52 urand (void)
53 {
54   next *= 1103515245;
55   next += 12345;
56   return ((unsigned int) (next >> 16) & 0xFFFF);
57 }
58
59 void
60 gsrand (unsigned int seed)
61 {
62   next = seed;
63 }
64
65
66
67 void
68 TimeCalc ()
69 {
70 /* adjust number of moves remaining in gamein games */
71   int increment = 0;
72   int topsum = 0;
73   int tcompsum = 0;
74   int me,him;
75   int i;
76 /* dont do anything til you have enough numbers */
77   if (GameCnt < (MINGAMEIN * 2)) return;
78 /* calculate average time in sec for last MINGAMEIN moves */
79   for (i = 0; i < MINGAMEIN; i++)
80     {
81       tcompsum += timecomp[i];
82       topsum += timeopp[i];
83     }
84   topsum /= (100 * MINGAMEIN);
85   tcompsum /= (100 * MINGAMEIN);
86 /* if I have less time than opponent add another move */
87         me = TimeControl.clock[computer]/100; 
88         him = TimeControl.clock[opponent]/100;
89         if(me < him) increment += 2;
90         if((him - me) > 60 || (me<him && me < 120))increment++;
91 /* if I am losing more time with each move add another */
92   /*if ( !((me - him) > 60) && tcompsum > topsum) increment++;*/
93   if ( tcompsum > topsum) increment +=2;
94 /* but dont let moves go below MINMOVES */
95   else if (TimeControl.moves[computer] < MINMOVES && !increment) increment++;
96 /* if I am doing really well use more time per move */
97   else if (me > him && tcompsum < topsum) increment = -1;
98 /* if not fischer clock be careful about time */
99   if(TCadd == 0 && increment >0)increment += 2;
100   if(me == 0 && increment >0)increment += 2;
101   TimeControl.moves[computer] += increment;
102 }
103
104
105
106
107 /*
108  * Set ResponseTime, TCcount, and TCleft.
109  */
110  
111 void SetResponseTime (short int side)
112 {
113
114 #ifdef ALTERNATIVE_TC
115
116       int DetermineTCcount = true;
117
118       if (TCflag)
119         {
120           TCcount = 0;
121           if (TimeControl.moves[side] < 1)
122             TimeControl.moves[side] = 1;
123           /* special case time per move specified */
124           if (flag.onemove)
125             { 
126               ResponseTime = TimeControl.clock[side] - 100;
127               TCleft = 0;
128             }
129           else
130             {
131               /* calculate avg time per move remaining */
132               if ( TimeControl.clock[side] <= 0 )
133                 {
134                   ResponseTime = 0;
135                   TCleft = (long)MINRESPONSETIME / MAXTCCOUNTX;
136                 }
137               else
138                 {
139 #ifdef DEBUG
140                   char buffer[80];
141 #endif
142                   short rtf = in_opening_stage ? 8 : 2; 
143                   short tcq = in_opening_stage ? 2 : 4;
144                   TimeControl.clock[side] += TCadd;
145                   ResponseTime = 
146                       (TimeControl.clock[side]) /
147                       (((TimeControl.moves[side]) * rtf) + 1);
148                   TCleft = (long)ResponseTime / tcq; 
149                   ResponseTime += TCadd/2;
150 #ifdef DEBUG
151                   sprintf(buffer,"rtf=%d tcq=%d rt=%ld tl=%ld",
152                                 rtf,tcq,ResponseTime,TCleft);
153                   ShowMessage(buffer);
154 #endif
155                 }
156               if (TimeControl.moves[side] < 5)
157                 {
158                   TCcount = MAXTCCOUNTX - 10;
159                   if ( TCcount < 0 ) TCcount = 0;
160                   DetermineTCcount = false;
161                 }    
162             }
163           if (ResponseTime < MINRESPONSETIME)
164             {
165               ResponseTime = MINRESPONSETIME;   
166               TCcount = MAXTCCOUNTX - 10;
167               if ( TCcount < 0 ) TCcount = 0;
168               DetermineTCcount = false;
169             }
170 #ifndef HARDTIMELIMIT
171           else if (ResponseTime < 2*MINRESPONSETIME)
172             {
173               TCcount = MAXTCCOUNTX - 10;
174               if ( TCcount < 0 ) TCcount = 0;
175               DetermineTCcount = false;
176             }
177 #endif
178         }
179       else
180         { 
181           TCleft = 0;
182           ResponseTime = MaxResponseTime;
183           ElapsedTime(COMPUTE_AND_INIT_MODE);
184         }
185                   
186       if ( DetermineTCcount )
187         if ( TCleft  )
188           {
189             int AllowedCounts = ((int)((TimeControl.clock[side] - ResponseTime)) / 2) / TCleft;
190             
191             if ( AllowedCounts <= 0 )
192               TCcount = MAXTCCOUNTX; 
193             else if (AllowedCounts > MAXTCCOUNTX)
194               TCcount = 0;
195             else
196               TCcount = MAXTCCOUNTX - AllowedCounts;
197           }
198         else
199           {
200             TCcount = MAXTCCOUNTX;
201           }
202
203       if ( ResponseTime < MINRESPONSETIME )
204         ResponseTime = MINRESPONSETIME; 
205
206 #else
207
208       if (TCflag)
209         {
210           TCcount = 0;
211           if (TimeControl.moves[side] < 1)
212             TimeControl.moves[side] = 1;
213           /* special case time per move specified */
214           if (flag.onemove)
215             {
216               ResponseTime = TimeControl.clock[side] - 100;
217               TCleft = 0;
218             }
219           else
220             {
221               /* calculate avg time per move remaining */
222               TimeControl.clock[side] += TCadd;
223
224               ResponseTime = (TimeControl.clock[side]) / (((TimeControl.moves[side]) * 2) + 1);
225               TCleft = (int) ResponseTime / 3;
226               ResponseTime += TCadd / 2;
227               if (TimeControl.moves[side] < 5)
228                 TCcount = MAXTCCOUNTX - 10;
229             }
230           if (ResponseTime < 101)
231             {
232               ResponseTime = 100;
233               TCcount = MAXTCCOUNTX - 10;
234             }
235           else if (ResponseTime < 200)
236             {
237               TCcount = MAXTCCOUNTX - 10;
238             }
239         }
240       else
241         {
242           ResponseTime = MaxResponseTime;
243           TCleft = 0;
244           ElapsedTime (COMPUTE_AND_INIT_MODE);
245         }
246       if (TCleft)
247         {
248           TCcount = ((int) ((TimeControl.clock[side] - ResponseTime)) / 2) / TCleft;
249           if (TCcount > MAXTCCOUNTX)
250             TCcount = 0;
251           else
252             TCcount = MAXTCCOUNTX - TCcount;
253         }
254       else
255         TCcount = MAXTCCOUNTX;
256
257 #endif
258
259       assert(TCcount <= MAXTCCOUNTX);
260
261 }
262
263
264 void CheckForTimeout (int score, int globalscore, int Jscore, int zwndw)
265 {
266       if (flag.musttimeout || Sdepth >= MaxSearchDepth)
267         flag.timeout = true;
268
269       else if (TCflag && (Sdepth > (MINDEPTH - 1)) && (TCcount < MAXTCCOUNTR))
270         {
271           if (killr0[1] != PrVar[1] /* || Killr0[2] != PrVar[2] */ )
272             {
273               TCcount++;
274               ExtraTime += TCleft;
275             }
276           if (TCcount < MAXTCCOUNTR && (abs (score - globalscore) / Sdepth) > ZDELTA)
277             {
278               TCcount++;
279               ExtraTime += TCleft;
280             }
281         }
282       if (score > (Jscore - zwndw) && score > (Tree[1].score + 250))
283          ExtraTime = 0;
284       ElapsedTime(COMPUTE_MODE);
285       if (root->flags & exact)
286         flag.timeout = true;
287       /*else if (Tree[1].score < -SCORE_LIMIT) flag.timeout = true;*/
288 #if defined OLDTIME || !defined HASGETTIMEOFDAY
289       else if (!(Sdepth < MINDEPTH) && TCflag && ((4 * et) > (2*ResponseTime + ExtraTime)))
290                          flag.timeout = true;
291 #else
292       else if (!(Sdepth < MINDEPTH) && TCflag &&
293                 ((int)(1.93913099l * (pow((double)et,1.12446928l))) > (ResponseTime + ExtraTime)))
294                          flag.timeout = true;
295 #endif
296 #if !defined BAREBONES
297         if ( flag.timeout )
298           ShowMessage("timeout");
299 #endif
300 }
301
302