Как стать автором
Обновить

Создаем библиотеку теории игр на питоне: как вообще это будет работать?

Уровень сложностиПростой
Время на прочтение19 мин
Количество просмотров3.3K

Решать задачу написания библиотеки для решения максимального количества задач методами теории игр не так уж просто. Здесь не построишь план или дорожную карту, поскольку дорога становится сильно размытой уже в зоне ближайшей видимости...

Здесь не применишь метод "нарезать слона на бифштексы и так его съесть", поскольку размеры и количество этих бифштексов пока не ясны, и можно подавиться уже первым...

Скорее всего, здесь подойдет метод "выгрызания дыр в сыре, пока весь сыр не будет съеден" - при этом мы пока не представляем истинных размеров сыра, но можем выгрызать те области, которые на сегодня более-менее понятны...

Сегодня сделаем наброски примеров кода работы с библиотекой (как если бы библиотека была полностью готовой) - это поможет в дальнейшем при создании классов, их атрибутов и методов и в целом, задаст ориентиры для дальнейшей работы. Напишем очередной класс Очередь Игроков. А ещё поддадимся модной тенденции и спросим совета у ChatGPT-3...

В предыдущих статьях мы:

В этой статье мы:

  1. Набросаем примеры кода - как вообще могла бы работать такая библиотека? Создадим примеры кода для исследования нескольких классических задач.

  2. Спросим у ChatGPT-3, какие методы и атрибуты она порекомендовала бы для наших классов.

  3. Реализуем класс Очередь Игроков (Queue) - один из центральных классов в любой Игре.

1. Примеры кода работы библиотеки

Итак, набросаем примеры того, как могла бы работать наша библиотека...

Загрузка и подготовка

Здесь все должно работать, как при обычной загрузке python-библиотек:

pip install my_python_game_theory_library
import my_python_game_theory_library as gtl

Одновременная игра с простой матрицей

Создадим игру, в которой 2 Игрока ходят одновременно, выигрывая случайное количество очков в зависимости от выбранного варианта.

Для этого мы создадим:

  • двух Игроков,

  • Игральные кости, которые будут привязаны к отдельным вариантам/опциям выбора Игроков (Игрок выбирает опцию - какую кость бросить, либо выбрать фиксированный выигрыш),

  • сами варианты/опции и матрицу Игры с ними

import my_python_game_theory_library as gtl

# Создадим 2 Игроков
p1 = gtl.Player()
p2 = gtl.Player()

print(p1.name)  # 'Player_1'
print(p2.name)  # 'Player_2'

# Создадим классическую Игральную кость
d1 = gtl.Dice(faces = (1,6))
# Создадим нестандартную Игральную кость - 
# равноценные грани с разными очками, 1 и 6 выпадут с вероятностью 1/3, 
# а 2 и 5 - с вероятностью 1/6
d2 = gtl.Dice(faces = [1,1,2,5,6,6])

print(d1.name)  # 'Dice_1'
print(d2.name)  # 'Dice_2'

# Создадим опции Стандарт, Риск, Фиксированная с разными исходами
o1 = gtl.Option(name='Standart', benefits=d1)
o2 = gtl.Option(name='Risk', benefits=d2)
o3 = gtl.Option(name='Fix', benefits=3)

# Создадим матрицу Игры, одинаковую для всех Игроков
# Можно задавать опции как по именам, так и по ссылкам на экземпляр класса (o3)
m = gtl.Matrix(name='Matrix_3_types', options=['Standart', 'Risk', o3])

# Игра, где у каждого Игрока есть выбор между 3 опциями
# Очередь Игроков можно было бы задать и так: players = [p1, p2]
# is_parallel=True означает, что все Игроки делаю ходы/ставки одновременно, 
# поэтому очередь queues - это просто список участвующих Игроков, без очередности
g1 = gtl.Game(name='Simple_game_3_options', 
              queues=['Player_1', 'Player_2'],
              matrices='Matrix_3_types',
              is_parallel=True
             )

# Сыграем 3 раунда, в каждом из которых кажыдый Игрок выберет одну из опций
g1.play(rounds=3) # Выводит таблицу результатов каждого Игрока
'Simple_game_3_options', rounds=3

Player_1: 12
Player_2: 15

Одновременная игра с матрицей, зависящей от хода другого Игрока

Это игры типа "дилемма заключенных" (их разбор с существующими библиотеками nashpy и axelrod можно посмотреть в предыдущей статье).

