Фоновая будущее
В 2017 году вы и ваш противник встретитесь в футуристическом бою, в котором выживет только один. Действительно ли вы достаточно опытный , чтобы победить вашего противника? Сейчас самое время отточить свои навыки владения оружием на вашем любимом языке программирования и бороться со всеми трудностями!
Результаты турнира
Этот турнир завершился в UTC утром Feburary 2 - й , 2017. Благодаря нашим конкурсанток, мы имели захватывающий футуристический турнир!
MontePlayer - окончательный победитель после близких сражений с CBetaPlayer и StudiousPlayer. Три лучших дуэлянта Гена сделали памятную фотографию:
MontePlayer - by TheNumberOne
+------------+
CBetaPlayer | | - by George V. Williams
+------------+ # 1 | StudiousPlayer - by H Walters
| +----------------+
| # 2 # 3 |
+------------------------------------------+
The Futurustic Gun Duel @ PPCG.SE 2017
Поздравляем победителей! Подробная таблица лидеров видна в конце этого поста.
Общее руководство
- Посетите официальный репозиторий для исходного кода, используемого в этом турнире.
- Записи C ++: пожалуйста, наследуйте
Player
класс. - Записи не на C ++: выберите один интерфейс в разделе Интерфейс для заявок, не относящихся к C ++ .
- В настоящее время разрешены не языки C ++: Python 3, Java.
Дуэль
- Каждый игрок начинает с незаряженного оружия, которое может загрузить бесконечное количество патронов.
- Каждый ход игроки одновременно выбирают одно из следующих действий:
0
- Загрузите 1 боеприпас в пистолет.1
- выстрелить в противника; стоит 1 заряженный патрон.2
- выстрелить плазменным лучом в противника; стоит 2 заряженных патрона.-
- Защищать входящую пулю с помощью металлического щита.=
- Защитить входящий плазменный луч с помощью теплового дефлектора.
- Если оба игрока выживают после 100- го хода, они истощаются до смерти, что приводит к ничьей .
Игрок проигрывает дуэль с оружием, если он
- Возможно , НЕ использовать металлический экран для защиты входящей пули.
- Возможно , НЕ используйте тепловой дефлектор , чтобы защитить входящую плазму.
- Стреляйте из пистолета, не загружая достаточно патронов, в результате чего их пистолет сам взорвется и убьет владельца.
Предостережения
Согласно Руководству для владельцев футуристических ружей :
- Металлический щит НЕ МОЖЕТ защищать от поступающего плазменного луча. Аналогично, тепловой дефлектор НЕ МОЖЕТ защищать от входящей пули.
- Плазменный луч подавляет пулю (потому что первый требует больше заряженных боеприпасов). Поэтому, если игрок стреляет плазменным лучом по противнику, который стреляет пулей в тот же ход, противник убивается.
- Если оба игрока одновременно выпускают пули друг в друга, пули отменяются, и оба игрока выживают. Аналогично, если оба игрока стреляют друг в друга плазменным лучом в один ход, оба игрока выживают.
Также стоит отметить, что:
- Вы НЕ будете знать действия своего противника в ход, пока он не закончится.
- Отражение плазменных лучей и защитных пуль НЕ причинит вреда вашему противнику.
Таким образом, в каждом ходу есть всего 25 действительных комбинаций действий:
+-------------+---------------------------------------------+
| Outcome | P L A Y E R B |
| Table +--------+-----------------+------------------+
| for Players | Load | Bullet Plasma | Metal Thermal |
+---+---------+--------+--------+--------+--------+---------+
| P | Load | | B wins | B wins | | |
| L +---------+--------+--------+--------+--------+---------+
| A | Bullet | A wins | | B wins | | A wins |
| Y | +--------+--------+--------+--------+---------+
| E | Plasma | A wins | A wins | | A wins | |
| R +---------+--------+--------+--------+--------+---------+
| | Metal | | | B wins | | |
| | +--------+--------+--------+--------+---------+
| A | Thermal | | B wins | | | |
+---+---------+--------+--------+---------------------------+
Note: Blank cells indicate that both players survive to the next turn.
Пример дуэли
Вот дуэль, которую я когда-то имел с другом. В то время мы мало что знали о программировании, поэтому мы использовали жесты рук и передавали сигналы со скоростью два оборота в секунду. Слева направо наши действия были в свою очередь:
Me: 001-000-1201101001----2
Friend: 00-10-=1-==--0100-1---1
По правилам выше я проиграл. Вы понимаете почему? Это потому, что я выпустил последний плазменный луч, когда у меня был только один заряженный патрон, и мой пистолет взорвался.
C ++ Player
Вы , как цивилизованный футуристический программист, не будете напрямую обращаться с оружием. Вместо этого вы пишете код, Player
который борется против других. Публично наследуя класс c ++ в проекте GitHub, вы можете начать писать свою городскую легенду.
Player.hpp can be found in Tournament\Player.hpp
An example of a derived class can be found in Tournament\CustomPlayer.hpp
Что вы должны или можете сделать
- Вы должны наследовать
Player
класс через публичное наследование и объявить свой класс финальным. - Вы должны переопределить
Player::fight
, который возвращает действительныйPlayer::Action
каждый раз, когда он вызывается. - При желании, переопределить
Player::perceive
иPlayer::declared
следить за действиями вашего противника и отслеживать ваши победы. - При желании используйте частные статические члены и методы в производном классе для выполнения более сложных вычислений.
- При желании используйте другие стандартные библиотеки C ++.
Что вы не должны делать
- Вы НЕ ДОЛЖНЫ использовать какой-либо прямой метод для распознавания своего противника, кроме указанного идентификатора противника, который перемешивается в начале каждого турнира. Вы можете только догадываться, кто является игроком через их игру в турнире.
- Вы должны НЕ переопределить любые методы в
Player
классе , который не объявлен виртуальным. - Вы должны НЕ объявлять или инициализировать что - либо в глобальном масштабе.
- Начиная с дебюта (теперь дисквалифицированного)
BlackHatPlayer
, игрокам НЕ разрешается заглядывать или изменять состояние вашего оппонента.
Пример дуэли
Процесс оружейного поединка проводится с использованием GunDuel
класса. Пример боя смотрите Source.cpp
в разделе « Инициирование поединка» .
Мы витрина GunClubPlayer
, HumanPlayer
и GunDuel
класс, который можно найти в Tournament\
каталоге репозитория.
В каждом поединке GunClubPlayer
будет загружаться пуля; уволить его; промыть и повторить. Во время каждого хода HumanPlayer
вам будет предложено сыграть против вашего оппонента. Ваши клавиши управления символы 0
, 1
, 2
, -
и =
. В Windows вы можете использовать HumanPlayer
для отладки вашего представления.
Начало дуэли
Вот как вы можете отлаживать плеер через консоль.
// Source.cpp
// An example duel between a HumanPlayer and GunClubPlayer.
#include "HumanPlayer.hpp"
#include "GunClubPlayer.hpp"
#include "GunDuel.hpp"
int main()
{
// Total number of turns per duel.
size_t duelLength = 100;
// Player identifier 1: HumanPlayer.
HumanPlayer human(2);
// Player identifier 2: GunClubPlayer.
GunClubPlayer gunClub(1);
// Prepares a duel.
GunDuel duel(human, gunClub, duelLength);
// Start a duel.
duel.fight();
}
Примеры игр
Наименьшее количество ходов, которое вам нужно победить, GunClubPlayer
составляет 3. Вот повтор игры 0-1
против GunClubPlayer
. Число в парантезе - это количество заряженных боеприпасов для каждого игрока, когда ход заканчивается.
:: Turn 0
You [0/12/-=] >> [0] load ammo (1 ammo)
Opponent selects [0] load ammo (1 ammo)
:: Turn 1
You [0/12/-=] >> [-] defend using metal shield (1 ammo)
Opponent selects [1] fire a bullet (0 ammo)
:: Turn 2
You [0/12/-=] >> [1] fire a bullet (0 ammo)
Opponent selects [0] load ammo (1 ammo)
:: You won after 3 turns!
:: Replay
YOU 0-1
FOE 010
Press any key to continue . . .
Самый быстрый способ быть побежденным, GunClubPlayer
не делая недопустимых ходов, - это последовательность действий 0=
, потому что пуля стреляет прямо через тепловой отражатель. Переигровка
:: Turn 0
You [0/12/-=] >> [0] load ammo (1 ammo)
Opponent selects [0] load ammo (1 ammo)
:: Turn 1
You [0/12/-=] >> [=] defend using thermal deflector (1 ammo)
Opponent selects [1] fire a bullet (0 ammo)
:: You lost after 2 turns!
:: Replay
YOU 0=
FOE 01
Press any key to continue . . .
Турнир
Турнир проводится в формате «Последний игрок». В турнире все действительные материалы (включая GunClubPlayer
) помещаются в пул. Каждой заявке присваивается рандомизированный, но уникальный идентификатор, который остается неизменным в течение всего турнира. Во время каждого раунда:
- Каждое представление начинается с 0 очков и сыграет 100 поединков против каждого другого представления.
- Каждый победный поединок дает 1 очко; Рисование и проигрыш дают 0 очков.
- В конце раунда заявки с минимальным количеством очков покидают турнир. В случае ничьей, игрок с наименьшим количеством очков, заработанных с начала турнира, уйдет.
- Если осталось более одного игрока, начинается следующий раунд.
- Очки НЕ переносятся на следующий раунд.
представление
Вы отправите одного игрока за ответ. Вы можете отправить несколько файлов для игрока, если они не мешают другим представлениям. Чтобы все было гладко, пожалуйста:
- Назовите ваш основной заголовочный файл как
<Custom>Player.hpp
, - Назовите другие файлы как
<Custom>Player*.*
, например,MyLittlePlayer.txt
если ваше имя классаMyLittlePlayer
, илиEmoPlayerHates.cpp
если ваше имя классаEmoPlayer
. - Если ваше имя содержит
Shooter
или похожие слова, которые соответствуют контексту этого турнира, вам не нужно добавлятьPlayer
в конце. Если вы твердо уверены, что ваше имя работает лучше без суффиксаPlayer
, вам также не нужно добавлятьPlayer
. - Убедитесь, что ваш код можно скомпилировать и связать под Windows.
Вы можете комментировать, чтобы попросить разъяснений или определить лазейки. Надеюсь, вам понравится этот футуристический Gun Duel и желаю вам счастливого Нового года!
осветление
- Вам разрешено иметь случайное поведение.
- Недопустимые действия (стрельба при загруженных боеприпасах недостаточно) разрешены.
- Если игрок делает неверный ввод, его пистолет взорвется немедленно.
- Вам разрешено изучать ответы.
- Вам явно разрешено записывать поведение противника в каждом турнире.
- Каждый раунд вы будете играть 100 поединков против каждого противника; порядок 100 поединков, однако, рандомизирован - вам не гарантировано, что вы будете сражаться с одним и тем же противником 100 поединков подряд.
Дополнительные ресурсы
@flawr перевел предоставленный источник C ++ на Java в качестве ссылки, если вы хотите отправить записи C ++.
Интерфейс для не-C ++ представлений
В настоящее время принимаются: Python 3, Java.
Пожалуйста, следуйте одной из спецификаций ниже:
Спецификация интерфейса 1: код выхода
Ваша подача будет выполняться один раз за ход.
Expected Command Line Argument Format:
<opponent-id> <turn> <status> <ammo> <ammo-opponent> <history> <history-opponent>
Expected Return Code: The ASCII value of a valid action character.
'0' = 48, '1' = 49, '2' = 50, '-' = 45, '=' = 61
<opponent-id> is an integer in [0, N), where N is size of tournament.
<turn> is 0-based.
If duel is in progress, <status> is 3.
If duel is draw / won / lost, <status> is 0 / 1 / 2.
<history> and <history-opponent> are strings of actions, e.g. 002 0-=
If turn is 0, <history> and <history-opponent> are not provided.
You can ignore arguments you don't particularly need.
Вы можете проверить свои представления PythonPlayer\
и JavaPlayer\
каталоги.
Спецификация интерфейса 2: стандартный ввод / вывод
(Кредит Х Уолтерсу)
Ваша заявка будет проходить один раз за турнир.
Для всех записей о том, как выполнять ввод / вывод, существует фиксированное требование, поскольку и stdin, и stdout подключены к драйверу турнира. Нарушение этого может привести к тупику. Все записи ДОЛЖНЫ следовать этому алгоритму EXACT (в псевдокоде):
LOOP FOREVER
READ LINE INTO L
IF (LEFT(L,1) == 'I')
INITIALIZE ROUND
// i.e., set your/opponent ammo to 0, if tracking them
// Note: The entire line at this point is a unique id per opponent;
// optionally track this as well.
CONTINUE LOOP
ELSE IF (LEFT(L,1) == 'F')
WRITELN F // where F is your move
ELSE IF (LEFT(L,1) == 'P')
PROCESS MID(L,2,1) // optionally perceive your opponent's action.
END IF
CONTINUE LOOP
QUIT
Здесь F является одним из 0
, 1
, 2
, -
, или =
для load / bullet / plasma / metal / thermal
. ПРОЦЕСС означает опционально реагировать на действия противника (включая отслеживание патронов противника, если вы это делаете). Обратите внимание, что действие противника также является одним из «0», «1», «2», «-» или «=» и относится ко второму символу.
Финальное табло
08:02 AM Tuesday, February 2, 2017 Coordinated Universal Time (UTC)
| Player | Language | Points | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
|:------------------ |:---------- | ------:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:|
| MontePlayer | C++ | 11413 | 1415 | 1326 | 1247 | 1106 | 1049 | 942 | 845 | 754 | 685 | 555 | 482 | 381 | 287 | 163 | 115 | 61 |
| CBetaPlayer | C++ | 7014 | 855 | 755 | 706 | 683 | 611 | 593 | 513 | 470 | 414 | 371 | 309 | 251 | 192 | 143 | 109 | 39 |
| StudiousPlayer | C++ | 10014 | 1324 | 1233 | 1125 | 1015 | 907 | 843 | 763 | 635 | 555 | 478 | 403 | 300 | 201 | 156 | 76 |
| FatedPlayer | C++ | 6222 | 745 | 683 | 621 | 655 | 605 | 508 | 494 | 456 | 395 | 317 | 241 | 197 | 167 | 138 |
| HanSoloPlayer | C++ | 5524 | 748 | 668 | 584 | 523 | 490 | 477 | 455 | 403 | 335 | 293 | 209 | 186 | 153 |
| SurvivorPlayer | C++ | 5384 | 769 | 790 | 667 | 574 | 465 | 402 | 354 | 338 | 294 | 290 | 256 | 185 |
| SpecificPlayer | C++ | 5316 | 845 | 752 | 669 | 559 | 488 | 427 | 387 | 386 | 340 | 263 | 200 |
| DeceptivePlayer | C++ | 4187 | 559 | 445 | 464 | 474 | 462 | 442 | 438 | 369 | 301 | 233 |
| NotSoPatientPlayer | C++ | 5105 | 931 | 832 | 742 | 626 | 515 | 469 | 352 | 357 | 281 |
| BarricadePlayer | C++ | 4171 | 661 | 677 | 614 | 567 | 527 | 415 | 378 | 332 |
| BotRobotPlayer | C++ | 3381 | 607 | 510 | 523 | 499 | 496 | 425 | 321 |
| SadisticShooter | C++ | 3826 | 905 | 780 | 686 | 590 | 475 | 390 |
| TurtlePlayer | C++ | 3047 | 754 | 722 | 608 | 539 | 424 |
| CamtoPlayer | C++ | 2308 | 725 | 641 | 537 | 405 |
| OpportunistPlayer | C++ | 1173 | 426 | 420 | 327 |
| GunClubPlayer | C++ | 888 | 500 | 388 |
| PlasmaPlayer | C++ | 399 | 399 |
Турнир продлится до 1 февраля 2017 года, если не указано иное.
источник
Player
реализации, которая вызывает другой процесс, чтобы вычислить текущий ход. Это позволило бы людям участвовать на любом языке, который вы с удовольствием используете на своей машине.Player::fight
» / «Вы можете наследоватьPlayer::perceive
» ... в обоих случаях термин переопределяет , а не наследует .GunDuel.hpp
, какvalidA
иvalidB
использоватьactionA
Ответы:
MontePlayer
Этот игрок использует алгоритм поиска дерева «Развязанный UCT Монте-Карло», чтобы решить, какой выбор он должен сделать. Он отслеживает, что делает враг, чтобы предсказать его действия. Он имитирует врага как самого себя, если ему не хватает данных.
Этот бот действительно хорошо работает против любого другого бота, кроме cβ. В 10000 поединках против cβ Монте выиграл 5246 поединков. С небольшим количеством математики это означает, что Монте выиграет поединок против cβ 51,17% до 53,74% времени (уверенность 99%).
источник
Теперь: я почти уверен, что это должно быть немедленно дисквалифицировано, но забавно, что я явно не нарушаю ни одно из правил, изложенных выше:
BlackHat не пытается распознать противника - фактически, совершенно не имеет значения, кто является противником, учитывая, что его мозг заменяется немедленно.
Все происходит локально с
fight
виртуальной функцией.источник
#ifdef __BLACKHAT_PLAYER_HPP__
␊#error "Dependency issue; to compile, please include this file before BlackHatPlayer.hpp"
␊#else
␊#define __BLACKHAT_PLAYER_HPP__
␊#endif
␊#pragma once
;-)Далее, самый страшный из всех существ, он был в аду и обратно и сражался буквально с 900000 других ботов , его ...
BotRobot был назван, обучен и построен автоматически по очень простому генетическому алгоритму.
Две команды из 9 были настроены против друг друга, в каждом поколении каждый робот из команды 1 противостоит каждому роботу из команды 2. Роботы с большим количеством побед, чем поражений, сохранили свою память, а другие вернулись к последнему шагу и был шанс что-то забыть, надеюсь, плохо. Сами боты - прославленные таблицы поиска, где, если они найдут то, чего не видели раньше, они просто выберут случайную действительную опцию и сохранят ее в памяти. Версия C ++ не делает этого, она должна была выучить . Как указывалось ранее, победившие боты сохраняют эту новую найденную память, так же ясно, как она работала. Потерять ботов не надо, и сохраните то, с чего они начали.
В конце концов, бои с ботами проходили довольно близко, из-за этого они редко оказывались в тупике. Победитель был выбран из пула двух команд после эволюции, который составлял 100000 поколений.
BotRobot с его случайно сгенерированным и КРАСИВЫМ именем был счастливчиком.
Генератор
bot.lua
Пересмотр: Хотя робот был довольно умным против себя и других похожих роботов, он оказался довольно бесполезным в реальных битвах. Итак, я восстановил его мозг против некоторых из уже созданных ботов.
Результаты, как легко увидеть, представляют собой гораздо более сложный мозг, в котором у противника есть 12 патронов.
Я не уверен, что он боролся против того, чтобы получить до 12 патронов, но что-то сделал.
И конечно же, готовый продукт ...
Я ненавижу C ++ сейчас ...
источник
00
.источник
GetRandomDouble
, вы можете удалить аргумент max.Мне везде не хватает комментариев, поэтому я пока не могу задать свои вопросы. Так что это очень простой игрок, чтобы выиграть у первого бота.
[Редактировать] Спасибо, теперь предыдущий статус больше не соответствует действительности, но я думаю, что лучше сохранить его, чтобы мы могли понять контекст этого бота.
Оппортунист часто посещает тот же оружейный клуб, что и GunClubPlayers, однако он поспорил с новичком, что он может победить каждого GunClubPlayers. Поэтому он использует привычку, которую давно заметил, и заставляет себя не стрелять, а лишь немного подождать, чтобы победить.
источник
Новейшие изменения:
Улучшены случайные числа (спасибо Frenzy Li).
источник
getAmmoOpponent
не такgetOpponentAmmo
. Вы также пропускаете#endif // !__BARRICADE_PLAYER_HPP__
Обратите внимание, что это отслеживает информацию о противниках в соответствии с правилами вызова; см. ниже метод «синглтон в стиле Мейерса» с ограничением объема «хранится ()». (Некоторые люди задавались вопросом, как это сделать; теперь вы знаете!)
источник
В
GunClubPlayer
ы хотел бы пойти в клуб ружья. Во время каждой дуэли они сначала загружали патроны, затем стреляли пулями и повторяли этот процесс до концамировойдуэли. На самом деле им все равно, выиграют они или нет, и они сосредоточены исключительно на том, чтобы получить приятный опыт сами.источник
источник
источник
Этот бот не особенно хорош - однако, каждому KOTH нужны некоторые начальные записи, чтобы запустить его :)
Локальное тестирование показало, что это выигрывает против обоих
GunClubPlayer
иOpportunist
100% времени.BotRobotPlayer
Казалось, битва против всегда приводила к ничьей, поскольку оба прячутся за щитами.источник
Я не пишу код на C ++, поэтому любые улучшения кода будут приветствоваться.
источник
DeceptivePlayer
, это лучшее имя?HanSoloPlayer
Стреляет первым! Все еще работаю над его пересмотром, но это довольно хорошо.
источник
источник
#endif // ! __CAMTO_HPP__
<>&
это боль.using namespace std
потому что это мешает турниру. Если вы хотите отладить, вы можете использоватьstd::cout
и т.д.источник
... потому что я хотел бы посмотреть, как ранжируется случайный игрок.
источник
SpecificPlayer
SpecificPlayer следует простому плану выбора некоторых случайных (допустимых) действий. Однако его главная особенность заключается в том, что он следит за определенными ситуациями, анализируя количество боеприпасов и предыдущий ход противника.
Я впервые пишу что-нибудь на C ++, и впервые пытаюсь написать что-нибудь конкурентное для ботов. Поэтому я надеюсь, что моя скудная попытка, по крайней мере, сделает что-то интересное :)
источник
NotSoPatientPlayer
источник