Updating to version 1.3, release made by Mike Vanier (mvanier@bbb.caltech.edu).
[gnushogi.git] / gnushogi / tcontrl.c
diff --git a/gnushogi/tcontrl.c b/gnushogi/tcontrl.c
new file mode 100644 (file)
index 0000000..df3a1ec
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * FILE: tcontrl.c
+ *
+ * ----------------------------------------------------------------------
+ * Copyright (c) 1993, 1994, 1995 Matthias Mutz
+ * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
+ *
+ * GNU SHOGI is based on GNU CHESS
+ *
+ * Copyright (c) 1988, 1989, 1990 John Stanback
+ * Copyright (c) 1992 Free Software Foundation
+ *
+ * This file is part of GNU SHOGI.
+ *
+ * GNU Shogi is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 1, or (at your option) any
+ * later version.
+ *
+ * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNU Shogi; see the file COPYING.  If not, write to the Free
+ * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------
+ *
+ */
+
+
+#include "gnushogi.h"
+#include <math.h>
+
+#define ALTERNATIVE_TC
+
+
+/*
+ * In a networked enviroment gnushogi might be compiled on different hosts
+ * with different random number generators; that is not acceptable if they
+ * are going to share the same transposition table.
+ */
+
+static unsigned long next = 1;
+
+unsigned int
+urand(void)
+{
+    next *= 1103515245;
+    next += 12345;
+    return ((unsigned int) (next >> 16) & 0xFFFF);
+}
+
+
+
+void
+gsrand(unsigned int seed)
+{
+    next = seed;
+}
+
+
+
+void
+TimeCalc()
+{
+    /* adjust number of moves remaining in gamein games */
+    int increment = 0;
+    int topsum = 0;
+    int tcompsum = 0;
+    int me, him;
+    int i;
+
+    /* Don't do anything until you have enough numbers. */
+    if (GameCnt < (MINGAMEIN * 2))
+        return;
+
+    /* Calculate average time in sec for last MINGAMEIN moves. */
+    for (i = 0; i < MINGAMEIN; i++)
+    {
+        tcompsum += timecomp[i];
+        topsum += timeopp[i];
+    }
+
+    topsum   /= (100 * MINGAMEIN);
+    tcompsum /= (100 * MINGAMEIN);
+
+    /* If I have less time than opponent add another move. */
+    me  = TimeControl.clock[computer] / 100;
+    him = TimeControl.clock[opponent] / 100;
+
+    if (me < him)
+        increment += 2;
+
+    if (((him - me) > 60) || ((me < him) && (me < 120)))
+        increment++;
+
+    /* If I am losing more time with each move add another. */
+    /* If (!((me - him) > 60) && tcompsum > topsum) increment++; */
+
+    if (tcompsum > topsum)
+    {
+        increment += 2;
+    }
+    else if ((TimeControl.moves[computer] < MINMOVES) && !increment)
+    {
+        /* ... but don't let moves go below MINMOVES. */
+        increment++;
+    }
+    else if ((me > him) && (tcompsum < topsum))
+    {
+        /* If I am doing really well use more time per move. */
+        increment = -1;
+    }
+
+    /* If not fischer clock be careful about time. */
+    /* CHECKME: what's a fischer clock? */
+
+    if ((TCadd == 0) && (increment > 0))
+        increment += 2;
+
+    if ((me == 0) && (increment > 0))
+        increment += 2;
+
+    TimeControl.moves[computer] += increment;
+}
+
+
+
+/*
+ * Set ResponseTime, TCcount, and TCleft.
+ */
+
+void SetResponseTime(short side)
+{
+#ifdef ALTERNATIVE_TC
+    int DetermineTCcount = true;
+
+    if (TCflag)
+    {
+        TCcount = 0;
+
+        if (TimeControl.moves[side] < 1)
+            TimeControl.moves[side] = 1;
+
+        /* special case time per move specified */
+        if (flag.onemove)
+        {
+            ResponseTime = TimeControl.clock[side] - 100;
+            TCleft = 0;
+        }
+        else
+        {
+            /* calculate avg time per move remaining */
+            if (TimeControl.clock[side] <= 0)
+            {
+                ResponseTime = 0;
+                TCleft = (long)MINRESPONSETIME / MAXTCCOUNTX;
+            }
+            else
+            {
+                short rtf = in_opening_stage ? 8 : 2;
+                short tcq = in_opening_stage ? 2 : 4;
+
+                TimeControl.clock[side] += TCadd;
+                ResponseTime = (TimeControl.clock[side])
+                    / (((TimeControl.moves[side]) * rtf) + 1);
+                TCleft = (long)ResponseTime / tcq;
+                ResponseTime += TCadd / 2;
+            }
+
+            if (TimeControl.moves[side] < 5)
+            {
+                TCcount = MAXTCCOUNTX - 10;
+
+                if (TCcount < 0)
+                    TCcount = 0;
+
+                DetermineTCcount = false;
+            }
+        }
+
+        if (ResponseTime < MINRESPONSETIME)
+        {
+            ResponseTime = MINRESPONSETIME;
+            TCcount = MAXTCCOUNTX - 10;
+
+            if (TCcount < 0)
+                TCcount = 0;
+
+            DetermineTCcount = false;
+        }
+
+        if (!hard_time_limit && (ResponseTime < 2 * MINRESPONSETIME))
+        {
+            TCcount = MAXTCCOUNTX - 10;
+
+            if (TCcount < 0)
+                TCcount = 0;
+
+            DetermineTCcount = false;
+        }
+    }
+    else
+    {
+        TCleft = 0;
+        ResponseTime = MaxResponseTime;
+        ElapsedTime(COMPUTE_AND_INIT_MODE);
+    }
+
+    if (DetermineTCcount)
+    {
+        if (TCleft )
+        {
+            int AllowedCounts
+                = ((int)((TimeControl.clock[side] - ResponseTime)) / 2)
+                / TCleft;
+
+            if (AllowedCounts <= 0)
+                TCcount = MAXTCCOUNTX;
+            else if (AllowedCounts > MAXTCCOUNTX)
+                TCcount = 0;
+            else
+                TCcount = MAXTCCOUNTX - AllowedCounts;
+        }
+        else
+        {
+            TCcount = MAXTCCOUNTX;
+        }
+    }
+
+    if (ResponseTime < MINRESPONSETIME)
+        ResponseTime = MINRESPONSETIME;
+
+#else
+
+    if (TCflag)
+    {
+        TCcount = 0;
+
+        if (TimeControl.moves[side] < 1)
+            TimeControl.moves[side] = 1;
+
+        /* special case time per move specified */
+        if (flag.onemove)
+        {
+            ResponseTime = TimeControl.clock[side] - 100;
+            TCleft = 0;
+        }
+        else
+        {
+            /* calculate avg time per move remaining */
+            TimeControl.clock[side] += TCadd;
+
+            ResponseTime = (TimeControl.clock[side])
+                / (((TimeControl.moves[side]) * 2) + 1);
+            TCleft = (int) ResponseTime / 3;
+            ResponseTime += TCadd / 2;
+
+            if (TimeControl.moves[side] < 5)
+                TCcount = MAXTCCOUNTX - 10;
+        }
+
+        if (ResponseTime < 101)
+        {
+            ResponseTime = 100;
+            TCcount = MAXTCCOUNTX - 10;
+        }
+        else if (ResponseTime < 200)
+        {
+            TCcount = MAXTCCOUNTX - 10;
+        }
+    }
+    else
+    {
+        ResponseTime = MaxResponseTime;
+        TCleft = 0;
+        ElapsedTime(COMPUTE_AND_INIT_MODE);
+    }
+
+    if (TCleft)
+    {
+        TCcount = ((int)((TimeControl.clock[side] - ResponseTime)) / 2)
+            / TCleft;
+
+        if (TCcount > MAXTCCOUNTX)
+            TCcount = 0;
+        else
+            TCcount = MAXTCCOUNTX - TCcount;
+    }
+    else
+    {
+        TCcount = MAXTCCOUNTX;
+    }
+#endif
+
+    assert(TCcount <= MAXTCCOUNTX);
+}
+
+
+
+void
+CheckForTimeout(int score, int globalscore, int Jscore, int zwndw)
+{
+    if (flag.musttimeout || (Sdepth >= MaxSearchDepth))
+        flag.timeout = true;
+
+    else if (TCflag && (Sdepth > (MINDEPTH - 1)) && (TCcount < MAXTCCOUNTR))
+    {
+        if (killr0[1] != PrVar[1] /* || Killr0[2] != PrVar[2] */)
+        {
+            TCcount++;
+            ExtraTime += TCleft;
+        }
+
+        if ((TCcount < MAXTCCOUNTR)
+            && (abs(score - globalscore) / Sdepth) > ZDELTA)
+        {
+            TCcount++;
+            ExtraTime += TCleft;
+        }
+    }
+
+    if ((score > (Jscore - zwndw)) && (score > (Tree[1].score + 250)))
+        ExtraTime = 0;
+
+    ElapsedTime(COMPUTE_MODE);
+
+    if (root->flags & exact)
+        flag.timeout = true;
+    /*else if (Tree[1].score < -SCORE_LIMIT) flag.timeout = true;
+     */
+#if defined OLDTIME || !defined HAVE_GETTIMEOFDAY
+    else if (!(Sdepth < MINDEPTH)
+             && TCflag
+             && ((4 * et) > (2*ResponseTime + ExtraTime)))
+        flag.timeout = true;
+#else
+    else if (!(Sdepth < MINDEPTH)
+             && TCflag
+             && ((int)(1.93913099l * (pow((double)et, 1.12446928l)))
+                 > (ResponseTime + ExtraTime)))
+        flag.timeout = true;
+#endif
+
+    if (flag.timeout)
+        ShowMessage("timeout");
+}