Особенность игры в том, что выигрыш каждого Игрока зависит от того, какой ход сделает другой Игрок (Игроки).

import my_python_game_theory_library as gtl

# Создадим 2 Игроков
gtl.Player(name='Федор')
gtl.Player(name='Теодор')

# Создадим матрицу Игры, содержащую варианты/опции для выбора каждым Игроком
gtl.Matrix(name='Matrix_dilemma', options=[[(-3,-3), (0,-6)], [(-6,0), (-1,-1)]])

game_dilemma = gtl.Game(name='Dilemma', 
                        queues=['Player_1', 'Player_2'],
                        matrices='Matrix_dilemma',
                        is_parallel=True
                       )

# Сыграем 3 раунда, в каждом из которых кажыдый Игрок выберет одну из опций
game_dilemma.play(rounds=3) # Выводит таблицу результатов каждого Игрока

Поочередная игра с деревом вариантов

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

При этом, выбор очередным Игроком варианта/опции приводит к сворачиванию на определенную развилку, со своими вариантами.

import my_python_game_theory_library as gtl

# Создадим 2 Игроков и очередность в порядке создания
gtl.Player(name='Федор')
gtl.Player(name='Теодор')
q1 = gtl.Queue(priority = gtl.Player.all)

# Создадим 4 Игральные кости

# Создадим классическую Игральную кость
d1 = gtl.Dice(faces = (1,6))

# Создадим нестандартную Игральную кость - 
# равноценные грани с разными очками, 1 и 6 выпадут с вероятностью 1/3, 
# а 2 и 5 - с вероятностью 1/6
d2 = gtl.Dice(faces = [1,1,2,5,6,6])

# Создадим нестандартную Игральную кость
d3 = gtl.Dice(faces = [1,3,3,3,3,6])

# Создадим нестандартную Игральную кость c разными вероятностями броска
# разных костей
d4 = gtl.Dice(faces = {d2:0.4, d3:0.6})

# Создадим экземпляр класса опции, как дерево вариантов 
# с максимум 2 уровнями:
o1 = gtl.Option(is_tree=True, max_levels=2)
# На первом уровне Игрок может выбрать бросок кости 1 или 2
o1.set_level(num_level=0, variants={'v1':d1, 'v2':d2})
# На втором уровне следующий Игрок может выбрать бросок кости 2 или 3,
# если первый выбрал v1, и 3 или 4, если первый выбрал v2
o1.set_level(num_level=2, variants=[{'v1':d2, 'v2':d3}, 
                                    {'v1':d3, 'v2':d4}})

game_tree = gtl.Game(name='Tree', 
                     queues=q1,
                     options=o1,
                     is_parallel=False  # Игра поочередная, согласно списку
                    )

# Сыграем 10 раундов
# Подсчет результатов по итогам раундов counting='binary',
# что означает, что за 1 место дается 1, за последующие - 0
# Возможны также 'sum' - сумма набранных баллов и 'avg' - их среднее
game_tree.play(rounds=10, counting='binary') # Выводит таблицу результатов каждого Игрока

Игра, в которой нужно выбирать число в интервале

Игра типа "Ультиматум", в которой Игрок 1 получает сумму X и должен предложить Игроку 2 ее часть (от 0 до X). Если Игрок 2 соглашается, то оба получают деньги, если нет - никто не получает. Далее Игрок 2 получает для раздела сумму Y. Эти суммы могут быть заданными, например, 10 монет, либо выбираться броском кубика - используем кубик с гранями от 5 до 10 включительно.

import my_python_game_theory_library as gtl

# Создадим 2 Игроков и очередность в порядке создания
gtl.Player(name='Федор')
gtl.Player(name='Теодор')

# Разобъем игроков на партии по 2 человека 
q1 = gtl.Queue(priority = gtl.Player.all, 
               parties=2, 
               parties_type='permutations')

game_ultim = gtl.Game(name='Ultim', 
                     queues=q1,
                     options=(0,10),  # Опции - выбор суммы от 0 до 10
                     options_type='partition',  # Тип - раздел суммы
                     condition='all',  # Условия получения - все согласны 
                     is_parallel=False  # Игра поочередная, согласно списку
                    )

# Сыграем 10 раундов
# Подсчет результатов по итогам раундов counting='sum',
# - сумма набранных баллов
game_ultim.play(rounds=10, counting='sum') # Выводит таблицу результатов каждого Игрока

Английский аукцион с очередностью

