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.