Updating to version 1.3, release made by Mike Vanier (mvanier@bbb.caltech.edu).
[gnushogi.git] / src / pattern.c
diff --git a/src/pattern.c b/src/pattern.c
deleted file mode 100644 (file)
index 3fa8b3d..0000000
+++ /dev/null
@@ -1,1002 +0,0 @@
-/*
- * pattern.c - C source for GNU SHOGI
- *
- * Copyright (c) 1993, 1994, 1995 Matthias Mutz
- *
- * 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.
- *
- * 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 DEBUG && !defined EXTPATTERNFILE
-/* #define DEBUG_PATTERN */
-/* #define TEST_PATTERN */
-#endif            
-
-
-#ifdef DEBUG_PATTERN
-#include <assert.h>
-#endif
-
-
-#include "pattern.h"
-
-
-#ifdef EXTPATTERNFILE
-
-#define MAX_PATTERN_DATA 5000
-
-small_short pattern_data[MAX_PATTERN_DATA];
-
-#define MAX_OPENING_SEQUENCE 20
-#define MAX_PATTERN 200
-
-#else
-
-/* constants and pattern_data are generated by "pat2inc" */
-
-#include "pattern.inc"
-
-#endif
-
-struct Pattern_rec Pattern[MAX_PATTERN];
-struct OpeningSequence_rec OpeningSequence[MAX_OPENING_SEQUENCE];
-
-
-
-#if defined DEBUG || defined DEBUG_EVAL                             
-static small_ushort sequence_id;               
-#endif
-
-
-
-short ValueOfOpeningName (char *name)
-{
-  short i;
-  i = (name[0] == 'C') ? 0 : 100;
-  switch ( name[7] ) {
-    case 'S' : i += 10; break;
-    case 'R' : i += 20; break;
-    case 'U' : i += 30; break;
-    default  : i += 40; break;
-  }
-  switch ( name[9] ) {
-    case 'S' : i += 1; break;
-    case 'R' : i += 2; break;
-    case 'U' : i += 3; break;
-    default  : i += 4; break;
-  }
-  return(i);
-}
-
-
-void NameOfOpeningValue (short i, char *name)
-{
-  if ( i < 100 )
-    strcpy(name,"CASTLE_?_?");
-  else {
-    strcpy(name,"ATTACK_?_?");
-    i -= 100;
-  }
-  switch ( i / 10 ) {
-    case 1   : name[7] = 'S'; break;
-    case 2   : name[7] = 'R'; break;
-    case 3   : name[7] = 'U'; break;
-    default  : name[7] = '*'; break;
-  }
-  switch ( i % 10 ) {
-    case 1   : name[9] = 'S'; break;
-    case 2   : name[9] = 'R'; break;
-    case 3   : name[9] = 'U'; break;
-    default  : name[9] = '*'; break;
-  }
-}
-
-
-#ifdef EXTPATTERNFILE
-
-char *patternfile = PATTERNFILE;
-
-#define is_digit(c) ((c) >= '0' && (c) <= '9')
-#define is_alfa(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
-
-#define eos(s) (*s == '\0' || *s == '\n')
-
-
-/* skip blanks and comments in brackets */
-
-static void skipbb(char **s) 
- { while (**s == ' ' || **s == '|' || **s == '[') { 
-     if ( **s == '[' ) 
-       while (**s != ']') (*s)++; 
-     (*s)++; 
-   } \
- }  
-                        
-/* skip unsigned numbers */
-
-static void skipi(char **s)
- { 
-   while ( is_digit(**s) ) 
-     (*s)++;
-   skipbb(s);
- }
-
-
-static
-short
-ScanPiece (char **s, small_short *side, small_short *piece, small_short *square)
-{
-  short isp, isw, c, r;
-  
-  /* determine promotion status */
-  if ( **s == '+' )
-    isp = true, (*s)++;
-  else
-    isp = false;
-  /* determine side and piece */
-  for (c = 0; c < NO_PIECES; c++)
-    if ((isw = (**s == pxx[c])) || **s == qxx[c])
-      {
-       *piece = isp ? promoted[c] : unpromoted[c];
-       *side  = isw;
-       (*s)++; 
-       break;
-      } 
-  if (c == NO_PIECES) 
-    return(1);
-  if ( **s == '*' )
-    {
-      /* piece is captured */ 
-      (*s)++;
-      *square = NO_SQUARES + *piece;
-    }
-  else
-    {        
-      /* determine column */
-      for (c = 0; c < NO_COLS; c++)
-        if (**s == cxx[c])
-          {
-           (*s)++; 
-           break;
-          }
-      if (c >= NO_COLS) 
-        return(1);
-      /* determine row */
-      for (r = 0; r < NO_ROWS; r++)
-        if (**s == rxx[r])
-          {
-           (*s)++;
-           break;
-          }
-      if (r >= NO_ROWS) return(1);
-      /* determine square */
-      *square = r*NO_COLS + c;
-    }
-  skipbb(s); 
-  return(0);
-}
-
-
-static
-short
-ScanPattern (char *s, short *pindex)
-{        
-  small_short side, piece, square;
-  skipbb(&s); /* skip blanks and comments */
-  while ( is_digit(*s) ) {                             
-    pattern_data[(*pindex)++] = atoi(s);
-    skipi(&s);
-  }
-  pattern_data[(*pindex)++] = END_OF_LINKS;
-  skipbb(&s); 
-  while ( !eos(s) ) { 
-      if ( ScanPiece(&s, &side, &piece, &square) ) {
-        return(1);
-      } else {
-        pattern_data[(*pindex)++] = piece;
-        pattern_data[(*pindex)++] = (side ? -square : square);
-      }
-  }
-  pattern_data[(*pindex)++] = END_OF_FIELDS;
-  return(0); 
-}
-
-
-void
-ReadOpeningSequences (short *pindex)
-
-{ 
-    FILE *fd;
-    char s[256];
-    short max_pattern = 0;
-    short max_opening_sequence = 0;
-
-    if ( (fd = fopen (patternfile, "r")) == NULL )
-       fd = fopen ("gnushogi.pat", "r");       
-
-    if ( fd != NULL ) {
-       *pindex = 0;
-       while ( fgets (s, 256, fd) != NULL )
-         {
-           if ( *s == '#' ) { 
-             /* comment, skip line */
-           } else if ( is_alfa(*s) ) {
-               if ( max_opening_sequence++ > 0 ) {
-                 pattern_data[(*pindex)++] = END_OF_PATTERNS;
-               }
-                pattern_data[(*pindex)++] = ValueOfOpeningName(s);
-           } else {
-               if ( ScanPattern(s,pindex) ) {
-                   ShowMessage("error in pattern sequence...");
-                   exit(1);
-               } else {  
-                   max_pattern++;
-               }
-           }
-         }
-       pattern_data[(*pindex)++] = END_OF_PATTERNS;
-       pattern_data[(*pindex)++] = END_OF_SEQUENCES;
-#if defined NONDSP || defined MSDOS
-       sprintf(s, "Pattern: %d bytes for %d sequences with %d patterns.\n", 
-                       *pindex, max_opening_sequence, max_pattern);
-       ShowMessage(s);
-#endif  
-       fclose(fd);
-    }
-#if defined NONDSP || defined MSDOS
-      else {
-       sprintf(s, "no pattern file '%s'",patternfile);
-       ShowMessage(s);
-    }      
-#endif
-}                           
-
-
-void 
-WriteOpeningSequences (short pindex)
-{
-  FILE *fd;
-  short n = 0;
-  short max_pattern = 0;
-  short max_opening_sequence = 0;
-
-  fd = fopen ("pattern.inc", "w"); 
-  fprintf(fd,"#define MAX_PATTERN_DATA %d\n\n",pindex);
-  fprintf(fd,"small_short pattern_data[MAX_PATTERN_DATA] =\n{\n");
-  do {
-    fprintf(fd,"  %d,\n",pattern_data[n++]);
-    do {
-      fprintf(fd,"    ");
-      /* write links */
-      while ( pattern_data[n] != END_OF_LINKS ) {
-        fprintf(fd,"%d, ",pattern_data[n++]);
-      };
-      fprintf(fd,"%d, ",pattern_data[n++]);
-      /* write pattern */
-      do {
-        fprintf(fd,"%d,",pattern_data[n++]);
-      } while ( pattern_data[n] != END_OF_FIELDS );
-      fprintf(fd,"%d,\n",pattern_data[n++]);
-      max_pattern++;
-    } while ( pattern_data[n] != END_OF_PATTERNS );
-    fprintf(fd,"    %d,\n",pattern_data[n++]);
-    max_opening_sequence++;
-  } while ( pattern_data[n] != END_OF_SEQUENCES );
-  fprintf(fd,"  %d\n};\n",pattern_data[n++]);
-#ifdef DEBUG_PATTERN
-  assert(n == pindex);
-#endif
-  fprintf(fd,"\n#define MAX_OPENING_SEQUENCE %d\n",max_opening_sequence);
-  fprintf(fd,"\n#define MAX_PATTERN %d\n",max_pattern);
-  fclose(fd);
-}
-
-
-#endif
-
-
-
-void
-GetOpeningPatterns (short *max_opening_sequence)
-
-{
-  short pindex = 0;
-  short os = 0;
-  short p = 0;
-  short i;
-
-  do {
-    OpeningSequence[os].opening_type = pattern_data[pindex++];
-    OpeningSequence[os].first_pattern[0] = p;
-    for ( i=1; i<MAX_SEQUENCE; i++ )
-      OpeningSequence[os].first_pattern[i] = END_OF_PATTERNS;
-    do {
-      Pattern[p].reachedGameCnt[black] = MAXMOVES;
-      Pattern[p].reachedGameCnt[white] = MAXMOVES;
-      Pattern[p].first_link = pindex;
-      while ( pattern_data[pindex] != END_OF_LINKS ) pindex++;
-      pindex++;
-      Pattern[p].first_field = pindex;
-      while ( pattern_data[pindex] != END_OF_FIELDS ) pindex += 2;
-      pindex++;
-      if ( pattern_data[pindex] != END_OF_PATTERNS )
-       Pattern[p].next_pattern = p+1;
-      else 
-       Pattern[p].next_pattern = END_OF_PATTERNS;
-      p++;
-    } while (pattern_data[pindex] != END_OF_PATTERNS );
-    pindex++;
-    os++;
-  } while ( pattern_data[pindex] != END_OF_SEQUENCES ); 
-  *max_opening_sequence = os;
-}
-                            
-
-
-void
-ShowOpeningPatterns (short max_opening_sequence)
-
-{ 
-  short os, p, n, i;
-
-  for ( os=0; os<max_opening_sequence; os++ ) {
-    char name[16];
-    NameOfOpeningValue(OpeningSequence[os].opening_type, name);
-    printf("Opening Type: %s\n",name);
-    for ( p=OpeningSequence[os].first_pattern[0],n=0; p != END_OF_PATTERNS; p=Pattern[p].next_pattern,n++ ) {
-      printf("Pattern %d (%d) with links ",p,n);
-      for ( i=Pattern[p].first_link; pattern_data[i]!=END_OF_LINKS; i++ ) {
-        printf("%d ",pattern_data[i]);
-      }
-      printf("\n");
-      DisplayPattern(stdout,Pattern[p].first_field);
-    } 
-  }
-
-}
-
-
-void set_field (short i, struct PatternField *field)
-{
-      field->piece  = pattern_data[i];
-      field->square = pattern_data[i+1];
-      if ( field->square < 0 ) {
-        field->square = -(field->square);
-        field->side  = white;
-      } else {
-        field->side  = black;
-      }
-}
-
-
-
-short
-piece_to_pattern_distance 
-  (short side, short piece, short pside, short pattern)
-
-/*
- * Determine the minimum number of moves from the current position
- * to a specific pattern for a specific piece.
- * Consider the "side" piece of the pattern.
- * The pattern should match for "pside".
- */
-{
-  short nP, P[4], nB, B[4]; /* at most 4 pieces of same kind */
-  short nC, i, j, r, dd, occupied, mindd, c[4], d[4];
-  short c1 = side ^ pside; /* a "side" patternfield must match a "c1" piece on board */
-  
-  /*
-   * If pside == white, a black piece in the pattern should match
-   * a white piece on board, and vice versa. Furthermore, if
-   * pside == white, reversed pattern should match board.
-   */
-
-  /* special pawn handling */     
-
-  if ( piece == pawn ) {
-    mindd = occupied = 0; 
-    for ( i = Pattern[pattern].first_field; pattern_data[i] != END_OF_FIELDS; i += 2 ) {
-      struct PatternField field;
-      set_field(i, &field);
-      if ( (field.side == side) && (field.piece == pawn) ) {
-       short t = field.square;
-        short pcol = column(t);
-       dd = CANNOT_REACH;
-       if ( PawnCnt[c1][(side == c1) ? pcol : (8 - pcol)] ) {
-         /* there is a pawn on the column */
-          for ( j = 0; j <= PieceCnt[c1]; j++) {
-           short sq = (short)PieceList[c1][j];
-           if ( board[sq] == pawn ) {
-             if ( pside == white ) sq = NO_SQUARES - 1 - sq;
-              if ( column(sq) == pcol ) {
-               dd = piece_distance (side, pawn, sq, t);
-#ifdef TEST_PATTERN 
-                printf("update %d pawn from %d to %d is %d\n", side, sq, t, dd);
-#endif                                       
-                break;
-             } 
-           } 
-         }
-        } else {
-         /* there is no pawn on the column; drop possible? */
-         if ( Captured[c1][pawn] ) {
-           dd = 1;
-#ifdef TEST_PATTERN
-            printf("update %d pawn drop to %d is %d\n", side, t, dd);
-#endif                                       
-         }
-        }  
-       if ( dd >= 0 ) {
-         /* Increment distance if pattern field is occupied */
-         short psq, pc;
-          if ( pside == black ) {
-           psq = t;
-           pc = field.side;
-         } else {
-           psq = (NO_SQUARES - 1 - t);
-           pc = ~field.side;
-         }
-         if ( (color[psq] == pc) && (board[psq] != pawn) ) {
-#ifdef TEST_PATTERN
-            printf("square %d is occupied\n", psq);
-#endif                                       
-           ++occupied;            
-         }
-         mindd += dd;
-        } else {
-         return (CANNOT_REACH);
-       }
-      }
-    }
-    return (mindd + occupied);
-  }
-
-  /* 
-   * Determine list of "side" "piece"s in pattern. 
-   */
-
-  for ( occupied = nP = 0, i = Pattern[pattern].first_field; pattern_data[i] != END_OF_FIELDS; i+=2 ) {
-       struct PatternField field;
-       set_field(i, &field);
-       if ( (field.side == side) && (field.piece == piece) ) {
-         short psq, pc;
-         P[nP] = field.square;
-#ifdef TEST_PATTERN
-          printf("pattern %d piece %d on square %d\n",side,piece,P[nP]);
-#endif
-         nP++;
-         /* Increment distance if pattern field is occupied */
-          if ( pside == black ) {
-           psq = field.square;
-            pc = field.side;
-          } else {
-           psq = (NO_SQUARES - 1 - field.square);
-           pc = field.side ^ 1;
-          }
-         if ( (color[psq] == pc) && (board[psq] != field.piece) ) {
-#ifdef TEST_PATTERN
-            printf("square %d is occupied\n", psq);
-#endif                                       
-           ++occupied;            
-         }
-       }
-  }
-
-  if ( nP == 0 )
-    return (0);
-
-#ifdef TEST_PATTERN
-  printf("finding in pattern %d pieces %d of side %d\n", nP, piece, side);
-#endif
-
-  /* 
-   * Determine list of "side ^ pside" "piece"s captured or on board. 
-   */
-
-  for ( nB = 0; nB < Captured[c1][piece]; nB++ )
-    B[nB] = NO_SQUARES + piece;
-
-  for ( i = 0; i <= PieceCnt[c1]; i++ ) {
-       short sq = PieceList[c1][i];
-       if ( board[sq] == piece ) {
-         B[nB] = (pside == black) ? sq : (NO_SQUARES - 1 - sq);
-#ifdef TEST_PATTERN
-         printf("%d piece %d on square %d\n",side,piece,B[nB]);
-#endif
-         nB++;
-       }
-  }
-
-#ifdef TEST_PATTERN
-  printf("found on board %d pieces %d of side %d\n", nB, piece, side);
-#endif
-
-  if ( nP > nB ) {
-    return (CANNOT_REACH);
-  }
-
-  /* Determine best assignment from board piece to pattern piece */
-
-  r = 0; c[0] = -1; mindd = CANNOT_REACH;
-
-  while ( (r >= 0) && (mindd != 0) ) {
-
-    if ( ++c[r] == nB ) {
-       r--;
-    } else {
-       for ( i = 0; i < r; i++ )
-         if ( c[i] == c[r] )
-           break;
-       if ( i == r ) {
-         d[r] =  piece_distance (side, piece, B[c[r]], P[r]);
-#ifdef TEST_PATTERN
-          printf("update d[%d] from  %d to %d is %d\n", r, B[c[r]], P[r], d[r]);
-#endif
-         if ( d[r] < 0 ) {
-           /* r--; */
-         } else {
-           if ( ++r == nP ) {
-               for (dd = i = 0; i < nP; i++)
-                 dd += d[i];
-               if ( (dd < mindd) || (mindd < 0) ) {
-                 mindd = dd;        
-#ifdef TEST_PATTERN
-                  printf("update min %d\n", mindd);
-#endif
-               }
-               r--;
-           } else
-               c[r] = -1;
-         }
-       }
-    }
-
-  }
-               
-  if ( mindd < 0 )
-    return (CANNOT_REACH);
-  else
-    return (mindd + occupied);
-
-}
-
-
-short
-pattern_distance (short pside, short pattern)
-
-/*
- * Determine the minimum number of moves for the pieces from
- * the current position to reach a pattern.
- * The result is CANNOT_REACH, if there is no possible sequence
- * of moves.
- */
-
-{
-   short side, piece, d, n;
-
-#ifdef TEST_PATTERN
-   printf("\nchecking pattern %d for pside=%d\n\n",pattern,pside);
-#endif
-
-   for ( n = side = 0; side <= 1 && n >= 0; side++ )
-     for ( piece = pawn; piece <= king; piece++ ) {
-       d = piece_to_pattern_distance (side, piece, pside, pattern);
-       if ( d < 0 ) {
-         n = CANNOT_REACH; break;
-       } else
-         n += d;
-     }
-
-#ifdef TEST_PATTERN
-   printf("\ndistance to pattern is %d\n\n",n);
-#endif
-
-   return (n);
-       
-}
-
-
-short
-board_to_pattern_distance 
-  (short pside, short osequence, short pmplty, short GameCnt)
-
-/*
- * Determine the maximal difference of the number of moves from the pattern 
- * to the initial position and to the current position.
- * Differences are weighted, i.e. the more closer a position is to a pattern
- * the more valuable is a move towards the pattern.
- * Patterns, which are at least "pmplty" halfmoves away, are not counted.
- */
-
-{
-   short i, d, dist, diff, weighted_diff;
-   short maxdiff = 0, max_weighted_diff = 0;
-   short pattern;
-
-#ifdef DEBUG_EVAL
-   if ( debug_eval ) {
-     char name[MAX_NAME];
-     NameOfOpeningValue(OpeningSequence[osequence].opening_type,name);
-     fprintf(debug_eval_file,"board to %s pattern distance pside=%s, pmplty=%d, GameCnt=%d\n",
-       name, ColorStr[pside], pmplty, GameCnt);
-   }
-#endif
-           
-   for ( i=0; i<MAX_SEQUENCE; i++ )
-    for ( pattern = OpeningSequence[osequence].first_pattern[i]; pattern != END_OF_PATTERNS; pattern = Pattern[pattern].next_pattern ) {
-#ifdef DEBUG_EVAL
-     if ( debug_eval )
-       fprintf(debug_eval_file,"%spattern %d",
-                       (i?"common ":""),pattern);
-#endif
-     if ( (d = Pattern[pattern].distance[pside]) >= 0 ) {
-#ifdef DEBUG_EVAL 
-       if ( debug_eval )
-           fprintf(debug_eval_file," initially reachable in %d steps\n",d);
-#endif
-       if ( pmplty > d ) 
-         { 
-          dist = pattern_distance (pside, pattern);
-           if ( dist >= 0 )
-             { 
-              /* "dist" is the distance of the current board position to the pattern.
-               * "d - dist" is the difference between the current distance and the 
-               * initial distance. Compute "diff" as the weighted difference.
-               */
-#ifdef DEBUG_EVAL 
-               if ( debug_eval ) {
-                  fprintf(debug_eval_file," now reachable in %d steps\n",dist);
-                  DisplayPattern(debug_eval_file,Pattern[pattern].first_field);
-              }
-#endif
-              /* try to reach the nearest pattern */
-              weighted_diff = (diff = (d - dist)) * (pmplty - d);
-              if ( weighted_diff > max_weighted_diff ) {
-#ifdef COUNT_DIFF
-                 maxdiff = diff; 
-#else
-                 maxdiff = weighted_diff; 
-#endif
-                 max_weighted_diff = weighted_diff;
-#ifdef DEBUG_EVAL 
-                  if ( debug_eval )
-                     fprintf(debug_eval_file,"current maximum gain %d\n",maxdiff);
-#endif
-              } 
-#ifdef DEBUG_EVAL 
-              else {
-                  if ( debug_eval )
-                     fprintf(debug_eval_file,"gain %d\n",diff);
-              }
-#endif
-              /* A reached pattern should not be considered in the future (if GameCnt >= 0) */
-              if ( dist == 0 && GameCnt >= 0)
-                {
-                  Pattern[pattern].reachedGameCnt[pside] = GameCnt;
-#ifdef DEBUG_EVAL 
-                   if ( debug_eval )
-                     fprintf(debug_eval_file,"pattern reached in move %d\n",GameCnt);
-#endif
-                }
-             }
-#ifdef DEBUG_EVAL
-          else          
-           if ( debug_eval )
-             fprintf(debug_eval_file," now unreachable\n");
-#endif
-        }
-#ifdef DEBUG_EVAL 
-       else 
-        {
-           if ( debug_eval )
-             fprintf(debug_eval_file," beyond %d steps\n",pmplty);
-         }         
-#endif
-     } 
-#ifdef DEBUG_EVAL
-     else {
-       if ( debug_eval )
-         fprintf(debug_eval_file,
-                 (d == NOT_TO_REACH) ? " not to reach\n" : 
-                 (d == IS_REACHED) ? " is reached\n" : 
-                 (d == IS_SUCCESSOR) ? " is successor\n" : " cannot reach\n");
-     }
-#endif
-   }
-   
-   return (maxdiff);
-       
-}
-
-
-void
-DisplayPattern (FILE *fd, short n)
-
-{
-  small_short pboard[NO_SQUARES], pcolor[NO_SQUARES];
-  short sq, i,  r, c;
-
-  for (sq = 0; sq < NO_SQUARES; sq++)
-    {      
-      pboard[sq] = no_piece;
-      pcolor[sq] = neutral;
-    }
-
-  for (i = n; pattern_data[i] != END_OF_FIELDS; i += 2)
-    {
-      struct PatternField field;
-      set_field(i,&field);
-      pboard[field.square] = field.piece;
-      pcolor[field.square] = field.side;
-    }
-
-  for (r = NO_ROWS-1; r >= 0; r--)
-    {
-      for (c = 0; c < NO_COLS; c++)
-        {
-         sq = r*NO_COLS + c;
-         i = pboard[sq];
-         if ( i == no_piece )
-           fprintf(fd," -");
-         else
-           fprintf(fd,"%c%c",is_promoted[i]?'+':' ',pcolor[sq]?pxx[i]:qxx[i]);
-        }
-      fprintf(fd,"\n");
-    }
-
-  fprintf(fd,"\n");
-
-}                 
-
-
-
-
-static
-void
-VisitReachable (int pside, short osequence, int k, int n, int remove)
-{
-  short i,j;
-  short pattern;
-       
-#ifdef DEBUG_PATTERN
-  printf("visit reachable %d %d %s\n",k,n,remove?"remove":"");
-#endif
-
-  /* Adjust to sequence pattern n */                       
-  for (i=0,pattern=OpeningSequence[osequence].first_pattern[k]; i<n; i++)
-      pattern = Pattern[pattern].next_pattern;
-
-#ifdef DEBUG_PATTERN
-  printf("pattern id = %d\n",pattern);
-#endif
-
-  /* do not perform visited link twice */
-  if ( Pattern[pattern].visited ) {
-#ifdef DEBUG_PATTERN
-      printf("pattern %d %d visited\n",n,pattern);
-#endif
-      return;
-  } else
-      Pattern[pattern].visited = true;
-
-  /* Declare links unreachable */
-  for (j=Pattern[pattern].first_link; pattern_data[j] != END_OF_LINKS; j++)
-    VisitReachable(pside,osequence,k,pattern_data[j],remove);
-
-  /* Declare unreachable */
-  if ( remove && Pattern[pattern].distance[pside] >= 0 )  {
-    Pattern[pattern].distance[pside] = IS_SUCCESSOR;
-#ifdef DEBUG_PATTERN
-    printf("removing %d\n",n);
-#endif
-  }
-
-}      
-
-                                               
-/* simplified matching for opening type names */
-                   
-#define match_char(a,b) (a == b || (a == '*' && b != 'U') || (b == '*' && a != 'U'))
-#define match_name(a,b,l) (l>8 && match_char(a[0],b[0]) && match_char(a[7],b[7]) && match_char(a[9],b[9])) 
-
-
-short locate_opening_sequence(short pside, char *s, short GameCnt)
-
-{ 
-   short i,j,k, os, removed, d;
-#ifdef DEBUG_PATTERN
-   short n = 0, m = 0;
-#endif
-   short l = strlen(s); 
-   short check_visited[MAX_SEQUENCE];
-   char name[MAX_NAME], name2[MAX_NAME];   
-
-  /* 
-   * Look for opening pattern name in the list of opening patterns.
-   */
-
-   name[0] = '\0';
-   for ( i = 1,os = 0; os<MAX_OPENING_SEQUENCE; os++ )
-     { 
-       /* locate matching opening type name */
-        NameOfOpeningValue(OpeningSequence[os].opening_type,name);
-#ifdef notdef
-       printf("try to match %s with %s\n",s,name);
-#endif
-       if ( match_name(s,name,l) ) {
-#ifdef DEBUG_PATTERN
-         printf("%s matches pattern %d %s\n",s,os,name);
-#endif
-         /* locate successor matching names */
-         for ( k=os+1; k<MAX_OPENING_SEQUENCE; k++ ) {
-            NameOfOpeningValue(OpeningSequence[k].opening_type,name2);
-           if ( match_name(s,name2,l) ) {
-#ifdef DEBUG_PATTERN
-             printf("%s matches pattern %d %s [%d]\n",s,k,name2,i);
-#endif
-             OpeningSequence[os].first_pattern[i++] = OpeningSequence[k].first_pattern[0];
-           }
-         }
-          break;
-        }
-     }
-
-   if ( os>=MAX_OPENING_SEQUENCE )
-     return(END_OF_SEQUENCES);
-   else     
-     for ( ; i<MAX_SEQUENCE; OpeningSequence[os].first_pattern[i++] = END_OF_PATTERNS);
-
-#ifdef DEBUG_PATTERN                             
-   printf("%s uses opening line %s\n",ColorStr[pside],name);
-#endif
-
-  /*
-   * Determine patterns which can be reached from the current
-   * board position. Only patterns which can be reached will be
-   * checked in the following search.
-   */           
-
-   for ( i=0; i<MAX_SEQUENCE; i++) {
-    check_visited[i] = false;
-    for ( k=OpeningSequence[os].first_pattern[i]; k!=END_OF_PATTERNS; k=Pattern[k].next_pattern )
-       Pattern[k].visited = false; 
-   }
-       
-   for ( i=0; i<MAX_SEQUENCE; i++) 
-    for ( k=OpeningSequence[os].first_pattern[i]; k!=END_OF_PATTERNS; k=Pattern[k].next_pattern )
-     {
-       Pattern[k].distance[pside] = pattern_distance(pside,k);
-       /* Actually reached patterns need not to be observed. */
-       if ( Pattern[k].distance[pside] == 0 ) {
-        Pattern[k].distance[pside] = CANNOT_REACH;
-#ifdef DEBUG_PATTERN
-         printf("pattern id=%d removed because reached\n",k);
-         DisplayPattern(stdout,Pattern[k].first_field);
-#endif                         
-        check_visited[i] = Pattern[k].visited = true;                           
-         for (j=Pattern[k].first_link; pattern_data[j]!=END_OF_LINKS; j++) {
-#ifdef DEBUG_PATTERN
-           printf("visit successors for link %d\n",pattern_data[j]);
-#endif
-           VisitReachable(pside,os,i,pattern_data[j],false);  
-        }
-       } else if ( GameCnt >= 0 && GameCnt >= Pattern[k].reachedGameCnt[pside] ) {
-        Pattern[k].distance[pside] = IS_REACHED; 
-#ifdef DEBUG_PATTERN
-         printf("pattern %d removed because reached at GameCnt %d below current %d\n",
-                       k,Pattern[k].reachedGameCnt[pside],GameCnt);
-#endif
-       }
-       if ( Pattern[k].reachedGameCnt[pside] >= GameCnt )
-         Pattern[k].reachedGameCnt[pside] = MAXMOVES;
-     }            
-                            
-  /*
-   * Remove reachable patterns from search, which are successors of
-   * reachable patterns. So, only the next pattern of a pattern sequence
-   * is observed. 
-   */                    
-    
-   for ( i=0; i<MAX_SEQUENCE; i++)
-    for ( k=OpeningSequence[os].first_pattern[i]; k!=END_OF_PATTERNS; k=Pattern[k].next_pattern ) {
-       if ( check_visited[i] && !Pattern[k].visited ) {
-         Pattern[k].distance[pside] = NOT_TO_REACH;
-#ifdef DEBUG_PATTERN
-         printf("pattern id = %d removed because no successor of reached pattern\n",
-                       k);
-#endif
-       } else
-         Pattern[k].visited = false;
-    }  
-
-#ifdef DEBUG_PATTERN
-   for ( i=0; i<MAX_SEQUENCE; i++)
-    for (k=OpeningSequence[os].first_pattern[i]; k!=END_OF_PATTERNS; k=Pattern[k].next_pattern) {
-       short d = Pattern[k].distance[pside];
-       assert(!Pattern[k].visited);                                           
-        printf("%d %s\n",k,
-                 (d == NOT_TO_REACH) ? " not to reach" : 
-                 (d == IS_REACHED) ? " is reached" : 
-                 (d == IS_SUCCESSOR) ? " is successor" : " cannot reach");
-    }
-#endif
-       
-   for ( i=0; i<MAX_SEQUENCE; i++)
-    for (k=OpeningSequence[os].first_pattern[i]; k!=END_OF_PATTERNS; k=Pattern[k].next_pattern)
-     if ( (d = Pattern[k].distance[pside]) >= 0 ) {
-       for (j=Pattern[k].first_link; pattern_data[j]!=END_OF_LINKS; j++) {
-#ifdef DEBUG_PATTERN
-         printf("removing successors for link %d\n",pattern_data[j]);
-#endif
-         VisitReachable(pside,os,i,pattern_data[j],true);  
-       }
-     }
-
-  /*
-   * Look, whether there is still a reachable pattern.
-   */  
-
-   for ( i=0; i<MAX_SEQUENCE; i++ )
-    for ( k=OpeningSequence[os].first_pattern[i]; k!=END_OF_PATTERNS; k=Pattern[k].next_pattern )
-     if ( (d = Pattern[k].distance[pside]) >= 0 )
-       {
-#ifdef DEBUG_PATTERN
-         for ( i=n=m=0; i<MAX_SEQUENCE; i++ )
-          for (k=OpeningSequence[os].first_pattern[i]; k!=END_OF_PATTERNS; k=Pattern[k].next_pattern,n++)
-            if ( (d = Pattern[k].distance[pside]) >= 0 )
-             m++;
-        printf("%d reachable %s patterns out of %d patterns\n",
-                       m,ColorStr[pside],n);
-#endif
-         return(os);
-       }
-
-#ifdef DEBUG_PATTERN
-   printf("all %s patterns out of %d patterns (%d reachable) removed\n",
-               ColorStr[pside],n,m);
-#endif
-
-   return (END_OF_SEQUENCES);
-}
-
-
-void update_advance_bonus (short pside, short os)
-{
-   struct PatternField field;
-   short i, j, k, d;
-               
-   for ( j=0; j<MAX_SEQUENCE; j++ )
-    for ( k=OpeningSequence[os].first_pattern[j]; k!=END_OF_PATTERNS; k=Pattern[k].next_pattern )
-     if ( (d = Pattern[k].distance[pside]) >= 0 )
-       {
-          for ( i = Pattern[k].first_field; pattern_data[i]!=END_OF_FIELDS; i+=2 ) {
-           set_field(i,&field);
-           if ( field.side == black ) {
-               short square = (pside == black) 
-                               ? field.square 
-                               : NO_SQUARES - 1 - field.square;
-               (*Mpiece[field.piece])[pside][square] += ADVNCM[field.piece];
-           }
-         }
-       }
-}