Игра, в которой на аукцион выставляется товар (класс Ресурс), и есть несколько Игроков-покупателей (случайное число от 3 до 10), каждый из которых оценивает Ресурс индивидуально, например, от 50 до 100 монет. Пусть Игроки называют свои ставки по очереди, либо говорят "пас". Побеждает тот, после которого все говорят "пас". Торговля начинается с определенной суммы, которая выбирается случайно в интервале (25, 75). Ставку можно увеличивать на фиксированную сумму - пусть случайно выбирается в интервале (1, 10).

import my_python_game_theory_library as gtl

# Создадим Игральную кость, выбирающую от 3 до 10 Игроков
d1 = gtl.Dice(faces=(3,10))

# Создадим Игральную кость, выбирающую ценность ресурса для Игрока -
# от 50 до 100 монет
d2 = gtl.Dice(faces=(50,100))

# Создадим Игральную кость, выбирающую начальную ставку -
# от 25 до 75 монет
d3 = gtl.Dice(faces=(25,75))

# Создадим Ресурс
r1 = gtl.Resource(name='Ценная картина', count=1)

# Создадим случайное кол-во Игроков со случайной оценкой Ресурса 
gtl.create(create_class='Player', num=d1, values={'Ценная картина': d2})

# И очередность в порядке создания
q1 = gtl.Queue(priority = gtl.Player.all)

game_auct = gtl.Game(name='Auction', 
                     queues=q1,
                     options=['bid', 'pass'],  # Опции - ставка или пас
                     options_type='eng_auction',  # Тип - английский аукцион
                     condition='last',  # Условия получения - последняя ставка
                     resourses=r1,  # Выставленный на аукцион ресурс, либо список
                     starting_prices=d3,
                     is_parallel=False  # Игра поочередная, согласно списку
                    )

# Сыграем аукцион
game_auct.play(rounds=1) # Выводит таблицу ставок каждого Игрока и победителя

Классический базар - много товаров, продавцов и много покупателей

Случайно выбирается несколько Ресурсов (от 3 до 5). Случайно выбирается количество Игроков (от 3 до 10), у каждого от 0 до 10 единиц каждого Ресурса. Каждый Игрок оценивает каждый Ресурс в определенную сумму и готов поменять его на другой, если ему предложат лучший.

Модель производит случайные обмены, пока будет выгодно меняться. Получить итоговое распределение Ресурсов между Игроками и их выигрыши - разницу между первоначальной и итоговой оценкой Игроками имеющихся Ресурсов.

import my_python_game_theory_library as gtl

# Создадим Игральную кость, выбирающую от 3 до 10 Игроков
d1 = gtl.Dice(faces=(3,10))

# Создадим Игральную кость, выбирающую количество Ресурсов для обмена -
# от 3 до 5
d2 = gtl.Dice(faces=(3,5))

# Создадим Игральную кость, выбирающую ценность ресурса для Игрока -
# от 1 до 10 монет
d3 = gtl.Dice(faces=(1,10))

# Создадим Игральную кость, выбирающую количество Ресурсов у Игрока -
# от 0 до 10
d4 = gtl.Dice(faces=(0,10))

# Создадим Ресурсы
gtl.create(create_class='Resource', num=d2)

# Создадим случайное кол-во Игроков со случайным количеством ресурсов
# и случайной оценкой Ресурса 
gtl.create(create_class='Player', 
           num=d1, 
           resourses=(gtl.Resource.all, d4),
           values=(gtl.Resource.all, d3))

# И список Игроков для обмена
q1 = gtl.Queue(priority = gtl.Player.all)

game_change = gtl.Game(name='Change', 
                     queues=q1,
                     options=['change', 'pass'],  # Опции - меняюсь или пас
                     options_type='change',  # Тип - обмен ресурсами
                     condition='over',  # Условия обмена - выше ценность
                     resourses=gtl.Resource.all,  # Список ресурсов
                     is_parallel=False  # Игра поочередная, согласно списку
                    )

# Сыграем обмен
# Выводит таблицы всех обменов, ресурсов и эффектов каждого Игрока
game_change.play(outs=['changes', 'resourses', 'effects']) 

2. Спросим совета у ChatGPT-3

Сразу выскажу резюме: если раньше гугление или поиск в Яндексе сравнивали с затратами времени и сил на поход в библиотеку и поиск там информации доступными средствами (каталоги в шкафчиках), то в данном случае ответы ChatGPT-3 можно сравнить с виртуальным консилиумом или даже мозговым штурмом целой банды специалистов в теории игр, ООП и написании библиотек на питоне... Убедитесь сами (по ссылке полный список вопросов-ответов по построению библиотеки):

