Changing license to GPL3 (and bumping version to 1.4.0).
[gnushogi.git] / gnushogi / tcontrl.c
blob9142d20950f03587c4357d869cea863f160811fa
1 /*
2 * FILE: tcontrl.c
4 * ----------------------------------------------------------------------
6 * Copyright (c) 2012 Free Software Foundation
8 * GNU SHOGI is based on GNU CHESS
10 * This file is part of GNU SHOGI.
12 * GNU Shogi is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 3 of the License,
15 * or (at your option) any later version.
17 * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with GNU Shogi; see the file COPYING. If not, see
24 * <http://www.gnu.org/licenses/>.
25 * ----------------------------------------------------------------------
30 #include "gnushogi.h"
31 #include <math.h>
33 #define ALTERNATIVE_TC
37 * In a networked enviroment gnushogi might be compiled on different hosts
38 * with different random number generators; that is not acceptable if they
39 * are going to share the same transposition table.
42 static unsigned long next = 1;
44 unsigned int
45 urand(void)
47 next *= 1103515245;
48 next += 12345;
49 return ((unsigned int) (next >> 16) & 0xFFFF);
54 void
55 gsrand(unsigned int seed)
57 next = seed;
62 void
63 TimeCalc()
65 /* adjust number of moves remaining in gamein games */
66 int increment = 0;
67 int topsum = 0;
68 int tcompsum = 0;
69 int me, him;
70 int i;
72 /* Don't do anything until you have enough numbers. */
73 if (GameCnt < (MINGAMEIN * 2))
74 return;
76 /* Calculate average time in sec for last MINGAMEIN moves. */
77 for (i = 0; i < MINGAMEIN; i++)
79 tcompsum += timecomp[i];
80 topsum += timeopp[i];
83 topsum /= (100 * MINGAMEIN);
84 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;
90 if (me < him)
91 increment += 2;
93 if (((him - me) > 60) || ((me < him) && (me < 120)))
94 increment++;
96 /* If I am losing more time with each move add another. */
97 /* If (!((me - him) > 60) && tcompsum > topsum) increment++; */
99 if (tcompsum > topsum)
101 increment += 2;
103 else if ((TimeControl.moves[computer] < MINMOVES) && !increment)
105 /* ... but don't let moves go below MINMOVES. */
106 increment++;
108 else if ((me > him) && (tcompsum < topsum))
110 /* If I am doing really well use more time per move. */
111 increment = -1;
114 /* If not fischer clock be careful about time. */
115 /* CHECKME: what's a fischer clock? */
117 if ((TCadd == 0) && (increment > 0))
118 increment += 2;
120 if ((me == 0) && (increment > 0))
121 increment += 2;
123 TimeControl.moves[computer] += increment;
129 * Set ResponseTime, TCcount, and TCleft.
132 void SetResponseTime(short side)
134 #ifdef ALTERNATIVE_TC
135 int DetermineTCcount = true;
137 if (TCflag)
139 TCcount = 0;
141 if (TimeControl.moves[side] < 1)
142 TimeControl.moves[side] = 1;
144 /* special case time per move specified */
145 if (flag.onemove)
147 ResponseTime = TimeControl.clock[side] - 100;
148 TCleft = 0;
150 else
152 /* calculate avg time per move remaining */
153 if (TimeControl.clock[side] <= 0)
155 ResponseTime = 0;
156 TCleft = (long)MINRESPONSETIME / MAXTCCOUNTX;
158 else
160 short rtf = in_opening_stage ? 8 : 2;
161 short tcq = in_opening_stage ? 2 : 4;
163 TimeControl.clock[side] += TCadd;
164 ResponseTime = (TimeControl.clock[side])
165 / (((TimeControl.moves[side]) * rtf) + 1);
166 TCleft = (long)ResponseTime / tcq;
167 ResponseTime += TCadd / 2;
170 if (TimeControl.moves[side] < 5)
172 TCcount = MAXTCCOUNTX - 10;
174 if (TCcount < 0)
175 TCcount = 0;
177 DetermineTCcount = false;
181 if (ResponseTime < MINRESPONSETIME)
183 ResponseTime = MINRESPONSETIME;
184 TCcount = MAXTCCOUNTX - 10;
186 if (TCcount < 0)
187 TCcount = 0;
189 DetermineTCcount = false;
192 if (!hard_time_limit && (ResponseTime < 2 * MINRESPONSETIME))
194 TCcount = MAXTCCOUNTX - 10;
196 if (TCcount < 0)
197 TCcount = 0;
199 DetermineTCcount = false;
202 else
204 TCleft = 0;
205 ResponseTime = MaxResponseTime;
206 ElapsedTime(COMPUTE_AND_INIT_MODE);
209 if (DetermineTCcount)
211 if (TCleft )
213 int AllowedCounts
214 = ((int)((TimeControl.clock[side] - ResponseTime)) / 2)
215 / TCleft;
217 if (AllowedCounts <= 0)
218 TCcount = MAXTCCOUNTX;
219 else if (AllowedCounts > MAXTCCOUNTX)
220 TCcount = 0;
221 else
222 TCcount = MAXTCCOUNTX - AllowedCounts;
224 else
226 TCcount = MAXTCCOUNTX;
230 if (ResponseTime < MINRESPONSETIME)
231 ResponseTime = MINRESPONSETIME;
233 #else
235 if (TCflag)
237 TCcount = 0;
239 if (TimeControl.moves[side] < 1)
240 TimeControl.moves[side] = 1;
242 /* special case time per move specified */
243 if (flag.onemove)
245 ResponseTime = TimeControl.clock[side] - 100;
246 TCleft = 0;
248 else
250 /* calculate avg time per move remaining */
251 TimeControl.clock[side] += TCadd;
253 ResponseTime = (TimeControl.clock[side])
254 / (((TimeControl.moves[side]) * 2) + 1);
255 TCleft = (int) ResponseTime / 3;
256 ResponseTime += TCadd / 2;
258 if (TimeControl.moves[side] < 5)
259 TCcount = MAXTCCOUNTX - 10;
262 if (ResponseTime < 101)
264 ResponseTime = 100;
265 TCcount = MAXTCCOUNTX - 10;
267 else if (ResponseTime < 200)
269 TCcount = MAXTCCOUNTX - 10;
272 else
274 ResponseTime = MaxResponseTime;
275 TCleft = 0;
276 ElapsedTime(COMPUTE_AND_INIT_MODE);
279 if (TCleft)
281 TCcount = ((int)((TimeControl.clock[side] - ResponseTime)) / 2)
282 / TCleft;
284 if (TCcount > MAXTCCOUNTX)
285 TCcount = 0;
286 else
287 TCcount = MAXTCCOUNTX - TCcount;
289 else
291 TCcount = MAXTCCOUNTX;
293 #endif
295 assert(TCcount <= MAXTCCOUNTX);
300 void
301 CheckForTimeout(int score, int globalscore, int Jscore, int zwndw)
303 if (flag.musttimeout || (Sdepth >= MaxSearchDepth))
304 flag.timeout = true;
306 else if (TCflag && (Sdepth > (MINDEPTH - 1)) && (TCcount < MAXTCCOUNTR))
308 if (killr0[1] != PrVar[1] /* || Killr0[2] != PrVar[2] */)
310 TCcount++;
311 ExtraTime += TCleft;
314 if ((TCcount < MAXTCCOUNTR)
315 && (abs(score - globalscore) / Sdepth) > ZDELTA)
317 TCcount++;
318 ExtraTime += TCleft;
322 if ((score > (Jscore - zwndw)) && (score > (Tree[1].score + 250)))
323 ExtraTime = 0;
325 ElapsedTime(COMPUTE_MODE);
327 if (root->flags & exact)
328 flag.timeout = true;
329 /*else if (Tree[1].score < -SCORE_LIMIT) flag.timeout = true;
331 #if defined OLDTIME || !defined HAVE_GETTIMEOFDAY
332 else if (!(Sdepth < MINDEPTH)
333 && TCflag
334 && ((4 * et) > (2*ResponseTime + ExtraTime)))
335 flag.timeout = true;
336 #else
337 else if (!(Sdepth < MINDEPTH)
338 && TCflag
339 && ((int)(1.93913099l * (pow((double)et, 1.12446928l)))
340 > (ResponseTime + ExtraTime)))
341 flag.timeout = true;
342 #endif
344 if (flag.timeout)
345 ShowMessage("timeout");