Vladimir Medvedev, Sat May 05, 2007 6:20 am wrote: http://sdchess.ru/Strelka.htm
http://sdchess.ru/engines/Strelka.rar
Author claims it plays on the level of 2700-2800. I did not test it yet.
Forbidden Tree
- kingliveson
- Posts: 1388
- Joined: Thu Jun 10, 2010 1:22 am
- Real Name: Franklin Titus
- Location: 28°32'1"N 81°22'33"W
Forbidden Tree
In the beginning: New engine from Russia
PAWN : Knight >> Bishop >> Rook >>Queen
- kingliveson
- Posts: 1388
- Joined: Thu Jun 10, 2010 1:22 am
- Real Name: Franklin Titus
- Location: 28°32'1"N 81°22'33"W
Re: Forbidden Tree
Evgenii Manev, Wed Jul 11, 2007 4:49 pm wrote:Hi all
I hope this translation is more accurate than the first one. Any suggestion to improve it are welcome.
Y.Osipov wrote:Ahh again created a mess… I’m already beginning to get used that each of my body movements provokes a storm of paradoxical feelings, which I could not ignore, according to present tendencies of the theory of verbal positivism…
Therefore I’ll tell the whole truth in order of how Strelka was created. I hope this will explain a lot.
1.As the basis of program was taken source code of Fruit (little less than two years ago).
2.The algorithm has been completely rewritten to bitboards. This operation had not changed anything, only improved performance twice (x2).
3.Since then, work has begun on improving the evaluation function and search algorithm. Optimization of evaluation functions was performed by correlation analysis. I sought the maximum correlation between static evaluation and minimax.
4.After Rybka had appeared a thought was borh to make a correlation analysis of Rybka assessment of the positions. I varied weights of assessment functions, I changed heuristics extensions and reductions in the search, and eventually I was able to achieve a very high degree of similarity of behaviour of Strelka and Rybka. In some positions, it was just a perfect match.
5.I was looking for and finding a reliable (and unreliable too) information on the algorithm of Rybka. Having carefully studied the works of Larry Kaufman researches of estimating imbalance material, as I had a great suspicion that Vasik used the same idea.
6.And the most legally suspicious thing : I carefully studied the code of Rybka using disassembler trying to understand the algorithm of its work. Altogether, I studied about 20% of the code. I am not interested in how works UCI-protokol or other functions, such as move generator. I already have my own ones, and I was not intending to engage with any protocol, since I was not going to make an engine.
I was only interested in search heuristics and evaluation function. This allowed me to achieve greater similarity (resemblance) with Rybka. In addition, I found that Vasik walked the same way (path) – he has taken Fruit as a basis, rewrote it to bitboard and included tables of material imbalance of Kaufman. Some of the tables I kidnapped (ravished) from the Rybka.
7. The last point in the history was made by man nicknamed Rybkin. Today we can say-he hammered the last nail in the coffin of Strelka. Unlike most participants in the forum, I believed him because I already knew much about Rybka by myself. It was because of him that I begun to understand the algorithm of how Rybka used tables of material evaluation. Rybkin was not right in one thing – he was wrong in his understanding that this big table was as a result of functions like material_comp_info. I am almost certain that Vasik processed big base of games, and the result of that was that table. In fact, this is the same what Kaufman did in the late 1990s.
8. After all for no apparent reason I wanted to make an engine and participate in tournaments. At the site WBEC I read the requirements for the engines - there has been emphasis on the fact that should be maintained the protocol Winboard and UCI-engines must work through an adapter Polyglot. I decided that writing Winboard-protocol is the shortest path. At least, that has to saving me the study of Polyglot. I looked in the Internet, and found the source code of Beowulf, from which I copied the protocol. Then it turned out that man who wrote Beowulf -- Corbit, subsequently investigated the source code of Strelka, and he was very surprised to find in it the code of Beowulf.
9. The New UCI-version of Strelka virtually has no difference from the first beta. The only thing I succeded to make was to find a functional relationship to the evaluation of material imbalance and somehow to correct these evaluations (assesments). The rest of the source code of Strelka remains virtually unchanged. So I was a little surprised by the allegations that the first version was not clone, but the second one became a clone. I can once again send the sources to Corbit and Hoffmann – let them compare.
That's it the whole story. You can lynch me if my actions have serious criminality. If so, I will not repent (regret ?), and would prefer to remain a free artist, just the same I has been so far. I will live as before and do what is interesting to me. And I don’t care about any ratings, participation in tournaments, all kinds of CCRL, etc. I can live without them, as they -- without me. I am a free man, and not promised to marry anyone.
PAWN : Knight >> Bishop >> Rook >>Queen
- kingliveson
- Posts: 1388
- Joined: Thu Jun 10, 2010 1:22 am
- Real Name: Franklin Titus
- Location: 28°32'1"N 81°22'33"W
Re: Forbidden Tree
Evgenii Manev, Sat Jan 12, 2008 5:33 pm wrote:From KasparovChess forum:
http://kasparovchess.crestbook.com/view ... 65#p135465
Youri Osipov wrote:
Vas: I've taken a look this morning at the Strelka 2.0 sources.
In early december Vasik already had the source code of the last version of Strelka. He himself wrote about this in rybkaforum.
Vas: Vast sections of these sources started their life as a decompiled Rybka 1.0.
If this is true then I am a genius. Thanks for the compliments.
Vas: The traces of this are everywhere.
Everyone who looked at the source code of Strelka came to conclusion that "everywhere" there is traces of Fruit. Or Rybka contains Fruit too?
Vas: The board representation is identical...
It's easy to see that "board representation is identical" to Fruit with changing some parts to bitboard.
Vas: ... and all sorts of absolutely unique Rybka code methods, bitboard tricks...
Noone found in Strelka some unique code methods or bitboard tricks. Just the contrary, everyone is thinking that there is nothing unusual or outstanding.
Vas: ... and even exact data tables are used throughout.
If he means the data tables from emater.c file, there is no such data tables in Rybka -- I have checked it. And everyone can check it scanning Rybka's exe. In Strelka there is no other big data tables.
Vas: Significant portions of the search and evaluation logic are not fully disassembled...
Then how it works if it is not fully disassembled?
Vas: ... he hasn't yet fully understood what is happening.
I guess, everyone understood the logic of the program (except me and Vasik may be?)
Vas: Rybka's UCI string are used throughout.
I'm not a masochist to disassemble UCI-block of Rybka when there is fine written Fruit.
Vas: The author did at first make attempts to hide the Rybka origins, for example by masking the table values in earlier Strelka versions.
Does it mean that source code of the earlier versions of Streka was known to Vasik? Then why he kept silence for so long?
After this there is a paragraph about differences between Strelka and Rybka. And again -- differences are found "everywhere". Question: what is more -- differences or identities?
Vas: In light of the above, I am claiming Strelka 2.0 as my own and will release it in the next few days under my own name.
Your welcome. I had not declared anywhere nor I had registered the copyright of Strelka. I had not restricted the use of Strelka with no any licenses. So everybody can declare himself as the author of Strelka. You can claim yourself as Napoleon too, if you wish so.
Vas: The name of the author with the pen name "Osipov" will be included...
How can I prove that me is me? How can I prove that I'm existing in real, and my real name is Yuri Ivanovich Osipov? I can show my ID-card. Or may be arrange a confrontation.
Vas: However, 'Osipov' has already threatened to repeat the procedure with Rybka 2.3.2a.
When I was talking about such thing?
Vas: He did this after I declined to grant him rights to commercialize Strelka.
I never intent to release commercial Strelka. Convekta has had such an idea, but this idea got Vasik's veto. It was internal business between Convekta and Vasik. I have no any relation with this. And I have absolutely no regrets that this project was not carried out. I preffer to be free person.
Vas: ... if someone has information about 'Osipov', please get in touch with me.
Vasik, accept my invitation and be my guest. Come, I'll be glad to meet you, to talk and to drink some cup of tea together. I am absolutely ordinary person, not Monte Cristo.
PAWN : Knight >> Bishop >> Rook >>Queen
- kingliveson
- Posts: 1388
- Joined: Thu Jun 10, 2010 1:22 am
- Real Name: Franklin Titus
- Location: 28°32'1"N 81°22'33"W
Re: Forbidden Tree
Norman Schmidt, Mon Aug 18, 2008 1:16 pm wrote:FRUIT:
static void parse_setoption( char string [])
{
const char *name;
char* value;
name = strstr(string, "name ");
value = strstr(string, "value ");
if (name == NULL || value == NULL || name >= value)return;
value[-1] = '\0';
name += 5;
value += 6;
STRELKA:
void parse_setoption(char string[])
{
char *name, *value;
int size;
name = strstr(string,"name ");
value = strstr(string,"value ");
if (name == NULL || value == NULL || name >= value) return;
value[-1] = 0;
name += 5;
value += 6;
---------------------------------------------------------------
FRUIT:
bool input_available()
{
static bool init = false, is_pipe;
static HANDLE stdin_h;
DWORD val, error;
if (stdin->_cnt > 0) return true;
if (!init)
{
init = true;
stdin_h = GetStdHandle(STD_INPUT_HANDLE);
is_pipe = !GetConsoleMode(stdin_h, &val);
if (!is_pipe)
{
SetConsoleMode(stdin_h, val & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
FlushConsoleInputBuffer(stdin_h);
}
}
if (is_pipe)
{
if (!PeekNamedPipe(stdin_h, NULL, 0, NULL, &val, NULL))
return true;
return val > 0;
}
else
{
GetNumberOfConsoleInputEvents(stdin_h, &val);
return val > 1;
}
return false;
}
STRELKA:
int input_available()
{
static int init = 0, is_pipe;
static HANDLE stdin_h;
DWORD val;
if (stdin->_cnt > 0) return 1;
if (!init)
{
init = 1;
stdin_h = GetStdHandle(STD_INPUT_HANDLE);
is_pipe = !GetConsoleMode(stdin_h, &val);
if (!is_pipe)
{
SetConsoleMode(stdin_h, val & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
FlushConsoleInputBuffer(stdin_h);
}
}
if (is_pipe)
{
if (!PeekNamedPipe(stdin_h, NULL, 0, NULL, &val, NULL))
return 1;
return val > 0;
}
else
{
GetNumberOfConsoleInputEvents(stdin_h, &val);
return val > 1;
}
return 0;
}
---------------------------------------------------------------
FRUIT:
static void parse_position( char string [] )
{
const char *fen;
char* moves;
const char *ptr;
char move_string[256];
int move;
undo_t undo[1];
fen = strstr(string, "fen ");
moves = strstr(string, "moves ");
if (fen != NULL)
{
if (moves != NULL)
{
ASSERT(moves > fen);
moves[-1] = '\0'; // dirty, but so is UCI
}
board_from_fen(SearchInput->board, fen + 4);
}
else
{
board_from_fen(SearchInput->board, StartFen);
}
if (moves != NULL)
{
ptr = moves + 6;
while (*ptr != '\0')
{
move_string[0] = *ptr++;
move_string[1] = *ptr++;
move_string[2] = *ptr++;
move_string[3] = *ptr++;
if (*ptr == '\0' || *ptr == ' ')
{
move_string[4] = '\0';
}
else
{
move_string[4] = *ptr++;
move_string[5] = '\0';
}
move = move_from_string(move_string, SearchInput->board);
move_do(SearchInput->board, move, undo);
while (*ptr == ' ')
ptr++;
}
}
}
STRELKA:
void parse_position( char string [] )
{
const char *fen;
char *moves;
const char *ptr;
char move_string[256];
int move;
struct undo_t undo[1];
fen = strstr(string, "fen ");
moves = strstr(string, "moves ");
if (fen != NULL)
{
if (moves != NULL)
moves[-1] = 0; // Das ist UCI
board_from_fen(fen + 4);
}
else
board_from_fen(start_pos);
if (moves != NULL)
{
ptr = moves + 6;
while (*ptr != 0)
{
move_string[0] = *ptr++;
move_string[1] = *ptr++;
move_string[2] = *ptr++;
move_string[3] = *ptr++;
if (*ptr == 0 || *ptr == ' ')
move_string[4] = 0;
else
{
move_string[4] = *ptr++;
move_string[5] = 0;
}
move = move_from_string(move_string);
move_do(move, undo);
while (*ptr == ' ')
ptr++;
}
}
}
---------------------------------------------------------------
FRUIT:
static void parse_go( char string [] )
{
const char *ptr;
bool infinite, ponder;
int depth, mate, movestogo;
sint64 nodes;
double binc, btime, movetime, winc, wtime;
double time, inc;
double time_max, alloc;
infinite = false;
ponder = false;
depth = -1;
mate = -1;
movestogo = -1;
nodes = -1;
binc = -1.0;
btime = -1.0;
movetime = -1.0;
winc = -1.0;
wtime = -1.0;
ptr = strtok(string, " ");
for ( ptr = strtok(NULL, " "); ptr != NULL; ptr = strtok(NULL, " ") )
{
if (false)
{
}
else if (string_equal(ptr, "binc"))
{
ptr = strtok(NULL, " ");
if (ptr == NULL)
my_fatal("parse_go(): missing argument\n");
binc = double(atoi(ptr)) / 1000.0;
ASSERT(binc >= 0.0);
}
else if (string_equal(ptr, "btime"))
{
ptr = strtok(NULL, " ");
if (ptr == NULL)
my_fatal("parse_go(): missing argument\n");
btime = double(atoi(ptr)) / 1000.0;
ASSERT(btime >= 0.0);
}
else if (string_equal(ptr, "depth"))
{
ptr = strtok(NULL, " ");
if (ptr == NULL)
my_fatal("parse_go(): missing argument\n");
depth = atoi(ptr);
ASSERT(depth >= 0);
}
else if (string_equal(ptr, "infinite"))
{
infinite = true;
}
else if (string_equal(ptr, "mate"))
{
ptr = strtok(NULL, " ");
if (ptr == NULL)
my_fatal("parse_go(): missing argument\n");
mate = atoi(ptr);
ASSERT(mate >= 0);
}
else if (string_equal(ptr, "movestogo"))
{
ptr = strtok(NULL, " ");
if (ptr == NULL)
my_fatal("parse_go(): missing argument\n");
movestogo = atoi(ptr);
ASSERT(movestogo >= 0);
}
else if (string_equal(ptr, "movetime"))
{
ptr = strtok(NULL, " ");
if (ptr == NULL)
my_fatal("parse_go(): missing argument\n");
movetime = double(atoi(ptr)) / 1000.0;
ASSERT(movetime >= 0.0);
}
else if (string_equal(ptr, "nodes"))
{
ptr = strtok(NULL, " ");
if (ptr == NULL)
my_fatal("parse_go(): missing argument\n");
nodes = my_atoll(ptr);
ASSERT(nodes >= 0);
}
else if (string_equal(ptr, "ponder"))
{
ponder = true;
}
else if (string_equal(ptr, "searchmoves"))
{
}
else if (string_equal(ptr, "winc"))
{
ptr = strtok(NULL, " ");
if (ptr == NULL)
my_fatal("parse_go(): missing argument\n");
winc = double(atoi(ptr)) / 1000.0;
ASSERT(winc >= 0.0);
}
else if (string_equal(ptr, "wtime"))
{
ptr = strtok(NULL, " ");
if (ptr == NULL)
my_fatal("parse_go(): missing argument\n");
wtime = double(atoi(ptr)) / 1000.0;
ASSERT(wtime >= 0.0);
}
}
search_clear();
if (depth >= 0)
{
SearchInput->depth_is_limited = true;
SearchInput->depth_limit = depth;
}
else if (mate >= 0)
{
SearchInput->depth_is_limited = true;
SearchInput->depth_limit = mate * 2 - 1;
}
if (COLOUR_IS_WHITE(SearchInput->board->turn))
{
time = wtime;
inc = winc;
}
else
{
time = btime;
inc = binc;
}
if (movestogo <= 0 || movestogo > 30)
movestogo = 30;
if (inc < 0.0)
inc = 0.0;
if (movetime >= 0.0)
{
SearchInput->time_is_limited = true;
SearchInput->time_limit_1 = movetime * 5.0;
SearchInput->time_limit_2 = movetime;
}
else if (time >= 0.0)
{
time_max = time * 0.95 - 1.0;
if (time_max < 0.0)
time_max = 0.0;
SearchInput->time_is_limited = true;
alloc = (time_max + inc * double(movestogo - 1)) / double(movestogo);
alloc *= (option_get_bool("Ponder") ? PonderRatio : NormalRatio);
if (alloc > time_max)
alloc = time_max;
SearchInput->time_limit_1 = alloc;
alloc = (time_max + inc * double(movestogo - 1)) * 0.5;
if (alloc < SearchInput->time_limit_1)
alloc = SearchInput->time_limit_1;
if (alloc > time_max)
alloc = time_max;
SearchInput->time_limit_2 = alloc;
}
if (infinite || ponder)
SearchInput->infinite = true;
Searching = true;
Infinite = infinite || ponder;
Delay = false;
search();
search_update_current();
Searching = false;
Delay = Infinite;
if (!Delay)
send_best_move();
}
STRELKA:
void start_go( char string [] )
{
const char *ptr;
int infinite, ponder;
int depth, mate, movestogo, zapas;
__int64 nodes;
int binc, btime, movetime, winc, wtime;
int time, inc, alloc;
struct board_t BoardSave[1];
infinite = 0;
ponder = 0;
depth = -1;
mate = -1;
movestogo = -1;
nodes = -1;
binc = -1;
btime = -1;
movetime = -1;
winc = -1;
wtime = -1;
ptr = strtok(string, " ");
for ( ptr = strtok(NULL, " "); ptr != NULL; ptr = strtok(NULL, " ") )
{
if (!strcmp(ptr, "binc"))
{
ptr = strtok(NULL, " ");
binc = atoi(ptr);
}
else if (!strcmp(ptr, "btime"))
{
ptr = strtok(NULL, " ");
btime = atoi(ptr);
}
else if (!strcmp(ptr, "depth"))
{
ptr = strtok(NULL, " ");
depth = atoi(ptr);
}
else if (!strcmp(ptr, "infinite"))
{
infinite = 1;
}
else if (!strcmp(ptr, "mate"))
{
ptr = strtok(NULL, " ");
mate = atoi(ptr);
}
else if (!strcmp(ptr, "movestogo"))
{
ptr = strtok(NULL, " ");
movestogo = atoi(ptr);
}
else if (!strcmp(ptr, "movetime"))
{
ptr = strtok(NULL, " ");
movetime = atoi(ptr);
}
else if (!strcmp(ptr, "nodes"))
{
ptr = strtok(NULL, " ");
sscanf(ptr, "%I64d", &nodes);
}
else if (!strcmp(ptr, "ponder"))
{
ponder = 1;
}
else if (!strcmp(ptr, "winc"))
{
ptr = strtok(NULL, " ");
winc = atoi(ptr);
}
else if (!strcmp(ptr, "wtime"))
{
ptr = strtok(NULL, " ");
wtime = atoi(ptr);
}
}
NS ->(the following 10 lines of code essentially do the same thing as Fruit’s search_clear function, i.e. initialize search vars to 0 or false)
_______________________________________
best_move = 0;
best_score = 0;
depth_score = 0;
check_nb = 1024;
start_time = GetTickCount();
can_stop = 0;
bad_1 = bad_2 = change = easy = flag = 0;
* pv_str = 0;
stop_search = 0;
depth_is_limited = time_is_limited = 0;
________________________________________
if (depth >= 0)
{
depth_is_limited = 1;
depth_limit = depth;
}
else if (mate >= 0)
{
depth_is_limited = 1;
depth_limit = mate * 2 - 1;
}
if ((Board->turn) == 0)
{
time = wtime;
inc = winc;
}
else
{
time = btime;
inc = binc;
}
zapas = 0;
if (movestogo <= 0)
movestogo = 30;
if (movestogo > 30)
{
movestogo = 30;
zapas = 1;
}
time_max = 100000;
if (inc < 0)
inc = 0;
if (movetime >= 0)
{
time_is_limited = 1;
time_max = movetime;
time_limit_1 = movetime * 5;
time_limit_2 = movetime;
}
else if (time >= 0)
{
time_is_limited = 1;
if (zapas)
time_max = ((time / 10) * 9) - 5000;
else
time_max = time - 2000;
if (time_max < 0)
time_max = 0;
alloc = (time_max + inc * (movestogo - 1)) / movestogo;
if (alloc > time_max)
alloc = time_max;
time_limit_1 = alloc;
alloc = (time_max + inc * (movestogo - 1)) / 2;
if (alloc < time_limit_1)
alloc = time_limit_1;
if (alloc > time_max)
alloc = time_max;
time_limit_2 = alloc;
}
Infinite = 0;
if (infinite || ponder)
Infinite = 1;
Searching = 1;
Delay = 0;
memcpy(BoardSave, Board, sizeof(struct board_t));
start_search();
memcpy(Board, BoardSave, sizeof(struct board_t));
search_time = GetTickCount() - start_time;
if (search_time < 0)
search_time = 0;
Searching = 0;
Delay = Infinite;
if (!Delay)
send_best_move();
}
---------------------------------------------------------------
FRUIT:
void trans_alloc( trans_t *trans )
{
uint32 size, target;
target = option_get_int("Hash");
if (target < 4) target = 16;
target *= 1024 * 1024;
for ( size = 1; size != 0 && size <= target; size *= 2 );
size /= 2;
size /= sizeof(entry_t);
trans->size = size + (ClusterSize - 1);
trans->mask = size - 1;
trans->table = (entry_t *)my_malloc(trans->size * sizeof(entry_t));
trans_clear(trans);
}
STRELKA:
void trans_alloc( int target )
{
int size;
target *= 1024 * 1024;
for ( size = 1; size != 0 && size <= target; size *= 2 );
size /= 2;
size /= sizeof(struct entry_t);
trans_size = size + (ClusterSize - 1);
trans_mask = size - 2;
trans_entry = (struct entry_t *)malloc(trans_size * sizeof(struct entry_t) + 64);
trans_clear();
}
---------------------------------------------------------------
FRUIT:
void trans_store( trans_t *trans, uint64 key, int move, int depth, int min_value, int max_value )
{
entry_t* entry, * best_entry;
int score, best_score;
int i;
trans->write_nb++;
best_entry = NULL;
best_score = -32767;
entry = trans_entry(trans, key);
for ( i = 0; i < ClusterSize; i++, entry++ )
{
if (entry->lock == KEY_LOCK(key))
{
trans->write_hit++;
if (entry->date != trans->date)
trans->used++;
entry->date = trans->date;
if (depth > entry->depth)
entry->depth = depth;
if (move != MoveNone && depth >= entry->move_depth)
{
entry->move_depth = depth;
entry->move = move;
}
if (min_value > -ValueInf && depth >= entry->min_depth)
{
entry->min_depth = depth;
entry->min_value = min_value;
}
if (max_value < +ValueInf && depth >= entry->max_depth)
{
entry->max_depth = depth;
entry->max_value = max_value;
}
return;
}
score = trans->age[entry->date] * 256 - entry->depth;
if (score > best_score)
{
best_entry = entry;
best_score = score;
}
}
entry = best_entry;
if (entry->date == trans->date)
{
trans->write_collision++;
}
else
{
trans->used++;
}
entry->lock = KEY_LOCK(key);
entry->date = trans->date;
entry->depth = depth;
entry->move_depth = (move != MoveNone) ? depth : DepthNone;
entry->move = move;
entry->min_depth = (min_value > -ValueInf) ? depth : DepthNone;
entry->max_depth = (max_value < +ValueInf) ? depth : DepthNone;
entry->min_value = min_value;
entry->max_value = max_value;
}
STRELKA:
void trans_store(unsigned __int16 move, char depth, __int16 value)
{
int i, score, best_score;
struct entry_t *entry;
struct entry_t *best_entry;
best_entry = NULL;
best_score = 0;
entry = trans_entry + (KEY_INDEX &trans_mask);
for ( i = 0; i < ClusterSize; i++, entry++ )
{
if (entry->lock == KEY_LOCK)
{
entry->date = (unsigned char)trans_date;
if (depth > entry->depth)
entry->depth = depth;
if (depth >= entry->move_depth)
{
entry->move_depth = depth;
entry->move = move;
}
if (depth >= entry->min_depth)
{
entry->min_depth = depth;
entry->min_value = value;
}
if (depth >= entry->max_depth)
{
entry->max_depth = depth;
entry->max_value = value;
}
return;
}
score = trans_score[entry->date] - (entry->depth);
if (score > best_score)
{
best_entry = entry;
best_score = score;
}
}
best_entry->lock = KEY_LOCK;
best_entry->date = (unsigned char)trans_date;
best_entry->depth = depth;
best_entry->move_depth = depth;
best_entry->move = move;
best_entry->min_depth = depth;
best_entry->min_value = value;
best_entry->max_depth = depth;
best_entry->max_value = value;
}
---------------------------------------------------------------
FRUIT:
static void loop_step()
{
char string[65536];
get(string, 65536);
if (false)
{
}
else if (string_start_with(string, "debug "))
{
}
else if (string_start_with(string, "go "))
{
if (!Searching && !Delay)
{
init();
parse_go(string);
}
}
else if (string_equal(string, "isready"))
{
if (!Searching && !Delay)
{
init();
}
send("readyok");
}
else if (string_equal(string, "ponderhit"))
{
if (Searching)
{
SearchInput->infinite = false;
Infinite = false;
}
else if (Delay)
{
send_best_move();
Delay = false;
}
}
else if (string_start_with(string, "position "))
{
if (!Searching && !Delay)
{
init();
parse_position(string);
}
}
else if (string_equal(string, "quit"))
{
exit(EXIT_SUCCESS);
}
else if (string_start_with(string, "setoption "))
{
if (!Searching && !Delay)
{
parse_setoption(string);
}
}
else if (string_equal(string, "stop"))
{
if (Searching)
{
SearchInfo->stop = true;
Infinite = false;
}
else if (Delay)
{
send_best_move();
Delay = false;
}
}
else if (string_equal(string, "uci"))
{
send("id name Fruit " VERSION);
send("id author Fabien Letouzey");
option_list();
send("uciok");
}
else if (string_equal(string, "ucinewgame"))
{
if (!Searching && !Delay && Init)
{
trans_clear(Trans);
}
else
{
}
}
}
STRELKA:
void get_uci_command()
{
char string[65536];
char *ptr;
(void)fgets(string, 65536, stdin);
if (feof(stdin))
exit(0);
ptr = strchr(string, '\n');
if (ptr != NULL)
* ptr = 0;
if (!strcmp(string, "uci"))
{
fprintf(stdout, "id name Strelka 2.0 B\n");
fprintf(stdout, "id author Jury Osipov\n");
fprintf(stdout, "option name Hash type spin default 32 min 4 max 1024\n");
fprintf(stdout, "option name MultiPV type spin default 1 min 1 max 100\n");
fprintf(stdout, "uciok\n");
}
else if (!strcmp(string, "ucinewgame"))
{
if (!Searching && !Delay)
trans_clear();
}
else if (!strcmp(string, "isready"))
{
fprintf(stdout, "readyok\n");
}
else if (!strcmp(string, "ponderhit"))
{
if (Searching)
Infinite = 0;
else if (Delay)
{
send_best_move();
Delay = 0;
}
}
else if (!memcmp(string, "position", 8))
{
if (!Searching && !Delay)
parse_position(string);
}
else if (!memcmp(string, "setoption", 9))
{
if (!Searching && !Delay)
parse_setoption(string);
}
else if (!memcmp(string, "go", 2))
{
if (!Searching && !Delay)
start_go(string);
}
else if (!strcmp(string, "stop"))
{
if (Searching)
{
stop_search = 1;
Infinite = 0;
}
else if (Delay)
{
send_best_move();
Delay = 0;
}
}
else if (!strcmp(string, "quit"))
exit(0);
#ifdef TEST_VER
else if (!memcmp(string, "epd", 3))
run_epd_test(string);
else if (!memcmp(string, "pgn", 3))
run_pgn_test(string);
#endif
}
---------------------------------------------------------------
Please note:
both sets of code have been formatted with polystyle for regularity and clarity
ASSERTs have been removed
lines (and blank lines) have been aligned for easy content comparison
all comments removed except for the translation of Fabien's
// dirty, but so is UCI
to
// Das ist UCI
(which is really odd considering Jury is Russian?)
My sincere esitmate is that at least 40-50% of the codebase is extremely similar or exact, with the rest of Strelka's code being a well done bitboard implementation utilizing standard inlined assembly language routines (like first_one, last_one, etc.), various bitmasks, popcnt, etc.
It's clear that a very significant and major effort was required to create this bitboard backend, and integrate it with so much of what appears to be Fruit source code. It's would be no trivial task indeed.
This has nothing to do with it, but from my limited testing (100 games) it appears that Strelka 2.0 is very strong: probably ~+100 ELO better than toga14beta5c, but more games need to be played.
Norm
PAWN : Knight >> Bishop >> Rook >>Queen
- kingliveson
- Posts: 1388
- Joined: Thu Jun 10, 2010 1:22 am
- Real Name: Franklin Titus
- Location: 28°32'1"N 81°22'33"W
Re: Forbidden Tree
Times have changed:
chrisw wrote:Interesting you ignore this part of his postbob wrote:The problem is, his statement is pure and utter nonsense. He is making _no_ distinction between "program" and "algorithm". Yes we order moves the same way, more or less. But the "how" is hugely different. For example, let's say everyone does moves in _exactly_ this order:Uri Blass wrote:Vas also responded in the rybka Forum
http://rybkaforum.net/cgi-bin/rybkaforu ... =99683;hl=
hash
winning captures
equal captures
killer moves.
rest of moves
how many that have written programs do this: Search hash move before generating a single move? Search killers before generating non-captures? Generate captures and non-captures separately? Generate captures and non-captures and check evasions separately? generate captures and non-captures and check-evasions and qsearch checking moves separately? How many rank captures by SEE, vs MVV/LVA? If you are in check, do you generate legal moves only, or generate pseudo-legal and exclude illegal ones by testing for in check after making the move? Or reject it by capturing the king?
The _programming_ differences are limitless. Very much like the room full of monkeys, except that each monkey is a programmer. So while the "algorithms" might look close, the programming will not. And to suggest that it will is _really_ a dishonest statement. One can find dozens of academic references on detecting plagiarism in programming, where we don't give 40,000 line projects.
This post was just so much nonsense that it is hard to believe a _real_ programmer would write such garbage. That makes him look worse than had he remained silent, in fact.
Vas wrote:
Generally, code theft is easy to show - just show the two sections of identical code, side-by-side. There isn't much to debate in such cases.
and choose to insult him instead.
It's put up or shut time, Bob.
Show the sections of identical code, Rybka - Fruit.
I don't know either way. Maybe they exist and maybe they don't, but I, for sure, and others probably, are not going to believe these accusations without them.
PAWN : Knight >> Bishop >> Rook >>Queen
- kingliveson
- Posts: 1388
- Joined: Thu Jun 10, 2010 1:22 am
- Real Name: Franklin Titus
- Location: 28°32'1"N 81°22'33"W
Re: Forbidden Tree
And there was:
Evaluation
Rybka's evaluation has been the subject of much speculation ever since its appearance. Various theories have been put forth about the inner workings of the evaluation, but with the publication of Strelka, it was shown just how wrong everyone was. It is perhaps ironic that Rybka's evaluation is its most similar part to Fruit; it contains, in my opinion, the most damning evidence of all.
General Differences
Simply put, Rybka's evaluation is virtually identical to Fruit's. There are a few important changes though, that should be kept in mind when viewing this analysis.
•Most obviously, the translation to Rybka's bitboard data structures. In some instances, such as in the pawn evaluation, the bitboard version will behave slightly differently than the original. But the high-level functionality is always equivalent in these cases; the changes are brought about because of a more natural representation in bitboards, or for a slight speed gain. In other cases the code has been reorganized a bit; this should be seen more as an optimization than as a real change, since the end result is the same.
•All of the endgame and draw recognition logic in Fruit has been replaced by a large material table in Rybka. This serves mostly the same purpose as the material hash table in Fruit, since it has an evaluation and a flags field.
•All of the weights have been tuned. Due to the unnatural values of Rybka's evaluation parameters, they were mostly likely tuned in some automated fashion. However, there are a few places where the origin of the values in Fruit is still apparent: piece square tables, passed pawn scores, and the flags in the material table.
Evaluation Detail
In the following pages I will go into more depth about the details of each aspect of the evaluations and their similarities and differences.
•Pawn evaluation: pawn_get_info()
•Piece evaluation: eval_piece()
•King Safety/Shelter: eval_king()
•Passed Pawns: eval_passer()
•Patterns: eval_pattern()
•Material
https://webspace.utexas.edu/zzw57/rtc/eval/eval.html
Evaluation
Rybka's evaluation has been the subject of much speculation ever since its appearance. Various theories have been put forth about the inner workings of the evaluation, but with the publication of Strelka, it was shown just how wrong everyone was. It is perhaps ironic that Rybka's evaluation is its most similar part to Fruit; it contains, in my opinion, the most damning evidence of all.
General Differences
Simply put, Rybka's evaluation is virtually identical to Fruit's. There are a few important changes though, that should be kept in mind when viewing this analysis.
•Most obviously, the translation to Rybka's bitboard data structures. In some instances, such as in the pawn evaluation, the bitboard version will behave slightly differently than the original. But the high-level functionality is always equivalent in these cases; the changes are brought about because of a more natural representation in bitboards, or for a slight speed gain. In other cases the code has been reorganized a bit; this should be seen more as an optimization than as a real change, since the end result is the same.
•All of the endgame and draw recognition logic in Fruit has been replaced by a large material table in Rybka. This serves mostly the same purpose as the material hash table in Fruit, since it has an evaluation and a flags field.
•All of the weights have been tuned. Due to the unnatural values of Rybka's evaluation parameters, they were mostly likely tuned in some automated fashion. However, there are a few places where the origin of the values in Fruit is still apparent: piece square tables, passed pawn scores, and the flags in the material table.
Evaluation Detail
In the following pages I will go into more depth about the details of each aspect of the evaluations and their similarities and differences.
•Pawn evaluation: pawn_get_info()
•Piece evaluation: eval_piece()
•King Safety/Shelter: eval_king()
•Passed Pawns: eval_passer()
•Patterns: eval_pattern()
•Material
https://webspace.utexas.edu/zzw57/rtc/eval/eval.html
PAWN : Knight >> Bishop >> Rook >>Queen
- kingliveson
- Posts: 1388
- Joined: Thu Jun 10, 2010 1:22 am
- Real Name: Franklin Titus
- Location: 28°32'1"N 81°22'33"W
Re: Forbidden Tree
And the question:
Alexander Schmidt wrote: The increase in playing strength of the latest chess engines is unbelieveable. We have since some time with Fruit 2.1 by Fabien Letouzey a very strong open source engine. Do you see a relation between the published sources of such a strong engine and the increase of strength in computer chess in general? How much influence do the ideas of Fruit have on the future of computerchess?
Vas maintains Rybka is "100% original at the source level."Vasik Rajlich wrote: Yes, the publication of Fruit 2.1 was huge. Look at how many engines took a massive jump in its wake: Rybka, Hiarcs, Fritz, Zappa, Spike, List, and so on. I went through the Fruit 2.1 source code forwards and backwards and took many things.
It is a bit of a pity that Rybka won't make the same contribution to the computer chess community, but at the moment I must also think about protecting my secrets. It's the eternal struggle for a computer chess programmer.
PAWN : Knight >> Bishop >> Rook >>Queen
- thorstenczub
- Posts: 593
- Joined: Wed Jun 09, 2010 12:51 pm
- Real Name: Thorsten Czub
- Location: United States of Europe, germany, NRW, Lünen
- Contact:
Re: Forbidden Tree
christian computerchess poll:
do you believe earth is a disc ?
yes.......................................75 %
no .......................................2%
no clear answer because
died on the fire or thrown into water................ 25%
(includes the 2% no)
do you believe earth is a disc ?
yes.......................................75 %
no .......................................2%
no clear answer because
died on the fire or thrown into water................ 25%
(includes the 2% no)