Вопросы задавались на английском, ответы переведены на русский.

Я хочу разработать код библиотеки на питоне для решения разнообразных задач методами теории игр. Какие рекомендации ты можешь мне дать по разработке такой библиотеки?

Ответ, возможно, покажется банальным, но его стоит прочитать:

Конечно, вот несколько рекомендаций, которые могут помочь вам в разработке библиотеки Python для решения задач с использованием методов теории игр:

 1.     Начните с основ: Прежде чем углубляться в сложные алгоритмы теории игр, важно хорошо понимать основные концепции теории игр. Изучите различные типы игр, такие как кооперативные и некооперативные игры, игры с нулевой суммой и ненулевыми суммами и т.д.

2.     Выберите правильные структуры данных: При разработке библиотеки выбор правильной структуры данных важен для эффективной реализации. Рассмотрите возможность использования массивов NumPy или фреймов данных Pandas для хранения игровых данных и управления ими.

3.     Рассмотрите уже существующие библиотеки: Прежде чем разрабатывать свою собственную библиотеку, изучите существующие библиотеки, такие как Gambit, PyGMO и NetworkX, чтобы узнать, обладают ли они уже необходимой вам функциональностью.

4.     Сосредоточьтесь на удобочитаемости и документации: При написании вашего кода убедитесь, что он удобочитаем и хорошо документирован. Это облегчит другим понимание и использование вашего кода, а также облегчит вам его обслуживание и обновление в будущем.

5.     Реализуйте множество алгоритмов: Библиотека должна включать в себя ряд алгоритмов для решения различных типов игр, включая равновесие Нэша, минимакс и наилучший отклик.

6.     Тщательно протестируйте: обязательно тщательно протестируйте свой код, чтобы убедиться в его правильности и надежности. Подумайте о написании модульных тестов для каждой функции или алгоритма, которые вы реализуете.

7.     Сделайте его удобным для пользователя: Рассмотрите возможность предоставления пользователям удобного интерфейса для взаимодействия с библиотекой, такого как интерфейс командной строки или графический пользовательский интерфейс. 

Я надеюсь, что эти рекомендации помогут вам в вашем путешествии по разработке библиотеки Python для теории игр. Удачи!

Ок, давай начнем с пункта 1 твоей предыдущей рекомендации. Напиши топ-10 параметров и характеристик, которые может иметь игра в теории игр. Например, количество игроков, последовательные или одновременные ходы и тому подобное.

Узнаем ли мы что-то новенькое?
  1. Количество игроков: Количество игроков в игре определяет количество участников, вовлеченных в процесс принятия решений

  2. Тип игры: Существуют различные типы игр, включая кооперативные и некооперативные игры, игры с нулевой суммой и ненулевыми суммами и т.д.

  3. Пространство стратегии: Пространство стратегии относится к набору возможных стратегий, доступных каждому игроку в игре

  4. Матрица выплат: Матрица выплат определяет награды или выигрыши, которые получает каждый игрок на основе выбранных им стратегий

  5. Последовательные или одновременные ходы: В игре с последовательными ходами игроки по очереди делают ходы, в то время как в игре с одновременными ходами все игроки делают свои ходы одновременно

  6. Информационная структура: Информационная структура относится к информации, доступной игрокам о ходах друг друга и выплатах

  7. Полная или неполная информация: В игре с полной информацией все игроки обладают полными знаниями об игре, в то время как в игре с неполной информацией некоторая информация может быть скрыта

  8. Статическая или динамическая игра: В статической игре игра проводится только один раз, в то время как в динамической игре игра проводится несколько раз, при этом игроки обновляют свои стратегии на основе своего прошлого опыта

  9. Детерминированная или стохастическая игра: В детерминированной игре исход определяется стратегиями, выбранными игроками, в то время как в стохастической игре исход определяется случайностью

  10. Конечные условия: Конечные условия определяют, когда заканчивается игра и как определяются выплаты. Например, в игре с нулевой суммой конечным условием может быть то, что один игрок выигрывает, а другой проигрывает

Уточни про типы игры: назови топ-10 типов игры в теории игр, кроме названных (кооперативные и некооперативные игры, игры с нулевой суммой и ненулевыми суммами).

