Only build pat2inc and declare it as dep for pattern.inc when not cross-compiling.
[gnushogi.git] / gnushogi / tcontrl.c
blob2ce441639b8d0f4e13349b502da627a955e2b389
1 /*
2 * FILE: tcontrl.c
4 * ----------------------------------------------------------------------
5 * Copyright (c) 1993, 1994, 1995 Matthias Mutz
6 * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
7 * Copyright (c) 2008, 2013, 2014 Yann Dirson and the Free Software Foundation
9 * GNU SHOGI is based on GNU CHESS
11 * Copyright (c) 1988, 1989, 1990 John Stanback
12 * Copyright (c) 1992 Free Software Foundation
14 * This file is part of GNU SHOGI.
16 * GNU Shogi is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License as published by the
18 * Free Software Foundation; either version 3 of the License,
19 * or (at your option) any later version.
21 * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
22 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * for more details.
26 * You should have received a copy of the GNU General Public License along
27 * with GNU Shogi; see the file COPYING. If not, see
28 * <http://www.gnu.org/licenses/>.
29 * ----------------------------------------------------------------------
34 #include "gnushogi.h"
35 #include <math.h>
37 #define ALTERNATIVE_TC
41 * In a networked enviroment gnushogi might be compiled on different hosts
42 * with different random number generators; that is not acceptable if they
43 * are going to share the same transposition table.
46 static unsigned long next = 1;
48 unsigned int
49 urand(void)
51 next *= 1103515245;
52 next += 12345;
53 return ((unsigned int) (next >> 16) & 0xFFFF);
58 void
59 gsrand(unsigned int seed)
61 next = seed;
66 void
67 TimeCalc()
69 /* adjust number of moves remaining in gamein games */
70 int increment = 0;
71 int topsum = 0;
72 int tcompsum = 0;
73 int me, him;
74 int i;
76 /* Don't do anything until you have enough numbers. */
77 if (GameCnt < (MINGAMEIN * 2))
78 return;
80 /* Calculate average time in sec for last MINGAMEIN moves. */
81 for (i = 0; i < MINGAMEIN; i++)
83 tcompsum += timecomp[i];
84 topsum += timeopp[i];
87 topsum /= (100 * MINGAMEIN);
88 tcompsum /= (100 * MINGAMEIN);
90 /* If I have less time than opponent add another move. */
91 me = TimeControl.clock[computer] / 100;
92 him = TimeControl.clock[opponent] / 100;
94 if (me < him)
95 increment += 2;
97 if (((him - me) > 60) || ((me < him) && (me < 120)))
98 increment++;
100 /* If I am losing more time with each move add another. */
101 /* If (!((me - him) > 60) && tcompsum > topsum) increment++; */
103 if (tcompsum > topsum)
105 increment += 2;
107 else if ((TimeControl.moves[computer] < MINMOVES) && !increment)
109 /* ... but don't let moves go below MINMOVES. */
110 increment++;
112 else if ((me > him) && (tcompsum < topsum))
114 /* If I am doing really well use more time per move. */
115 increment = -1;
118 /* If not fischer clock be careful about time. */
119 /* CHECKME: what's a fischer clock? */
121 if ((TCadd == 0) && (increment > 0))
122 increment += 2;
124 if ((me == 0) && (increment > 0))
125 increment += 2;
127 TimeControl.moves[computer] += increment;
133 * Set ResponseTime, TCcount, and TCleft.
136 void SetResponseTime(short side)
138 #ifdef ALTERNATIVE_TC
139 int DetermineTCcount = true;
141 if (TCflag)
143 TCcount = 0;
145 if (TimeControl.moves[side] < 1)
146 TimeControl.moves[side] = 1;
148 /* special case time per move specified */
149 if (flag.onemove)
151 ResponseTime = TimeControl.clock[side] - 100;
152 TCleft = 0;
154 else
156 /* calculate avg time per move remaining */
157 if (TimeControl.clock[side] <= 0)
159 ResponseTime = 0;
160 TCleft = (long)MINRESPONSETIME / MAXTCCOUNTX;
162 else
164 short rtf = in_opening_stage ? 8 : 2;
165 short tcq = in_opening_stage ? 2 : 4;
167 TimeControl.clock[side] += TCadd;
168 ResponseTime = (TimeControl.clock[side])
169 / (((TimeControl.moves[side]) * rtf) + 1);
170 TCleft = (long)ResponseTime / tcq;
171 ResponseTime += TCadd / 2;
174 if (TimeControl.moves[side] < 5)
176 TCcount = MAXTCCOUNTX - 10;
178 if (TCcount < 0)
179 TCcount = 0;
181 DetermineTCcount = false;
185 if (ResponseTime < MINRESPONSETIME)
187 ResponseTime = MINRESPONSETIME;
188 TCcount = MAXTCCOUNTX - 10;
190 if (TCcount < 0)
191 TCcount = 0;
193 DetermineTCcount = false;
196 if (!hard_time_limit && (ResponseTime < 2 * MINRESPONSETIME))
198 TCcount = MAXTCCOUNTX - 10;
200 if (TCcount < 0)
201 TCcount = 0;
203 DetermineTCcount = false;
206 else
208 TCleft = 0;
209 ResponseTime = MaxResponseTime;
210 ElapsedTime(COMPUTE_AND_INIT_MODE);
213 if (DetermineTCcount)
215 if (TCleft )
217 int AllowedCounts
218 = ((int)((TimeControl.clock[side] - ResponseTime)) / 2)
219 / TCleft;
221 if (AllowedCounts <= 0)
222 TCcount = MAXTCCOUNTX;
223 else if (AllowedCounts > MAXTCCOUNTX)
224 TCcount = 0;
225 else
226 TCcount = MAXTCCOUNTX - AllowedCounts;
228 else
230 TCcount = MAXTCCOUNTX;
234 if (ResponseTime < MINRESPONSETIME)
235 ResponseTime = MINRESPONSETIME;
237 #else
239 if (TCflag)
241 TCcount = 0;
243 if (TimeControl.moves[side] < 1)
244 TimeControl.moves[side] = 1;
246 /* special case time per move specified */
247 if (flag.onemove)
249 ResponseTime = TimeControl.clock[side] - 100;
250 TCleft = 0;
252 else
254 /* calculate avg time per move remaining */
255 TimeControl.clock[side] += TCadd;
257 ResponseTime = (TimeControl.clock[side])
258 / (((TimeControl.moves[side]) * 2) + 1);
259 TCleft = (int) ResponseTime / 3;
260 ResponseTime += TCadd / 2;
262 if (TimeControl.moves[side] < 5)
263 TCcount = MAXTCCOUNTX - 10;
266 if (ResponseTime < 101)
268 ResponseTime = 100;
269 TCcount = MAXTCCOUNTX - 10;
271 else if (ResponseTime < 200)
273 TCcount = MAXTCCOUNTX - 10;
276 else
278 ResponseTime = MaxResponseTime;
279 TCleft = 0;
280 ElapsedTime(COMPUTE_AND_INIT_MODE);
283 if (TCleft)
285 TCcount = ((int)((TimeControl.clock[side] - ResponseTime)) / 2)
286 / TCleft;
288 if (TCcount > MAXTCCOUNTX)
289 TCcount = 0;
290 else
291 TCcount = MAXTCCOUNTX - TCcount;
293 else
295 TCcount = MAXTCCOUNTX;
297 #endif
299 assert(TCcount <= MAXTCCOUNTX);
304 void
305 CheckForTimeout(int score, int globalscore, int Jscore, int zwndw)
307 if (flag.musttimeout || (Sdepth >= MaxSearchDepth))
308 flag.timeout = true;
310 else if (TCflag && (Sdepth > (MINDEPTH - 1)) && (TCcount < MAXTCCOUNTR))
312 if (killr0[1] != PrVar[1] /* || Killr0[2] != PrVar[2] */)
314 TCcount++;
315 ExtraTime += TCleft;
318 if ((TCcount < MAXTCCOUNTR)
319 && (abs(score - globalscore) / Sdepth) > ZDELTA)
321 TCcount++;
322 ExtraTime += TCleft;
326 if ((score > (Jscore - zwndw)) && (score > (Tree[1].score + 250)))
327 ExtraTime = 0;
329 ElapsedTime(COMPUTE_MODE);
331 if (root->flags & exact)
332 flag.timeout = true;
333 /*else if (Tree[1].score < -SCORE_LIMIT) flag.timeout = true;
335 #if defined OLDTIME || !defined HAVE_GETTIMEOFDAY
336 else if (!(Sdepth < MINDEPTH)
337 && TCflag
338 && ((4 * et) > (2*ResponseTime + ExtraTime)))
339 flag.timeout = true;
340 #else
341 else if (!(Sdepth < MINDEPTH)
342 && TCflag
343 && ((int)(1.93913099l * (pow((double)et, 1.12446928l)))
344 > (ResponseTime + ExtraTime)))
345 flag.timeout = true;
346 #endif
348 if (flag.timeout)
349 dsp->ShowMessage("timeout");
354 * Determine the time that has passed since the search was started. If the
355 * elapsed time exceeds the target(ResponseTime + ExtraTime) then set timeout
356 * to true which will terminate the search.
357 * iop = COMPUTE_MODE calculate et, bump ETnodes
358 * iop = COMPUTE_AND_INIT_MODE calculate et, set timeout if time exceeded,
359 * set reference time
361 void
362 ElapsedTime(ElapsedTime_mode iop)
364 long current_time;
365 #ifdef HAVE_GETTIMEOFDAY
366 struct timeval tv;
367 #endif
369 dsp->PollForInput();
371 #ifdef HAVE_GETTIMEOFDAY
372 gettimeofday(&tv, NULL);
373 current_time = tv.tv_sec*100 + (tv.tv_usec/10000);
374 #else
375 et = ((current_time = time((long *) 0)) - time0) * 100;
376 #endif
378 #ifdef INTERRUPT_TEST
379 if (iop == INIT_INTERRUPT_MODE)
381 itime0 = current_time;
383 else if (iop == COMPUTE_INTERRUPT_MODE)
385 it = current_time - itime0;
387 else
388 #endif
390 #ifdef HAVE_GETTIMEOFDAY
391 et = current_time - time0;
392 #endif
393 ETnodes = NodeCnt + znodes;
395 if (et < 0)
397 #ifdef INTERRUPT_TEST
398 printf("elapsed time %ld not positive\n", et);
399 #endif
400 et = 0;
403 if (iop == COMPUTE_AND_INIT_MODE)
405 if ((et > (ResponseTime + ExtraTime)) && (Sdepth > MINDEPTH))
406 flag.timeout = true;
408 time0 = current_time;
411 #ifdef QUIETBACKGROUND
412 if (!background)
413 #endif
414 dsp->UpdateClocks();
419 void
420 SetTimeControl(void)
422 if (TCflag)
424 TimeControl.moves[black] = TimeControl.moves[white] = TCmoves;
425 TimeControl.clock[black] += 6000L * TCminutes + TCseconds * 100;
426 TimeControl.clock[white] += 6000L * TCminutes + TCseconds * 100;
428 else
430 TimeControl.moves[black] = TimeControl.moves[white] = 0;
431 TimeControl.clock[black] = TimeControl.clock[white] = 0;
434 flag.onemove = (TCmoves == 1);
435 et = 0;
436 ElapsedTime(COMPUTE_AND_INIT_MODE);