Покер

Тема в разделе "Машинное отделение", создана пользователем WildCat, 4 дек 2006.

  1. WildCat
    Оффлайн

    WildCat Коршунов Игорь Команда форума

    Репутация:
    0
    Меня в последнее время заинтересовал покер (в основном техасский холдем).
    Может быть здесь найдутся те, кому будет интересно программирование покера? Оно в корне отличается от шахматного, т.к. позиция соперника (его карты) неизвестна.

    Пока у меня первый технический вопрос: как сравнить две руки (нашу и соперника)?
    Попутно нужно определится с представлением карт. Т.к. в колоде 52 карты, то напрашивается использовать битборды.

    Чтобы сравнить две руки можно каждой поставить в соответствие целое цисло (силу руки). Дальше просто сравниваем целые числа.

    Итак, задача: по заданным картам найти силу руки.

    Первое, что приходит в голову - искать комбинации по старшинству:
    - стрейтфлеш
    - каре
    - фуллхауз
    - флеш
    - стрейт
    - тройка
    - две пары
    - пара
    - нет комбинации

    Внутри комбинаций сила определяется по старшинству карт.

    Нужно придумать как это реализовать технически.

    Например, можно так определить есть ли у нас флеш:
    Код:
        BitCount(cards & ALL_SPADES)   >= 5 ||
        BitCount(cards & ALL_DIAMONDS) >= 5 ||
        BitCount(cards & ALL_HEARTS)   >= 5 ||
        BitCount(cards & ALL_CLUBS)    >= 5
    Есть слухи, что все комбинации (кроме флеша) можно посчитать заранее (т.е. скорость не критична) в таблицу 13^7 = 62748517 (около 120 мБ). Эту таблицу можно расчитывать при запуске программы.
     
  2. NS
    Оффлайн

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

    Репутация:
    3
    Элементарно -
    В качестве параметров две руки.
    Для каждой руки определяется ранг комбинации (от 1 до 9) вызовом последовательно проверок на комбинации.
    Далее сверяется ранг рук. Если у одной выше, значит у неё лучше комбинация.
    Если ранг одинаков - то смотрятся доп. условия.

    Стоит наверно задача определить комбинацию как можно быстрее? Если просто определение - то никаких проблем быть не должно.
     
  3. NS
    Оффлайн

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

    Репутация:
    3
    Отдельно храним для руки масти и номиналы (то есть отдельно нужно определять только Фреш-Стрит)
    На семи картах сочетаний мастей 4^7 (берем с запасом, если масти отсортировать, то число сочетаний 10!/7!/3!=120), Для определения факта флеша (все карты одной масти) нужен битовый массив на 2^14 бит
    - 2 Килобайта. (либо на 120 бит - 15 байт :) )

    Для определения ранговых комбинаций - число сочетаний номиналов по семи картам (k+n-1!)/n!/(k-1)! (13+7-1)!/7!/12!=19!/7!/12!=50388 Комбинаций, откуда взяты цифры в сотни мегабайт - абсолютно непонятно :)
     
  4. WildCat
    Оффлайн

    WildCat Коршунов Игорь Команда форума

    Репутация:
    0
    ессно

    Из твоего объяснения я так и не понял как вычислять индекс в таблице.
     
  5. NS
    Оффлайн

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

    Репутация:
    3
    Так-же как и в шашках, идет сортировка от большего к меньшего, отличие только в том, что каждое следующее значение не больше предыдущего (в отличие от ЭБ, где каждое следующее значение меньше предыдущего) от этого немного меняется формула, и количество возможных значений. Расчет индекса в этой ветке напишу.
     
  6. NS
    Оффлайн

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

    Репутация:
    3
    По порядку -
    for i1:= 1 to 13 do
    for i2:=i1 to 13 do
    for i3:=i2 to 13 do
    for i4:=i3 to 13 do
    for i5:=i4 to 13 do
    for i6:=i5 to 13 do
    for i7:=i6 to 13 do
    sch:=sch+1;
    50388 - то есть с количеством комбинаций не ошибся. :) (в подсчете не учитывается тот факт что не может быть больше четырех карт одного номинала - но это и не нужно)
     
  7. WildCat
    Оффлайн

    WildCat Коршунов Игорь Команда форума

    Репутация:
    0
    Вряд ли меня это обрадует. Хочется побыстрее, а память экономить в последнюю очередь.
     
  8. NS
    Оффлайн

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

    Репутация:
    3
    Сортировка семи элементов - это "в среднем" пара десятков операций.
    Так-же можно использовать тот Факт что всего возможных значений 13 (сортировка по значению с вспомогательным массивом на 13 элементов) - так-же для сортировки необходимо всего пара десятков операций.
     
  9. Mustitz
    Оффлайн

    Mustitz баннер

    Репутация:
    36
    При оценки руки один из наиболее быстрых это Cactus Kev's Poker Hand Evaluator (правда только на пяти картах, эту идею надо распространить на семь карт).

    Описание достаточно сильного движка есть здесь.
     
  10. NS
    Оффлайн

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

    Репутация:
    3
    Насчет оценки рук - Предварительное вычисление - минутное дело (всего возможных комбинаций около 50 тысяч), сама оценка - миллионы в секунду...
    Насчет силы движков - все авторы называют свои движки сильными, но часто оказывается что это просто грубый Пиар, не имеющий ничего общего с действительностью.
     
  11. WildCat
    Оффлайн

    WildCat Коршунов Игорь Команда форума

    Репутация:
    0
    Думаю что для начала можно реализовать что-то не особенно эффективное. А уж извращаться над оптимизацией (если она вообще понадобится) можно будет потом.

    Кстати, NS, как там у тебя с покером?
     
  12. NS
    Оффлайн

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

    Репутация:
    3
    У меня хорошо. Я сейчас его пишу. (и паралельно срочно добиваю шашки)
    Сейчас как раз переписываю под массив определение силы рук по семи картам. :)

    У меня еще неделя вылетела - совсем слег, только вчера к вечеру начал понемногу ходить.
    Но уже половина пути пройдена - мучаться осталось недолго :)
     
  13. WildCat
    Оффлайн

    WildCat Коршунов Игорь Команда форума

    Репутация:
    0
    Значит оно уже как-то написано? Стоит ли переписывать? Может и так пока сгодится?
     
  14. Chemer
    Оффлайн

    Chemer Максим

    Репутация:
    0
    Сдался вам этот покер, преф на порядок лучше и интелектуальнее. Хотя я может быть фанат преферанса.
     
  15. WildCat
    Оффлайн

    WildCat Коршунов Игорь Команда форума

    Репутация:
    0
    Еще за бридж, чисто из любопытства, можно было бы взяться, но никак не преф.
    А покер намного лучше потому, что там бабок немеряно.
    К тому же покер считается психологической игрой. А это считается очень трудным для компьютера. Инересно так ли это ;)
     
  16. Chemer
    Оффлайн

    Chemer Максим

    Репутация:
    0
    В преф только на бабки и играют. И как правило немалые!
     
  17. WinPooh
    Оффлайн

    WinPooh В.М. Команда форума

    Репутация:
    95
    Кто знает, в какую силу играют нынешние покерные программы? На мой дилетантский взгляд, они должны показывать зверскую силу - игра-то за вычетом психологии (не действующей на компьютер) полностью сводится к теории вероятностей...
     
  18. WildCat
    Оффлайн

    WildCat Коршунов Игорь Команда форума

    Репутация:
    0
    Преф и покер - это совсем разные бабки :)
     
  19. NS
    Оффлайн

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

    Репутация:
    3
    Вообще да, для менеджера быстро не надо - но уже поздняк дергаться :)
    Мне интересно стало :)
    В преф только на бабки и играют. И как правило немалые!

    Хочешь сравнить сколько денег в Покере, и сколько в Префе? :)
    Хочешь сравнить Количество скачиваний Покерных программ, и программ в Преф?
    Их стоимость?
    И я вот смотрю он-лайн Казино - вроде всё-таки в Техас Холдем играют, но никак не в преф.
    И Преф как минимум неинтересен. Он достаточно прост.
     
  20. WildCat
    Оффлайн

    WildCat Коршунов Игорь Команда форума

    Репутация:
    0
    Вроде есть одна, которая 1х1 умеет наравне с лучшими людьми играть. Но за обычным столом из 10 человек - таких похоже нет.
    Покер сводится к задаче из теории игр, причем размерность просто неподъемная для современных компьютеров.
    Теорией вероятности тут много не добьешься. Хотя попробовать можно.
     
  21. WildCat
    Оффлайн

    WildCat Коршунов Игорь Команда форума

    Репутация:
    0
    Вот здесь в посте от M_White Thu Nov 09, 2006 2:56 am:
    http://www.poker-academy.com/forums/viewtopic.php?t=4787
    описывается оценка силы руки на ассемблере. Выглядит интересно, правда я пока не особо вникал.
     
  22. NS
    Оффлайн

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

    Репутация:
    3
    Достаточно того что приведены цифры - около 7 000 000 оценок в секунду.
    Нужно попытаться выйти на тот-же результат.
     
  23. WildCat
    Оффлайн

    WildCat Коршунов Игорь Команда форума

    Репутация:
    0
    Я все еще никак не решусь начать :)
    Хочется все продумать сперва. А у тебя уже есть на чем мерять скорость? И каковы результаты? Думаю надо выходить на скорость порядка нескольких десятков миллионов позиций в секунду. Ну это если, конечно, озаботится на скорости ;)
     
  24. NS
    Оффлайн

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

    Репутация:
    3
    Надо озаботиться. Пока ничего не готово, только Форма с Картинками, и половина процедуры оценки рук.
    Хочу сделать самую быструю оценку рук :) , но сам алгоритм выбора лучшего действия еще до конца не продуман.
    приступать без готовых алгоритмов не хочется, я обычно сначала всё продумываю, а потом в последний момент срочно пишу :)
    И опять начал разбрасываться -
    Вчера написал программку
    http://kasparovchess.crestbook.com/viewtopic.php?pid=42385#p42385
    Срочно, к первому января нужно добивать шашки (а у меня еще не готова ОФ)
    Но сейчас пишу именно Покер.
     
  25. WildCat
    Оффлайн

    WildCat Коршунов Игорь Команда форума

    Репутация:
    0
    Вот что у меня получилось:
    Код:
    #define HIGH_CARD      0x100000
    #define PAIR           0x200000
    #define TWO_PAIRS      0x300000
    #define TRIPS          0x400000
    #define STRAIGHT       0x500000
    #define FLUSH          0x600000
    #define FULL_HOUSE     0x700000
    #define QUADS          0x800000
    #define STRAIGHT_FLUSH 0x900000
    
    typedef unsigned int uint;
    typedef unsigned __int16 uint16;
    typedef unsigned __int64 uint64;
    
    uint High5Bits[0x2000]; // ноль, если в индексе нет пяти бит
    uint High3Bits[0x2000];
    uint HighBit[0x2000];
    
    union Cards
    {
        uint64 all;
        struct
        {
            uint16 spades;
            uint16 hearts;
            uint16 diamonds;
            uint16 clubs;
        } suits;
    };
    
    int EvalHand(Cards *h)
    {
        uint code = High5Bits[h->suits.spades] | High5Bits[h->suits.hearts] | High5Bits[h->suits.diamonds] | High5Bits[h->suits.clubs];
    
        // стрейт-флаш
        if (code >= STRAIGHT) return code + (STRAIGHT_FLUSH - STRAIGHT);
    
        // считаем singles, pairs, trips, quads
        
        uint16 singles = h->suits.spades | h->suits.hearts;
    
        uint16 pairs = h->suits.spades & h->suits.hearts;
    
        uint16 trips = pairs & h->suits.diamonds;
        pairs   |= singles & h->suits.diamonds;
        singles |= h->suits.diamonds;
    
        uint16 quads = trips & h->suits.clubs;
        trips   |= pairs & h->suits.clubs;
        pairs   |= singles & h->suits.clubs;
        singles |= h->suits.clubs;
    
        // каре
        if (quads) return QUADS + HighBit[quads];
    
        // фулл-хауз
        if (trips)
        {
            int htrip = HighBit[trips];
            if (pairs & ~(1 << htrip)) return FULL_HOUSE + htrip;
        }
    
        // флаш
        if (code) return code + (FLUSH - HIGH_CARD);
    
        // стрейт
        code = High5Bits[singles];
        if (code >= STRAIGHT) return code;
    
        // сет (тройка)
        if (trips) return TRIPS + HighBit[trips];
    
        // пары
        if (pairs)
        {
            int hpair = HighBit[pairs];
            uint16 other_pairs = pairs & ~(1 << hpair);
    
            // две пары
            if (other_pairs) return TWO_PAIRS + 13 * 13 * hpair + 13 * HighBit[other_pairs] + HighBit[singles & ~((1 << hpair) | (1 << HighBit[other_pairs]))];
    
            // одна пара
            return PAIR + 13 * 13 * 13 * hpair + High3Bits[singles & ~pairs];
        }
    
        // нет комбинации
        return code;
    }
    Может и не самый быстрый, но для первого раза покатит.
    Осталось только сделать инициализацию массивов.

    NS! Делай оболочку (лишь бы правила знала) поскорее. Уже хочется отладить всю эту хрень.
     
  26. NS
    Оффлайн

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

    Репутация:
    3
    Делаю - за выходные, если опять что-нибудь не случиться - должен отладить.
     
  27. WildCat
    Оффлайн

    WildCat Коршунов Игорь Команда форума

    Репутация:
    0
    Судя по всему здесь эта тема никому не интересна.
    Я сделал симуляцию раздач на 10 игроков. Результаты на геймдеве.
     
  28. NS
    Оффлайн

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

    Репутация:
    3
    Я не смог прислать книгу - у тебя ящик переполнился.
     
  29. NS
    Оффлайн

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

    Репутация:
    3
    Оба-на, вот это да.
    Это в каком-же состоянии я был, ежели не помню что такая ветка была на гостевой...
     
  30. Guest
    Оффлайн

    Guest

    Репутация:
    0
    NS, если я читаю между строк правильно, Вы себя чуствуете лучше. Поздравляю! (ну и плюю через плечо и стучу по дереву).
     
  31. NS
    Оффлайн

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

    Репутация:
    3
    Намного лучше. Только я практически ничего не помню из того что происходило эти пол-года.
     
  32. Guest
    Оффлайн

    Guest

    Репутация:
    0
    Это ничего, у нас не все, но многое записано :)
     
  33. WildCat
    Оффлайн

    WildCat Коршунов Игорь Команда форума

    Репутация:
    0
    Я не перестаю поражаться насколько у NS веселая жизнь :)
     
  34. NS
    Оффлайн

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

    Репутация:
    3
    Блин, вот в этом уже ничего веселого нет.
    Мало того что год жизни пропал, куча денег выкинута, да еще и не факт что вылечился...
    Хотя есть и плюсы :) Шашки умудрился в безсознательном состоянии написать, шахматы - правда их писал пока еще вменяемый был, но это с препугу что умру, а шахматной программы для потомков не оставлю :)
     
  35. WildCat
    Оффлайн

    WildCat Коршунов Игорь Команда форума

    Репутация:
    0
    Ну, у каждого свои понятия веселья. Для меня это измененные состояния сознания. Все остальное очень грустно.