И что у нас там в топ-10 типов игр?
  1. Игры в нормальной форме: Игры в нормальной форме, также известные как матричные игры, - это игры для двух игроков, в которых каждый игрок выбирает стратегию одновременно, не наблюдая за выбором другого игрока

  2. Игры в расширенной форме: Игры в расширенной форме, также известные как игры в виде дерева, моделируют игры, в которых игроки делают ходы последовательно

  3. Игры с одновременными ходами: Игры с одновременными ходами - это игры, в которых все игроки делают свои ходы одновременно, не наблюдая за ходами друг друга - дублируется с п.1 - прим.автора

  4. Динамические игры: Динамические игры моделируют ситуации, в которых игроки принимают решения с течением времени и обновляют свои стратегии на основе результатов предыдущих раундов

  5. Повторяющиеся игры: Повторяющиеся игры - это игры, в которые играют несколько раз, позволяя игрокам создавать репутацию и принимать решения, основанные на прошлом опыте - дублируется с п.4 - прим.автора

  6. Байесовские игры: Байесовские игры моделируют ситуации, в которых у игроков разные убеждения или предварительные оценки состояния игры

  7. Аукционы: Аукционы - это игры, в которых игроки делают ставки на товар или ресурс, а победитель определяется по самой высокой ставке

  8. Игры с голосованием: Игры с голосованием моделируют ситуации, когда группа людей принимает коллективное решение, основанное на их предпочтениях

  9. Игры для переговоров: Игры для переговоров моделируют ситуации, когда два или более игроков ведут переговоры с целью достижения взаимовыгодного соглашения

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

Это некоторые из распространенных типов игр в теории игр. Каждый тип игры имеет свой собственный набор характеристик и требует различных методов решения.

Перейдем к конкретике:

Какие топ-10 классов в библиотеке на питоне для решения задач методами теории игр ты предложить создать? Напиши названия классов и их краткое описание

ИИ предожил формировать классы по типам игр, в отличие от моего подхода, в котором класс - отдельная сущность (Игрок, Игра, Матрица, Ресурс, Случайность и т.д.)

Вот 10 лучших классов, которые я бы предложил включить в библиотеку python для решения задач с использованием методов теории игр:

  1. Game: Базовый класс, который представляет игру и содержит информацию о количестве игроков, типе игры и других ключевых характеристиках

  2. NormalFormGame: класс, который представляет игры нормальной формы и предоставляет методы для решения игр для двух игроков в матричном виде

  3. ExtensiveFormGame: класс, который представляет игры расширенной формы и предоставляет методы для решения последовательных игр в виде дерева

  4. DynamicGame: класс, который представляет динамические игры и предоставляет методы для решения игр с игроками, обновляющими свои стратегии с течением времени

  5. RepeatedGame: класс, который представляет повторяющиеся игры и предоставляет методы для решения игр, в которые играют несколько раз

  6. BayesianGame: класс, который представляет байесовские игры и предоставляет методы для решения игр с игроками, имеющими разные убеждения или приоритеты

  7. Auction: класс, который представляет аукционы и предоставляет методы для решения аукционных игр с различными форматами аукционов, такими как аукционы по первой цене, по второй цене и на английском языке

  8. VotingGame: класс, который представляет игры для голосования и предоставляет методы для решения игр для голосования с различными системами голосования, такими как множественное, мажоритарное и пропорциональное представительство

  9. BargainingGame: класс, который представляет игры для ведения переговоров и предоставляет методы для решения игр для ведения переговоров с использованием различных протоколов переговоров

  10. MechanismDesign: класс, который представляет проблемы проектирования механизмов и предоставляет методы для решения проблем проектирования механизмов с различными информационными структурами

Эти классы обеспечили бы гибкую и модульную архитектуру для моделирования и решения различных типов игр с использованием методов теории игр. Методы, предоставляемые этими классами, будут включать алгоритмы для нахождения равновесий Нэша, обратной индукции, байесовского обновления и других ключевых методов в теории игр.

Попробуем раскрутить ИИ думать в том же направлении, что и я - каждая сущность - отдельный класс:

Хорошо, но я хотел бы каждую сущность в теории игр выделить в отдельный класс. Например, класс Player. Какие топ-10 классов ты порекомендуешь?

Насколько структура классов, предложенная ИИ, будет отличаться от моей?

