Пилю программку по обсчёту китайского покера

Последний пост:26.11.2023
22
1 59 79 80 81 82 101 114
  • Цитата (БиллиУбили @ 30.5.2020)
    И чем нолик в левый верхний угол отличается от нолик в правый верхний угол?


    БиллиУбили, по ев ничем , справа евшка до сотых равная
    для примера чтобы разобраться как это устроено и работает хватит
    487/882
    Ответить Цитировать
    0
  • Цитата (c00l0ne @ 30.5.2020)
    по ев ничем , справа евшка до сотых равная

    так она должна быть равной с вариантами 6 и 8.
    Да и вообще у тебя какой-то дисбаланс: 250К vs 3500 посещений. Или ты хочешь сказать, что после вариантов 6,8 на своём следующем ходу MCTS играет 0 или 2? Тем более не должно быть отличий между любым углом.
    706/741
    Ответить Цитировать
    0
  • БиллиУбили, мне лень разбираться в с# , это не мой родной язык программирования, но думаю на все твои не хитрые вопросы ты найдешь ответы в коде
    488/882
    Ответить Цитировать
    0
  • Цитата (c00l0ne @ 30.5.2020)
    ты найдешь ответы в коде

    так я и спрашиваю про конкретный код, результат работы которого ты привёл.
    Цитата (c00l0ne @ 30.5.2020)
    вкратце вот весь код мткс

    Как на самом деле работает MCTS - это отдельный разговор.
    707/741
    Ответить Цитировать
    0
  • Лично мне видется такое расширение(модификацию) для китайского(покера).
    Имеем руку и Партию. Рука - это карты во всех 4ёх линиях, включая сброс.
    Партия - это колода + очердность хода + 2 Руки.
    Очевидно, что Состояние - это Партия + исход. Исход измеряется в очках(разница между очками, которые набрали Руки соперников + возможные бонусы за скуп и/или фантазию).
    Тогда можно сделать следующее.
    Взять Руку, найти наиболее очковые завершения(скажем, штук 20...или 200), которая позволяет текущая колода и... загрузить их в дерево(!). Если у нас осталось 2 подьёма, то возможно всего 6 вариантов собрать завершение(очередность прихода "нужных" карт). Загрузим эти 20Х6 завершений в дерево. Обойдём его снизу вверх, обновляя счётчик посещения узла и очки, которые он принёс. Это будет остов(каркас). Ну, а далее в деле включится великий уравнитель aka рандом.
    Будем, начиная с корня, делать рандомные ходы, рандомное(!) разложение и передавать дальше вниз колоду(без заигранных карт). В результате, между соседними предками, которые доступны для перехода из конкретного узла одним ходом(в подьёме 3 карты = 3 варианта заиграть определённые 2), возникнет "борьба", исход которой решит рандом, он же кол-во посещений.
    При таком подходе, если я правильно понимаю, нам не нужно считать вероятность того или иного подьёма(какие именно 3 карты пришли из колоды). Нам не нужно делать перебор всех варинатов подьём. Достаточно делать одновременные переходы по всем возможным потомкам узла, а уж МКТС посчитает, сколько очков принесёт тот или иной вариант из 3. "плохой вариант" будет содержать меньше "нужных" карт в переданной колоде и рано или поздно загнётся.
    Таким образом, планирую пока остановится на одной комбинации "флаш" и руке из 2ух линий. Собирать будем 2 флаша(возможно даже одной масти). Ну, а в колоде, естественно, будет по Ni карт разной масти. Пространство состояний невелико: либо +8 очков за 2 флаша, либо +4 очка за флаш только внизу, либо 0 очков за ничего, либо -6 очков за флаш во второй линии и ничего внизу.
    Сможет дерево потянуть 2 линии - сможет и 3 )
    ЗЫ Соперника тоже пока не будет, хотя было бы забавно собрать "ничего" и получить +6очков за скуп.
    708/741
    Ответить Цитировать
    0
  • Цитата (БиллиУбили @ 31.5.2020)
    Рука - это карты во всех 4ёх линиях, включая сброс.


    Оч много состояний будет... Карты не стоит использовать...
    Достаточно описать базовые вещи
    489/882
    Ответить Цитировать
    0
  • Цитата (БиллиУбили @ 31.5.2020)
    Сможет дерево потянуть 2 линии - сможет и 3 )


    Количество деревьев МК ограничено только фантазией) new root_1 new root_2 new root_3
    490/882
    Ответить Цитировать
    0
  • Цитата (БиллиУбили @ 31.5.2020)
    Таким образом, планирую пока остановится на одной комбинации "флаш" и руке из 2ух линий. Собирать будем 2 флаша(возможно даже одной масти). Ну, а в колоде, естественно, будет по Ni карт разной масти. Пространство состояний невелико: либо +8 очков за 2 флаша, либо +4 очка за флаш только внизу, либо 0 очков за ничего, либо -6 очков за флаш во второй линии и ничего внизу.
    Сможет дерево потянуть 2 линии - сможет и 3 )


    Нашел пяти минут ку ответить:
    С МК с упрощать ничего не нужно, просто в ноды пиши верх любой, а собирай низ и середину...
    Два флеша например
    для каждой сдачи свое 🌲
    И в процессе симуляции эти деревья все прокачаются одновременно...

    Голова после Кеша не варит, но как смог объяснил...
    491/882
    Ответить Цитировать
    0
  • ну раз тут такой блог про программирование
    вот вам темка для прожарки
    есть операторы "if else end if" синтаксис vb
    в с# синтаксис
    if (rule1)
    {
    work1
    }
    else if (rule2)
    {
    work2
    }
    else
    {
    work_else
    }

    так вот синтаксис этих операторов мне нравится , но а что если перед проверкой второго уже условия , нам необходимо выполнить какую то работу
    prework_ifworkrule2
    получается синтаксис уже не позволяет этого сделать
    приходится юзать раздельные операторы
    if (rule1)
    {
    }
    else
    {
    prework_ifworkrule2
    if (rule2)
    {
    work2
    }
    ...
    }

    так вот как сделать так чтобы синтаксис первый остался прежнем, все проверки находились на одной уровне , но было доступно выполнение операций перед проверками

    отвечу сразу чтобы долго голову не грели ) создаем функции prework_rule2 prework_rule3 и в них выполняем нужную работу
    function prework_rule2 as boolean
    prework2
    return True
    end function

    if rule1 then
    elseif prework_rule2 and rule2 then
    .....

    минусы приходиться функцию вызывать
    вот такой пока еще не совершенный синтаксис условных операторов .... а 21 век на дворе )
    для исправления этого неудобства надо добавить к синтаксису частицу preelseif
    if then
    preelseif
    elseif
    preelseif
    elseif
    end if
    Сообщение отредактировал c00l0ne - 2.6.2020, 22:48
    492/882
    Ответить Цитировать
    0
  • Ну и? Ev (node_fd_fd) = ?
    493/882
    Ответить Цитировать
    0
  • c00l0ne,
    Цитата (c00l0ne @ 4.6.2020)
    Ev (node_fd_fd) =

    пока только построил дерево.
    У меня вопрос такой: поиск ноды, которую надо прогнать на "завершение" - он всегда начинается с корня? И результатом обязательно должен быть предок корня?
    А если, предположим, не на 1ом(обсчитываемом) подьёме, а на 2ом или 3ьем, я обнаружу ноду, которая дала(даёт) много очков - я могу принудительно прогнать её рандомом(вручную переключится на её исследование)?
    Или тогда посыпется вся конструкция с
    Best+Child+%28UCT%29+This+is+the+standard+UCT+equation.jpg

    Иными словами, если я произвольно влезу в уровень ниже...вроде бы мы ноды всё-равно будут собирать число посещений и среднее ЕВ...но будет ли работать приведённая формула(которая по алгоритму подсказывает нам, какую ноду исследовать в первую очередь)?
    709/741
    Ответить Цитировать
    0
  • Цитата (c00l0ne @ 31.5.2020)
    Количество деревьев МК ограничено только фантазией) new root_1 new root_2 new root_3

    это не понял
    Цитата (c00l0ne @ 2.6.2020)
    для каждой сдачи свое 🌲
    И в процессе симуляции эти деревья все прокачаются одновременно...

    тоже не понял. Какое ещё свое дерево? для какой сдачи?
    У меня одно дерево состояний. Руку можно сделать любой. Хоть одна линия из 5 карт, хоть 4 линии из 3ёх карт...
    710/741
    Ответить Цитировать
    0
  • Странное всё-таки решение в этих крестиках-ноликах.
    Те позиции, в которых определился исход, сходу получают EV узла = -10000 очков, а остальные позиции доигрываются 500 раз по рандому (с +3 очка за победу и -1 за поражение).
    Не, я конечно всё понимаю...но что таким образом экономится?
    Это что, заградительный барьер? Чтобы узел "-10000" с 1 посещением никогда не стал привлекательнее узла "-300" с 300 посещениями? С таким же успехом достаточно давать "-500" и 1 посещение, там же в знаменателе дроби число посещений узла.
    Кто прав: я или автор кода?
    711/741
    Ответить Цитировать
    0
  • БиллиУбили, ну пока чай пью ...
    мысли такие
    Цитата (БиллиУбили @ 4.6.2020)
    пока только построил дерево


    root =new root ?
    опиши структуру узлов ... что ты туда запихал ...
    Цитата (БиллиУбили @ 4.6.2020)
    это не понял

    тоже не понял. Какое ещё свое дерево? для какой сдачи?
    У меня одно дерево состояний. Руку можно сделать любой. Хоть одна линия из 5 карт, хоть 4 линии из 3ёх карт...


    ну смотри почему нужно дерево для каждой сдачи :
    у нас оно универсальное (не из карт , а там из абстракции) а эти абстракции могут переходить друг в друга , поэтому
    нам выгоднее просто дерево разделить на несколько деревьев ... как будто мы решаем задачу раздельно друг от друга
    1. евшка 1 сдачи
    2. евшка 2 сдачи
    3. евшка 3 сдачи
    4. евшка 4 сдачи

    я бы так делал

    и получается через мктс в итоге ты стартер решишь)
    скорее всего даже компу хватит мощей обычному ... но вся сила в абстракции ...
    ну банально ты можешь выбирать со сдачи фичи типа (пара флеш флешдро в лайне и т.д. )

    я скорее всего глубже подсказать уже не смогу бро ... тут будет просто рецепт )
    пиши в телеграмм
    494/882
    Ответить Цитировать
    0
  • БиллиУбили, про обход дерева по UCT
    LwvPVzk-S2aphR7Re5Bhjw.png

    тут просто смотрим на детей кто лучше и достаточно вырос того и выставляем на бой

    т.е. мы смотрим как на ЕВшку так и на число посещений ... чтобы дерево по минимуму выросло ... чтобы не пропустить ходов
    495/882
    Ответить Цитировать
    0
  • Цитата (БиллиУбили @ 4.6.2020)
    Странное всё-таки решение в этих крестиках-ноликах.
    Те позиции, в которых определился исход, сходу получают EV узла = -10000 очков, а остальные позиции доигрываются 500 раз по рандому (с +3 очка за победу и -1 за поражение).
    Не, я конечно всё понимаю...но что таким образом экономится?
    Это что, заградительный барьер? Чтобы узел "-10000" с 1 посещением никогда не стал привлекательнее узла "-300" с 300 посещениями? С таким же успехом достаточно давать "-500" и 1 посещение, там же в знаменателе дроби число посещений узла.
    Кто прав: я или автор кода?


    ну давай гляну код , пяток минут потрачу
    сразу бросается в глаза что код нифига не доделан :
    Wfkzx9h6R2yRuqZbCJnXnQ.png


    вот вызов монтекарлы
    iqzHK7vtRISGyD9t3GJamA.png

    50к максимально симуляций используется

    и погнали попадает сначала сюда , а потом сюда

    ub9FbC5oQ_GquBWCLrBgfA.png

    GetTopActions создает дерево , корень его является ТЕКУЩЕЕ СОСТОЯНИЕ +ХОД .... понимаешь? т.е. решается не сначала от текущего состояния ... но в китайском тебе надо все дерево будет держать ) чтобы решение иметь на любую ситуацию )
    поэтому разные деревья для разных сдач ...
    вообще рассматривай дерево монте карло как способ хранения информации ... а обход дерева это алгоритм решения задачи ....

    но это возможно не верно , но в моем представлении оно так
    короче дерево создали строчкой var root = new Node<TPlayer, TAction>(state)
    root.buildtree(())
    и возвращаем return root.Children
    .OrderByDexcending()
    вот и весь алгоритм)

    теперь процесс создание дерева :
    ну там ничего нового корень добавляется + неиспользованные действия (ходы):
    U7k0of60QeSCKAic25XUIQ.png

    на примере все ходы нолика доступные - покроют все выходы из этой ноды

    далее создание дерева
    выбор хода -чилдов :
    _MoG-lTBQ1uRt2W8cK4yDw.png

    выбираем если все ходы уже в дереве :
    !node.UntriedActons.Any неиспользованных ходов нету
    и ход не последний в игре , если сделали последний игра завершена выбирать нечего :
    node.Actions.Any()

    далее
    условие пока у нас есть неиспользованные ходы мы добавляем ноды ...
    node.UntriedActions.Any()

    и доигрываем по стратегии случайной:
    while (state.Actions.Any())
    state.ApplyAction(state.Actions.RandomChoice());

    а далее backpropagate
    while (node != null)
    {
    node.NumRuns++;
    node.NumWins += state.GetResult(this.Player);
    node = node.Parent;
    }
    мы с последней ноды записываем результат в каждую ноду до корня , которую посетили
    NumWins += state.getresult(this.player)

    теперь самое интересное выбор хода
    node.selectChild
    ну выбор у них по UCT идет
    LK9AwSMQRmGdhEB79ffZqQ.png

    т.е. по той формуле argmax UCTvalue
    по этим формулам :
    LVp06EFoTI2NXwwj1RwwAA.png
    Сообщение отредактировал c00l0ne - 4.6.2020, 23:07
    496/882
    Ответить Цитировать
    0
  • Цитата (c00l0ne @ 4.6.2020)
    ну давай гляну код , пяток минут потрачу

    так чего его смотреть
    h if (tempNode.playerNo == boardStatus && boardStatus == opponent)
    {
    node.parent->winScore -= 10000;
    }
    else if (tempNode.playerNo == boardStatus && boardStatus == me)
    {
    node.parent->winScore -= 10000;
    }

    // int count = 0;
    while (boardStatus == IN_PROGRESS)
    {здесь продолжение по рандому
    712/741
    Ответить Цитировать
    0
  • Цитата (c00l0ne @ 4.6.2020)
    опиши структуру узлов ... что ты туда запихал ...

    Руку(вместе с колодой), число посещений, кол-во набранных очков
    Цитата (c00l0ne @ 4.6.2020)
    нам выгоднее просто дерево разделить на несколько деревьев ...

    первый раз такое слышу. Чем выгоднее?

    Цитата (c00l0ne @ 4.6.2020)
    у нас оно универсальное (не из карт , а там из абстракции) а эти абстракции могут переходить друг в друга

    У меня состояния состоят из Руки, а она из карт. И, к большому сожалению, руки из разных узлов не пересекаются: рук очень много, искать одинаковые в разных ответвлениях - времени не хватит
    713/741
    Ответить Цитировать
    0
  • Цитата (c00l0ne @ 4.6.2020)
    т.е. мы смотрим как на ЕВшку так и на число посещений ... чтобы дерево по минимуму выросло ...

    Это понятно, я спрашивал про другое. Когда мы ищем узел для обхода по UCT, мы начинаем обход с корня(с самого начала). Вопрос: если мы руками пропустим уровень(вниз) и руками назначим "начало обхода" = произвольный узел - формула поломается или будет работать?
    714/741
    Ответить Цитировать
    0
  • Цитата (c00l0ne @ 4.6.2020)
    на примере все ходы нолика доступные - покроют все выходы из этой ноды

    К сожалению, крестики-нолики - не Китай. Здесь 8-9 возможных ходов, в Китае ~С(45,3)
    Планирую добавлять их(потомков к узлу) по рандому, пока будет хватать времени...
    715/741
    Ответить Цитировать
    0
1 59 79 80 81 82 101 114
1 человек читает эту тему (1 гость):
Зачем регистрироваться на GipsyTeam?
  • Вы сможете оставлять комментарии, оценивать посты, участвовать в дискуссиях и повышать свой уровень игры.
  • Если вы предпочитаете четырехцветную колоду и хотите отключить анимацию аватаров, эти возможности будут в настройках профиля.
  • Вам станут доступны закладки, бекинг и другие удобные инструменты сайта.
  • На каждой странице будет видно, где появились новые посты и комментарии.
  • Если вы зарегистрированы в покер-румах через GipsyTeam, вы получите статистику рейка, бонусные очки для покупок в магазине, эксклюзивные акции и расширенную поддержку.s