+++ /dev/null
-/*
- * 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];
- }
- }
- }
-}