Конечно, вот 10 классов, которые я бы порекомендовал:

  1. Player: класс, который представляет игрока в игре и содержит информацию о стратегиях игрока и выплатах - ок, только выплаты у меня содержатся в классе Матрица - прим. автора

  2. Action: класс, представляющий действие, которое игрок может предпринять в игре - неплохо, у меня это Option - опция, вариант, которые может выбрать Игрок - прим. автора

  3. Outcome: класс, который представляет исход игры и содержит информацию о выплатах для каждого игрока - отлично, у меня это Benefits - выигрыши. Возможно, он имел в виду матрицу выигрышей - тогда у меня это класс Matrix - прим. автора

  4. Strategy: класс, представляющий стратегию, которую игрок может использовать в игре - вот это да, у меня также стратегии выделены в отдельный класс - прим.автора

  5. Game: Базовый класс, который представляет игру и содержит информацию о количестве игроков, типе игры и других ключевых характеристиках - отлично, без этого класса набор был бы неполным...

  6. NormalFormGame: класс, который представляет игры нормальной формы и предоставляет методы для решения игр для двух игроков в матричном виде - здесь он снова пошел по производным классам от Game - прим. автора

  7. ExtensiveFormGame: класс, который представляет игры расширенной формы и предоставляет методы для решения последовательных игр в виде дерева

  8. DynamicGame: класс, который представляет динамические игры и предоставляет методы для решения игр с игроками, обновляющими свои стратегии с течением времени

  9. RepeatedGame: класс, который представляет повторяющиеся игры и предоставляет методы для решения игр, в которые играют несколько раз

  10. BayesianGame: класс, который представляет байесовские игры и предоставляет методы для решения игр с игроками, имеющими разные убеждения или приоритеты

    Эти классы обеспечили бы четкое разделение сущностей в теории игр, упростив моделирование и решение игр с использованием методов теории игр. Класс Player содержал бы информацию об игроках в игре, в то время как классы Action, Result и Strategy обеспечивали бы структурированное представление элементов, составляющих игру. Класс Game и его дочерние классы предоставляли бы методы для решения различных типов игр с использованием методов теории игр.

Предложим свои классы и попросим объяснить, как она понимает их свойства:

Я хочу разработать код библиотеки на питоне для решения разнообразных задач методами теории игр.

У меня будут классы: Game, Player, Queue, Coalition, Strategy, Option, Benefit, Situation, Matrix, Resource, Dice.

Как, по-твоему, должны быть связаны эти классы?

ChatGPT верно интерпретировала все классы, за исключением Situation (это набор Игрок-Опция-Выигрыш) - возможно, нужно переназвать этот класс?

Чтобы спроектировать классы для вашей библиотеки Python для теории игр, вы могли бы рассмотреть следующие взаимосвязи между классами:

  1. Game: Это был бы основной класс, представляющий игру. У него были бы такие атрибуты, как вовлеченные игроки, правила игры и стратегии, которые можно использовать.

  2. Player: Этот класс будет представлять каждого отдельного игрока в игре. У него были бы такие атрибуты, как имя игрока, стратегия игрока и текущая ситуация игрока.

  3. Queue: Этот класс может быть использован для представления последовательности игроков в пошаговой игре. В нем могут быть методы для изменения порядка игроков, добавления новых игроков или удаления существующих игроков.

  4. Coalition: Этот класс может представлять группу игроков, которые работают вместе в игре. У него могли бы быть такие атрибуты, как члены коалиции, стратегия коалиции и выгода коалиции.

  5. Strategy: Этот класс будет представлять доступные стратегии, которые могут быть использованы игроками или коалициями в игре.

  6. Option: Этот класс может быть использован для представления различных вариантов, которые игрок или коалиция могут выбрать в игре. У него могут быть такие атрибуты, как название опции, преимущества опции и стоимость опции.

  7. Benefit: Этот класс может представлять различные преимущества, которые игроки или коалиции могут получить от выбора определенных опций. У него могут быть такие атрибуты, как название , пособия и тип .

  8. Situation: Этот класс будет представлять текущее состояние игры. У него могут быть такие атрибуты, как текущие игроки, их стратегии и доступные текущие опции.

  9. Matrix: Этот класс может быть использован для представления матрицы выплат в игре. В нем могут быть такие атрибуты, как вовлеченные игроки, их доступные стратегии и выплаты, связанные с каждой комбинацией стратегий игроков.

  10. Resource: Этот класс может представлять любые ресурсы, которые используются в игре. У него могут быть такие атрибуты, как имя ресурса, значение ресурса и тип ресурса.

  11. Dice: Этот класс может представлять кости или другие генераторы случайных чисел, которые используются в игре. У него могли бы быть методы, позволяющие бросить кости и вернуть случайное число.

