The ProDeo (Rebel) EOC database as open source. 5 minutes away easily building the biggest chess tree in the word and use it to improve your chess engine.
Add the following features to your chess engine or even your chess interface:
Use an EOC database as an opening book;
Use an EOC database to guide the search;
Use it as a (book/position) learning system;
Use it for display purposes in your GUI.
All info at: http://www.top-5000.nl/eoc.htm
Ed
EOC databases now as open source
Moderators: hgm, Rebel, chrisw
-
- Posts: 3196
- Joined: Fri May 26, 2006 3:00 am
- Location: WY, USA
- Full name: Michael Sherwin
Re: EOC databases now as open source
Hi Ed,
Life is strange at times. There are coincidences all the time that we do not know wether they were intentional or accidental. There are often confluinces that lead people down virtually the same path with out realizing it. This seems as though this could be one of those times. As, RomiChess has had these abilities for almost a year now, almost exactly as how you describe them. RomiChess remembers every game she plays and stores it in a giant tree with percentages similar to yours including a bonus/penalty system. This tree is used as an opening book, as a book learner, as a position learner, to guide the search and has had the ability to merge an external database of millions of games. It has been demonstrated on this board and at the Winboard forum numerous times and shown that with not that many learned games that it can even beat much stronger learning engines like Glaurung 1.2.1 with a 90% plus score when dealing with a limited number of starting positions. I even emailed all this to you about six months ago and suggested that you do something similar for Pro Deo. I even sent/or_mentioned_where_you_could_get the_source_code for RomiChess, but with no reply from you.
I believe in pure coincidences and I will tell you of another ironic coincidence. After I had first released RomiChess I read your paper on chess programming and noted that our approaches were very similar and now our programs are even more similar! Although RomiChess pales in comparison to Rebel and Pro Deo.
Since so many people here are aware of my work and undoubtably can see the simularity of our learning systems it might be a good idea for you to address the above noted coincidences. After all, I always said that anyone can use and improve upon my learning system and all that I asked is to be given some credit. However, if you arrived at the same destination with out knowledge of my work then people aught to hear it from you, so they will not believe that you cloned someone else work, with out acknowledement.
I do appreciate this contribution that you have made and am very interested in how it has been improved. I hope that many programmers find it very useful!
Mike
Life is strange at times. There are coincidences all the time that we do not know wether they were intentional or accidental. There are often confluinces that lead people down virtually the same path with out realizing it. This seems as though this could be one of those times. As, RomiChess has had these abilities for almost a year now, almost exactly as how you describe them. RomiChess remembers every game she plays and stores it in a giant tree with percentages similar to yours including a bonus/penalty system. This tree is used as an opening book, as a book learner, as a position learner, to guide the search and has had the ability to merge an external database of millions of games. It has been demonstrated on this board and at the Winboard forum numerous times and shown that with not that many learned games that it can even beat much stronger learning engines like Glaurung 1.2.1 with a 90% plus score when dealing with a limited number of starting positions. I even emailed all this to you about six months ago and suggested that you do something similar for Pro Deo. I even sent/or_mentioned_where_you_could_get the_source_code for RomiChess, but with no reply from you.
I believe in pure coincidences and I will tell you of another ironic coincidence. After I had first released RomiChess I read your paper on chess programming and noted that our approaches were very similar and now our programs are even more similar! Although RomiChess pales in comparison to Rebel and Pro Deo.
Since so many people here are aware of my work and undoubtably can see the simularity of our learning systems it might be a good idea for you to address the above noted coincidences. After all, I always said that anyone can use and improve upon my learning system and all that I asked is to be given some credit. However, if you arrived at the same destination with out knowledge of my work then people aught to hear it from you, so they will not believe that you cloned someone else work, with out acknowledement.
I do appreciate this contribution that you have made and am very interested in how it has been improved. I hope that many programmers find it very useful!
Mike
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
-
- Posts: 12541
- Joined: Wed Mar 08, 2006 8:57 pm
- Location: Redmond, WA USA
Re: EOC databases now as open source
Ed Schroder is the nicest guy in the world.
The only problem is that you have set the bar too high for the rest of us!
The only problem is that you have set the bar too high for the rest of us!
-
- Posts: 1808
- Joined: Wed Mar 08, 2006 9:19 pm
- Location: Oslo, Norway
Re: EOC databases now as open source
Hello Michael,Michael Sherwin wrote:It has been demonstrated on this board and at the Winboard forum numerous times and shown that with not that many learned games that it can even beat much stronger learning engines like Glaurung 1.2.1 with a 90% plus score when dealing with a limited number of starting positions.
Just a pedantic correction: Glaurung 1.2.1 is not a learning engine in any meaningful sense of the word. It is true that there is a UCI parameter named "Position learning", but all this feature does is to remember the results of the last few searches from the root and store them to a an array and a small binary file. If you play a computer vs computer match, the entire learning file will probably be overwritten multiple times before the same position occurs again on the board. As a consequence, the learning feature almost certainly has no effect whatsoever in engine vs engine games.
The only purpose of the learning feature in Glaurung is to make the program a better analysis tool. During interactive analysis session, when Glaurung wants to play a move which you know is bad, show it why it is bad (by playing out the relevant lines on the board while Glaurung runs in analysis mode) and back up to the position you started with, and Glaurung will (hopefully) understand why the move is bad.
Because hardly anyone uses Glaurung as an analysis tool (and I can't blame them; the program is far too speculative to be reliable for analysis) and because nobody understands the purpose of the learning function, I've decided not to include it in future versions.
Of course, what I write above is not intended as criticism of the excellent work you have done on RomiChess' learning function - your results are certainly very impressive.
Tord
Re: EOC databases now as open source
Hi Michael,
Nice to meet a brother in EOC. I am sorry, I do not remember an email of yours, most likely it became a target of my spam filter as I do have the intention to answer email.
I had the EOC idea already in the early 90's but then the availability of games was so little the system made no sense at all so I never activated the code. It remained that way till 1998 till the volume of available games was high enough to justify a commercial release, see: http://www.rebel.nl/rebel10e.htm
I have retired from the playing strength circus but of curiosity reasons only I definitely going to try the EOC comp-comp database and find out if 6.x million comp-comp positions bring any difference.
This is big fun.
Regards,
Ed
Nice to meet a brother in EOC. I am sorry, I do not remember an email of yours, most likely it became a target of my spam filter as I do have the intention to answer email.
I had the EOC idea already in the early 90's but then the availability of games was so little the system made no sense at all so I never activated the code. It remained that way till 1998 till the volume of available games was high enough to justify a commercial release, see: http://www.rebel.nl/rebel10e.htm
I have retired from the playing strength circus but of curiosity reasons only I definitely going to try the EOC comp-comp database and find out if 6.x million comp-comp positions bring any difference.
This is big fun.
Regards,
Ed
Michael Sherwin wrote:Hi Ed,
Life is strange at times. There are coincidences all the time that we do not know wether they were intentional or accidental. There are often confluinces that lead people down virtually the same path with out realizing it. This seems as though this could be one of those times. As, RomiChess has had these abilities for almost a year now, almost exactly as how you describe them. RomiChess remembers every game she plays and stores it in a giant tree with percentages similar to yours including a bonus/penalty system. This tree is used as an opening book, as a book learner, as a position learner, to guide the search and has had the ability to merge an external database of millions of games. It has been demonstrated on this board and at the Winboard forum numerous times and shown that with not that many learned games that it can even beat much stronger learning engines like Glaurung 1.2.1 with a 90% plus score when dealing with a limited number of starting positions. I even emailed all this to you about six months ago and suggested that you do something similar for Pro Deo. I even sent/or_mentioned_where_you_could_get the_source_code for RomiChess, but with no reply from you.
I believe in pure coincidences and I will tell you of another ironic coincidence. After I had first released RomiChess I read your paper on chess programming and noted that our approaches were very similar and now our programs are even more similar! Although RomiChess pales in comparison to Rebel and Pro Deo.
Since so many people here are aware of my work and undoubtably can see the simularity of our learning systems it might be a good idea for you to address the above noted coincidences. After all, I always said that anyone can use and improve upon my learning system and all that I asked is to be given some credit. However, if you arrived at the same destination with out knowledge of my work then people aught to hear it from you, so they will not believe that you cloned someone else work, with out acknowledement.
I do appreciate this contribution that you have made and am very interested in how it has been improved. I hope that many programmers find it very useful!
Mike
Re: EOC databases now as open source
The sentiment is mutual Dann, but I can assure Mrs. Schroder at times totally disagrees with you.Dann Corbit wrote:Ed Schroder is the nicest guy in the world.
EPD regards,
Ed
-
- Posts: 12541
- Joined: Wed Mar 08, 2006 8:57 pm
- Location: Redmond, WA USA
Re: EOC databases now as open source
Here is your code as a C++ class:
Code: Select all
/* EOC module for Chess Programs
written by Ed Schr”der
Version 1.00
This information provides the way how to include the ProDeo EOC system
into your chess engine.
Include "eoc.c" into your project and compile.
EXAMPLE.EOC - Example demonstration EOC database. An EOC database is the
statistic representation of a game collection (PGN or DAT),
see: http://www.rebel.nl/r11-eoc.htm
EOC databases can be easily made with ProDeo Tools. Get it
at: http://www.top-5000.nl/prodeodos.htm
Initialization - Call the routine "initialize_eoc()" once.
Operation - Create an EPD string from the position you want to find and
strcpy it into the string "EPD", then call the routine
"search_position_in_eoc" to search the EOC database.
- When the position is found "amount" contains the number
of games the position occurs and "percentage" contains
the percentage of the position has scored. When the position
is not found both variables contain -1.
Possibilities - Both variables provide enough information to allow you to add
the following features to your chess engine or even your chess
interface: 1) Use an EOC database as an opening book;
2) Use an EOC database to guide the search;
3) Use it as a (book/position) learning system;
4) Use it for display purposes in your GUI.
As openingbook - The basic idea: if a position occurs 20 times in the EOC
database with a score of 60% it's safe to enter this position.
Procedure: for every legal move call "search_position_in_eoc"
and via "amount" and "percentage" decide if the move
is a candidate book move. See also the demonstration code in
the "main" section.
As guide - As an alternative you can use the EOC information as a tool to
guide the search. Based on "amount" and "percentage"
create a bonus/penalty score for each found EOC move and update
the corresponding root move with that score. It's fully explained
at: http://www.rebel.nl/r11-eoc.htm (section: alternative goals
of EOC).
As learner - Just create an EOC database from the games your program has
played with ProDeo Tools. Via "amount" and "percentage"
decide which opening to avoid or to stimulate. When your engine
has entered a position with a bad percentage consider to switch
to a somewhat different playing style to avoid your engine to
lose again.
Display info - Add a nice statitic to your chess interface, see example
picture of an EOC database running under ChessPartner at:
http://www.top-5000.nl/pics/eoc.jpg
When a position is found 4 more other variables are filled:
won : games won
lost : games lost
draw : games ended in a draw
total : total positions of the loaded EOC database.
See the demonstration code in the "main" section.
EPD creation - To create an EPD string from the current board position check
chapter 16 from: http://www.tim-mann.org/Standard
Castling status and en-passant information are not needed to
include in the EPD string, the module only needs the current
position and the colour to move.
Remarks - Realize that white moves usually score 5-7% better than black
moves during the first moves. This is represented in the
variables: "perc_white" and "perc_black" and pre-filled
with 55% and 45% respectively as a base for calculation. See the
demonstration code in the "main" section.
Technical - Short description of the EOC format:
Each position is stored into 11 bytes and 2 separate files,
1 for white and 1 for black (*.EOC and *.BAL)
Byte 1-8 : 64 bit hashkey
Byte 9 : number positions won by white
Byte 10 : number positions won by black
Byte 11 : number of draw positions
Positions over 256 games are stored in 2 separate files, 1 for
white and 1 for black (*.WBX and *.BBX). Same format as above
only now with 32-bit counters. These are only few so a lot of
disk-space and consistently processor time is saved.
The 2 big EOC files (*.EOC and *.BAL) are controlled by 2 index
files (*.WBI and *.BBI) for fast access.
Copyright - This file and its components although distributed as freeware in
no way may become subject to any form of commerce. Permission
must be asked first.
- This file and its components come as is and can only be used as
such. It's forbidden to change, add, delete any of its components
and only can be distributed in original form.
Questions - For questions, suggestions, bug reports etc. contact me at the
CCC forum: http://216.25.93.108/forum
Ed Schr”der
Deventer, May 2007
matador@home.nl
www.top-5000.nl
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <io.h>
#include <fcntl.h>
static const char BORDPOS[] =
{
8, 18, 28, 38, 48, 58, 68, 78,
7, 17, 27, 37, 47, 57, 67, 77,
6, 16, 26, 36, 46, 56, 66, 76,
5, 15, 25, 35, 45, 55, 65, 75,
4, 14, 24, 34, 44, 54, 64, 74,
3, 13, 23, 33, 43, 53, 63, 73,
2, 12, 22, 32, 42, 52, 62, 72,
1, 11, 21, 31, 41, 51, 61, 71, 0
};
#define RBI_BITS 16 /* bits used index file */
#define RBI_MASK 0xffff /* the corresponding bit mask */
#define WHITE 0
#define BLACK 1
class EOC {
private:
char file[FILENAME_MAX]; /* full path goes here */
char EPD[200];
long RANDOM1[1120];
long RANDOM2[1120];
char _BORD[256];
long HK1,
HK2;
char ERROR;
float amount;
float percentage;
int won;
int loss;
int draw;
int total;
int perc_white;
int perc_black;
int minimum_games;
char message[100];
char color;
public:
EOC() {
char *eoc_location;
memset(EPD, 0, sizeof EPD);
memset(RANDOM1, 0, sizeof RANDOM1);
memset(RANDOM2, 0, sizeof RANDOM2);
memset(_BORD, 0, sizeof _BORD);
memset(message, 0, sizeof message);
HK1 = 0;
HK2 = 0;
ERROR = 0;
color = WHITE;
amount = percentage = 0.0;
won = loss = draw = total = 0;
perc_white = 55;
perc_black = 45;
minimum_games = 10;
strcpy(file, "eoc\\example.eoc");
eoc_location = getenv("EOC_LOCATION");
if (eoc_location) {
if (strlen(eoc_location) < sizeof file)
strcpy(file, eoc_location);
else
printf("EOC_LOCATION (%s) is longer than the longest allowed file name on your system.");
}
initialize_eoc();
}
~EOC() {
;
}
/* Private member inquiry methods */
inline char *get_file() {
return file;
}
inline char *get_EPD() {
return EPD;
}
inline char *get_BORD() {
return _BORD;
}
inline long get_HK1() {
return HK1;
}
inline long get_HK2() {
return HK2;
}
inline char get_ERROR() {
return ERROR;
}
inline float get_amount() {
return amount;
}
inline float get_percentage() {
return percentage;
}
inline int get_won() {
return won;
}
inline int get_loss() {
return loss;
}
inline int get_draw() {
return draw;
}
inline int get_total() {
return total;
}
inline int get_perc_white() {
return perc_white;
}
inline int get_perc_black() {
return perc_black;
}
inline int get_minimum_games() {
return minimum_games;
}
inline char *get_message() {
return message;
}
inline char get_color() {
return color;
}
/* Private member modification methods */
inline void set_HK1(long rhs) {
HK1 = rhs;
}
inline void set_HK2(long rhs) {
HK2 = rhs;
}
inline void set_ERROR(char rhs) {
ERROR = rhs;
}
inline void set_amount(float rhs) {
amount = rhs;
}
inline void set_percentage(float rhs) {
percentage = rhs;
}
inline void set_won(int rhs) {
won = rhs;
}
inline void set_loss(int rhs) {
loss = rhs;
}
inline void set_draw(int rhs) {
draw = rhs;
}
inline void set_total(int rhs) {
total = rhs;
}
inline void set_perc_white(int rhs) {
perc_white = rhs;
}
inline void set_perc_black(int rhs) {
perc_black = rhs;
}
inline void set_minimum_games(int rhs) {
minimum_games = rhs;
}
inline void set_color(char rhs) {
color = rhs;
}
inline void set_message(char *rhs) {
strncpy(message, rhs, sizeof message);
}
inline void set_file(char *rhs) {
strncpy(file, rhs, sizeof file);
}
inline void set_EPD(char *rhs) {
strncpy(EPD, rhs, sizeof EPD);
}
inline void set_BORD(char *rhs) {
strncpy(_BORD, rhs, sizeof _BORD);
}
/*
Typical output for unit test method:
Get moves for start position
Result for 1.e4 4067.000000% positions (56.97%)
Result for 1.d4 4756.000000% positions (55.40%)
Result for 1.c4 911.000000% positions (54.12%)
Press <Enter key> to continue
Get moves after 1.e4
Result for 1.e4 c5 1648.000000% positions (45.39%)
Result for 1.e4 e5 1249.000000% positions (41.83%)
Result for 1.e4 d6 128.000000% positions (36.72%)
Let's now decide which of the 3 above moves are good candidate book moves.
Press <Enter key> to continue
Result for 1.e4 c5 1648.000000% positions (45.39%)
play
Result for 1.e4 e5 1249.000000% positions (41.83%)
play
Result for 1.e4 d6 128.000000% positions (36.72%)
don't play
Let's now create some statistics for the interface.
Press <Enter key> to continue
Move Won Draw Loss Perc Total
c7c5 332 832 484 45.39% 1648
e7e5 180 685 384 41.83% 1249
d7d6 24 46 58 36.72% 128
Tot 536 1563 926 3025
Total positions in EOC database: 431767
*/
inline int unit_test(int argc, char *argv[]) {
int tot_won,
tot_draw,
tot_loss;
char string[20];
if (ERROR) {
printf("Something went wrong, error-code %d", ERROR);
exit(1);
}
/* */
/* Get moves for start position */
/* */
printf("\n\nGet moves for start position\n\n");
strcpy(EPD, "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq e3"); /* search for 1.e4 */
search_position_in_eoc();
if (ERROR)
printf("Something went wrong, error-code %d", ERROR);
printf("Result for 1.e4 %f%% positions (%.2f%%)\n", amount, percentage);
strcpy(EPD, "rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR w KQkq d3"); /* search for 1.d4 */
search_position_in_eoc();
if (ERROR)
printf("Something went wrong, error-code %d", ERROR);
printf("Result for 1.d4 %f%% positions (%.2f%%)\n", amount, percentage);
strcpy(EPD, "rnbqkbnr/pppppppp/8/8/2P5/8/PP1PPPPP/RNBQKBNR w KQkq c3"); /* search for 1.c4 */
search_position_in_eoc();
if (ERROR)
printf("Something went wrong, error-code %d", ERROR);
printf("Result for 1.c4 %f%% positions (%.2f%%)\n", amount, percentage);
printf("Press <Enter key> to continue ");
fgets(string, sizeof string, stdin);
/* */
/* Get moves after 1.e4 */
/* */
printf("\n\nGet moves after 1.e4\n\n");
strcpy(EPD, "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR b KQkq c6"); /* search for 1.e4 c5 */
search_position_in_eoc();
printf("Result for 1.e4 c5 %f%% positions (%.2f%%)\n", amount, percentage);
strcpy(EPD, "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e6"); /* search for 1.e4 e5 */
search_position_in_eoc();
printf("Result for 1.e4 e5 %f%% positions (%.2f%%)\n", amount, percentage);
strcpy(EPD, "rnbqkbnr/ppp1pppp/3p4/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq -"); /* search for 1.e4 d6 */
search_position_in_eoc();
printf("Result for 1.e4 d6 %f%% positions (%.2f%%)\n", amount, percentage);
printf("Let's now decide which of the 3 above moves are good candidate book moves.\n");
printf("Press <Enter key> to continue ");
fgets(string, sizeof string, stdin);
/* */
/* Check moves after 1.e4 */
/* */
strcpy(EPD, "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR b KQkq c6"); /* search for 1.e4 c5 */
search_position_in_eoc();
printf("\n\nResult for 1.e4 c5 %f%% positions (%.2f%%)\n", amount, percentage);
to_play_or_not_to_play();
printf("%s\n", message);
strcpy(EPD, "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e6"); /* search for 1.e4 e5 */
search_position_in_eoc();
printf("Result for 1.e4 e5 %f%% positions (%.2f%%)\n", amount, percentage);
to_play_or_not_to_play();
printf("%s\n", message);
strcpy(EPD, "rnbqkbnr/ppp1pppp/3p4/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq -"); /* search for 1.e4 d6 */
search_position_in_eoc();
printf("Result for 1.e4 d6 %f%% positions (%.2f%%)\n", amount, percentage);
to_play_or_not_to_play();
printf("%s\n\n", message);
printf("Let's now create some statistics for the interface.\n");
printf("Press <Enter key> to continue ");
fgets(string, sizeof string, stdin);
/* */
/* Statistics */
/* */
strcpy(EPD, "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR b KQkq c6"); /* search for 1.e4 c5 */
search_position_in_eoc();
printf("\n\nMove Won Draw Loss Perc Total\n\n");
printf("c7c5 %6d %6d %6d %.2f%% %6d\n", won, draw, loss, percentage, won + draw + loss);
tot_won = won;
tot_draw = draw;
tot_loss = loss;
strcpy(EPD, "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e6"); /* search for 1.e4 e5 */
search_position_in_eoc();
printf("e7e5 %6d %6d %6d %.2f%% %6d\n", won, draw, loss, percentage, won + draw + loss);
tot_won = tot_won + won;
tot_draw = tot_draw + draw;
tot_loss = tot_loss + loss;
strcpy(EPD, "rnbqkbnr/ppp1pppp/3p4/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq -"); /* search for 1.e4 d6 */
search_position_in_eoc();
printf("d7d6 %6d %6d %6d %.2f%% %6d\n", won, draw, loss, percentage, won + draw + loss);
tot_won = tot_won + won;
tot_draw = tot_draw + draw;
tot_loss = tot_loss + loss;
printf("\nTot %6d %6d %6d %6d\n\n", tot_won, tot_draw, tot_loss, tot_won + tot_draw + tot_loss);
printf("Total positions in EOC database: %d\n\n", total);
return 0;
}
inline void to_play_or_not_to_play() {
int mg,
perc;
if (color == WHITE)
perc = perc_white; /* get percentage for color */
else
perc = perc_black;
if (amount > 25)
perc--; /* allow 1% lower if more than 25
* games are played */
if (amount > 50)
perc--; /* allow 2% lower if more than 50
* games are played */
if (amount > 100)
perc--; /* allow 3% lower if more than 100
* games are played */
if (amount > 500)
perc--; /* allow 4% lower if more than 500
* games are played */
if (percentage < perc) {
printf("don't play");
return; /* don't play this move */
}
mg = minimum_games; /* check now for minimum
* games played */
mg -= (int) (percentage - perc); /* decrease minimum games
* when high percentage */
if (amount < mg) {
printf("don't play");
return; /* don't play this move */
}
printf("play");
}
inline void initialize_eoc() { /* read hashkeys in memory */
int x,
y;
char s[300];
char *q;
FILE *fp1;
FILE *fp2;
fp1 = fopen("random1.bin", "rb");
if (fp1 == NULL) {
fclose(fp1);
ERROR = 1;
return;
}
fp2 = fopen("random2.bin", "rb");
if (fp2 == NULL) {
fclose(fp2);
ERROR = 1;
return;
}
for (x = 0; x < 1120; x++) {
fread(&RANDOM1[x], 4, 1, fp1);
fread(&RANDOM2[x], 4, 1, fp2);
}
fclose(fp1);
fclose(fp2);
y = open(file, O_RDONLY);
x = filelength(y);
close(y); /* calculate total positions */
total = x / 11;
if ((total * 11) != x) {
ERROR = 5;
return;
}
strcpy(s, file);
strlwr(s);
q = strstr(s, ".eoc");
if (q == NULL) {
ERROR = 6;
return;
} /* wrong eoc filename */
q[1] = 'b';
q[2] = 'a';
q[3] = 'l'; /* *.eoc to *.bal */
y = open(s, O_RDONLY);
x = filelength(y);
close(y); /* get filelemgth (black) */
y = (x / 11);
if ((y * 11) != x) {
ERROR = 7;
return;
}
total = total + y;
strcpy(s, file);
strlwr(s);
q = strstr(s, ".eoc");
q[1] = 'w';
q[2] = 'b';
q[3] = 'x';
y = open(s, O_RDONLY);
x = filelength(y);
close(y);
y = x / 20;
total = total + y;
strcpy(s, file);
strlwr(s);
q = strstr(s, ".eoc");
q[1] = 'b';
q[2] = 'b';
q[3] = 'x';
y = open(s, O_RDONLY);
x = filelength(y);
close(y);
y = x / 20;
total = total + y;
}
inline void search_position_in_eoc() {
int x,
y,
v;
FILE *fp3 = 0,
*fp4 = 0,
*fp5 = 0;
unsigned long rbi;
long hk1,
hk2;
char *q;
float f1,
f2,
f3,
f4,
f5,
f6;
char fn[100];
char s[100];
char ch;
char fentab[] = "??PNBRQKpnbrqk??";
char fenkleur[] = "wb??";
amount = -1;
percentage = -1;
/* retrieve EPD */
/* ============ */
for (x = 1; x <= 78; x++)
if (_BORD[x] > 0)
_BORD[x] = 1; /* empty board */
x = -1;
y = 0;
epd:
x++;
ch = EPD[x];
if (ch == '/')
goto epd;
if (ch >= '1' && ch <= '8') {
v = ch - 48;
y = y + v;
goto test;
}
for (v = 2; v <= 15; v++)
if (fentab[v] == ch) {
_BORD[BORDPOS[y]] = v;
y++;
break;
}
if (v > 13)
goto error;
test: if (y < 64)
goto epd;
x++;
if (EPD[x] != ' ')
goto error;
x++;
if (EPD[x] == fenkleur[0]) {
color = 0;
goto ready;
} /* white to move */
if (EPD[x] == fenkleur[1]) {
color = 1;
goto ready;
} /* black to move */
error: ERROR = 2;
return;
ready: strcpy(s, file);
strlwr(s);
q = strstr(s, ".eoc");
if (q == NULL) {
ERROR = 4;
goto end;
} /* faulty eoc filename */
q[0] = 0; /* remove extension (.eoc") */
if (color == WHITE) {
strcpy(fn, s);
strcat(fn, ".eoc");
fp3 = fopen(fn, "rb"); /* 8-bit positions (white) */
strcpy(fn, s);
strcat(fn, ".wbi");
fp4 = fopen(fn, "rb"); /* index (white) */
strcpy(fn, s);
strcat(fn, ".wbx");
fp5 = fopen(fn, "rb");
}
/* 32-bit positions (white) */
else {
strcpy(fn, s);
strcat(fn, ".bal");
fp3 = fopen(fn, "rb"); /* 8-bit positions (black) */
strcpy(fn, s);
strcat(fn, ".bbi");
fp4 = fopen(fn, "rb"); /* index (black) */
strcpy(fn, s);
strcat(fn, ".bbx");
fp5 = fopen(fn, "rb");
} /* 32-bit positions (black) */
if (fp3 == NULL) {
ERROR = 3;
goto end;
} /* eoc database not found */
make_hashkey();
check: y = fread(&hk1, 4, 1, fp5);
/* check the 32 bit positions */
if (y < 1)
goto done;
fread(&hk2, 4, 1, fp5);
fread(&won, 4, 1, fp5);
fread(&loss, 4, 1, fp5);
fread(&draw, 4, 1, fp5);
if (hk1 == HK1 && hk2 == HK2)
goto found; /* position found */
goto check;
done: rbi = HK1 >> RBI_BITS; /* get index */
rbi = rbi & RBI_MASK;
rbi = rbi << 2;
fseek(fp4, rbi, SEEK_SET);
fread(&rbi, 4, 1, fp4);
fseek(fp3, rbi, SEEK_SET);
next: y = fread(&hk1, 4, 1, fp3);
if (y < 1)
goto end;
fread(&hk2, 4, 1, fp3);
if (hk1 > HK1)
goto end;
if (HK1 == hk1 && HK2 == hk2) {
fread(&won, 1, 1, fp3);
won = won & 255;
fread(&loss, 1, 1, fp3);
loss = loss & 255;
fread(&draw, 1, 1, fp3);
draw = draw & 255;
goto found;
}
fread(&s, 3, 1, fp3); /* skip 3 bytes */
goto next;
found: f1 = (float) won;
f1 *= 2.0f;
f2 = (float) draw;
f4 = (f1 + f2) * 50.0f;
f1 = (float) won;
f3 = (float) loss;
f5 = f1 + f2 + f3;
f6 = f4 / f5;
amount = f5;
percentage = f6;
end: fclose(fp3);
fclose(fp4);
fclose(fp5);
}
inline void make_hashkey() {
int x,
y,
v,
sc;
HK1 = 0;
HK2 = 0;
for (x = 1; x <= 78; x++) {
if (_BORD[x] < 2)
continue;
sc = _BORD[x];
v = sc << 6;
y = sc << 4;
y = y + v;
HK1 = HK1 ^ RANDOM1[y + x];
HK2 = HK2 ^ RANDOM2[y + x];
}
}
};
/* End of story */
int main(int argc, char **argv)
{
EOC EdsGroovyEncyclopedia;
EdsGroovyEncyclopedia.unit_test(argc, argv);
return 0;
}
-
- Posts: 12541
- Joined: Wed Mar 08, 2006 8:57 pm
- Location: Redmond, WA USA
Re: EOC databases now as open source
Correction for percentages that were not supposed to be percentages:
Code: Select all
/* EOC module for Chess Programs
written by Ed Schr”der
Version 1.00
This information provides the way how to include the ProDeo EOC system
into your chess engine.
Include "eoc.c" into your project and compile.
EXAMPLE.EOC - Example demonstration EOC database. An EOC database is the
statistic representation of a game collection (PGN or DAT),
see: http://www.rebel.nl/r11-eoc.htm
EOC databases can be easily made with ProDeo Tools. Get it
at: http://www.top-5000.nl/prodeodos.htm
Initialization - Call the routine "initialize_eoc()" once.
Operation - Create an EPD string from the position you want to find and
strcpy it into the string "EPD", then call the routine
"search_position_in_eoc" to search the EOC database.
- When the position is found "amount" contains the number
of games the position occurs and "percentage" contains
the percentage of the position has scored. When the position
is not found both variables contain -1.
Possibilities - Both variables provide enough information to allow you to add
the following features to your chess engine or even your chess
interface: 1) Use an EOC database as an opening book;
2) Use an EOC database to guide the search;
3) Use it as a (book/position) learning system;
4) Use it for display purposes in your GUI.
As openingbook - The basic idea: if a position occurs 20 times in the EOC
database with a score of 60% it's safe to enter this position.
Procedure: for every legal move call "search_position_in_eoc"
and via "amount" and "percentage" decide if the move
is a candidate book move. See also the demonstration code in
the "main" section.
As guide - As an alternative you can use the EOC information as a tool to
guide the search. Based on "amount" and "percentage"
create a bonus/penalty score for each found EOC move and update
the corresponding root move with that score. It's fully explained
at: http://www.rebel.nl/r11-eoc.htm (section: alternative goals
of EOC).
As learner - Just create an EOC database from the games your program has
played with ProDeo Tools. Via "amount" and "percentage"
decide which opening to avoid or to stimulate. When your engine
has entered a position with a bad percentage consider to switch
to a somewhat different playing style to avoid your engine to
lose again.
Display info - Add a nice statitic to your chess interface, see example
picture of an EOC database running under ChessPartner at:
http://www.top-5000.nl/pics/eoc.jpg
When a position is found 4 more other variables are filled:
won : games won
lost : games lost
draw : games ended in a draw
total : total positions of the loaded EOC database.
See the demonstration code in the "main" section.
EPD creation - To create an EPD string from the current board position check
chapter 16 from: http://www.tim-mann.org/Standard
Castling status and en-passant information are not needed to
include in the EPD string, the module only needs the current
position and the colour to move.
Remarks - Realize that white moves usually score 5-7% better than black
moves during the first moves. This is represented in the
variables: "perc_white" and "perc_black" and pre-filled
with 55% and 45% respectively as a base for calculation. See the
demonstration code in the "main" section.
Technical - Short description of the EOC format:
Each position is stored into 11 bytes and 2 separate files,
1 for white and 1 for black (*.EOC and *.BAL)
Byte 1-8 : 64 bit hashkey
Byte 9 : number positions won by white
Byte 10 : number positions won by black
Byte 11 : number of draw positions
Positions over 256 games are stored in 2 separate files, 1 for
white and 1 for black (*.WBX and *.BBX). Same format as above
only now with 32-bit counters. These are only few so a lot of
disk-space and consistently processor time is saved.
The 2 big EOC files (*.EOC and *.BAL) are controlled by 2 index
files (*.WBI and *.BBI) for fast access.
Copyright - This file and its components although distributed as freeware in
no way may become subject to any form of commerce. Permission
must be asked first.
- This file and its components come as is and can only be used as
such. It's forbidden to change, add, delete any of its components
and only can be distributed in original form.
Questions - For questions, suggestions, bug reports etc. contact me at the
CCC forum: http://216.25.93.108/forum
Ed Schr”der
Deventer, May 2007
matador@home.nl
www.top-5000.nl
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <io.h>
#include <fcntl.h>
static const char BORDPOS[] =
{
8, 18, 28, 38, 48, 58, 68, 78,
7, 17, 27, 37, 47, 57, 67, 77,
6, 16, 26, 36, 46, 56, 66, 76,
5, 15, 25, 35, 45, 55, 65, 75,
4, 14, 24, 34, 44, 54, 64, 74,
3, 13, 23, 33, 43, 53, 63, 73,
2, 12, 22, 32, 42, 52, 62, 72,
1, 11, 21, 31, 41, 51, 61, 71, 0
};
#define RBI_BITS 16 /* bits used index file */
#define RBI_MASK 0xffff /* the corresponding bit mask */
#define WHITE 0
#define BLACK 1
class EOC {
private:
char file[FILENAME_MAX]; /* full path goes here */
char EPD[200];
long RANDOM1[1120];
long RANDOM2[1120];
char _BORD[256];
long HK1,
HK2;
char ERROR;
float amount;
float percentage;
int won;
int loss;
int draw;
int total;
int perc_white;
int perc_black;
int minimum_games;
char message[100];
char color;
public:
EOC() {
char *eoc_location;
memset(EPD, 0, sizeof EPD);
memset(RANDOM1, 0, sizeof RANDOM1);
memset(RANDOM2, 0, sizeof RANDOM2);
memset(_BORD, 0, sizeof _BORD);
memset(message, 0, sizeof message);
HK1 = 0;
HK2 = 0;
ERROR = 0;
color = WHITE;
amount = percentage = 0.0;
won = loss = draw = total = 0;
perc_white = 55;
perc_black = 45;
minimum_games = 10;
strcpy(file, "eoc\\example.eoc");
eoc_location = getenv("EOC_LOCATION");
if (eoc_location) {
if (strlen(eoc_location) < sizeof file)
strcpy(file, eoc_location);
else
printf("EOC_LOCATION (%s) is longer than the longest allowed file name on your system.");
}
initialize_eoc();
}
~EOC() {
;
}
/* Private member inquiry methods */
inline char *get_file() {
return file;
}
inline char *get_EPD() {
return EPD;
}
inline char *get_BORD() {
return _BORD;
}
inline long get_HK1() {
return HK1;
}
inline long get_HK2() {
return HK2;
}
inline char get_ERROR() {
return ERROR;
}
inline float get_amount() {
return amount;
}
inline float get_percentage() {
return percentage;
}
inline int get_won() {
return won;
}
inline int get_loss() {
return loss;
}
inline int get_draw() {
return draw;
}
inline int get_total() {
return total;
}
inline int get_perc_white() {
return perc_white;
}
inline int get_perc_black() {
return perc_black;
}
inline int get_minimum_games() {
return minimum_games;
}
inline char *get_message() {
return message;
}
inline char get_color() {
return color;
}
/* Private member modification methods */
inline void set_HK1(long rhs) {
HK1 = rhs;
}
inline void set_HK2(long rhs) {
HK2 = rhs;
}
inline void set_ERROR(char rhs) {
ERROR = rhs;
}
inline void set_amount(float rhs) {
amount = rhs;
}
inline void set_percentage(float rhs) {
percentage = rhs;
}
inline void set_won(int rhs) {
won = rhs;
}
inline void set_loss(int rhs) {
loss = rhs;
}
inline void set_draw(int rhs) {
draw = rhs;
}
inline void set_total(int rhs) {
total = rhs;
}
inline void set_perc_white(int rhs) {
perc_white = rhs;
}
inline void set_perc_black(int rhs) {
perc_black = rhs;
}
inline void set_minimum_games(int rhs) {
minimum_games = rhs;
}
inline void set_color(char rhs) {
color = rhs;
}
inline void set_message(char *rhs) {
strncpy(message, rhs, sizeof message);
}
inline void set_file(char *rhs) {
strncpy(file, rhs, sizeof file);
}
inline void set_EPD(char *rhs) {
strncpy(EPD, rhs, sizeof EPD);
}
inline void set_BORD(char *rhs) {
strncpy(_BORD, rhs, sizeof _BORD);
}
/*
Typical output for unit test method:
Get moves for start position
Result for 1.e4 4067 positions (56.97%)
Result for 1.d4 4756 positions (55.40%)
Result for 1.c4 911 positions (54.12%)
Press <Enter key> to continue
Get moves after 1.e4
Result for 1.e4 c5 1648 positions (45.39%)
Result for 1.e4 e5 1249 positions (41.83%)
Result for 1.e4 d6 128 positions (36.72%)
Let's now decide which of the 3 above moves are good candidate book moves.
Press <Enter key> to continue
Result for 1.e4 c5 1648 positions (45.39%)
play
Result for 1.e4 e5 1249 positions (41.83%)
play
Result for 1.e4 d6 128 positions (36.72%)
don't play
Let's now create some statistics for the interface.
Press <Enter key> to continue
Move Won Draw Loss Perc Total
c7c5 332 832 484 45.39% 1648
e7e5 180 685 384 41.83% 1249
d7d6 24 46 58 36.72% 128
Tot 536 1563 926 3025
Total positions in EOC database: 431767
*/
inline int unit_test(int argc, char *argv[]) {
int tot_won,
tot_draw,
tot_loss;
char string[20];
if (ERROR) {
printf("Something went wrong, error-code %d", ERROR);
exit(1);
}
/* */
/* Get moves for start position */
/* */
printf("\n\nGet moves for start position\n\n");
strcpy(EPD, "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq e3"); /* search for 1.e4 */
search_position_in_eoc();
if (ERROR)
printf("Something went wrong, error-code %d", ERROR);
printf("Result for 1.e4 %.0f positions (%.2f%%)\n", amount, percentage);
strcpy(EPD, "rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR w KQkq d3"); /* search for 1.d4 */
search_position_in_eoc();
if (ERROR)
printf("Something went wrong, error-code %d", ERROR);
printf("Result for 1.d4 %.0f positions (%.2f%%)\n", amount, percentage);
strcpy(EPD, "rnbqkbnr/pppppppp/8/8/2P5/8/PP1PPPPP/RNBQKBNR w KQkq c3"); /* search for 1.c4 */
search_position_in_eoc();
if (ERROR)
printf("Something went wrong, error-code %d", ERROR);
printf("Result for 1.c4 %.0f positions (%.2f%%)\n", amount, percentage);
printf("Press <Enter key> to continue ");
fgets(string, sizeof string, stdin);
/* */
/* Get moves after 1.e4 */
/* */
printf("\n\nGet moves after 1.e4\n\n");
strcpy(EPD, "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR b KQkq c6"); /* search for 1.e4 c5 */
search_position_in_eoc();
printf("Result for 1.e4 c5 %.0f positions (%.2f%%)\n", amount, percentage);
strcpy(EPD, "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e6"); /* search for 1.e4 e5 */
search_position_in_eoc();
printf("Result for 1.e4 e5 %.0f positions (%.2f%%)\n", amount, percentage);
strcpy(EPD, "rnbqkbnr/ppp1pppp/3p4/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq -"); /* search for 1.e4 d6 */
search_position_in_eoc();
printf("Result for 1.e4 d6 %.0f positions (%.2f%%)\n", amount, percentage);
printf("Let's now decide which of the 3 above moves are good candidate book moves.\n");
printf("Press <Enter key> to continue ");
fgets(string, sizeof string, stdin);
/* */
/* Check moves after 1.e4 */
/* */
strcpy(EPD, "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR b KQkq c6"); /* search for 1.e4 c5 */
search_position_in_eoc();
printf("\n\nResult for 1.e4 c5 %.0f positions (%.2f%%)\n", amount, percentage);
to_play_or_not_to_play();
printf("%s\n", message);
strcpy(EPD, "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e6"); /* search for 1.e4 e5 */
search_position_in_eoc();
printf("Result for 1.e4 e5 %.0f positions (%.2f%%)\n", amount, percentage);
to_play_or_not_to_play();
printf("%s\n", message);
strcpy(EPD, "rnbqkbnr/ppp1pppp/3p4/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq -"); /* search for 1.e4 d6 */
search_position_in_eoc();
printf("Result for 1.e4 d6 %.0f positions (%.2f%%)\n", amount, percentage);
to_play_or_not_to_play();
printf("%s\n\n", message);
printf("Let's now create some statistics for the interface.\n");
printf("Press <Enter key> to continue ");
fgets(string, sizeof string, stdin);
/* */
/* Statistics */
/* */
strcpy(EPD, "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR b KQkq c6"); /* search for 1.e4 c5 */
search_position_in_eoc();
printf("\n\nMove Won Draw Loss Perc Total\n\n");
printf("c7c5 %6d %6d %6d %.2f%% %6d\n", won, draw, loss, percentage, won + draw + loss);
tot_won = won;
tot_draw = draw;
tot_loss = loss;
strcpy(EPD, "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e6"); /* search for 1.e4 e5 */
search_position_in_eoc();
printf("e7e5 %6d %6d %6d %.2f%% %6d\n", won, draw, loss, percentage, won + draw + loss);
tot_won = tot_won + won;
tot_draw = tot_draw + draw;
tot_loss = tot_loss + loss;
strcpy(EPD, "rnbqkbnr/ppp1pppp/3p4/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq -"); /* search for 1.e4 d6 */
search_position_in_eoc();
printf("d7d6 %6d %6d %6d %.2f%% %6d\n", won, draw, loss, percentage, won + draw + loss);
tot_won = tot_won + won;
tot_draw = tot_draw + draw;
tot_loss = tot_loss + loss;
printf("\nTot %6d %6d %6d %6d\n\n", tot_won, tot_draw, tot_loss, tot_won + tot_draw + tot_loss);
printf("Total positions in EOC database: %d\n\n", total);
return 0;
}
inline void to_play_or_not_to_play() {
int mg,
perc;
if (color == WHITE)
perc = perc_white; /* get percentage for color */
else
perc = perc_black;
if (amount > 25)
perc--; /* allow 1% lower if more than 25
* games are played */
if (amount > 50)
perc--; /* allow 2% lower if more than 50
* games are played */
if (amount > 100)
perc--; /* allow 3% lower if more than 100
* games are played */
if (amount > 500)
perc--; /* allow 4% lower if more than 500
* games are played */
if (percentage < perc) {
printf("don't play");
return; /* don't play this move */
}
mg = minimum_games; /* check now for minimum
* games played */
mg -= (int) (percentage - perc); /* decrease minimum games
* when high percentage */
if (amount < mg) {
printf("don't play");
return; /* don't play this move */
}
printf("play");
}
inline void initialize_eoc() { /* read hashkeys in memory */
int x,
y;
char s[300];
char *q;
FILE *fp1;
FILE *fp2;
fp1 = fopen("random1.bin", "rb");
if (fp1 == NULL) {
fclose(fp1);
ERROR = 1;
return;
}
fp2 = fopen("random2.bin", "rb");
if (fp2 == NULL) {
fclose(fp2);
ERROR = 1;
return;
}
for (x = 0; x < 1120; x++) {
fread(&RANDOM1[x], 4, 1, fp1);
fread(&RANDOM2[x], 4, 1, fp2);
}
fclose(fp1);
fclose(fp2);
y = open(file, O_RDONLY);
x = filelength(y);
close(y); /* calculate total positions */
total = x / 11;
if ((total * 11) != x) {
ERROR = 5;
return;
}
strcpy(s, file);
strlwr(s);
q = strstr(s, ".eoc");
if (q == NULL) {
ERROR = 6;
return;
} /* wrong eoc filename */
q[1] = 'b';
q[2] = 'a';
q[3] = 'l'; /* *.eoc to *.bal */
y = open(s, O_RDONLY);
x = filelength(y);
close(y); /* get filelemgth (black) */
y = (x / 11);
if ((y * 11) != x) {
ERROR = 7;
return;
}
total = total + y;
strcpy(s, file);
strlwr(s);
q = strstr(s, ".eoc");
q[1] = 'w';
q[2] = 'b';
q[3] = 'x';
y = open(s, O_RDONLY);
x = filelength(y);
close(y);
y = x / 20;
total = total + y;
strcpy(s, file);
strlwr(s);
q = strstr(s, ".eoc");
q[1] = 'b';
q[2] = 'b';
q[3] = 'x';
y = open(s, O_RDONLY);
x = filelength(y);
close(y);
y = x / 20;
total = total + y;
}
inline void search_position_in_eoc() {
int x,
y,
v;
FILE *fp3 = 0,
*fp4 = 0,
*fp5 = 0;
unsigned long rbi;
long hk1,
hk2;
char *q;
float f1,
f2,
f3,
f4,
f5,
f6;
char fn[100];
char s[100];
char ch;
char fentab[] = "??PNBRQKpnbrqk??";
char fenkleur[] = "wb??";
amount = -1;
percentage = -1;
/* retrieve EPD */
/* ============ */
for (x = 1; x <= 78; x++)
if (_BORD[x] > 0)
_BORD[x] = 1; /* empty board */
x = -1;
y = 0;
epd:
x++;
ch = EPD[x];
if (ch == '/')
goto epd;
if (ch >= '1' && ch <= '8') {
v = ch - 48;
y = y + v;
goto test;
}
for (v = 2; v <= 15; v++)
if (fentab[v] == ch) {
_BORD[BORDPOS[y]] = v;
y++;
break;
}
if (v > 13)
goto error;
test: if (y < 64)
goto epd;
x++;
if (EPD[x] != ' ')
goto error;
x++;
if (EPD[x] == fenkleur[0]) {
color = 0;
goto ready;
} /* white to move */
if (EPD[x] == fenkleur[1]) {
color = 1;
goto ready;
} /* black to move */
error: ERROR = 2;
return;
ready: strcpy(s, file);
strlwr(s);
q = strstr(s, ".eoc");
if (q == NULL) {
ERROR = 4;
goto end;
} /* faulty eoc filename */
q[0] = 0; /* remove extension (.eoc") */
if (color == WHITE) {
strcpy(fn, s);
strcat(fn, ".eoc");
fp3 = fopen(fn, "rb"); /* 8-bit positions (white) */
strcpy(fn, s);
strcat(fn, ".wbi");
fp4 = fopen(fn, "rb"); /* index (white) */
strcpy(fn, s);
strcat(fn, ".wbx");
fp5 = fopen(fn, "rb");
}
/* 32-bit positions (white) */
else {
strcpy(fn, s);
strcat(fn, ".bal");
fp3 = fopen(fn, "rb"); /* 8-bit positions (black) */
strcpy(fn, s);
strcat(fn, ".bbi");
fp4 = fopen(fn, "rb"); /* index (black) */
strcpy(fn, s);
strcat(fn, ".bbx");
fp5 = fopen(fn, "rb");
} /* 32-bit positions (black) */
if (fp3 == NULL) {
ERROR = 3;
goto end;
} /* eoc database not found */
make_hashkey();
check: y = fread(&hk1, 4, 1, fp5);
/* check the 32 bit positions */
if (y < 1)
goto done;
fread(&hk2, 4, 1, fp5);
fread(&won, 4, 1, fp5);
fread(&loss, 4, 1, fp5);
fread(&draw, 4, 1, fp5);
if (hk1 == HK1 && hk2 == HK2)
goto found; /* position found */
goto check;
done: rbi = HK1 >> RBI_BITS; /* get index */
rbi = rbi & RBI_MASK;
rbi = rbi << 2;
fseek(fp4, rbi, SEEK_SET);
fread(&rbi, 4, 1, fp4);
fseek(fp3, rbi, SEEK_SET);
next: y = fread(&hk1, 4, 1, fp3);
if (y < 1)
goto end;
fread(&hk2, 4, 1, fp3);
if (hk1 > HK1)
goto end;
if (HK1 == hk1 && HK2 == hk2) {
fread(&won, 1, 1, fp3);
won = won & 255;
fread(&loss, 1, 1, fp3);
loss = loss & 255;
fread(&draw, 1, 1, fp3);
draw = draw & 255;
goto found;
}
fread(&s, 3, 1, fp3); /* skip 3 bytes */
goto next;
found: f1 = (float) won;
f1 *= 2.0f;
f2 = (float) draw;
f4 = (f1 + f2) * 50.0f;
f1 = (float) won;
f3 = (float) loss;
f5 = f1 + f2 + f3;
f6 = f4 / f5;
amount = f5;
percentage = f6;
end: fclose(fp3);
fclose(fp4);
fclose(fp5);
}
inline void make_hashkey() {
int x,
y,
v,
sc;
HK1 = 0;
HK2 = 0;
for (x = 1; x <= 78; x++) {
if (_BORD[x] < 2)
continue;
sc = _BORD[x];
v = sc << 6;
y = sc << 4;
y = y + v;
HK1 = HK1 ^ RANDOM1[y + x];
HK2 = HK2 ^ RANDOM2[y + x];
}
}
};
/* End of story */
int main(int argc, char **argv)
{
EOC EdsGroovyEncyclopedia;
EdsGroovyEncyclopedia.unit_test(argc, argv);
return 0;
}
-
- Posts: 3196
- Joined: Fri May 26, 2006 3:00 am
- Location: WY, USA
- Full name: Michael Sherwin
Re: EOC databases now as open source
Hi Ed,
Thanks for the clarification. We must think a lot alike, except your better at it!
Mike
Thanks for the clarification. We must think a lot alike, except your better at it!
Mike
ed wrote:Hi Michael,
Nice to meet a brother in EOC. I am sorry, I do not remember an email of yours, most likely it became a target of my spam filter as I do have the intention to answer email.
I had the EOC idea already in the early 90's but then the availability of games was so little the system made no sense at all so I never activated the code. It remained that way till 1998 till the volume of available games was high enough to justify a commercial release, see: http://www.rebel.nl/rebel10e.htm
I have retired from the playing strength circus but of curiosity reasons only I definitely going to try the EOC comp-comp database and find out if 6.x million comp-comp positions bring any difference.
This is big fun.
Regards,
Ed
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
-
- Posts: 3196
- Joined: Fri May 26, 2006 3:00 am
- Location: WY, USA
- Full name: Michael Sherwin
Re: EOC databases now as open source
Thanks Tord, for both the correction and especially the compliment about my learning system! That really makes me feel good that the author of such a strong engine such as Glaurung has noticed my work!!Tord Romstad wrote:Hello Michael,Michael Sherwin wrote:It has been demonstrated on this board and at the Winboard forum numerous times and shown that with not that many learned games that it can even beat much stronger learning engines like Glaurung 1.2.1 with a 90% plus score when dealing with a limited number of starting positions.
Just a pedantic correction: Glaurung 1.2.1 is not a learning engine in any meaningful sense of the word. It is true that there is a UCI parameter named "Position learning", but all this feature does is to remember the results of the last few searches from the root and store them to a an array and a small binary file. If you play a computer vs computer match, the entire learning file will probably be overwritten multiple times before the same position occurs again on the board. As a consequence, the learning feature almost certainly has no effect whatsoever in engine vs engine games.
The only purpose of the learning feature in Glaurung is to make the program a better analysis tool. During interactive analysis session, when Glaurung wants to play a move which you know is bad, show it why it is bad (by playing out the relevant lines on the board while Glaurung runs in analysis mode) and back up to the position you started with, and Glaurung will (hopefully) understand why the move is bad.
Because hardly anyone uses Glaurung as an analysis tool (and I can't blame them; the program is far too speculative to be reliable for analysis) and because nobody understands the purpose of the learning function, I've decided not to include it in future versions.
Of course, what I write above is not intended as criticism of the excellent work you have done on RomiChess' learning function - your results are certainly very impressive.
Tord
Mike
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through