Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: Chess program that learns from PGN

Author: Dann Corbit

Date: 11:02:59 03/03/05

Go up one level in this thread


On March 03, 2005 at 02:13:39, pavel wrote:

>I remember sometime ago there was this chess program (possibly winboard
>compatible), that used to learn by parsing pgn file.
>
>I forgot the name of the program or where I can get it. Does anyone remember
>what program I am talking about?

Beowulf has a command to study a PGN file.
http://www.chessbrain.net/beowulf/

Here is the code involved:
/* Study a pgn file for adding to the opening book.
 * Parses each game and plays through it until the first
 * unknown position or move is encountered.  If the side
 * to move eventually wins then it learns that position
 * and the best move. */
void StudyFile(void) {
  char PGNFile[FILENAME_MAX],temp[10]="",FEN[100],AcceptDraws, Verbose, Weight;
  Board B;
  MOVE *moves,move,bookmove;
  int maxdepth,nmoves,elo,minelo,minlength,n,opno,m,winner,longest=0;
  int NumGames=0, NewPositions=0, NewMoves=0, breakout=0,from,to;
  Openpos *O;
  FILE *fp;

  /* Get directory listing */
  fprintf(stdout,"Directory of PGN Files\n\n");
  (void)system(DIR_COMMAND"*.pgn");
  fprintf(stdout,"\nPlease Choose : ");
  /* Get chosen filename */
  (void)fgets(PGNFile,50,stdin);
  PGNFile[strlen(PGNFile)-1]=0;
  if (!strstr(PGNFile,".pgn")) strcat(PGNFile,".pgn");

  /* Try to open chosen file */
  if ((fp = fopen(PGNFile,"r"))==NULL) {
    fprintf(stdout,"Can't Open File %s!\n",PGNFile);
    return;
  }
  fprintf(stdout,"%s Loaded OK!\n",PGNFile);

  do {
    fprintf(stdout,"Maximum Number of Ply to Examine [>=1] : ");
    (void)fgets(temp,sizeof(temp),stdin);
    maxdepth = (int)strtol(temp,NULL,10);
  } while (maxdepth<1);

  do {
    fprintf(stdout,"Minimum ELO of Winning Player [>=0] : ");
    (void)fgets(temp,sizeof(temp),stdin);
    minelo = (int)strtol(temp,NULL,10);
  } while (minelo<0);

  do {
    fprintf(stdout,"Minimum Game Length (ply) [>=1] : ");
    (void)fgets(temp,sizeof(temp),stdin);
    minlength = (int)strtol(temp,NULL,10);
  } while (minlength<1);

  do {
    fprintf(stdout,"Accept Drawn Games? [Y/N] : ");
    (void)fgets(temp,sizeof(temp),stdin);
    AcceptDraws = toupper(temp[0]);
  } while (AcceptDraws != 'N' && AcceptDraws != 'Y');

  do {
    fprintf(stdout,"Verbose Output? [Y/N] : ");
    (void)fgets(temp,sizeof(temp),stdin);
    Verbose = toupper(temp[0]);
  } while (Verbose != 'N' && Verbose != 'Y');

  do {
    fprintf(stdout,"Weight Moves by ELO? [Y/N] : ");
    (void)fgets(temp,sizeof(temp),stdin);
    Weight = toupper(temp[0]);
  } while (Weight!= 'N' && Weight != 'Y');

  if (Verbose == 'N') fprintf(stdout,"Studying ");

  /* Load in the games, one at a time, and study them */
  do {

    /* Load in the next game */
    moves = ImportPGNGame(fp,&winner,&nmoves,&elo, NULL, NULL);

    // Dud game?
    if (moves == NULL || nmoves==0) {
      fprintf(stdout,"x");
      break;
    }

    breakout = 0;
    NumGames++;

     /* Print game details */
    if (Verbose == 'Y') {
      fprintf(stdout,"\nLoaded Game Number %d  :  %d Moves, Winner =
",NumGames,nmoves);
      switch(winner) {
        case (WHITE) : fprintf(stdout,"White  "); break;
        case (BLACK) : fprintf(stdout,"Black  "); break;
        default      : fprintf(stdout,"Drawn  "); break;
      }
      if (winner != NEUTRAL) {
        fprintf(stdout,"Winning ELO = ");
        if (elo > 0) fprintf(stdout,"%d",elo);
        else fprintf(stdout,"Unknown");
      }
      fprintf(stdout,"\n");
      if (elo < minelo) fprintf(stdout,"Winner's ELO (%d) too low -
Skipping!\n",elo);
      if (nmoves < minlength) fprintf(stdout,"Game too short (%d moves) -
Skipping!\n",nmoves);
      if (AcceptDraws == 'N' &&  winner == NEUTRAL) fprintf(stdout,"Game was a
draw - Skipping!\n");
    }
     /* Print (tidy) progress */
    else {
      if (NumGames % 1000 == 0) fprintf(stdout,"[%d]",NumGames);
      else if (NumGames % 100 == 0) fprintf(stdout,"x");
      else fprintf(stdout,".");
    }

     /* Check to see if we can reject this game */
    if (elo < minelo) {free(moves); continue;}
    if (nmoves < minlength) {free(moves); continue;}
    if (AcceptDraws == 'N' &&  winner == NEUTRAL) {free(moves); continue;}

    ResetBoard(&B);
    /* Step through the moves */
    for (n=0;n<nmoves;n++) {
      // Set up this move
      if (Verbose == 'Y') fprintf(stdout,"%d ",n+1);
      move = moves[n];
      assert(move != NO_MOVE);
      if (n >= maxdepth) break;
      if (n>longest) longest = n;

      /* Skip moves for the losing side */
      if (B.side != winner && winner != NEUTRAL) {
        (void)DoMove(&B, move);
        continue;
      }

      /* Get the FEN for the current board */
      BoardToFEN(&B,FEN);

      /* Cycle through the positions in the opening book */
      for (opno=0;opno<NPos;opno++) {
        O = (Openings+opno);

        /* See if this opening book entry matches the current board position */
        if (!strcmp(FEN,O->FEN)) {
          assert(O->nmoves > 0);

          /* It matches!  Now check the moves to see if the move played is
           * already stored. */
          for (m=0;m<O->nmoves;m++) {
            bookmove = O->m[m];
            from = MFrom(bookmove); to = MTo(bookmove);
            /* Check if this is an en-passant move */
            if (!IsEP(bookmove) && PType(B.pieces[from])==pawn &&
File(to)!=File(from) && B.pieces[to]==empty)
              bookmove |= SPECIAL_FLAG;
            /* Check if this is a castling move */
            if (!IsCastle(bookmove)) {
              if (PType(B.pieces[from])==king && File(from)==FileE &&
File(to)==FileC)
                bookmove |= SPECIAL_FLAG;
              if (PType(B.pieces[from])==king && File(from)==FileE &&
File(to)==FileG)
                bookmove |= SPECIAL_FLAG;
            }
            /* If we've found this exact move - just increase its weighting by
an amount
            * varying with the ELO of whoever played it.  If the score is
currently
            * zero then leave it alone (this is a move that we want to be aware
of,
            * but never actually play). */
            if (bookmove == move && O->sc[m]>0) {
              if (Weight == 'Y') O->sc[m] += ELOBonus(elo);
              else O->sc[m]++;
            }
            if (bookmove == move) break;
          }
          /* This is a new move - add it to the list */
          if (m == O->nmoves) {
            (O->nmoves)++;
            O->m  = (MOVE *)realloc(O->m,sizeof(MOVE)*(m+1));
            O->sc = (int *)realloc(O->sc,sizeof(int)*(m+1));
            assert(O->m != NULL);
            assert(O->sc != NULL);
            O->m[m] = move;
            O->sc[m] = ELOBonus(elo);
            if (Verbose == 'Y') {
              fprintf(stdout,"\nExisting Position %s\n",FEN);
              fprintf(stdout,"Added New Move ");
              PrintMove(move,FALSE,stdout);
            }
            /* Stop parsing this game */
            breakout = 1;
            NewMoves++;
          }
          break;
        }
      }

      /* This position was not found - add it! */
      if (opno == NPos) {
        NPos++;
        if (NPos>1) Openings = (Openpos
*)realloc(Openings,sizeof(Openpos)*NPos);
        else Openings = (Openpos *)malloc(sizeof(Openpos));
        assert(Openings != NULL);
        O = (Openings+opno);
        O->FEN = (char *)malloc(sizeof(char)*(strlen(FEN)+1));
        assert(O->FEN != NULL);
        strncpy(O->FEN,FEN,strlen(FEN));
        O->FEN[strlen(FEN)]=0;
        O->nmoves = 1;
        O->m = (MOVE *)malloc(sizeof(MOVE));
        O->sc = (int *)malloc(sizeof(int));
        assert(O->m != NULL);
        assert(O->sc != NULL);
        O->m[0] = move;
        O->sc[0] = ELOBonus(elo);
        if (Verbose == 'Y') {
          fprintf(stdout,"\nLearning New Position %s\n",FEN);
          fprintf(stdout,"Best Move ");
          PrintMove(move,FALSE,stdout);
        }
        /* Stop parsing this game */
        breakout = 1;
        NewPositions++;
      }
      if (breakout) break;
      (void)DoMove(&B,move);
    }
    free(moves);
    if (Verbose == 'Y') fprintf(stdout,"\n");
  } while (!feof(fp));

  /* Close the input file handle */
  fclose(fp);

  /* Print out the results */
  fprintf(stdout,"\nFile %s Studied\n",PGNFile);
  fprintf(stdout,"Total Games         : %d\n",NumGames);
  fprintf(stdout,"Total New Positions : %d\n",NewPositions);
  fprintf(stdout,"Total New Moves     : %d\n",NewMoves);
  fprintf(stdout,"Longest Line        : %d\n\n",longest);
  fprintf(stdout,"Type 'savebook' to write out the new positions\n\n");
}



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.