Точные отношения между этими классами будут зависеть от специфики задач теории игр, которые вы пытаетесь решить. Однако эти классы должны стать хорошей отправной точкой для создания гибкой и расширяемой библиотеки теории игр на Python.

Далее серия вопросов, которая выжимает из ИИ максимум знаний об атрибутах и методах класса Игрок - Player (очевидно, он изучил большое количество кода, где есть такой класс - а он есть во многих играх!)

Отлично, какие топ-10 атрибутов ты мог бы предложить для класса Player?

10 атрбутов для класса Игрок
  1. name: Строка, представляющая имя игрока

  2. strategies: Список объектов/экземпляров класса Strategy, который представляет стратегии, доступные игроку

  3. payoffs: Словарь, который сопоставляет каждый объект Outcome с выигрышем, полученным игроком в этом результате

  4. preferred_strategy: Предпочтительная стратегия игрока, представленная в виде объекта Strategy - интересно! - прим. автора

  5. beliefs: Словарь, который представляет убеждения игрока о стратегиях и выигрышах других игроков - еще более интересно! - прим. автора

  6. utility_function: функция, которая сопоставляет каждый объект Outcome с полезностью игрока для этого результата - здесь нужно подумать - прим. автора

  7. type: строка, представляющая тип игрока, например "кооперативный" или "некооперативный" - полезно - это отнести в класс Коалиции? - прим.автора

  8. num_actions: целое число, представляющее количество действий, доступных игроку - интересно - прим.автора

  9. num_strategies: целое число, представляющее количество стратегий, доступных игроку - интересно - прим.автора

  10. is_rational: логическое значение, указывающее, считается ли игрок рациональным - очень интересно! - прим.автора

Эти атрибуты обеспечили бы всестороннее представление об игроке в игре, включая его доступные стратегии, выплаты, убеждения и другие ключевые характеристики. Класс Player послужил бы строительным блоком для моделирования игр в теории игр и позволил бы создавать сложные игры с несколькими игроками и разными типами игроков

Полный список вопросов и ответов на момент написания статьи доступен по ссылке

3. Реализуем класс Queue - Очередь Игроков

Экземпляры класса Queue - Очередь Игроков содержат список Игроков.

Этот список, priority, передается в экземпляр Игры.

  • Если ходы в Игре происходят одновременно, то список Игроков - это множество Игроков, без очередности.

  • Если ходы в Игре происходят поочерёдно, то список Игроков - это очередь Игроков.

  • Игра может происходить по партиям, когда Игроки разбиваются на пары, тройки, четверки и т.п. и играют "каждый с каждым". За это отвечают атрибуты parties - количество Игроков в такой партии, parties_type - комбинации, перестановки, случайное формирование партии Игроков, max_parties- максимальное количество партий, если задано (например, при случайном формировании партии).

  • Наконец, Игра может происходить в виде турнира на выбывание (пока не реализовано).

Очередь является эталонной, если с нее начинается Игра. Внутри Игры могут происходить пропуски ходов или внеочередные ходы, то есть кроме эталонного, существует актуальный экземпляр Очереди для каждой Игры в каждый момент! Поэтому экземпляр класса Очередь имеет атрибут is_reference=True, если это эталонный экземпляр, и атрибуты, обозначающие моменты для конкретной игры:

  • game: экземпляр Игры,

  • n_round: номер раунда Игры,

  • player: Игрок, после которого произошло изменение,

  • is_next_round: True, если данный экземпляр очереди сохраняется на следующий раунд

# Библиотека itertools позволяет получить комбинации и перестановки списка
import itertools

