Рыбная ловля

Discussion in 'Машинное отделение' started by Рыбкин, 16 Mar 2007.

  1. syrdon
    Оффлайн

    syrdon Учаcтник

    Репутация:
    0
    Мы ни к чему не придём.
    Я верю словам Рыбкина, Вы - нет.

    Хорошо, оставшиеся 2 мегабайта в Рыбке забиты морем знаний.
     
  2. Alexander
    Оффлайн

    Alexander баннер

    Репутация:
    43
    Интересно, а вводят ли настоящие авторы программ в свои движки ассемблерные фрагменты из ничего не меняющих операций, чтобы потом точно подвердить свое авторство? Или есть более изощренные способы, может, часть кода зашифровать?
     
  3. Fruit
    Оффлайн

    Fruit Александр баннер

    Репутация:
    3
    И всё ради одной цели: извиняюсь за выражение, понтануться на этом форуме. :)
     
  4. WildCat
    Оффлайн

    WildCat Коршунов Игорь Staff Member

    Репутация:
    0
    Fruit, разные мании бывают :)
     
  5. Terri
    Оффлайн

    Terri Зарегистрирован

    Репутация:
    0
    Похоже WildCat и NS будут искать паттерны до потери пулся, чем поверят в то, что все намного проще !
    Ребята а вам не кажется что все гениальное просто ?
    Вам же сказали нет в рыбке никаких знаний, тупой перебор и хорошо сбалансированная оценка позиции. Вы с этим то хоть согласились или нет ?
    Получения Си кода трогать не будем .
    Я не программист, но судя потому что с увеличением скорости и мощности процессора, в разы увеличивается сила рыбки - говорит о том, что там как и везде шустрый перебор.
     
  6. WinPooh
    Оффлайн

    WinPooh В.М. Staff Member

    Репутация:
    95
    Для начала давайте определимся, что значит "в разы".
    Было 2800 ELO - стало 5600, что ли? :)
     
  7. NS
    Оффлайн

    NS Нефёдов Сергей баннер

    Репутация:
    3
    Никто ничего в Рыбке не ищет. И всем понятно что в Рыбке обычный перебор и хорошая ОФ. Вопрос в том каким способом были получены веса в ОФ?

    С увеличением мощности и скорости процессора сила Рыбки растет так-же как и устальных сильных движков. Не быстрее и не медленней.
    Насчет паттернов - Вы хоть поняли что такое паттерны? Паттерны это сочетания. Практически любая табличная оценка это паттерны. И соотвественно практически в любой программе они есть.
     
  8. NS
    Оффлайн

    NS Нефёдов Сергей баннер

    Репутация:
    3
    Мне более интересно узнать что такое шустрый перебор, и почему при шустром переборе сила растет быстрее чем при "не шустром" :)

    И откуда возникло предположение что в Рыбке не "шустрый перебор"?
    Кто-то об этом что-ли что-то где-то говорил? Вроде в любой программе шустрый перебор, я не понимаю как программа может играть в шахматы без перебора.
     
  9. Terri
    Оффлайн

    Terri Зарегистрирован

    Репутация:
    0
    Ваш ответ меня устроил. Спасибо.
    Еще у меня пожелание есть - не бросайте "Стрелку" хороший движок ведь, не ужели никто не будет его доводить до ума ?
    Может вы NS ?
    Я так понял - автор стрелки потерял к ней интерес, а жалко.
     
  10. NS
    Оффлайн

    NS Нефёдов Сергей баннер

    Репутация:
    3
    Нет, автор Cтрелки это не NS :)
    Интерес теряют все... на время, а потом боьшинство начинает писать опять.
    У меня уже год как пропал интрес к шахматному программированию, наверно должен скоро вернуться :)
     
  11. stirlitz
    Оффлайн

    stirlitz баннер

    Репутация:
    13
    Я бы определил так - сила проги увеличилась в n раз, если новая её версия наберёт в длинном матче со старой в n раз больше очков (согласно рейтингов Эло). Во! :)
    Тогда увеличение силы в два раза примерно соответствует приращению 115 пунктов Эло.
     
  12. Fruit
    Оффлайн

    Fruit Александр баннер

    Репутация:
    3
    Мнение Доннингера о рыбке http://www.top-5000.nl/phpBB2/viewtopic.php?t=79 Кажется, он наш форум читает. А ещё там есть такие слова:

    How to I know? There was a post on a Russion forum by a hacker who dissassembled Rybka. Everybody sayed, he just invents this and its not true.
    But I have also disassembled some parts of the first Rybka Version. My findings are in aggreement with the statements of these guy.

    То есть, тоже дизассемблировал (Гидра клон теперь, да?) Рыбку и согласен с Рыбкиным!?!?

    PS: было бы здорово точный перевод почитать. :)
     
  13. Осипов Юрий
    Оффлайн

    Осипов Юрий Учаcтник

    Репутация:
    11
    И все-таки еще раз по поводу декомпиляции.
    Предположим, что мы хотим переписать Рыбку с ассемблера на Си.
    Берем дизассемблер IdaPro, загружаем в нее EXE-файл Рыбки и получаем ее ассемблерный исходник.
    Собираем из этого исходника рабочий проект в Visual Studio, компилируем и получаем EXE.
    После некоторых усилий и работы напильником, получаем проект на ассемблере, который компилируется в EXE и этот EXE работает точно так, как и оригинал.

    Теперь мы лезем в наш ASM-файл, выгруженный из Idapro.
    Нашли в нем, к примеру, такую процедуру, которую мы хотим переписать на Си:


    _sub_403490 proc near
    arg_0 = dword ptr 4
    mov eax, [esp+arg_0]
    push esi
    push edi
    push 8656 ; size_t
    push 0 ; int
    push offset _dword_667A90 ; void *
    mov esi, eax
    call _memset
    movsx ecx, byte ptr [esi]
    add esp, 0Ch
    mov edx, 56
    loc_4034B0: xor eax, eax
    loc_4034B2: lea edi, [ecx-31h]
    cmp edi, 7
    ja short loc_4034C0
    lea eax, [eax+ecx-30h]
    jmp short loc_4034D4
    loc_4034C0: mov ecx, ds:_dword_65E550[ecx*4]
    lea edi, [edx+eax]
    mov _dword_667A90[edi*4], ecx
    add eax, 1
    loc_4034D4: movsx ecx, byte ptr [esi+1]
    add esi, 1
    cmp eax, 7
    jle short loc_4034B2
    movsx ecx, byte ptr [esi+1]
    add esi, 1
    sub edx, 8
    jns short loc_4034B0
    cmp ecx, 62h
    jnz short loc_4034FE
    mov edx, 1
    mov _dword_667C20, edx
    jmp short loc_403504
    loc_4034FE: mov edx, _dword_667C20
    loc_403504: movsx eax, byte ptr [esi+2]
    add esi, 2
    cmp eax, 2Dh
    jnz short loc_403517
    movsx eax, byte ptr [esi+1]
    add esi, 1
    loc_403517: cmp eax, 4Bh
    jnz short loc_40352A
    or _dword_667C28, 1
    movsx eax, byte ptr [esi+1]
    add esi, 1
    loc_40352A: cmp eax, 51h
    jnz short loc_40353D
    or _dword_667C28, 2
    movsx eax, byte ptr [esi+1]
    add esi, 1
    loc_40353D: cmp eax, 6Bh
    jnz short loc_403550
    or _dword_667C28, 4
    movsx eax, byte ptr [esi+1]
    add esi, 1
    loc_403550: cmp eax, 71h
    jnz short loc_40355F
    or _dword_667C28, 8
    add esi, 1
    loc_40355F: movsx eax, byte ptr [esi+1]
    add esi, 1
    cmp eax, 2Dh
    jz short loc_4035B2
    movsx ecx, byte ptr [esi+1]
    lea ecx, [eax+ecx*8-1E9h]
    mov eax, ecx
    xor eax, 8
    cmp _dword_667A90[ecx*4], 0
    jnz short loc_4035AA
    mov esi, 3
    sub esi, edx
    cmp _dword_667A90[eax*4], esi
    jnz short loc_4035AA
    add edx, 2
    cmp _dword_667A8C[eax*4], edx
    jz short loc_4035AC
    cmp _dword_667A94[eax*4], edx
    jz short loc_4035AC
    loc_4035AA: xor ecx, ecx
    loc_4035AC: mov _dword_667C2C, ecx
    loc_4035B2: mov esi, offset _dword_667A90
    push esi
    call _sub_401100
    add esp, 4
    pop edi
    pop esi
    retn
    _sub_403490 endp


    Невкусный текст, не правда ли.
    Но мы не отчаиваемся, вытаскиваем эту процедуру из ASM-файла и втыкаем ее в Си-файл:



    void sub_403490(char * arg_0)
    { _asm {
    mov eax, arg_0
    push esi
    push edi
    push 8656
    push 0
    push offset dword_667A90
    mov esi, eax
    call memset
    movsx ecx, byte ptr [esi]
    add esp, 0Ch
    mov edx, 56
    loc_4034B0: xor eax, eax
    loc_4034B2: lea edi, [ecx-31h]
    cmp edi, 7
    ja loc_4034C0
    lea eax, [eax+ecx-30h]
    jmp loc_4034D4
    loc_4034C0: mov ecx, dword_65E550[ecx*4]
    lea edi, [edx+eax]
    mov dword_667A90[edi*4], ecx
    add eax, 1
    loc_4034D4: movsx ecx, byte ptr [esi+1]
    add esi, 1
    cmp eax, 7
    jle loc_4034B2
    movsx ecx, byte ptr [esi+1]
    add esi, 1
    sub edx, 8
    jns loc_4034B0
    cmp ecx, 62h
    jnz loc_4034FE
    mov edx, 1
    mov dword_667C20, edx
    jmp loc_403504
    loc_4034FE: mov edx, dword_667C20
    loc_403504: movsx eax, byte ptr [esi+2]
    add esi, 2
    cmp eax, 2Dh
    jnz loc_403517
    movsx eax, byte ptr [esi+1]
    add esi, 1
    loc_403517: cmp eax, 4Bh
    jnz loc_40352A
    or dword_667C28, 1
    movsx eax, byte ptr [esi+1]
    add esi, 1
    loc_40352A: cmp eax, 51h
    jnz loc_40353D
    or dword_667C28, 2
    movsx eax, byte ptr [esi+1]
    add esi, 1
    loc_40353D: cmp eax, 6Bh
    jnz loc_403550
    or dword_667C28, 4
    movsx eax, byte ptr [esi+1]
    add esi, 1
    loc_403550: cmp eax, 71h
    jnz loc_40355F
    or dword_667C28, 8
    add esi, 1
    loc_40355F: movsx eax, byte ptr [esi+1]
    add esi, 1
    cmp eax, 2Dh
    jz loc_4035B2
    movsx ecx, byte ptr [esi+1]
    lea ecx, [eax+ecx*8-1E9h]
    mov eax, ecx
    xor eax, 8
    cmp dword_667A90[ecx*4], 0
    jnz loc_4035AA
    mov esi, 3
    sub esi, edx
    cmp dword_667A90[eax*4], esi
    jnz loc_4035AA
    add edx, 2
    cmp dword_667A8C[eax*4], edx
    jz loc_4035AC
    cmp dword_667A94[eax*4], edx
    jz loc_4035AC
    loc_4035AA: xor ecx, ecx
    loc_4035AC: mov dword_667C2C, ecx
    loc_4035B2: mov esi, offset dword_667A90
    push esi
    call sub_401100
    add esp, 4
    pop edi
    pop esi
    }
    }


    Далее, разобравшись (по вызовам этой процедуры), что эта процедура делает, понимаем, что она инициализирует структуру позиции из строки FEN.
    Ну и помучившись с ASM-кодом, получаем примерно такой текст на Си:



    void board_from_fen(const char fen[])
    { int pos, i, j;
    char c;

    memset(dword_667A90, 0, 8656);
    pos = 0;
    c = fen[pos];
    for (i = 56; i >= 0; i-=8) {
    for (j = 0; j <= 7; ) {
    if (c <= '8') j += c - '0';
    else { dword_667A90[i+j] = dword_65E550[c]; j++; }
    c = fen[++pos];
    }
    c = fen[++pos];
    }
    if (c == 'b') dword_667C20 = 1;
    c = fen[++pos]; c = fen[++pos];
    if (c == '-') c = fen[++pos];
    if (c == 'K') { dword_667C28 |= 1; c = fen[++pos]; }
    if (c == 'Q') { dword_667C28 |= 2; c = fen[++pos]; }
    if (c == 'k') { dword_667C28 |= 4; c = fen[++pos]; }
    if (c == 'q') { dword_667C28 |= 8; c = fen[++pos]; }
    c = fen[++pos];
    if (c != '-') {
    i = c + fen[++pos] * 8 - 489;
    j = i ^ 8;
    if (dword_667A90 != 0) i = 0;
    else if (dword_667A90[j] != (3-dword_667C20)) i = 0;
    else if (dword_667A90[j-1] != (dword_667C20+2) && dword_667A90[j+1] != (dword_667C20+2)) i = 0;
    dword_667C2C = i;
    }
    sub_401100(dword_667A90);
    }


    Догадываемся, что dword_667A90 - это указатель на структуру отображения позиции типа Board размером 8656 байт.
    Создаем описание этой структуры на Си.
    А наша процедура в окончательном виде приобретает вполне цивильный вид:



    void board_from_fen(const char fen[])
    { int pos, i, j;
    char c;

    memset(Board, 0, sizeof(struct board_t));
    pos = 0;
    c = fen[pos];
    for (i = 56; i >= 0; i-=8) {
    for (j = 0; j <= 7; ) {
    if (c <= '8') j += c - '0';
    else { Board->square[i+j] = PieceFromChar[c]; j++; }
    c = fen[++pos];
    }
    c = fen[++pos];
    }
    if (c == 'b') Board->turn = 1;
    c = fen[++pos]; c = fen[++pos];
    if (c == '-') c = fen[++pos];
    if (c == 'K') { Board->flags |= 1; c = fen[++pos]; }
    if (c == 'Q') { Board->flags |= 2; c = fen[++pos]; }
    if (c == 'k') { Board->flags |= 4; c = fen[++pos]; }
    if (c == 'q') { Board->flags |= 8; c = fen[++pos]; }
    c = fen[++pos];
    if (c != '-') {
    i = c + fen[++pos] * 8 - 489;
    j = i ^ 8;
    if (Board->square != 0) i = 0;
    else if (Board->square[j] != (3-Board->turn)) i = 0;
    else if (Board->square[j-1] != (Board->turn+2) && Board->square[j+1] != (Board->turn+2)) i = 0;
    Board->ep_square = i;
    }
    board_init(Board);
    }
     
  14. Goranflo
    Оффлайн

    Goranflo баннер

    Репутация:
    678
    По моему проще с нуля написать...