Списки фигур

Тема в разделе "Машинное отделение", создана пользователем bankuss, 20 июн 2007.

  1. TopicStarter Overlay

    bankuss Александр

    • Заслуженный
    • Участник
    • Старожил
    Рег.:
    24.05.2006
    Сообщения:
    1.084
    Симпатии:
    38
    Репутация:
    6
    Оффлайн
    все таки заведу эту тему :)
    какие реализации? (Си интересует), что лучше там хранить.
    связка с исполнителем\возвращателем хода.

    если можно примеры ;)

    у меня сейчас простой скан по доске, но хотелось бы все в нормальный вид переделать.
  2. WinPooh В.М.

    • Команда форума
    Рег.:
    13.02.2006
    Сообщения:
    9.491
    Симпатии:
    3.118
    Репутация:
    95
    Адрес:
    Москва
    Оффлайн
  3. WildCat Коршунов Игорь

    • Команда форума
    Рег.:
    04.05.2006
    Сообщения:
    3.599
    Симпатии:
    4
    Репутация:
    0
    Адрес:
    Гомель
    Оффлайн
    Можно так: int Pieces[color][type][n];
  4. TopicStarter Overlay

    bankuss Александр

    • Заслуженный
    • Участник
    • Старожил
    Рег.:
    24.05.2006
    Сообщения:
    1.084
    Симпатии:
    38
    Репутация:
    6
    Оффлайн
    WildCat а если без color ? в типе и цвет прописать. а n это что?
  5. WinPooh В.М.

    • Команда форума
    Рег.:
    13.02.2006
    Сообщения:
    9.491
    Симпатии:
    3.118
    Репутация:
    95
    Адрес:
    Москва
    Оффлайн
    Можно перейти на C++, использовать что-то вроде vector<int> piecelists[2*6], и навсегда забыть про ручное управление размером n :)
  6. TopicStarter Overlay

    bankuss Александр

    • Заслуженный
    • Участник
    • Старожил
    Рег.:
    24.05.2006
    Сообщения:
    1.084
    Симпатии:
    38
    Репутация:
    6
    Оффлайн
    typedef struct tagPI {
    int pc; // тип фигуры
    int co; // цвет
    BOOL fDead; // было ли съедено
    int isq; // индекс поля на доске
    int val; // материальная оценка
    } PI, * PPI;

    typedef struct tagSQ {
    PPI ppi; //указатель на фигуру, или NULL.
    int isq; // индекс на внутренней доске.
    } SQ, * PSQ;

    вот такое нашел :)
  7. WildCat Коршунов Игорь

    • Команда форума
    Рег.:
    04.05.2006
    Сообщения:
    3.599
    Симпатии:
    4
    Репутация:
    0
    Адрес:
    Гомель
    Оффлайн
    Я боюсь, что оптимизатор не сможет нормально работать с vector.
  8. krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    главное, чтобы программа сначала заработала. а оптимизировать... :)
    интересно, зачем структуре tagPI дается псевдоним PI?
  9. TopicStarter Overlay

    bankuss Александр

    • Заслуженный
    • Участник
    • Старожил
    Рег.:
    24.05.2006
    Сообщения:
    1.084
    Симпатии:
    38
    Репутация:
    6
    Оффлайн
    тип фигуры я так понимаю нужен больше детектору шахов, чтоб знать какая фигура - слайд или нет.
    для слайд фигур первоначальную проверку на шах можно сделать простым сравнением - находиться ли король на одной линии с фигурой. ну а остальные по смещению проверить можно.
  10. WinPooh В.М.

    • Команда форума
    Рег.:
    13.02.2006
    Сообщения:
    9.491
    Симпатии:
    3.118
    Репутация:
    95
    Адрес:
    Москва
    Оффлайн
    Думаю, что бояться этого не стоит. Как минимум, по двум причинам:

    1. vector<> это шаблонный класс, т.е. уже в момент компиляции в распоряжении оптимизатора есть полная информация обо всём, что происходит - оптимизируй на здоровье
    2. это настолько часто используемая часть стандартной библиотеки, что уж её-то разработчики заоптимизировали по самое не хочу

    ну, и две цитаты из обсуждения http://www.thescripts.com/forum/thread163682.html - я с ними полностью согласен

    3. The speed-up is not in run-time, it's in development-
    time.
    4. You forgot the other big speed-up. It's not only in development-time,
    but in debugging-time. You don't worry as much about memory
    leaks/invalid pointers/etc...
  11. WinPooh В.М.

    • Команда форума
    Рег.:
    13.02.2006
    Сообщения:
    9.491
    Симпатии:
    3.118
    Репутация:
    95
    Адрес:
    Москва
    Оффлайн
    Для слайдеров проверку эффективнее всего делать от короля.
  12. WildCat Коршунов Игорь

    • Команда форума
    Рег.:
    04.05.2006
    Сообщения:
    3.599
    Симпатии:
    4
    Репутация:
    0
    Адрес:
    Гомель
    Оффлайн
    А я все равно боюсь.
  13. Shark Учаcтник

    • Участник
    Рег.:
    30.06.2007
    Сообщения:
    124
    Симпатии:
    0
    Репутация:
    0
    Адрес:
    Барнаул
    Оффлайн
    У меня списки такие:
    Код:
    struct FigureList
    {
        int m_count;
        idx_t m_indexes[10];
    };
    
    struct Cell
    {
        cell_t m_cell;
        int    m_listIdx;
    };
    
    class Board
    {
    ...
        Cell           m_cells[FIELD_SIZE];
        FigureList     m_lists[MAX_FIGURE_VALUE+1];
    ...
    };
    С выравниванием данных пока не заморачиваюсь
  14. WildCat Коршунов Игорь

    • Команда форума
    Рег.:
    04.05.2006
    Сообщения:
    3.599
    Симпатии:
    4
    Репутация:
    0
    Адрес:
    Гомель
    Оффлайн
    Покажи как ты их используешь.
  15. Shark Учаcтник

    • Участник
    Рег.:
    30.06.2007
    Сообщения:
    124
    Симпатии:
    0
    Репутация:
    0
    Адрес:
    Барнаул
    Оффлайн
    Самое простое - это добавление (естевственно все inline)
    Код:
        void setFigure( idx_t idx, cell_t figure )
        {
            FigureList& list = m_lists[figure];
            list.m_indexes[ list.m_count ] = idx;
            m_cells[idx].m_cell = figure;
            m_cells[idx].m_listIdx = list.m_count;
            list.m_count++;
            ...
        }
    Удаление как у тебя, примерно, но я предпочитаю разбивать действие по шагам, как бы подсказывая оптимизатору, что я хочу от него увидеть.
    Код:
        void clearFigure( idx_t idx, cell_t figure )
        {
            FigureList& list = m_lists[figure];
            list.m_count--;
            idx_t movedCellIdx = list.m_indexes[ list.m_count ];
            int deletedListIdx = m_cells[idx].m_listIdx;
            m_cells[ movedCellIdx ].m_listIdx = deletedListIdx;
            list.m_indexes[ deletedListIdx ] = movedCellIdx;
            m_cells[idx].m_cell = CELL_EMPTY;
    #ifdef _DEBUG
            list.m_indexes[ list.m_count ] = 0;
            m_cells[idx].m_listIdx = -1;
    #endif
            ...
        }
    Есть еще перемещение, просто это быстрее чем удалить и поставить

    Ктати выравнял размер FigureList до кратного степени двойки.
    Это дало выигрыш 0.2с или 1% в perft(6)
  16. Shark Учаcтник

    • Участник
    Рег.:
    30.06.2007
    Сообщения:
    124
    Симпатии:
    0
    Репутация:
    0
    Адрес:
    Барнаул
    Оффлайн
    Параметр cell_t figure в clearFigure() не обязательный, но с ним оптимизатор лучше работает, так как фигура уже обычно есть в каком либо регистре (функция инлайнится в do/undo move), и не надо повторно читать ее с доски. Разница - ощутима.
  17. WildCat Коршунов Игорь

    • Команда форума
    Рег.:
    04.05.2006
    Сообщения:
    3.599
    Симпатии:
    4
    Репутация:
    0
    Адрес:
    Гомель
    Оффлайн
    Я имел в виду генератор, а не перемещения фигур.
    Лучше выложи исходники своего perft со списком и без списка.
  18. Shark Учаcтник

    • Участник
    Рег.:
    30.06.2007
    Сообщения:
    124
    Симпатии:
    0
    Репутация:
    0
    Адрес:
    Барнаул
    Оффлайн
    Ну пока всю свою работу делать OpenSource - не планирую ;)
    Да и версионный контроль у меня не налажен,
    Версия без списков - не сохранилась.

    Но перебор 32 пустых ячеек сводился к 32 безусловным переходам (табица переходов switch оператора)
    А без списков трудно проверять наличие 2х слонов, например (разве что инкрементально).
  19. NS Нефёдов Сергей

    • Заслуженный
    • Ветеран
    • Старожил
    Рег.:
    02.05.2006
    Сообщения:
    6.811
    Симпатии:
    96
    Репутация:
    3
    Адрес:
    Санкт-Петербург
    Оффлайн
    Без списков легко проверяется наличие двух слонов.
    Например у меня :) В структуре позиции хранится количество фигур каждого вида (без списка)
  20. Shark Учаcтник

    • Участник
    Рег.:
    30.06.2007
    Сообщения:
    124
    Симпатии:
    0
    Репутация:
    0
    Адрес:
    Барнаул
    Оффлайн
    Я бы назвал это кастрированными списками :lol:
    Это вариант може оказаться, кстати, самым выгодным в плане быстродействия.
  21. NS Нефёдов Сергей

    • Заслуженный
    • Ветеран
    • Старожил
    Рег.:
    02.05.2006
    Сообщения:
    6.811
    Симпатии:
    96
    Репутация:
    3
    Адрес:
    Санкт-Петербург
    Оффлайн
    Я за скоростью не гнался. :)
    В миттельшпиле может так и может получится быстрее чем со списками, но в Эндшпиле списки точно будут быстрее.
  22. WildCat Коршунов Игорь

    • Команда форума
    Рег.:
    04.05.2006
    Сообщения:
    3.599
    Симпатии:
    4
    Репутация:
    0
    Адрес:
    Гомель
    Оффлайн
    Shark, можешь не вылаживать в открытую, а просто мне кинуть.
    Считать оператор switch безусловным переходом - это круто :)
    А я вот чего-то его не люблю.

    Между прочим, в моей шашечной программе версия со списками чуть ли не в два раза быстрее, чем без списков. А там ведь и свободных клеток поменьше и типов фигур только два.
  23. NS Нефёдов Сергей

    • Заслуженный
    • Ветеран
    • Старожил
    Рег.:
    02.05.2006
    Сообщения:
    6.811
    Симпатии:
    96
    Репутация:
    3
    Адрес:
    Санкт-Петербург
    Оффлайн
    В шашках доска сканируется дважды и соотношение время_на добавление_ходов(проверки возможности хода)/время_поиска_шашки - значительно меньше чем в шахматах.
    Хотя ведь можно не хранить списки, а формировать их при первом сканировании. (при проверке на возможность взятия)
  24. Shark Учаcтник

    • Участник
    Рег.:
    30.06.2007
    Сообщения:
    124
    Симпатии:
    0
    Репутация:
    0
    Адрес:
    Барнаул
    Оффлайн
    Ну вот смотри
    Код:
    void f( int v )
    {
        switch( v )
        {
        case 10:  g_v = 101; break;
        case 12:  g_v = 102; break;
        case 1:   g_v = 103; break;
        case 22:  g_v = 104; break;
        default:  g_v = 105; break;
        }
    }
    компилируется в
    Код:
    f:
    00401000  add         eax,0FFFFFFFFh 
    00401003  cmp         eax,15h 
    00401006  ja          $LN2+0Bh (401042h) 
    00401008  movzx       eax,byte ptr  (401064h)[eax] 
    0040100F  jmp         dword ptr  (401050h)[eax*4] 
    $LN5:
    00401016  mov         dword ptr [g_v (403378h)],65h 
    00401020  ret              
    $LN4:
    00401021  mov         dword ptr [g_v (403378h)],66h 
    0040102B  ret              
    $LN3:
    0040102C  mov         dword ptr [g_v (403378h)],67h 
    00401036  ret              
    $LN2:
    00401037  mov         dword ptr [g_v (403378h)],68h 
    00401041  ret              
    00401042  mov         dword ptr [g_v (403378h)],69h 
    0040104C  ret              
    0040104D  lea         ecx,[ecx] 
    00401050  db          2ch  
    00401051  db          10h  
    00401052  db          40h  
    00401053  db          00h  
    00401054  db          16h  
    00401055  db          10h  
    00401056  db          40h  
    00401057  db          00h  
    00401058  db          21h  
    00401059  db          10h  
    0040105A  db          40h  
    0040105B  db          00h  
    0040105C  db          37h  
    0040105D  db          10h  
    0040105E  db          40h  
    0040105F  db          00h  
    00401060  db          42h  
    00401061  db          10h  
    00401062  db          40h  
    00401063  db          00h  
    00401064  db          00h  
    00401065  db          04h  
    00401066  db          04h  
    00401067  db          04h  
    00401068  db          04h  
    00401069  db          04h  
    0040106A  db          04h  
    0040106B  db          04h  
    0040106C  db          04h  
    0040106D  db          01h  
    0040106E  db          04h  
    0040106F  db          02h  
    00401070  db          04h  
    00401071  db          04h  
    00401072  db          04h  
    00401073  db          04h  
    00401074  db          04h  
    00401075  db          04h  
    00401076  db          04h  
    00401077  db          04h  
    00401078  db          04h  
    00401079  db          03h
    т.е. сравнение одно с макимальным значением селектора
    остальное по таблице переходов, которая генерируется в конце

    Современные компиляторы MS с оптимизацией switch по целому числу справляются блестяще.
  25. WinPooh В.М.

    • Команда форума
    Рег.:
    13.02.2006
    Сообщения:
    9.491
    Симпатии:
    3.118
    Репутация:
    95
    Адрес:
    Москва
    Оффлайн
    Беда только в том, что конвейер всё равно сбрасывается...
  26. TopicStarter Overlay

    bankuss Александр

    • Заслуженный
    • Участник
    • Старожил
    Рег.:
    24.05.2006
    Сообщения:
    1.084
    Симпатии:
    38
    Репутация:
    6
    Оффлайн
    я у себя if then else использовал. switch не пробовал.
  27. WildCat Коршунов Игорь

    • Команда форума
    Рег.:
    04.05.2006
    Сообщения:
    3.599
    Симпатии:
    4
    Репутация:
    0
    Адрес:
    Гомель
    Оффлайн
    Ну если switch так нормально компилируется, то можно попробовать и битборды :)
  28. WinPooh В.М.

    • Команда форума
    Рег.:
    13.02.2006
    Сообщения:
    9.491
    Симпатии:
    3.118
    Репутация:
    95
    Адрес:
    Москва
    Оффлайн
    Возвращаясь к теме vector vs array.
    WildCat оказался прав, переход с векторов на массивы даёт моему perft-генератору ускорение не меньше 40%. Правда, это не вектора для списков фигур (у меня битборды), а структуры для сгенерированных ходов и служебной информации (для Unmake).

    Заменить вектора захотелось сразу же, как я взглянул в STL-ный исходный код и подсчитал количество if-ов на каждой элементарной операции вставки и очистки :)
  29. krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    вообще глупый вопрос назрел. если есть списки фигур - зачем в движке хранить еще и доску?
  30. WildCat Коршунов Игорь

    • Команда форума
    Рег.:
    04.05.2006
    Сообщения:
    3.599
    Симпатии:
    4
    Репутация:
    0
    Адрес:
    Гомель
    Оффлайн
    Для удобства. Можно быстро проверить кем занято нужное поле.

Поделиться этой страницей