Discussion of chess software programming and technical issues.
Moderators: hgm , Rebel , chrisw
Osipov Jury
Posts: 186 Joined: Mon Jan 21, 2008 2:07 pm
Location: Russia
Post
by Osipov Jury » Tue Apr 15, 2008 12:33 pm
Code: Select all
#include "stdio.h"
#include "io.h"
#include "windows.h"
struct BOOK {
unsigned char move_from;
unsigned char move_to;
unsigned char move_promo;
unsigned char priority;
unsigned int games;
unsigned int won_games;
unsigned int lost_games;
unsigned int hz;
int first_child;
int next_sibling;
} *book;
FILE * ft;
int linelength = 0;
void print_head()
{ fprintf(ft,"[White \"Alpha\"]\n");
fprintf(ft,"[Black \"Beta\"]\n\n");
}
void print_move(unsigned char move_from, unsigned char move_to,
unsigned char move_promo, int ply)
{ if (linelength > 80) {
fprintf(ft,"\n");
linelength = 0;
}
if ((ply & 1) == 0) { fprintf(ft,"%d.", ply / 2 + 1); linelength += 3; }
fprintf(ft,"%c%d%c%d",
(move_from & 7) + 'a',(move_from >> 3) + 1,
(move_to & 7) + 'a',(move_to >> 3) + 1);
if (move_promo) fprintf(ft,"Q"); // allways queen: this is incorrect
fprintf(ft," ");
linelength += 5;
}
void main(int argc, char *argv[])
{ int i, ply, filesize;
int node[1000];
struct MOVE {
unsigned char move_from;
unsigned char move_to;
unsigned char move_promo;
} moves[1000];
if (argc < 2) {
printf("Simple command-line converter from ABK to PGN\n");
printf("Usage: abk.exe <abk_file>\n");
printf("Result PGN-file: out.pgn\n");
exit(0);
}
ft = fopen(argv[1], "rb");
if (ft == NULL) {
printf("Cann't open file %s\n",argv[1]);
exit(0);
}
filesize = filelength(fileno(ft));
book = malloc(filesize);
fread(book, filesize / sizeof(struct BOOK), sizeof(struct BOOK), ft);
fclose(ft);
ft = fopen("out.pgn","w");
print_head();
ply = 0;
node[0] = 900; // offset to first node in abk-file
while (1) {
print_move(book[node[ply]].move_from, book[node[ply]].move_to,
book[node[ply]].move_promo, ply);
if (book[node[ply]].first_child > 0) { // current game
moves[ply].move_from = book[node[ply]].move_from;
moves[ply].move_to = book[node[ply]].move_to;
moves[ply].move_promo = book[node[ply]].move_promo;
node[ply + 1] = book[node[ply]].first_child;
ply++;
}
else { // new game
fprintf(ft,"\n\n");
node[ply] = book[node[ply]].next_sibling;
while (node[ply] < 0) {
ply--;
if (ply < 0) { fclose(ft); exit(0); }
node[ply] = book[node[ply]].next_sibling;
}
print_head();
linelength = 0;
for (i = 0; i < ply; i++) {
print_move(moves[i].move_from, moves[i].move_to, moves[i].move_promo, i);
}
}
if (node[ply] >= filesize / (int)sizeof(struct BOOK)) {
printf("Error: out of file\n");
fclose(ft);
exit(0);
}
}
}
pijl
Post
by pijl » Tue Apr 15, 2008 5:03 pm
Osipov Jury wrote: Code: Select all
if (move_promo) fprintf(ft,"Q"); // allways queen: this is incorrect
I just made my own converter, which is rather simple to do. Instead of reading in the whole book, I fseek-ed through the file, following the move pointers. Windows will cache the file in memory anyway.
I did investigate the values for promotion as well:
Values for move_promo are signed and can have 9 values:
0: no promotion
-1, 1: rook promotion
-2, 2: knight promotion
-3, 3: bishop promotion
-4, 4: queen promotion
Richard.
Last edited by pijl on Tue Apr 15, 2008 5:06 pm, edited 1 time in total.
beachknight
Posts: 3533 Joined: Tue Jan 09, 2007 8:33 pm
Location: Antalya, Turkey
Post
by beachknight » Tue Apr 15, 2008 5:05 pm
Excellent, Yuri.
I wanted to merge all my arena opening books.
and there were no such code or utility.
Thank you!
Next step would be to create an online
converter that processes abk book to pgn.
With such a tool, I can obtain all pgns back;
process them further if necessary and create
my huge Arena book.
Any takers?
Best,
hi, merhaba, hallo HT
Dann Corbit
Posts: 12540 Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA
Post
by Dann Corbit » Wed Apr 16, 2008 2:37 am
I made a few small changes for my own purposes (mostly for post processing, since the PGN standard demands the 7 mandatory tags):
Code: Select all
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
struct BOOK {
unsigned char move_from;
unsigned char move_to;
unsigned char move_promo;
unsigned char priority;
unsigned int games;
unsigned int won_games;
unsigned int lost_games;
unsigned int hz;
int first_child;
int next_sibling;
} *book;
FILE *ft;
int linelength = 0;
void print_head()
{
fprintf(ft, "*\n\n");
fprintf(ft, "[Event \"?\"]\n");
fprintf(ft, "[Site \"?\"]\n");
fprintf(ft, "[Date \"????.??.??\"]\n");
fprintf(ft, "[Round \"?\"]\n");
fprintf(ft, "[Result \"*\"]\n");
fprintf(ft, "[White \"?\"]\n");
fprintf(ft, "[Black \"?\"]\n\n");
}
void print_move(unsigned char move_from, unsigned char move_to, unsigned char move_promo, int ply)
{
if ((move_from >> 3) + 1 == 32 && (move_to >> 3) + 1 == 32) return;
if (linelength > 80) {
fprintf(ft, "\n");
linelength = 0;
}
if ((ply & 1) == 0) {
fprintf(ft, "%d.", ply / 2 + 1);
linelength += 3;
}
fprintf(ft, "%c%d%c%d",
(move_from & 7) + 'a', (move_from >> 3) + 1,
(move_to & 7) + 'a', (move_to >> 3) + 1);
if (move_promo)
fprintf(ft, "Q"); // allways queen: this is incorrect
fprintf(ft, " ");
linelength += 5;
}
int main(int argc, char *argv[])
{
int i,
ply;
size_t filesize;
int node[1000];
struct MOVE {
unsigned char move_from;
unsigned char move_to;
unsigned char move_promo;
} moves[1000];
if (argc < 2) {
printf("Simple command-line converter from ABK to PGN\n");
printf("Usage: abk.exe <abk_file>\n");
printf("Result PGN-file: out.pgn\n");
exit(0);
}
ft = fopen(argv[1], "rb");
if (ft == NULL) {
printf("Can't open file %s\n", argv[1]);
exit(0);
}
filesize = filelength(fileno(ft));
book = malloc(filesize);
fread(book, filesize / sizeof(struct BOOK), sizeof(struct BOOK), ft);
fclose(ft);
ft = fopen("out.pgn", "w");
print_head();
ply = 0;
node[0] = 900; // offset to first node in abk-file
for (;;) {
print_move(book[node[ply]].move_from, book[node[ply]].move_to,
book[node[ply]].move_promo, ply);
if (book[node[ply]].first_child > 0) { // current game
moves[ply].move_from = book[node[ply]].move_from;
moves[ply].move_to = book[node[ply]].move_to;
moves[ply].move_promo = book[node[ply]].move_promo;
node[ply + 1] = book[node[ply]].first_child;
ply++;
} else { // new game
fprintf(ft, "\n");
node[ply] = book[node[ply]].next_sibling;
while (node[ply] < 0) {
ply--;
if (ply < 0) {
fclose(ft);
exit(0);
}
node[ply] = book[node[ply]].next_sibling;
}
print_head();
linelength = 0;
for (i = 0; i < ply; i++) {
print_move(moves[i].move_from, moves[i].move_to, moves[i].move_promo, i);
}
}
if (node[ply] >= filesize / (int) sizeof(struct BOOK)) {
printf("Error: out of file\n");
fclose(ft);
exit(0);
}
}
return 0;
}
beachknight
Posts: 3533 Joined: Tue Jan 09, 2007 8:33 pm
Location: Antalya, Turkey
Post
by beachknight » Wed Apr 16, 2008 8:53 pm
Is there any executable that takes *.abk book as input
and produce *.pgn as output.
I'd be glad to have such a tool.
Best to you,
hi, merhaba, hallo HT
beachknight
Posts: 3533 Joined: Tue Jan 09, 2007 8:33 pm
Location: Antalya, Turkey
Post
by beachknight » Wed Apr 16, 2008 9:39 pm
OS: WinXPSP2
Best!
hi, merhaba, hallo HT
Jim Ablett
Posts: 1383 Joined: Fri Jul 14, 2006 7:56 am
Location: London, England
Full name: Jim Ablett
Post
by Jim Ablett » Thu Apr 17, 2008 2:07 am
beachknight wrote: Is there any executable that takes *.abk book as input
and produce *.pgn as output.
I'd be glad to have such a tool.
Best to you,
Here's the compiled windows exe 'abk2pgn.exe' from Dann's modified src.
Works fine, but output still needs a little bit of post-processing
with pgn-extract/pgntrim.
http://www.zshare.net/download/10653257fcb8f902/
Jim.
CThinker
Posts: 388 Joined: Wed Mar 08, 2006 10:08 pm
Post
by CThinker » Thu Apr 17, 2008 7:02 am
One more modification...
Replace this:
Code: Select all
if (move_promo)
fprintf(ft, "Q"); // allways queen: this is incorrect
with this:
Code: Select all
if (move_promo) {
static const char prm[] = "RNBQ";
fprintf(ft, "%c", prm[abs(move_promo)-1]);
}
Jim Ablett
Posts: 1383 Joined: Fri Jul 14, 2006 7:56 am
Location: London, England
Full name: Jim Ablett
Post
by Jim Ablett » Thu Apr 17, 2008 10:07 am
CThinker wrote: One more modification...
Replace this:
Code: Select all
if (move_promo)
fprintf(ft, "Q"); // allways queen: this is incorrect
with this:
Code: Select all
if (move_promo) {
static const char prm[] = "RNBQ";
fprintf(ft, "%c", prm[abs(move_promo)-1]);
}
abk2pgn with Lance Perkins mod
http://www.zshare.net/download/106703053e39962e/
For cleaning up pgns I created a little batch script for my personal use
which run a series of pgn tools one after the other automatically (saves a lot of typing on the command line).
http://www.zshare.net/download/1067058909ff22e0/
This what it does automatically >
To clean/normalize and process a pgn file
Step 1: Backup original pgn file.
Step 2: 'Pgn-Extract' to remove duplicates.
Step 3: 'CleanTag' to remove erroneous tags.
Step 4: 'Trim' to correctly re-format pgn file.
Step 5: 'PgnMan' to add ECO to openings.
Step 6: 'AddElo' to fill in missing Elo tags.
Step 7: 'CleanUp' to remove incorrect null values.
Step 8: 'NameList' to produce player stats file.
Step 9: 'Ratelist' to produce player elo stats file
Step 10: Output completed/processed pgn 'processed.pgn' and stats files.
On the command line type:
-----------------------------------------------
process <name of pgn file>
EXAMPLE:
process anand.pgn
When completed directory will additionally contain >
1. processed.pgn - the fully cleaned/normalized/processed pgn file.
2. Ratelist.txt - Ratings list of all players contained in the pgn.
3. Namelist.txt - List of all players contained in the pgn.
Jim.