class Queue(Mixin):
    """Очередь Игроков в порядке ходов, последовательность действий Игроков.

    Parameters
    ----------
    priority: list , по умолчанию пустой список
        Список имен или ссылок на экземпляры Игроков (трансформируются в имена)
        в порядке очередности хода. Если Игра одновременная, 
        то Очередь используется как список Игроков, принимающих участие
        TODO Можно задать название Группы или ссылку на экземпляр Группы
        TODO Можно задать экземпляр Dice, определяющий список Игроков

    parties: int
        Игра по партиям, то есть Игроки играют группами, переходя из группы в группу.
        Если играют парами, parties=2, тройками - parties=3 и т.д. 
     
    parties_type: str
        Если задан, то определяет, как соствляются партии. 
        'combinations' - получить комбинации,
        'combinations_with_myself' - комбинации с возможностью повторения, 
        'permutations' - перестановки
        Количество Игроков по партиям определяется parties. Пары, если parties не задано.
        parties_type  можно присвоить экземпляр Dice, выбирающий нескольких случайных игроков
    
    max_parties: int 
        Ограничить количество партий, по умолчанию не ограничено.
        Если parties_type присвоен экземпляр Dice, то по умолчанию max_parties = 1
        Рекомендуется задавать, если parties_type присвоен экземпляр Dice
    """

    all = dict()  # Словарь всех Очередей

    def __init__(self, priority: list = None, 
                 parties: int = None,
                 parties_type: str = None, 
                 max_parties: int = None, 
                 is_reference:bool = True,
                 game = None,
                 n_round: int = None,
                 game = None, 
                 is_next_round:bool = None,
                 **kwargs):
        
        self.priority = list()
        self.max_parties = max_parties
        if not priority is None:
            for player in priority:
                if isinstance(player, str):
                    self.priority.append(player)
                elif isinstance(player, Player):
                    for name, value in Player.all.items():
                        if player == value:
                            self.priority.append(name)
                else:
                    raise ValueError 
        
        self.parties = parties
        self.parties_type = parties_type
        self.start_priority = self.priority

        if (not self.parties_type is None) and (self.parties is None):
            self.parties = 2
        if self.parties_type == 'combinations':
            self.priority = [i for i in itertools.combinations(self.priority, self.parties)]
        elif self.parties_type == 'combinations_with_myself':
            self.priority = [i for i in 
                             itertools.combinations_with_replacement(self.priority, self.parties)]
        elif self.parties_type == 'permutations':
            self.priority = [i for i in itertools.permutations(self.priority, self.parties)]
        else:
            pass

        self.is_reference = is_reference
        self.game = game
        self.n_round = n_round
        self.is_next_round = is_next_round

        
        super().__init__(**kwargs,**{'priority': self.priority,
                                     'parties': self.parties,
                                     'parties_type': self.parties_type,
                                     'max_parties': self.max_parties,
                                     'is_reference': self.is_reference,
                                     'game': self.game,
                                     'n_round': self.n_round,
                                     'is_next_round': self.is_next_round
                                    })

Создадим нескольких игроков и очередь, состоящую из партий по 2 игрока, полученных перестановками:

# Создадим игроков
p1 = Player(name='Кая', about='Из коробки, дефолтные настройки')
p2 = Player()
p3 = Player()
p4 = Player(name='Дамилола', characteristics={'Профессия': 'Пилот'})

# Создадим очередь, состоящую из партий по 2 игрока, 
# полученных перестановками:
q1 = Queue(priority=Player.all, parties=2, parties_type='permutations')

# Посмотрим очередь игроков:
q1.priority
[('Кая', 'Player_0'),
 ('Кая', 'Player_1'),
 ('Кая', 'Дамилола'),
 ('Player_0', 'Кая'),
 ('Player_0', 'Player_1'),
 ('Player_0', 'Дамилола'),
 ('Player_1', 'Кая'),
 ('Player_1', 'Player_0'),
 ('Player_1', 'Дамилола'),
 ('Дамилола', 'Кая'),
 ('Дамилола', 'Player_0'),
 ('Дамилола', 'Player_1')]

На сегодня пока всё, следите за следующими статьями серии!

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Нужно ли спрашивать совета у нейросетей при разработке?
25% Однозначно, да — нейросети найдут варианты, которые уже мелькали в сети, но их сложно найти поиском…6
54.17% Да, в любом случае не помешает. Это как спросить совета новичка — свежий взгляд бывает полезен.13
12.5% Лучше не спрашивать — потеряем время на обдумывание кучи ненужной или общеизвестной информации…3
4.17% Ни в коем случае — не стоит даже давать себе повода впадать в детство и играть в глупые игрушки…1
4.17% Ни в коем случае — не стоит обучать потенциального противника, который может лишить тебя работы…1
0% Свой вариант в комментах0
Проголосовали 24 пользователя. Воздержались 6 пользователей.
Теги:
Хабы:
Всего голосов 4: ↑3 и ↓1+2
Комментарии1

Публикации

Истории

Работа

Data Scientist
61 вакансия
Python разработчик
137 вакансий

Ближайшие события