Updating to version 1.3, release made by Mike Vanier (mvanier@bbb.caltech.edu).
[gnushogi.git] / gnushogi / init.c
diff --git a/gnushogi/init.c b/gnushogi/init.c
new file mode 100644 (file)
index 0000000..e6df8cf
--- /dev/null
@@ -0,0 +1,1347 @@
+/*
+ * FILE: init.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"
+
+#if defined HAVE_GETTIMEOFDAY
+#include <sys/time.h>
+#endif
+
+#include <signal.h>
+
+#include "pattern.h"
+
+/****************************************
+ *     A variety of global flags.
+ ****************************************/
+
+/*
+ * If hard_time_limit is nonzero, exceeding the time limit means
+ * losing the game.
+ */
+
+short hard_time_limit = 1;
+short barebones       = 0;  /* Suppress printing of statistics
+                             * (mainly for xshogi). */
+#ifdef LIST_ON_EXIT
+short nolist          = 0;  /* List the game after exit. */
+#else
+short nolist          = 1;  /* Don't list the game after exit. */
+#endif
+
+/*
+ * The default display type can be DISPLAY_RAW, DISPLAY_CURSES,
+ * or DISPLAY_X; the default is DISPLAY_X to make life easier for xshogi.
+ */
+
+display_t display_type = DISPLAY_X;
+
+unsigned int ttbllimit;
+
+/* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
+
+
+#define max(a, b) (((a) < (b))?(b):(a))
+#define odd(a) ((a) & 1)
+
+
+const small_short piece_of_ptype[NO_PTYPE_PIECES] =
+{
+    pawn, lance, knight, silver, gold, bishop, rook, pbishop, prook, king,
+    pawn, lance, knight, silver, gold
+};
+
+
+const small_short side_of_ptype[NO_PTYPE_PIECES] =
+{
+    black, black, black, black, black, black, black, black, black, black,
+    white, white, white, white, white
+};
+
+#ifdef SAVE_NEXTPOS
+const small_short psweep[NO_PTYPE_PIECES] =
+{
+    false, true, false, false, false, true, true, true, true, false,
+    false, true, false, false, false
+};
+#endif
+
+const small_short sweep[NO_PIECES] =
+{
+    false, false, true, false, false, false, true, true,
+    false, false, false, false, true, true, false
+};
+
+
+#if !defined EXTLANGFILE
+
+char *CP[CPSIZE] =
+
+{
+/* 000: eng: */ "",
+#ifdef LANGFILE
+#include LANGFILE
+#else
+#include "gnushogi.lng"
+#endif
+};
+
+#else
+
+char *CP[CPSIZE];
+
+#endif
+
+
+/*
+ * Determine the minimum number of moves for a piece from
+ * square "f" to square "t". If the piece cannot reach "t",
+ * the count is set to CANNOT_REACH.
+ */
+
+#define csquare(sq) ((side == black) ? sq : (NO_SQUARES - 1 - sq))
+#define crow(sq) row(csquare(sq))
+#define ccol(sq) column(csquare(sq))
+
+short
+ptype_distance(short ptyp, short f, short t)
+{
+    short side, piece;
+    short colf, colt, rowf, rowt, dcol, drow;
+
+    if (f == t)
+        return 0;
+
+    piece = piece_of_ptype[ptyp];
+    side  = side_of_ptype[ptyp];
+
+    dcol = (colt = ccol(t)) - (colf = ccol(f));
+    drow = (rowt = crow(t)) - (rowf = crow(f));
+
+    switch (piece)
+    {
+    case pawn:
+        if ((dcol != 0) || (drow < 1))
+            return CANNOT_REACH;
+        else
+            return drow;
+
+    case lance:
+        if ((dcol != 0) || (drow < 1))
+            return CANNOT_REACH;
+        else
+            return 1;
+
+    case knight:
+        if (odd(drow) || (odd(drow / 2) != odd(dcol)))
+            return CANNOT_REACH;
+        else if ((drow == 0) || ((drow / 2) < abs(dcol)))
+            return CANNOT_REACH;
+        else
+            return (drow / 2);
+
+    case silver:
+        if (drow > 0)
+        {
+            if (odd(drow) == odd(dcol))
+            {
+                return max(abs(drow), abs(dcol));
+            }
+            else
+            {
+                if (abs(dcol) <= drow)
+                    return drow;
+                else
+                    return (max(abs(drow), abs(dcol)) + 1);
+            }
+        }
+        else
+        {
+            if (odd(drow) == odd(dcol))
+                return (max(abs(drow), abs(dcol)));
+            else
+                return (max(abs(drow) + 1, abs(dcol)) + 1);
+        };
+
+    case gold:
+    case ppawn:
+    case pknight:
+    case plance:
+    case psilver:
+        if (abs(dcol) == 0)
+            return (abs(drow));
+        else if (drow >= 0)
+            return max(drow, abs(dcol));
+        else
+            return (abs(dcol) - drow);
+
+    case bishop:
+        if (odd(dcol) != odd(drow))
+            return CANNOT_REACH;
+        else
+            return ((abs(dcol) == abs(drow)) ? 1 : 2);
+
+    case pbishop:
+        if (odd(dcol) != odd(drow))
+        {
+            if ((abs(dcol) <= 1) && (abs(drow) <= 1))
+                return 1;
+            else if (abs(abs(dcol) - abs(drow)) == 1)
+                return 2;
+            else
+                return 3;
+        }
+        else
+        {
+            return ((abs(dcol) == abs(drow)) ? 1 : 2);
+        }
+
+    case rook:
+        if ((dcol == 0) || (drow == 0))
+            return 1;
+        else
+            return 2;
+
+    case prook:
+        if ((dcol == 0) || (drow == 0))
+            return 1;
+        else if ((abs(dcol) == 1) && (abs(drow) == 1))
+            return 1;
+        else
+            return 2;
+
+    case king:
+        return max(abs(drow), abs(dcol));
+
+    default:
+        /* should never occur */
+        return (CANNOT_REACH);
+    }
+}
+
+
+#ifdef SAVE_DISTDATA
+short
+distance(short a, short b)
+{
+    return (short)computed_distance(a, b);
+}
+#else
+short
+distance(short a, short b)
+{
+    return (use_distdata
+            ? (short)(*distdata)[(int)a][(int)b]
+            : (short)computed_distance(a, b));
+}
+#endif
+
+
+#ifdef SAVE_PTYPE_DISTDATA
+short
+piece_distance(short side, short piece, short f, short t)
+{
+    return ((f > NO_SQUARES)
+            ? (short)1
+            : (short)ptype_distance(ptype[side][piece], f, t));
+}
+#else
+short
+piece_distance(short side, short piece, short f, short t)
+{
+    return ((f > NO_SQUARES)
+            ? (short)1
+            : (use_ptype_distdata
+               ? (short)(*ptype_distdata[ptype[side][piece]])[f][t]
+               : (short)ptype_distance(ptype[side][piece], f, t)));
+}
+#endif
+
+
+void
+Initialize_dist(void)
+{
+    short a, b, d, di, ptyp;
+#ifndef SAVE_DISTDATA
+    for (a = 0; a < NO_SQUARES; a++)
+    {
+        for (b = 0; b < NO_SQUARES; b++)
+        {
+            d = abs(column(a) - column(b));
+            di = abs(row(a) - row(b));
+            (*distdata)[a][b] = (small_short)((d > di) ? d : di);
+        }
+    }
+#endif
+#ifndef SAVE_PTYPE_DISTDATA
+    for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
+    {
+        for (a = 0; a < NO_SQUARES; a++)
+            for (b = 0; b < NO_SQUARES; b++)
+                (*ptype_distdata[ptyp])[a][b] = ptype_distance(ptyp, a, b);
+    }
+#endif
+}
+
+
+/*
+ * nextpos[piece][from-square], nextdir[piece][from-square] gives vector
+ * of positions reachable from from-square in ppos with piece such that the
+ * sequence
+ *
+ *     ppos = nextpos[piece][from-square];
+ *     pdir = nextdir[piece][from-square];
+ *     u = ppos[sq];
+ *
+ *     do
+ *     {
+ *         u = ppos[u];
+ *
+ *         if(color[u] != neutral)
+ *             u = pdir[u];
+ *     }
+ *     while (sq != u);
+ *
+ * will generate the sequence of all squares reachable from sq.
+ *
+ * If the path is blocked u = pdir[sq] will generate the continuation of the
+ * sequence in other directions.
+ */
+
+
+/*
+ * ptype is used to separate black and white pawns, like this; ptyp =
+ * ptype[side][piece] piece can be used directly in nextpos/nextdir when
+ * generating moves for pieces that are not white pawns.
+ */
+
+const small_short ptype[2][NO_PIECES] =
+{
+    {
+        ptype_no_piece, ptype_pawn,  ptype_lance,  ptype_knight,
+        ptype_silver,   ptype_gold,  ptype_bishop, ptype_rook,
+        ptype_gold,     ptype_gold,  ptype_gold,   ptype_gold,
+        ptype_pbishop,  ptype_prook, ptype_king
+    },
+    {
+        ptype_no_piece, ptype_wpawn, ptype_wlance, ptype_wknight,
+        ptype_wsilver,  ptype_wgold, ptype_bishop, ptype_rook,
+        ptype_wgold,    ptype_wgold, ptype_wgold,  ptype_wgold,
+        ptype_pbishop,  ptype_prook, ptype_king
+    },
+};
+
+const small_short promoted[NO_PIECES] =
+{
+    no_piece, ppawn, plance, pknight, psilver, gold, pbishop, prook,
+    ppawn, plance, pknight, psilver, pbishop, prook, king
+};
+
+const small_short unpromoted[NO_PIECES] =
+{
+    no_piece, pawn, lance, knight, silver, gold, bishop, rook,
+    pawn, lance, knight, silver, bishop, rook, king
+};
+
+const small_short is_promoted[NO_PIECES] =
+{
+    false, false, false, false, false, false, false, false,
+    true, true, true, true, true, true, false
+};
+
+/* data used to generate nextpos/nextdir */
+#if !defined SAVE_NEXTPOS
+static
+#endif
+const small_short direc[NO_PTYPE_PIECES][8] =
+{
+    {  11,   0,   0,   0,   0,   0,   0,   0 },   /*  0 ptype_pawn    */
+    {  11,   0,   0,   0,   0,   0,   0,   0 },   /*  1 ptype_lance   */
+    {  21,  23,   0,   0,   0,   0,   0,   0 },   /*  2 ptype_knight  */
+    {  10,  11,  12, -12, -10,   0,   0,   0 },   /*  3 ptype_silver  */
+    {  10,  11,  12,  -1,   1, -11,   0,   0 },   /*  4 ptype_gold    */
+    {  10,  12, -12, -10,   0,   0,   0,   0 },   /*  5 ptype_bishop  */
+    {  11,  -1,   1, -11,   0,   0,   0,   0 },   /*  6 ptype_rook    */
+    {  10,  12, -12, -10,  11,  -1,   1, -11 },   /*  7 ptype_pbishop */
+    {  11,  -1,   1, -11,  10,  12, -12, -10 },   /*  8 ptype_prook   */
+    {  10,  11,  12,  -1,   1, -12, -11, -10 },   /*  9 ptype_king    */
+    { -11,   0,   0,   0,   0,   0,   0,   0 },   /* 10 ptype_wpawn   */
+    { -11,   0,   0,   0,   0,   0,   0,   0 },   /* 11 ptype_wlance  */
+    { -21, -23,   0,   0,   0,   0,   0,   0 },   /* 12 ptype_wknight */
+    { -10, -11, -12,  12,  10,   0,   0,   0 },   /* 13 ptype_wsilver */
+    { -10, -11, -12,   1,  -1,  11,   0,   0 }
+};  /* 14 ptype_wgold */
+
+
+small_short diagonal(short d)
+{
+    return (abs(d) == 10 || abs(d) == 12);
+}
+
+
+static const small_short max_steps[NO_PTYPE_PIECES] =
+{
+    1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1
+};
+
+
+const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 4)] =
+{
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8, -1,
+    -1,  9, 10, 11, 12, 13, 14, 15, 16, 17, -1,
+    -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1,
+    -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1,
+    -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, -1,
+    -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1,
+    -1, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1,
+    -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, -1,
+    -1, 72, 73, 74, 75, 76, 77, 78, 79, 80, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+
+const small_short inunmap[NO_SQUARES] =
+{
+     23,  24,  25,  26,  27,  28,  29,  30,  31,
+     34,  35,  36,  37,  38,  39,  40,  41,  42,
+     45,  46,  47,  48,  49,  50,  51,  52,  53,
+     56,  57,  58,  59,  60,  61,  62,  63,  64,
+     67,  68,  69,  70,  71,  72,  73,  74,  75,
+     78,  79,  80,  81,  82,  83,  84,  85,  86,
+     89,  90,  91,  92,  93,  94,  95,  96,  97,
+    100, 101, 102, 103, 104, 105, 106, 107, 108,
+    111, 112, 113, 114, 115, 116, 117, 118, 119
+};
+
+
+int InitFlag = false;
+
+
+#if defined SAVE_NEXTPOS
+
+short
+next_direction(short ptyp, short *d, short sq)
+{
+    short delta, to, sfrom = inunmap[sq];
+
+    do
+    {
+        (*d)++;
+        if (*d >= 8)
+            return sq;
+
+        delta = direc[ptyp][*d];
+        if (delta == 0)
+            return sq;
+
+        to = nunmap[sfrom + delta];
+    }
+    while (to < 0);
+
+    return to;
+}
+
+
+short
+next_position(short ptyp, short *d, short sq, short u)
+{
+    if (*d < 4 && psweep[ptyp])
+    {
+        short to = nunmap[inunmap[u] + direc[ptyp][*d]];
+
+        if (to < 0)
+            return next_direction(ptyp, d, sq);
+        else
+            return to;
+    }
+    else
+    {
+        return next_direction(ptyp, d, sq);
+    }
+}
+
+
+short
+first_direction(short ptyp, short *d, short sq)
+{
+    *d = -1;
+    return next_direction(ptyp, d, sq);
+}
+
+#else
+
+/*
+ * This procedure pre-calculates all moves for every piece from every
+ * square.  This data is stored in nextpos/nextdir and used later in the
+ * move generation routines.
+ */
+
+void
+Initialize_moves(void)
+{
+    short ptyp, po, p0, d, di, s, delta;
+    unsigned char *ppos, *pdir;
+    short dest[8][9];
+    short sorted[9];
+    short steps[8];
+    short fpo = 23, tpo = 120;
+
+    for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
+    {
+        for (po = 0; po < NO_SQUARES; po++)
+        {
+            for (p0 = 0; p0 < NO_SQUARES; p0++)
+            {
+                (*nextpos[ptyp])[po][p0] = (unsigned char)po;
+                (*nextdir[ptyp])[po][p0] = (unsigned char)po;
+            }
+        }
+    }
+
+    for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
+    {
+        for (po = fpo; po < tpo; po++)
+        {
+            if (nunmap[po] >= (small_short)0)
+            {
+                ppos = (*nextpos[ptyp])[nunmap[po]];
+                pdir = (*nextdir[ptyp])[nunmap[po]];
+
+                /* dest is a function of direction and steps */
+                for (d = 0; d < 8; d++)
+                {
+                    dest[d][0] = nunmap[po];
+                    delta = direc[ptyp][d];
+
+                    if (delta != 0)
+                    {
+                        p0 = po;
+
+                        for (s = 0; s < max_steps[ptyp]; s++)
+                        {
+                            p0 = p0 + delta;
+
+                            /*
+                             * break if (off board) or (promoted rooks
+                             * wishes to move two steps diagonal) or
+                             * (promoted bishops wishes to move two steps
+                             * non-diagonal)
+                             */
+                            if ((nunmap[p0] < (small_short)0)
+                                || ((ptyp == ptype_prook)
+                                    && (s > 0)
+                                    && diagonal(delta))
+                                || ((ptyp == ptype_pbishop)
+                                    && (s > 0)
+                                    && !diagonal(delta)))
+                                break;
+                            else
+                                dest[d][s] = nunmap[p0];
+                        }
+                    }
+                    else
+                    {
+                        s = 0;
+                    }
+
+                    /*
+                     * Sort dest in number of steps order; currently no sort
+                     * is done due to compatibility with the move generation
+                     * order in old gnuchess.
+                     */
+
+                    steps[d] = s;
+
+                    for (di = d; s > 0 && di > 0; di--)
+                    {
+                        if (steps[sorted[di - 1]] == 0) /* should be: < s */
+                            sorted[di] = sorted[di - 1];
+                        else
+                            break;
+                    }
+
+                    sorted[di] = d;
+                }
+
+                /*
+                 * update nextpos/nextdir
+                 */
+
+                p0 = nunmap[po];
+                pdir[p0] = (unsigned char)dest[sorted[0]][0];
+
+                for (d = 0; d < 8; d++)
+                {
+                    for (s = 0; s < steps[sorted[d]]; s++)
+                    {
+                        ppos[p0] = (unsigned char)dest[sorted[d]][s];
+                        p0 = dest[sorted[d]][s];
+
+                        if (d < 7)
+                            pdir[p0] = (unsigned char)dest[sorted[d + 1]][0];
+
+                        /*
+                         * else is already initialized
+                         */
+                    }
+                }
+            }
+        }
+    }
+}
+
+#endif
+
+
+
+/*
+ * Reset the board and other variables to start a new game.
+ */
+
+void
+NewGame(void)
+{
+    short l, c, p, max_opening_sequence;
+#ifdef HAVE_GETTIMEOFDAY
+    struct timeval tv;
+#endif
+    compptr = oppptr = 0;
+    stage = 0;
+    stage2 = -1;    /* the game is not yet started */
+    flag.illegal = flag.mate = flag.post = flag.quit
+        = flag.reverse = flag.bothsides = flag.onemove = flag.force
+        = false;
+    flag.material = flag.coords = flag.hash = flag.easy
+        = flag.beep = flag.rcptr
+        = true;
+    flag.stars  = flag.shade = flag.back = flag.musttimeout = false;
+    flag.gamein = false;
+    flag.rv     = true;
+
+    mycnt1 = mycnt2 = 0;
+    GenCnt = NodeCnt = et0 = dither =  XCmore = 0;
+    znodes = ZNODES;
+    WAwindow = WAWNDW;
+    WBwindow = WBWNDW;
+    BAwindow = BAWNDW;
+    BBwindow = BBWNDW;
+    xwndw = BXWNDW;
+
+    if (!MaxSearchDepth)
+        MaxSearchDepth = MAXDEPTH - 1;
+
+    contempt = 0;
+    GameCnt = 0;
+    Game50 = 1;
+    CptrFlag[0] = TesujiFlag[0] = false;
+    hint = OPENING_HINT;
+    ZeroRPT();
+    GameType[0] = GameType[1] = UNKNOWN;
+    Pscore[0] = Tscore[0] = (SCORE_LIMIT + 3000);
+    opponent = player = black;
+    computer = white;
+
+    for (l = 0; l < TREE; l++)
+        Tree[l].f = Tree[l].t = 0;
+
+    gsrand((unsigned int) 1);
+
+    if (!InitFlag)
+    {
+        for (c = black; c <= white; c++)
+        {
+            for (p = pawn; p <= king; p++)
+            {
+                for (l = 0; l < NO_SQUARES; l++)
+                {
+                    (*hashcode)[c][p][l].key
+                         = (((unsigned long) urand()));
+                    (*hashcode)[c][p][l].key
+                        += (((unsigned long) urand()) << 16);
+                    (*hashcode)[c][p][l].bd
+                         = (((unsigned long) urand()));
+                    (*hashcode)[c][p][l].bd
+                        += (((unsigned long) urand()) << 16);
+#if SIZEOF_LONG == 8  /* 64-bit long i.e. 8 bytes */
+                    (*hashcode)[c][p][l].key
+                        += (((unsigned long) urand()) << 32);
+                    (*hashcode)[c][p][l].key
+                        += (((unsigned long) urand()) << 48);
+                    (*hashcode)[c][p][l].bd
+                        += (((unsigned long) urand()) << 32);
+                    (*hashcode)[c][p][l].bd
+                        += (((unsigned long) urand()) << 48);
+#endif
+                }
+            }
+        }
+
+        for (c = black; c <= white; c++)
+        {
+            for (p = pawn; p <= king; p++)
+            {
+                for (l = 0; l < MAX_CAPTURED; l++)
+                {
+                    (*drop_hashcode)[c][p][l].key
+                         = (((unsigned long) urand()));
+                    (*drop_hashcode)[c][p][l].key
+                        += (((unsigned long) urand()) << 16);
+                    (*drop_hashcode)[c][p][l].bd
+                         = (((unsigned long) urand()));
+                    (*drop_hashcode)[c][p][l].bd
+                        += (((unsigned long) urand()) << 16);
+#if SIZEOF_LONG == 8  /* 64-bit long i.e. 8 bytes */
+                    (*drop_hashcode)[c][p][l].key
+                        += (((unsigned long) urand()) << 32);
+                    (*drop_hashcode)[c][p][l].key
+                        += (((unsigned long) urand()) << 48);
+                    (*drop_hashcode)[c][p][l].bd
+                        += (((unsigned long) urand()) << 32);
+                    (*drop_hashcode)[c][p][l].bd
+                        += (((unsigned long) urand()) << 48);
+#endif
+                }
+            }
+        }
+    }
+
+    for (l = 0; l < NO_SQUARES; l++)
+    {
+        board[l] = Stboard[l];
+        color[l] = Stcolor[l];
+        Mvboard[l] = 0;
+    }
+
+    ClearCaptured();
+    ClearScreen();
+    InitializeStats();
+
+#ifdef HAVE_GETTIMEOFDAY
+    gettimeofday(&tv, NULL);
+    time0 = tv.tv_sec*100 + tv.tv_usec/10000;
+#else
+    time0 = time((long *) 0);
+#endif
+
+    /* resetting reference time */
+    ElapsedTime(COMPUTE_AND_INIT_MODE);
+    flag.regularstart = true;
+    Book = BOOKFAIL;
+
+    if (!InitFlag)
+    {
+        char sx[256];
+        strcpy(sx, CP[169]);
+
+        if (TCflag)
+            SetTimeControl();
+        else if (MaxResponseTime == 0)
+            SelectLevel(sx);
+
+        UpdateDisplay(0, 0, 1, 0);
+        GetOpenings();
+        GetOpeningPatterns(&max_opening_sequence);
+
+        InitFlag = true;
+    }
+
+#if ttblsz
+    if (TTadd)
+    {
+        ZeroTTable();
+        TTadd = 0;
+    }
+#endif /* ttblsz */
+
+    hashbd = hashkey = 0;
+    return;
+}
+
+
+
+int
+Initialize_data(void)
+{
+    size_t n;
+    int i;
+    char buffer[60];
+    int doit = true;
+
+    {
+        small_short x = -1;
+
+        if (x >= 0)
+        {
+            ShowMessage("datatype 'small_short' is unsigned; "
+                        "check gnushogi.h\n");
+            return 1;
+        }
+    }
+
+    n = sizeof(struct leaf) * (size_t)TREE;
+    Tree = malloc(n);
+
+    if (!Tree)
+    {
+        sprintf(buffer, "Cannot allocate %ld bytes for search tree",
+                (long)n);
+        ShowMessage(buffer);
+        return 1;
+    }
+
+    n = sizeof(hashcode_array);
+    hashcode = malloc(n);
+
+    if (!hashcode)
+    {
+        sprintf(buffer, "Cannot allocate %ld bytes for hashcode", (long)n);
+        ShowMessage(buffer);
+        return 1;
+    }
+
+    n = sizeof(drop_hashcode_array);
+    drop_hashcode = malloc(n);
+
+    if (!drop_hashcode)
+    {
+        sprintf(buffer,
+                "Cannot allocate %ld bytes for drop_hashcode",
+                (long)n);
+        ShowMessage(buffer);
+        return 1;
+    }
+
+    n = sizeof(struct GameRec) * (size_t)(MAXMOVES + MAXDEPTH);
+    GameList = malloc(n);
+
+    if (!GameList)
+    {
+        sprintf(buffer,
+                "Cannot allocate %ld bytes for game record",
+                (long)n);
+        ShowMessage(buffer);
+        return 1;
+    }
+
+#if !defined SAVE_NEXTPOS
+    n = sizeof(next_array);
+
+    for (i = 0; i < NO_PTYPE_PIECES; i++)
+    {
+        nextdir[i] = use_nextpos ? malloc(n) : NULL;
+
+        if (!nextdir[i])
+        {
+            if (use_nextpos)
+            {
+                sprintf(buffer, "cannot allocate %ld space for nextdir %d",
+                        (long)(n), i);
+                ShowMessage(buffer);
+            }
+
+            nextdir[i] = NULL;
+            use_nextpos = false;
+        }
+
+        nextpos[i] = use_nextpos ? malloc(n) : NULL;
+
+        if (!nextpos[i])
+        {
+            if (use_nextpos)
+            {
+                sprintf(buffer, "cannot allocate %ld space for nextpos %d",
+                        (long)(n), i);
+                ShowMessage(buffer);
+            }
+
+            use_nextpos = false;
+        }
+    }
+
+    if (!use_nextpos)
+    {
+        return 1;
+    }
+#endif
+
+    n = sizeof(value_array);
+    value = malloc(n);
+
+    if (!value)
+    {
+        ShowMessage("cannot allocate value space");
+        return 1;
+    }
+
+    n = sizeof(fscore_array);
+    fscore = malloc(n);
+
+    if (!fscore)
+    {
+        ShowMessage("cannot allocate fscore space");
+        return 1;
+    }
+
+#if defined HISTORY
+    n = sizeof_history;
+    history = malloc(n);
+
+    if (!history)
+    {
+        sprintf(buffer, "Cannot allocate %ld bytes for history table",
+                (long)sizeof_history);
+        ShowMessage(buffer);
+        use_history = false;
+    }
+#endif
+
+#if defined CACHE
+    n = sizeof(struct etable) * (size_t)ETABLE;
+
+    for (i = 0; i < 2; i++)
+    {
+        etab[i] = use_etable ? malloc(n) : 0;
+
+        if (!etab[i])
+        {
+            sprintf(buffer, "Cannot allocate %ld bytes for cache table %ld",
+                    (long)n, (long)i);
+            ShowMessage(buffer);
+            use_etable = false;
+        }
+    }
+#endif
+
+#if ttblsz
+
+    if (rehash < 0)
+        rehash = MAXrehash;
+
+    n = sizeof(struct hashentry)*(ttblsize + rehash);
+
+    while (doit && ttblsize > MINTTABLE)
+    {
+        ttable[0] = malloc(n);  /* FIXME: cast to the correct type. */
+        ttable[1] = ttable[0] ? malloc(n) : NULL;
+
+        if (!ttable[0] || !ttable[1])
+        {
+            if (!ttable[0])
+                free(ttable[0]);
+
+            if (!ttable[1])
+                free(ttable[1]);
+
+            ttblsize = ttblsize >> 1;
+            n = sizeof(struct hashentry) * (ttblsize + rehash);
+        }
+        else
+        {
+            doit = false;
+        }
+    }
+
+    if (ttblsize <= MINTTABLE)
+    {
+        use_ttable = false;
+    }
+
+    if (use_ttable)
+    {
+        /* CHECKME: is the precedence here correct? */
+        /* ttbllimit = ttblsize << 1 - ttblsize >> 2; */
+        ttbllimit = (ttblsize << 1) - (ttblsize >> 2);
+    }
+    else
+    {
+        sprintf(buffer, "Cannot allocate %ld bytes for transposition table",
+                (long)(2 * n));
+        ShowMessage(buffer);
+        ttable[0] = ttable[1] = NULL;
+    }
+#endif /* ttblsz */
+
+#if !defined SAVE_DISTDATA
+    n = sizeof(distdata_array);
+    distdata = malloc(n);
+
+    if (!distdata)
+    {
+        ShowMessage("cannot allocate distdata space...");
+        use_distdata = false;
+    }
+#endif
+
+#if !defined SAVE_PTYPE_DISTDATA
+    n = sizeof(distdata_array);
+
+    for (i = 0; i < NO_PTYPE_PIECES; i++)
+    {
+        ptype_distdata[i] = use_ptype_distdata ? malloc(n) : 0;
+
+        if (!ptype_distdata[i])
+        {
+            sprintf(buffer,
+                    "cannot allocate %ld bytes for ptype_distdata %d...",
+                    (long)n, i);
+            use_ptype_distdata = false;
+        }
+    }
+#endif
+
+    return 0;
+}
+
+
+#if defined EXTLANGFILE
+
+#ifdef OLDLANGFILE
+
+void
+InitConst(char *lang)
+{
+    FILE *constfile;
+    char s[256];
+    char sl[5];
+    char buffer[120];
+    int len, entry;
+    char *p, *q;
+    constfile = fopen(LANGFILE, "r");
+
+    if (!constfile)
+    {
+        ShowMessage("NO LANGFILE");
+        exit(1);
+    }
+
+    while (fgets(s, sizeof(s), constfile))
+    {
+        if (s[0] == '!')
+            continue;
+
+        len = strlen(s);
+
+        for (q = &s[len]; q > &s[8]; q--)
+            if (*q == '}')
+                break;
+
+        if (q == &s[8])
+        {
+            ShowMessage("{ error in cinstfile");
+            exit(1);
+        }
+
+        *q = '\0';
+
+        if ((s[3] != ':') || (s[7] != ':') || (s[8] != '{'))
+        {
+            sprintf(buffer, "Langfile format error %s", s);
+            ShowMessage(buffer);
+            exit(1);
+        }
+
+        s[3] = s[7] = '\0';
+
+        if (lang == NULL)
+        {
+            lang = sl;
+            strcpy(sl, &s[4]);
+        }
+
+        if (strcmp(&s[4], lang))
+            continue;
+
+        entry = atoi(s);
+
+        if ((entry < 0) || (entry >= CPSIZE))
+        {
+            ShowMessage("Langfile number error");
+            exit(1);
+        }
+
+        for (q = p = &s[9]; *p; p++)
+        {
+            if (*p != '\\')
+            {
+                *q++ = *p;
+            }
+            else if (*(p + 1) == 'n')
+            {
+                *q++ = '\n';
+                p++;
+            }
+        }
+
+        *q = '\0';
+
+        if ((entry < 0) || (entry > 255))
+        {
+            sprintf(buffer, "Langfile error %d\n", entry);
+            ShowMessage(buffer);
+            exit(0);
+        }
+
+        CP[entry] = (char *)GLOBAL_ALLOC((unsigned) strlen(&s[9]) + 1);
+
+        if (CP[entry] == NULL)
+        {
+            char buffer[80];
+            sprintf(buffer, "CP MALLOC, entry %d", entry);
+            perror(buffer);
+            exit(0);
+        }
+
+        strcpy(CP[entry], &s[9]);
+    }
+
+    fclose(constfile);
+}
+
+#else
+
+void
+InitConst(char *lang)
+{
+    FILE *constfile;
+    char s[256];
+    char sl[5];
+    char buffer[120];
+    int len, entry;
+    char *p, *q;
+    constfile = fopen(LANGFILE, "r");
+
+    if (!constfile)
+    {
+        ShowMessage("NO LANGFILE");
+        exit(1);
+    }
+
+    while (fgets(s, sizeof(s), constfile))
+    {
+        if (s[0] == '!')
+            continue;
+
+        len = strlen(s);
+
+        if ((len > 3) && (s[3] == ':') || (len > 7) && (s[7] == ':'))
+        {
+            ShowMessage("old Langfile error");
+            exit(1);
+        }
+
+        if (len <= 15)
+        {
+            ShowMessage("length error in Langfile");
+            exit(1);
+        }
+
+        for (q = &s[len]; q > &s[15]; q--)
+        {
+            if (*q == '"')
+                break;
+        }
+
+        if (q == &s[15])
+        {
+            ShowMessage("\" error in Langfile");
+            exit(1);
+        }
+
+        *q = '\0';
+
+        if ((s[6] != ':') || (s[10] != ':') || (s[15] != '"'))
+        {
+            sprintf(buffer, "Langfile format error %s", s);
+            ShowMessage(buffer);
+            exit(1);
+        }
+
+        s[6] = s[10] = '\0';
+
+        if (lang == NULL)
+        {
+            lang = sl;
+            strcpy(sl, &s[7]);
+        }
+
+        if (strcmp(&s[7], lang))
+            continue;
+
+        entry = atoi(&s[3]);
+
+        if ((entry < 0) || (entry >= CPSIZE))
+        {
+            ShowMessage("Langfile number error");
+            exit(1);
+        }
+
+        for (q = p = &s[16]; *p; p++)
+        {
+            if (*p != '\\')
+            {
+                *q++ = *p;
+            }
+            else if (*(p + 1) == 'n')
+            {
+                *q++ = '\n';
+                p++;
+            }
+        }
+
+        *q = '\0';
+
+        if ((entry < 0) || (entry > 255))
+        {
+            sprintf(buffer, "Langfile error %d\n", entry);
+            ShowMessage(buffer);
+            exit(0);
+        }
+
+        CP[entry] = (char *)GLOBAL_ALLOC((unsigned)strlen(&s[16]) + 1);
+
+        if (CP[entry] == NULL)
+        {
+            char buffer[80];
+            sprintf(buffer, "CP MALLOC, entry %d", entry);
+            perror(buffer);
+            exit(0);
+        }
+
+        strcpy(CP[entry], &s[16]);
+    }
+
+    fclose(constfile);
+}
+
+#endif
+
+#endif
+
+
+int
+InitMain(void)
+{
+    gsrand(starttime = ((unsigned int)time((long *)0)));    /* init urand */
+
+#if ttblsz
+    ttblsize = ttblsz;
+    rehash = -1;
+#endif /* ttblsz */
+
+    if (Initialize_data() != 0)
+        return 1;
+
+#if defined EXTLANGFILE
+    InitConst(Lang);
+#endif
+
+    strcpy(ColorStr[0], CP[118]);
+    strcpy(ColorStr[1], CP[119]);
+
+    XC = 0;
+    MaxResponseTime = 0;
+
+    if (XSHOGI)
+    {
+        signal(SIGINT, TerminateSearch);
+
+        TCmoves      = 40;
+        TCminutes    = 5;
+        TCseconds    = 0;
+        TCadd        = 0;
+
+        TCflag       = true;
+        OperatorTime = 0;
+        barebones    = 1;
+    }
+    else
+    {
+        TCflag       = false;
+        OperatorTime = 0;
+        barebones    = 0;
+    }
+
+    Initialize();
+    Initialize_dist();
+    Initialize_eval();
+#if !defined SAVE_NEXTPOS
+    Initialize_moves();
+#endif
+
+    NewGame();
+
+    flag.easy = ahead;
+    flag.hash = hash;
+
+    if (xwin)
+        xwndw = atoi(xwin);
+
+#ifdef HASHFILE
+    hashfile = NULL;
+#endif
+
+#if ttblsz
+#ifdef HASHFILE
+    hashfile = fopen(HASHFILE, RWA_ACC);
+
+    if (hashfile)
+    {
+        fseek(hashfile, 0L, SEEK_END);
+        filesz = ftell(hashfile) / sizeof(struct fileentry) - 1 - MAXrehash;
+        hashmask = filesz >> 1;
+        hashbase = hashmask + 1;
+    }
+#endif /* HASHFILE */
+#endif /* ttblsz */
+
+    savefile[0] = '\0';
+    listfile[0] = '\0';
+
+    return 0;
+}
+
+
+void
+ExitMain(void)
+{
+#if ttblsz
+#ifdef HASHFILE
+    if (hashfile)
+        fclose(hashfile);
+#endif /* HASHFILE */
+#endif /* ttblsz */
+
+    ExitShogi();
+}
+