Турнір епопеї скелі, паперу, ножиць, ящірок, спок


98

Найсвіжіша таблиця лідерів @ 2014-08-02 12:00

| Pos # | Author               | Name                    | Language   | Score | Win   | Draw  | Loss  | Avg. Dec. Time |
+-------+----------------------+-------------------------+------------+-------+-------+-------+-------+----------------+
| 1st   | Emil                 | Pony                    | Python2    | 064   | 064   | 000   | 005   | 0026.87 ms     |
| 2nd   | Roy van Rijn         | Gazzr                   | Java       | 062   | 062   | 001   | 006   | 0067.30 ms     |
| 2nd   | Emil                 | Dienstag                | Python2    | 062   | 062   | 001   | 006   | 0022.19 ms     |
| 4th   | ovenror              | TobiasFuenke            | Python2    | 061   | 061   | 001   | 007   | 0026.89 ms     |
| 5th   | PhiNotPi             | BayesianBot             | Perl       | 060   | 060   | 000   | 009   | 0009.27 ms     |
| 6th   | Claudiu              | SuperMarkov             | Python2    | 058   | 058   | 001   | 010   | 0026.77 ms     |
| 7th   | histocrat            | Alternator              | Ruby       | 057   | 057   | 001   | 011   | 0038.53 ms     |
| 8th   | histocrat            | LeonardShelby           | Ruby       | 053   | 053   | 000   | 016   | 0038.55 ms     |
| 9th   | Stretch Maniac       | SmarterBot              | Java       | 051   | 051   | 002   | 016   | 0070.02 ms     |
| 9th   | Martin Büttner       | Markov                  | Ruby       | 051   | 051   | 003   | 015   | 0038.45 ms     |
| 11th  | histocrat            | BartBot                 | Ruby       | 049   | 049   | 001   | 019   | 0038.54 ms     |
| 11th  | kaine                | ExcitingishBot          | Java       | 049   | 049   | 001   | 019   | 0065.87 ms     |
| 13th  | Thaylon              | UniformBot              | Ruby       | 047   | 047   | 001   | 021   | 0038.61 ms     |
| 14th  | Carlos Martinez      | EasyGame                | Java       | 046   | 046   | 002   | 021   | 0066.44 ms     |
| 15th  | Stretch Maniac       | SmartBot                | Java       | 045   | 045   | 001   | 023   | 0068.65 ms     |
| 16th  | Docopoper            | RoboticOboeBotOboeTuner | Python2    | 044   | 044   | 000   | 025   | 0156.55 ms     |
| 17th  | Qwix                 | Analyst                 | Java       | 043   | 043   | 001   | 025   | 0069.06 ms     |
| 18th  | histocrat            | Analogizer              | Ruby       | 042   | 042   | 000   | 027   | 0038.58 ms     |
| 18th  | Thaylon              | Naan                    | Ruby       | 042   | 042   | 004   | 023   | 0038.48 ms     |
| 20th  | Thaylon              | NitPicker               | Ruby       | 041   | 041   | 000   | 028   | 0046.21 ms     |
| 20th  | bitpwner             | AlgorithmBot            | Python2    | 041   | 041   | 001   | 027   | 0025.34 ms     |
| 22nd  | histocrat            | WereVulcan              | Ruby       | 040   | 040   | 003   | 026   | 0038.41 ms     |
| 22nd  | Ourous               | QQ                      | Cobra      | 040   | 040   | 003   | 026   | 0089.33 ms     |
| 24th  | Stranjyr             | RelaxedBot              | Python2    | 039   | 039   | 001   | 029   | 0025.40 ms     |
| 25th  | JoshDM               | SelfLoathingBot         | Java       | 038   | 038   | 001   | 030   | 0068.75 ms     |
| 25th  | Ourous               | Q                       | Cobra      | 038   | 038   | 001   | 030   | 0094.04 ms     |
| 25th  | Ourous               | DejaQ                   | Cobra      | 038   | 038   | 001   | 030   | 0078.31 ms     |
| 28th  | Luis Mars            | Botzinga                | Java       | 037   | 037   | 002   | 030   | 0066.36 ms     |
| 29th  | kaine                | BoringBot               | Java       | 035   | 035   | 000   | 034   | 0066.16 ms     |
| 29th  | Docopoper            | OboeBeater              | Python2    | 035   | 035   | 002   | 032   | 0021.92 ms     |
| 29th  | Thaylon              | NaanViolence            | Ruby       | 035   | 035   | 003   | 031   | 0038.46 ms     |
| 32nd  | Martin Büttner       | SlowLizard              | Ruby       | 034   | 034   | 004   | 031   | 0038.32 ms     |
| 33rd  | Kyle Kanos           | ViolentBot              | Python3    | 033   | 033   | 001   | 035   | 0032.42 ms     |
| 34th  | HuddleWolf           | HuddleWolfTheConqueror  | .NET       | 032   | 032   | 001   | 036   | 0029.86 ms     |
| 34th  | Milo                 | DogeBotv2               | Java       | 032   | 032   | 000   | 037   | 0066.74 ms     |
| 34th  | Timmy                | DynamicBot              | Python3    | 032   | 032   | 001   | 036   | 0036.81 ms     |
| 34th  | mccannf              | YAARBot                 | JS         | 032   | 032   | 002   | 035   | 0100.12 ms     |
| 38th  | Stranjyr             | ToddlerProof            | Java       | 031   | 031   | 010   | 028   | 0066.10 ms     |
| 38th  | NonFunctional User2..| IHaveNoIdeaWhatImDoing  | Lisp       | 031   | 031   | 002   | 036   | 0036.26 ms     |
| 38th  | john smith           | RAMBOBot                | PHP        | 031   | 031   | 002   | 036   | 0014.53 ms     |
| 41st  | EoinC                | SimpleRandomBot         | .NET       | 030   | 030   | 005   | 034   | 0015.68 ms     |
| 41st  | Martin Büttner       | FairBot                 | Ruby       | 030   | 030   | 006   | 033   | 0038.23 ms     |
| 41st  | Docopoper            | OboeOboeBeater          | Python2    | 030   | 030   | 006   | 033   | 0021.93 ms     |
| 44th  | undergroundmonorail  | TheGamblersBrother      | Python2    | 029   | 029   | 000   | 040   | 0025.55 ms     |
| 45th  | DrJPepper            | MonadBot                | Haskel     | 028   | 028   | 002   | 039   | 0008.23 ms     |
| 46th  | Josef E.             | OneBehind               | Java       | 027   | 027   | 007   | 035   | 0065.87 ms     |
| 47th  | Ourous               | GitGudBot               | Cobra      | 025   | 025   | 001   | 043   | 0053.35 ms     |
| 48th  | ProgramFOX           | Echo                    | .NET       | 024   | 024   | 004   | 041   | 0014.81 ms     |
| 48th  | JoshDM               | SelfHatingBot           | Java       | 024   | 024   | 005   | 040   | 0068.88 ms     |
| 48th  | Trimsty              | Herpetologist           | Python3    | 024   | 024   | 002   | 043   | 0036.93 ms     |
| 51st  | Milo                 | DogeBot                 | Java       | 022   | 022   | 001   | 046   | 0067.86 ms     |
| 51st  | William Barbosa      | StarWarsFan             | Ruby       | 022   | 022   | 002   | 045   | 0038.48 ms     |
| 51st  | Martin Büttner       | ConservativeBot         | Ruby       | 022   | 022   | 001   | 046   | 0038.25 ms     |
| 51st  | killmous             | MAWBRBot                | Perl       | 022   | 022   | 000   | 047   | 0016.30 ms     |
| 55th  | Mikey Mouse          | LizardsRule             | .NET       | 020   | 020   | 007   | 042   | 0015.10 ms     |
| 55th  | ja72                 | BlindForesight          | .NET       | 020   | 020   | 001   | 048   | 0024.05 ms     |
| 57th  | robotik              | Evolver                 | Lua        | 019   | 019   | 001   | 049   | 0008.19 ms     |
| 58th  | Kyle Kanos           | LexicographicBot        | Python3    | 018   | 018   | 003   | 048   | 0036.93 ms     |
| 58th  | William Barbosa      | BarneyStinson           | Lua        | 018   | 018   | 005   | 046   | 0005.11 ms     |
| 60th  | Dr R Dizzle          | BartSimpson             | Ruby       | 017   | 017   | 001   | 051   | 0038.22 ms     |
| 60th  | jmite                | IocainePowder           | Ruby       | 017   | 017   | 003   | 049   | 0038.50 ms     |
| 60th  | ArcticanAudio        | SpockOrRock             | PHP        | 017   | 017   | 001   | 051   | 0014.19 ms     |
| 60th  | Dr R Dizzle          | BetterLisaSimpson       | Ruby       | 017   | 017   | 000   | 052   | 0038.23 ms     |
| 64th  | Dr R Dizzle          | LisaSimpson             | Ruby       | 016   | 016   | 002   | 051   | 0038.29 ms     |
| 65th  | Martin Büttner       | Vulcan                  | Ruby       | 015   | 015   | 001   | 053   | 0038.26 ms     |
| 65th  | Dr R Dizzle          | Khaleesi                | Ruby       | 015   | 015   | 005   | 049   | 0038.29 ms     |
| 67th  | Dr R Dizzle          | EdwardScissorHands      | Ruby       | 014   | 014   | 002   | 053   | 0038.21 ms     |
| 67th  | undergroundmonorail  | TheGambler              | Python2    | 014   | 014   | 002   | 053   | 0025.47 ms     |
| 69th  | cipher               | LemmingBot              | Python2    | 011   | 011   | 002   | 056   | 0025.29 ms     |
| 70th  | Docopoper            | ConcessionBot           | Python2    | 007   | 007   | 000   | 062   | 0141.31 ms     |
+-------+----------------------+-------------------------+------------+-------+-------+-------+-------+----------------+
Total Players: 70
Total Matches Completed: 2415
Total Tourney Time: 06:00:51.6877573

Примітки до турніру

  • WOO HOO 70 BOTS
  • Еміль досі є КОТЕМ, Ponyа його новий бот Dienstagпосідає 3 місце
  • Вітаю Роя за те, що зі своїм Gazzrботом схопився на 2 місце
  • Вільям Барбоса виграє нагороду Quick Draw за свого ботаBarneyStinson
  • І Slow Poke нагорода вручається Docopoper за його боти R.O.B.O.Tі Concessionbotякі обидва були> 140мса в руку

  • Доступні журнали @ https://github.com/eoincampbell/big-bang-game/blob/master/tourneys/Tournament-2014-08-01-23-24-00.zip?raw=true

Виключені боти

  • BashRocksBot - все ще не радіє сценаріям .net execing cygwin bash
  • CounterPreferenceBot - очікування виправлення помилок
  • RandomlyWeighted - очікування виправлення помилок
  • CasinoShakespeare - виключається, оскільки він вимагає активного підключення до Інтернету

Оригінальне розміщене запитання

Ви заїхали до свого будинку друзів для найепічнішого розстрілу Battle of Rock, паперу, ножиць, ящірок, Спока. У справжньому стилі ботаніків BigBang жоден з гравців не грає сам, але створив консольні боти, щоб грати від їх імені. Ви виймаєте свій USB-ключ і передаєте його Шельдору Завойовнику для включення у розборку . Пенні хитається. Або, можливо, Говард хитається. Ми не судимо тут у квартирі Леонарда.

Правила

Застосовуються стандартні правила скелі, паперу, ножиць, ящірок, спок.

  • Ножицями вирізати папір
  • Папір охоплює Рок
  • Скеля дробить Ящірку
  • Ящі ящірки Спок
  • Спок розбиває Ножиці
  • Ножиці обезголовляють Ящірку
  • Ящірка їсть Папір
  • Папір спростовує Спок
  • Спок випаровує Скелю
  • Скеля дробить Ножиці

Правила RPSLV

Бот кожного гравця буде грати один матч проти одного бота в турнірі.

Кожен матч буде складатися з 100 ітерацій гри RPSLV.

Після кожного матчу переможцем стає гравець, який виграв найбільшу кількість ігор / рук зі 100.

Якщо ви виграєте матч, вам буде призначено 1 бал у таблиці ліги. В результаті розіграшу жоден гравець не набере очка.

Вимоги до бота

Ваш бот повинен бути запущений з командного рядка.

Коробка * nix Sheldor померла, тому ми запускаємо його з його ноутбука Windows 8 Gaming, тому переконайтеся, що пропоноване рішення може працювати на Windows. Шелдор люб’язно запропонував встановити будь-які необхідні умови виконання (в межах причини), щоб мати змогу запустити ваше рішення. (.NET, Java, Php, Python, Ruby, Powershell ...)

Вхідні дані

У першій грі кожного матчу вашому боту не подаються аргументи. У кожній наступній грі кожного матчу: - Arg1 буде містити історію рук / рішень ваших ботів у цьому матчі. - Arg2 міститиме історію рук / рішень ваших опонентів у цьому матчі.

Історія буде представлена ​​послідовністю одиничних великих літер, що представляють можливі руки, в які можна грати.

 | R | Rock     |
 | P | Paper    |
 | S | Scissors |
 | L | Lizard   |
 | V | Spock    |

Напр

  • Гра 1: MyBot.exe
  • Гра 2: MyBot.exe SV
  • Гра 3: MyBot.exe SS VL
  • Гра 4: MyBot.exe SSR VLS

Вихідні дані

Ваш бот повинен написати відповідь одного персонажа, що представляє його "руку" для кожної гри. Результат слід записати в STDOUT, а потім бот повинен вийти. Дійсні великі літери нижче.

 | R | Rock     |
 | P | Paper    |
 | S | Scissors |
 | L | Lizard   |
 | V | Spock    |

У випадку, коли ваш бот не поверне дійсну руку (тобто 1 з вищезгаданих 5 великих прописних літер, ви автоматично втрачаєте цю руку, і збіг триває.

У тому випадку, коли обидва боти не повертають дійсну руку, гра вважається нічиєю і матч продовжується.

Формат відповідності

Кожен представлений бот зіграє один матч проти одного бота на турнірі.

Кожен матч триватиме рівно 100 ігор.

Матчі будуть грати анонімно, ви не будете володіти передовими знаннями про конкретного бота, проти якого ви граєте, проте ви можете використовувати будь-яку та всю інформацію, яку ви зможете отримати від прийняття рішень протягом історії поточного матчу, щоб змінити свою стратегію проти своєї опонент. Ви також можете відстежувати історію попередніх ігор, щоб створити візерунки / евристику тощо ... (Див. Правила нижче)

Під час однієї гри механізм оркестрації запустить вашого бота та ваших супротивників ботом на відстані 100 мілісекунд, а потім порівняє результати, щоб уникнути будь-яких зіткнень PRNG на тій же мові / час виконання. (це насправді трапилось зі мною під час тестування).

Судження та обмеження

Доктор Шелдон Купер під виглядом Шельдора Завойовника ласкаво запропонував наглядати за ходом турніру. Шелдор Завойовник - справедливий і просто наглядач (в основному). Усі рішення Шелдора є остаточними.

Ігри будуть проводитись справедливо та належним чином:

  • Ваш бот-скрипт / програма буде зберігатися в механізмі оркестрації під підтеками Players\[YourBotName]\
  • Ви можете використовувати підпапку Players\[YourBotName]\dataдля реєстрації будь-яких даних або історії ігор з поточного турніру під час його проходження. Каталоги даних будуть очищені на початку кожного турнірного циклу.
  • Ви не можете отримати доступ до каталогу гравців іншого гравця турніру
  • Ваш бот не може мати конкретний код, який спрямований на іншу поведінку ботів
  • Кожен гравець може подати більше одного бота, щоб грати до тих пір, поки вони не взаємодіють і не допомагають один одному.

Редагувати - додаткові обмеження

  • Щодо втрат, вони не підтримуватимуться. Ваш бот повинен грати в одну з 5 дійсних рук. Я перевіряю кожного бота за межами турніру з деякими випадковими даними, щоб переконатися, що вони ведуть себе. Будь-які боти, які викидають помилки (тобто помилки помилки), будуть виключені з турніру, поки вони не будуть виправлені.
  • Боти можуть бути похідними до тих пір, поки вони лаконічно відрізняються своєю поведінкою. Боти (в тому числі іншими мовами), які виконують абсолютно таку саму поведінку, як і існуючий бот, будуть дискваліфіковані
  • Вже є спам-боти для наступного, тому, будь ласка, не надсилайте їх знову
    • Рок - BartSimpson
    • Папір - LisaSimpson
    • Ножиця - EdwardScissorhands
    • Спок - Вулкан
    • Ящірка - Халесі
    • Псевдо випадкові - SimpleRandomBot & FairBot
    • Psuedo Random RPS - ConservativeBot
    • Psuedo Random LV - Барні Стінсон
  • Боти можуть не звертатись до сторонніх служб чи веб-ресурсів (або чогось іншого, що значно сповільнює швидкість / час прийняття рішень у матчах). CasinoShakespeareє єдиним винятком, оскільки цей бот був поданий до додавання цього обмеження.

Шелдор буде оновлювати це питання настільки часто, наскільки це можливо, з результатами турніру, оскільки подається більше ботів.

Оркестровка / програма контролю

Програма оркестрації разом із вихідним кодом кожного бота доступна на github.

https://github.com/eoincampbell/big-bang-game

Деталі подання

Ваше подання має включати

  • Ім'я вашого бота
  • Ваш Код
  • Команда до
    • виконати свого бота з оболонки, наприклад
    • ruby myBot.rb
    • python3 myBot.py
    • АБО
    • спочатку компілюйте обидва, а потім виконайте це. напр
    • csc.exe MyBot.cs
    • MyBot.exe

Подання зразка

BotName: SimpleRandomBot
Compile: "C:\Program Files (x86)\MSBuild\12.0\Bin\csc.exe" SimpleRandomBot.cs
Run:     SimpleRandomBot [Arg1] [Arg2]

Код:

using System;
public class SimpleRandomBot
{
    public static void Main(string[] args)
    {
        var s = new[] { "R", "P", "S", "L", "V" };
        if (args.Length == 0)
        {
            Console.WriteLine("V"); //always start with spock
            return;
        }
        char[] myPreviousPlays = args[0].ToCharArray();
        char[] oppPreviousPlays = args[1].ToCharArray();
        Random r = new Random();
        int next = r.Next(0, 5);
        Console.WriteLine(s[next]);
    }
}

Уточнення

Будь-які питання, задайте у коментарях нижче.


7
Як виглядає історія, коли гравець втратив руку?
гістократ

1
Я збирався пройти все з аналітичним підходом, але більшість ботів тут досить дурні, щоб перемогти розумний ШІ.
пухнастий

1
Тільки тому, що я ніколи не веду за будь- який виклик KotH, в якому я змагався, я взяв знімок екрана як спогад.
Кайл Канос

3
Я проведу ще один турнір сьогодні ввечері і опублікую повні результати матчу на пастібіні ... Наступна партія матиме близько 450 ігор, але слід трохи швидше запустити, оскільки я реалізував деякі матеріали паралелізації в контрольній прозі
Eoin Campbell

3
Якщо я не помиляюся, в сценарії оркестрації здається серйозна помилка: Історії гравців 1 і 2 завжди передаються ботам як перший і другий аргумент відповідно, тоді як згідно з правилами, боти завжди повинні отримувати свої Перша власна історія. Зараз гравець 2 ефективно намагається перемогти себе. (Мені стало трохи підозріло, тому що мій бот вигравав кожен матч, де він був гравцем 1, а програвав половину інших матчів.)
Еміль

Відповіді:


26

Поні (Python 2)

Це засновано на боті-ножиці-бумазі-ножиці, про який я писав деякий час тому для виклику програмування в кінці онлайн-класу Udacity . Я змінив його, щоб включити Спока і ящірку і вніс деякі вдосконалення.

У програмі 11 різних простих стратегій, кожна з яких має 5 варіантів. Серед них він вибирається, виходячи з того, наскільки добре вони б виступали за останні раунди.

Я усунув резервну стратегію, яка просто грала випадковим чином проти сильніших опонентів. Я здогадуюсь, як це веселіше.

import sys

# just play Spock for the first two rounds
if len(sys.argv)<2 or len(sys.argv[1])<2: print 'V'; sys.exit()

# initialize and translate moves to numbers for better handling:
my_moves, opp_moves = sys.argv[1], sys.argv[2]
moves = ('R', 'P', 'S', 'V', 'L')   
history = zip([moves.index(i) for i in my_moves],
              [moves.index(i) for i in opp_moves])

# predict possible next moves based on history
def prediction(hist):
    N = len(hist)    

    # find longest match of the preceding moves in the earlier history
    cand_m = cand_o = cand_b = range(N-1)
    for l in xrange(1,min(N, 20)):
        ref = hist[N-l]
        cand_m = ([c for c in cand_m if c>=l and hist[c-l+1][0]==ref[0]]
                  or cand_m[-1:])
        cand_o = ([c for c in cand_o if c>=l and hist[c-l+1][1]==ref[1]]
                  or cand_o[-1:])
        cand_b = ([c for c in cand_b if c>=l and hist[c-l+1]==ref]
                  or cand_b[-1:])

    # analyze which moves were used how often
    freq_m, freq_o = [0]*5, [0]*5
    for m in hist:
        freq_m[m[0]] += 1
        freq_o[m[1]] += 1

    # return predictions
    return ([hist[-i][p] for i in 1,2 for p in 0,1]+   # repeat last moves
            [hist[cand_m[-1]+1][0],     # history matching of my own moves
             hist[cand_o[-1]+1][1],     # history matching of opponent's moves
             hist[cand_b[-1]+1][0],     # history matching of both
             hist[cand_b[-1]+1][1],
             freq_m.index(max(freq_m)), # my most frequent move
             freq_o.index(max(freq_o)), # opponent's most frequent move
             0])                        # good old rock (and friends)


# what would have been predicted in the last rounds?
pred_hist = [prediction(history[:i]) for i in xrange(2,len(history)+1)]

# how would the different predictions have scored?
n_pred = len(pred_hist[0])
scores = [[0]*5 for i in xrange(n_pred)]
for pred, real in zip(pred_hist[:-1], history[2:]):
    for i in xrange(n_pred):
        scores[i][(real[1]-pred[i]+1)%5] += 1
        scores[i][(real[1]-pred[i]+3)%5] += 1
        scores[i][(real[1]-pred[i]+2)%5] -= 1
        scores[i][(real[1]-pred[i]+4)%5] -= 1

# return best counter move
best_scores = [list(max(enumerate(s), key=lambda x: x[1])) for s in scores]
best_scores[-1][1] *= 1.001   # bias towards the simplest strategy    
if best_scores[-1][1]<0.4*len(history): best_scores[-1][1] *= 1.4
strat, (shift, score) = max(enumerate(best_scores), key=lambda x: x[1][1])
print moves[(pred_hist[-1][strat]+shift)%5]

Виконувати як:

python Pony.py

Редагувати : Я вніс невелику зміну, вніс ухил у бік найпростішої стратегії (тобто завжди грав однаковий хід) у невпевнених випадках. Це трохи допомагає не намагатися знаходити надмірно складні зразки там, де таких немає, наприклад у таких роботах, як ConservativeBot.

Примітка . Я спробував пояснити основну стратегію узгодження історії, яку цей бот використовує у публікації для мого іншого бота Dienstag .


3
96-відсотковий коефіцієнт виграшу є видатним
AndoDaan

Дуже хороша. Можливо, вам сподобається йокаїнова пудра , якщо ви її ще не бачили.
wchargin

@WChargin, звичайно. :) Коли я писав свій оригінальний код, я кілька років раніше читав про порошок Іокаїн і смутно згадував загальну ідею. Отже, Поні справді надихається цим, якщо не дуже безпосередньо. Як виявляється, вони дуже схожі. Я думаю, що у мого є більш широкий репертуар стратегій, в той час як йокаїновий порошок має розумний рівень мета-мета-міркувань, які я не включав.
Еміль

20

Марков, Рубі

Переглядає два останніх ходи опонента і визначає можливі (і, швидше за все,) подальші дії. Якщо комбінацію не вибирали раніше, він просто використовує всі ходи суперника (поки що). Потім він збирає всі можливі відповіді на них і підбирає випадкову.

responses = {
  'R' => ['P', 'V'],
  'P' => ['S', 'L'],
  'S' => ['R', 'V'],
  'L' => ['S', 'R'],
  'V' => ['P', 'L']
}

if ARGV.length == 0 || (history = ARGV[1]).length < 3
    choices = ['R','P','S','L','V']
else
    markov = Hash.new []
    history.chars.each_cons(3) { |chars| markov[chars[0..1].join] += [chars[2]] }

    choices = []
    likely_moves = markov.key?(history[-2,2]) ? markov[history[-2,2]] : history.chars
    likely_moves.each { |move| choices += responses[move] }
end

puts choices.sample

Бігай, як

markov.rb

А потім я використовую цю програму, щоб визначити найбільш можливий крок, який я зроблю далі, а потім з’ясувати, що ви будете робити, і, нарешті, знайти спосіб перемогти те, що ви будете робити, і нескінченно крутити всю справу знову і знову.
Джеймі

@Jamie Ви маєте на увазі, як цей хлопець? codegolf.stackexchange.com/a/35295/8478
Мартін Ендер

ти вгадаєш. (коментар був недостатньо довгим для розміщення)
Джеймі

19

КонсервативнийБот, Рубі

Нові речі - це погані речі.

puts ['R','P','S'].sample

Бігай, як

ruby conservative.rb

OG версія - найкраща версія.
maxywb

13

Фанат "Зоряних воєн" - Рубі

Накручуй тебе, Спок

puts ['R','P','L','S'].sample

Виконайте це так:

ruby starwarsfan.rb

Додано до контролера
Еойн Кемпбелл

Ви можете відкатати, відредагувавши відповідь - я просто прокоментую тут, коли я їх додав.
Еойн Кемпбелл

Чому R і S? : P
cjfaure

@mardavi Це фанат "Зоряних воєн", оскільки він не використовує Спока.
Вільям Барбоса

ах, ти маєш рацію (звичайно). Я прочитав це занадто швидко, моя помилка (але без наслідків на щастя)
mardavi

13

Барні Стінсон - Луа

Я маю лише одне правило: Нове завжди краще. Накрутіть старого Джо Кен По або як би ви його не назвали.

math.randomseed(os.time())
print(math.random() > 0.5 and "V" or "L")

Виконайте це так:

lua legenwaitforitdary.lua

8

Нудний бот (Java)

Він припускає, що всі завжди грають одне і те ж і планують відповідно. Зазвичай він підбирає скелі в краватках, хоча так всі інші правильно?

public class BoringBot
{
    public static void main(String[] args)
    {
        int Rock=0;
        int Paper=0;
        int Scissors=0;
        int Lizard=0;
        int Spock=0;

        if (args.length == 0)
        {
            System.out.print("P");
            return;
        }

        char[] oppPreviousPlays = args[1].toCharArray();

        for (int j=0; j<oppPreviousPlays.length; j++) {
            switch(oppPreviousPlays[j]){
                case 'R': Rock++; break;
                case 'P': Paper++; break;
                case 'S': Scissors++; break;
                case 'L': Lizard++; break;
                case 'V': Spock++;
            }
        }

        int Best = Math.max(Math.max(Lizard+Scissors-Spock-Paper,
                                     Rock+Spock-Lizard-Scissors),
                            Math.max(Math.max(Paper+Lizard-Spock-Rock,
                                              Paper+Spock-Rock-Scissors),
                                     Rock+Scissors-Paper-Lizard));

        if (Best== Lizard+Scissors-Spock-Paper){
            System.out.print("R"); return;
        } else if (Best== Rock+Spock-Lizard-Scissors){
            System.out.print("P"); return;
        } else if (Best== Paper+Lizard-Spock-Rock){
            System.out.print("S"); return;
        } else if(Best== Paper+Spock-Rock-Scissors){
            System.out.print("L"); return;
        } else {
            System.out.print("V"); return;
        }
    }
}

Зауважте, якщо це стратегія, яку вже використовує хтось, дайте мені знати, і я видалю. Це просто відчуває себе очевидним, якого я ще не бачив.
каїн

це C #. ви. властивості довжини неправильні. і немає методуmax
Еойн Кемпбелл

@EoinCampbell Це Java, я грав із обома і, мабуть, забув, до яких команд належать.
kaine

ах круто. залиште це зі мною, і я додам його.
Еойн Кемпбелл

досі зламаний. працює jre8 - java BoringBot.java - Помилка: не вдалося знайти або завантажити основний клас D: \ My Software Dev \ big-bang-game \ BigBang.Orchestrator \ bin \ Debug \ Players \ BoringBot \ BoringBot.java -
Eoin Campbell

8

IocainePowder, Ruby

введіть тут опис зображення

Виходячи з (безсоромно викраденої) стратегії РПС тут . Бот виглядає, вибирає здогадку, ідентичну боту Маркова, але потім припускає, що противник здогадався, що він вибере, і вибирає хід, щоб перемогти його відповідно.

Зауважте, що я щойно адаптував основну ідею пов'язаної стратегії, не дотримувався її докладно.

responses = {
  'R' => ['P', 'V'],
  'P' => ['S', 'L'],
  'S' => ['R', 'V'],
  'L' => ['S', 'R'],
  'V' => ['P', 'L']
}

if ARGV.length == 0 || (history = ARGV[1]).length < 3
    choices = ['R','P','S','L','V']
else
    markov = Hash.new []
    history.chars.each_cons(3) { |chars| markov[chars[0..1].join] += [chars[2]] }

    choices = []
    likely_moves = markov.key?(history[-2,2]) ? markov[history[-2,2]] : history.chars
    likely_moves.each { |move| choices += responses[move] }
end

myChoice = choices.sample 
theirChoice = responses[myChoice].sample
actualChoice = responses[theirChoice].sample
puts actualChoice

Бігай, як

iocaine.rb

5
Ви продовжуєте використовувати це слово. Я не думаю, що це означає, що ти думаєш, що це означає.
JoshDM

2
Справжня сила порошку Іокаїну полягала в тому, щоб перемикатися між використанням маркова і биття-маркова. Він починається як розумний марків, але як тільки він відчуває (починає програвати), переходить у режим побиття-маркова. Слід легко додати.
Рой ван Рійн

Ах, розумний! Не брешу, я лише чув, як Іокаїн описував мені, насправді не переглядав це докладно. Не соромтесь змінювати мій код, якщо ви хочете або подайте свій власний та отримайте кредит!
jmite

8

HuddleWolfTheConqueror - C #

HuddleWolf повернувся і краще, ніж будь-коли. Він переможе Шелдора Завойовника у власній грішній грі. HuddleWolf досить розумний для виявлення та протидії спамерським роботам. Для більш розумних супротивників HuddleWolf використовує свої знання про основні статистичні дані 5-го класу та використовує зважений рулон з кістки на основі історії опозиції.

using System;
using System.Collections.Generic;
using System.Linq;

public class HuddleWolfTheConqueror
{

    public static readonly char[] s = new[] { 'R', 'P', 'S', 'L', 'V' };

    public static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine(pickRandom());
            return;
        }

        char[] myPlays = args[0].ToCharArray();
        char[] oppPlays = args[1].ToCharArray();

        char tryPredict = canPredictCounter(oppPlays);
        if (tryPredict != '^')
        {
            Console.WriteLine(tryPredict);
        }
        else
        {
            Console.WriteLine(pickRandom());
        }
        return;
    }


    public static char canPredictCounter(char[] history)
    {
        // don't predict if insufficient data
        if (history.Length < 5)
        {
            return '^';
        }

        // calculate probability of win for each choice
        Dictionary<char, double> dic = getBestProabability(history);

        // get item with highest probability of win
        List<char> maxVals = new List<char>();
        char maxVal = '^';
        double mostFreq = 0;
        foreach (var kvp in dic)
        {
            if (kvp.Value > mostFreq)
            {
                mostFreq = kvp.Value;
            }
        }
        foreach (var kvp in dic)
        {
            if (kvp.Value == mostFreq)
            {
                maxVals.Add(kvp.Key);
            }
        }

        // return error
        if (maxVals.Count == 0)
        {
            return maxVal;
        }

        // if distribution is not uniform, play best play
        if (maxVals.Count <= 3)
        {
            Random r = new Random(Environment.TickCount);
            return maxVals[r.Next(0, maxVals.Count)];
        }

        // if probability is close to uniform, use weighted dice roll
        if (maxVals.Count == 4)
        {
            return weightedRandom(dic);
        }

        // if probability is uniform, use random dice roll
        if (maxVals.Count >= 5)
        {
            return pickRandom();
        }

        // return error
        return '^';
    }

    public static Dictionary<char, double> getBestProabability(char[] history)
    {
        Dictionary<char, double> dic = new Dictionary<char, double>();
        foreach (char c in s)
        {
            dic.Add(c, 0);
        }
        foreach (char c in history)
        {
            if (dic.ContainsKey(c))
            {
                switch(c)
                {
                    case 'R' : 
                        dic['P'] += (1.0/(double)history.Length);
                        dic['V'] += (1.0/(double)history.Length);
                        break;
                    case 'P' : 
                        dic['S'] += (1.0/(double)history.Length);
                        dic['L'] += (1.0/(double)history.Length);
                        break;
                    case 'S' : 
                        dic['V'] += (1.0/(double)history.Length);
                        dic['R'] += (1.0/(double)history.Length);
                        break;
                    case 'L' : 
                        dic['R'] += (1.0/(double)history.Length);
                        dic['S'] += (1.0/(double)history.Length);
                        break;
                    case 'V' : 
                        dic['L'] += (1.0/(double)history.Length);
                        dic['P'] += (1.0/(double)history.Length);
                        break;
                    default : 
                        break;

                }
            }
        }
        return dic;
    }

    public static char weightedRandom(Dictionary<char, double> dic)
    {
        Random r = new Random(Environment.TickCount);
        int next = r.Next(0, 100);
        int curVal = 0;
        foreach (var kvp in dic)
        {
            curVal += (int)(kvp.Value*100);
            if (curVal > next)
            {
                return kvp.Key;
            }
        }
        return '^';
    }

    public static char pickRandom()
    {
        Random r = new Random(Environment.TickCount);
        int next = r.Next(0, 5);
        return s[next];
    }
}

8

ToddlerProof

Цей досить дурний бот припускає, що він грає малюка, який буде "ганяти" за його ходом, завжди намагаючись перемогти те, що було останньо кинуто. Якщо бота бити кілька разів поспіль, він перестрибує до нової точки в шаблоні. Він заснований на моїй стратегії завжди побивати мого значно молодшого брата. :)

EDIT :: Змінено довжину смуги втрат, необхідної для стрибків у випадкові кидки. Виправлено також основну помилку випадковим стрибком.

Збережіть як ToddlerProof.java, компілюйте та запустіть ізjava ToddlerProof [me] [them]

import java.util.HashMap;
public class ToddlerProof
{
    char[] moves = new char[]{'R', 'P', 'S', 'L', 'V'};
    public static void main(String[] args)
    {
        if(args.length<1) //first Round
        {
            System.out.print('V');//Spock is best
            return;
        }
        else
        {
            String them = args[1];
            String me = args[0];
            int streak = 0;

            HashMap<Character, Character> nextMove = new HashMap<Character, Character>();
            //Next move beats things that beat my last move
            nextMove.put('L', 'V');
            nextMove.put('V', 'S');
            nextMove.put('S', 'P');
            nextMove.put('P', 'R');
            nextMove.put('R', 'L');
            //Check if last round was a tie or the opponent beat me
            int lastResult = winner(me.charAt(me.length()-1), them.charAt(them.length()-1));
            if(lastResult == 0)
            {
                //tie, so they will chase my last throw
                System.out.print(nextMove.get(me.charAt(me.length()-1)));

                return;
            }
            else if(lastResult == 1)
            {
                //I won, so they will chase my last throw
                System.out.print(nextMove.get(me.charAt(me.length()-1)));


                return;
            }

            else{
                //I lost
                //find streak
                for(int i = 0; i<me.length(); i++)
                {
                    int a = winner(me.charAt(i), them.charAt(i));
                    if(a >= 0) streak = 0;
                    else streak++;
                }
                //check lossStreak
                //If the streak is 2, then a rotation will make it even.
                //if it is >2, something bad has happened and I need to adjust.
                if(streak>2)
                {
                    //if they are on to me, do something random-ish
                    int r = (((them.length()+me.length()-1)*13)/7)%4;
                    System.out.print(move[r]);
                    return;
                }
                //otherwise, go on with the plan
                System.out.print(nextMove.get(me.charAt(me.length()-1)));
                return;
            }
        }
    }
    public static int winner(char me, char them)
    {
        //check for tie
        if(me == them) return 0;
        //check if they won
        if(me=='V' && (them == 'L' || them == 'P')) return -1;
        if(me=='S' && (them == 'V' || them == 'R')) return -1;
        if(me=='P' && (them == 'S' || them == 'L')) return -1;
        if(me=='R' && (them == 'P' || them == 'V')) return -1;
        if(me=='L' && (them == 'R' || them == 'S')) return -1;
        //otherwise, I won
        return 1;
    }
}

1
Чи повинні ми використовувати print або println? ... Я не був впевнений.
kaine

Хммм. Я б міг уявити, що обоє спрацюють, але я міг бачити, як println псується, якби програма управління захоплювала новий рядок замість символу. Дякую, що
вказали

@Stranjyr в останньому запуску було помилок. Це не бомбило програму управління, але якщо ви шукаєте історію для "ToddlerProof грає n", схоже, ваш бот повертав нуль для певних рук, а потім автоматично вимикав руку. Приклад гри - "Echo & ToddlerProof", де Echo грав у "LVSPRLV", перш ніж ваш бот почав лайнути.
Еойн Кемпбелл

@Eion Кемпбелл Дякую, що згадуєш про це. Я бачив це раніше, коли ви розміщували журнали з невдалого турніру, і, думаю, це я виправив. Він зіткнувся з помилкою, якщо, якщо він втратив більше 5 прямих, замість того, щоб перейти до випадкової гри, він просто кинув недійсне значення. А потім, оскільки це змусило його втратити, воно кинуло ще одне недійсне значення. Порочний цикл.
Stranjyr

Класно. Поновіть його зараз у контрольній програмі.
Еойн Кемпбелл

8

Барт Сімпсон

"Старий добрий рок! Нічого не б'є рок!"

puts 'R'

Виконати як

ruby DoTheBartman.rb

Ліза Сімпсон

"Бідний, передбачуваний Барт. Завжди вибирає рок".

puts 'P'

Виконати як

ruby LisaSimpson.rb

Краще Ліза Сімпсон

Мені стало погано робити Лізу зовсім такою дурною, тому я дозволив їй випадковим чином вибрати одну з рук, які будуть бити рок. Ще дурна, але вона - Сімпсон. Може, олівець застряг у її мозку?

puts ['P','V'].sample

Виконати як

ruby BetterLisaSimpson.rb


@ MartinBüttner Блін, цього не помітив. Програми все ще здаються різними справами - і, принаймні, Ліза тут може відчувати себе більш досконалою, перемігши дві різні версії свого брата.
Д-р R Dizzle

1
Шелдор погоджується ... там будуть BartBot та BartSimpson :)
Еойн Кемпбелл

3
У нас є лише BortBot.
JoshDM

1
Ці будуть забиті марковом :)
Cruncher

7

Відлуння

Написано на C #. Компілювати з csc Echo.cs. Бігай, як Echo.exe ARG1 ARG2.

Під час першого запуску Echo приймає випадковий варіант. Кожен пробіг після першого, Echo просто повторює останні дії суперника.

using System;

namespace Echo
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Random r = new Random();
                string[] options = new string[] { "R", "P", "S", "L", "V" };
                Console.WriteLine(options[r.Next(0, options.Length)]);
            }
            else if (args.Length == 2)
            {
                string opponentHistory = args[1];
                Console.WriteLine(opponentHistory[opponentHistory.Length - 1]);
            }
        }
    }
}

7

Вулкан, Рубі

Мої пальці склеєні.

puts 'V'

Бігай, як

ruby vulcan.rb

(Я думаю, що це єдина стратегія для символів для вашого фонового налаштування.)


Потрібно озирнутися на епізоди, щоб побачити, чи хтось народився з роздвоєним язиком. LizardMan FTW !!!
Еойн Кемпбелл

3
Але хіба не так грають всі на великому чутку?
kaine

2
@anotherguest Ось що я мав на увазі під «цією єдиною стратегією в характері».
Мартін Ендер

6

Тиранозавр, Годзілла, Барні ... Правило ящірок. Іноді вони потрапляють у біду та потребують виклику Спока чи кидання скелі

using System;
public class LizardsRule
{
    public static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine("L");
            return;
        }
        char[] oppPreviousPlays = args[1].ToCharArray();
        var oppLen = oppPreviousPlays.Length;
        if (oppPreviousPlays.Length > 2
            && oppPreviousPlays[oppLen - 1] == 'R'
            && oppPreviousPlays[oppLen - 2] == 'R'
            && oppPreviousPlays[oppLen - 3] == 'R')
        {
            //It's an avalance, someone call Spock
            Console.WriteLine("V");
            return;
        }

        if (oppPreviousPlays.Length > 2
                && oppPreviousPlays[oppLen - 1] == 'S'
                && oppPreviousPlays[oppLen - 2] == 'S'
                && oppPreviousPlays[oppLen - 3] == 'S')
        {
            //Scissors, Drop your tail and pick up a rock
            Console.WriteLine("R");
            return;
        }

        //Unleash the Fury Godzilla
        Console.WriteLine("L");     
    }
}

6

BayesianBot, Perl (зараз v2!)

Перш за все, це унікальна програма. У ній ви побачите блискучий злиття статистики та жахливу форму програмування. Також цей бот, ймовірно, порушує багато правил байєсівської статистики, але назва звучить крутіше.

Основна суть цього бота - це створення 250 різних прогнозних моделей. Кожна модель має форму "З огляду на те, що я грав у рок останнього ходу і мій опонент грав ножицями два обороти тому, це розподіл ймовірностей для наступного кроку мого опонента". Кожне розподіл ймовірностей має форму багатовимірного розподілу Діріхле.

Кожен поворот прогнози всіх застосованих моделей (як правило, 10) множать разом, щоб сформувати загальний прогноз, який потім використовується для визначення того, які кроки мають найбільший очікуваний окуп.

Редагувати 1: У цій версії я змінив попередній розподіл і зробив бота більш рандомізованим, коли він програє.

Є кілька речей, які можуть зазнати вдосконалення, такі як кількість моделей (250 - це лише 3-значний номер), вибір попереднього розповсюдження (на даний момент Dir (3,3,3,3,3)) та метод сплавлення прогнозів. Крім того, я ніколи не переймався нормалізацією будь-якого розподілу ймовірностей, що на сьогодні добре, тому що я їх множу.

Я не маю надвисоких очікувань, але сподіваюся, що цей бот зможе зробити добре.

my ($phist, $ohist) = @ARGV;

my %text2num = ('R',0,'V',1,'P',2,'L',3,'S',4);  #the RVPLS ordering is superior
my @num2text = ('R','V','P','L','S');

@phist = map($text2num{$_},split(//,$phist));
@ohist = map($text2num{$_},split(//,$ohist));

$lowerlimit = 0;
for($lowerlimit..~~@phist-3){$curloc=$_;
 $result = $ohist[$curloc+2];
 @moveset = ($ohist[$curloc],$ohist[$curloc+1],$phist[$curloc],$phist[$curloc+1]);
 for(0..3){$a=$_;
  for(0..$a){$b=$_;
   $predict[$a][$b][$moveset[$a]][$moveset[$b]][$result]++;
  }
 }
}

@recentmoves = ($ohist[-2],$ohist[-1],$phist[-2],$phist[-1]);

@curpred = (1,1,1,1,1);

for(0..3){$a=$_;
 for(0..$a){$b=$_;
  for(0..4){$move=$_;
   $curpred[$move] *= $predict[$a][$b][$recentmoves[$a]][$recentmoves[$b]][$move]/3+1;
  }
 }
}

@bestmove = (0,0,0,0,0);
for(0..4){
 $bestmove[$_] = $curpred[$_]/2+$curpred[$_-1]+$curpred[$_-2];
}

$max = 0;
for(0..4){
 if($bestmove[$_]>$max){
  $max = $bestmove[$_];
 }
}
@options=();
$offset=0;
if(($ohist[-1] - $phist[-1])%5 < 2 && ($ohist[-2] - $phist[-2])%5 < 2 && ($ohist[-3] - $phist[-3])%5 < 2){  #frequentist alert!
 $offset=int(rand(3));
}
for(0..4){
 if($bestmove[$_] == $max){
  push(@options,$num2text[($_+$offset)%5]);
 }
}
$outputb = $options[int(rand(~~@options))];

print "$outputb";

Я запускав цю програму так:

perl BayesianBot.plx

5

DynamicBot

Динамічний бот майже завжди змінюється. Це справді ненавидить повторюватися

import sys, random
choices = ['L','V','S','P','R'] * 20
if len(sys.argv) > 1:
    my_history = sys.argv[1]
    [choices.remove(my_history[-1]) for i in range(15)]
print(choices[random.randrange(len(choices))])

Мова: Python 3.4.1

Команда: python dynamicbot.py <history>або python3 dynamicbot.py <history>залежно від вашої системи


Так, подумав про це.
seequ

5

SmartBot - Java

Моя перша в історії публікація на цьому сайті!

Хоча це не дуже креативне ім’я ...

SmartBot знаходить послідовності рухів, коли ходи опонента та / або самого себе подібні до останніх зроблених кроків і планують відповідно.

name = SmartBot

Я думаю запустити це, виправте мене, якщо я помиляюся.

java -jar SmartBot.jar

import java.util.ArrayList;
public class SmartBot {
    public static void main(String[] args) {
        if(args.length ==0){
            System.out.print("L");
            return;
        }
        if(args[0].length()<3){
            String[] randLetter = new String[]{"R","P","S","L","V"};
            System.out.print(randLetter[(int) Math.floor(Math.random()*5)]);
            return;
        }
        String myHistory = args[0];
        String otherHistory = args[1];

        double rScore,pScore,sScore,lScore,vScore;//score - highest = highest probability of next opponent move
        rScore = pScore = sScore = lScore = vScore = 0;
        lScore = .001;
        ArrayList<ArrayList<Integer>> moveHits = new ArrayList<ArrayList<Integer>>();
        for(int g = 0;g<2;g++){
            for(int i=1;i<(myHistory.length() / 2) + 1;i++){
                if(g==0){
                    moveHits.add(findAll(myHistory.substring(myHistory.length() - i),myHistory));
                }
                else{
                    moveHits.add(findAll(otherHistory.substring(otherHistory.length() - i),otherHistory));
                }
            }
            for(int i = 0; i < moveHits.size();i++){
                int matchingMoves = i+1;
                ArrayList<Integer> moveIndexes = moveHits.get(i);
                for(Integer index:moveIndexes){
                    if(index+matchingMoves +1<= otherHistory.length()){
                        char nextMove = otherHistory.charAt(index + matchingMoves-1);
                        if(nextMove=='R'){rScore = rScore + matchingMoves;}
                        if(nextMove=='P'){pScore = pScore + matchingMoves;}
                        if(nextMove=='S'){sScore = sScore + matchingMoves;}
                        if(nextMove=='L'){lScore = lScore + matchingMoves;}
                        if(nextMove=='V'){vScore = vScore + matchingMoves;}
                    }
                }
            }
        }
        if(rScore >= pScore && rScore >= sScore && rScore >= lScore && rScore >= vScore){
            System.out.print("V");
            return;
        }
        if(pScore >= rScore && pScore >= sScore && pScore >= lScore && pScore >= vScore){
            System.out.print("L");
            return;
        }
        if(sScore >= pScore && sScore >= rScore && sScore >= lScore && sScore >= vScore){
            System.out.print("R");
            return;
        }
        if(vScore >= pScore && vScore >= sScore && vScore >= lScore && vScore >= rScore){
            System.out.print("L");
            return;
        }
        if(lScore >= pScore && lScore >= sScore && lScore >= rScore && lScore >= vScore){
            System.out.print("S");
        }
        return;
    }
    public static ArrayList<Integer> findAll(String substring,String realString){
        ArrayList<Integer> ocurrences = new ArrayList<Integer>();
        Integer index = realString.indexOf(substring);
        if(index==-1){return ocurrences;}
        ocurrences.add(index+1);
        while(index!=-1){
            index = realString.indexOf(substring,index + 1);
            if(index!=-1){
                ocurrences.add(index+1);
            }
        }
        return ocurrences;
    }
}

Він призначає бал за кожен можливий наступний хід, скільки разів подібні зразки траплялися.

Це трохи сприяє ящірці.


Я вважаю, що так ви запускаєте його, якщо спершу покладіть його. Якщо ви просто скомпілюєте його спочатку, тоді java ABotслід попрацювати (не забудьте назвати файл таким же, як і загальнодоступний клас)
Джастін

Дякую! Як відносно новий програміст, я цього не знав.
Maniac Stretch

5

SpockOrRock - PHP

SpockOrRock

Граючи в реальному світі, більшість людей інстинктивно вибирають ножиці. Цей бот вибирає Спок або Рок, щоб перемогти середнього гравця. Це не турбується про попередні раунди.

бігати з php spockorrock.php

<?php

//Pick either Spock or Rock
if (rand(0,1) == 0)     echo("R\n");
else                    echo("V\n");


?>

4

SlowLizard, Рубі

Починаючи з Ящірки, він завжди вибирає випадковий хід, який б'є попередній хід противника.

responses = {
  'R' => ['P', 'V'],
  'P' => ['S', 'L'],
  'S' => ['R', 'V'],
  'L' => ['S', 'R'],
  'V' => ['P', 'L']
}

if ARGV.length == 0
  puts 'L'
else
  puts responses[ARGV[1][-1]].sample
end

Бігай, як

ruby slowlizard.rb

4

Лексикографічний бот

Цей бот любить замовляти свої листи, тому він обере відповідь, яка на 1 вищу, ніж його опонент дав у попередньому раунді - якщо опонент не вибрав Вулкана, то він випадково вибирає відповідь.

import sys
import random

choices = ["L", "P", "R", "S", "V"]

total = len(sys.argv)
if total==1:
    print("L")
    sys.exit()

opponent = sys.argv[2]
opponent_last = opponent[-1]

if opponent_last == choices[-1]:
    print(random.choice(choices))
else:
    next = choices.index(opponent_last)+1
    print(choices[next])

Це очікує, що рука суперника буде видана друга:

                           me
                            v
python LexicographicBot.py SR RV
                              ^
                            opponent

@ MartinBüttner: Команда додана! Я був досить зайнятий на роботі, намагаючись опублікувати щось, отже, зникнення.
Кайл Канос

перерви на перший пробіг без аргументів. Traceback (останній дзвінок останній): файл "LexicographicBot \ LexicographicBot.py", рядок 10, в <module> противник = sys.argv [2] IndexError: список індексів поза діапазоном
Eoin Campbell

@EoinCampbell: Я забув вихідний пункт під час першого запуску, він доданий і повинен працювати нормально зараз.
Кайл Канос

4

Веревулкан - Рубі

Виконати як ruby werevulcan.rb

@rules = {

  'L' => %w[V P],
  'P' => %w[V R],
  'R' => %w[L S],
  'S' => %w[P L],
  'V' => %w[R S]
}

@moves = @rules.keys

def defeats?(move1, move2)
  @rules[move1].include?(move2)
end

def score(move1, move2)
  if move1 == move2
    0
  elsif defeats?(move1, move2)
    1
  else
    -1
  end
end

def move
  player, opponent = ARGV

  # For the first 30 rounds, pick a random move that isn't Spock
  if player.to_s.size < 30
    %w[L P R S].sample
  elsif opponent.chars.to_a.uniq.size < 5
    exploit(opponent)
  else
    # Pick a random move that's biased toward Spock and against lizards
    %w[L P P R R S S V V V].sample
  end

end

def exploit(opponent)
  @moves.shuffle.max_by{ |m| opponent.chars.map{|o| score(m,o) }.reduce(:+) }
end

puts move

Днями варвулкан виглядає нормально, але коли Місяць піднімається, його вуха стають точковими, а його ходи стають більш логічними.


4

Аналізатор - Ruby

Бігайте з ruby analogizer.rb. Я зробив логічне виправлення коду, але не маю поняття, чому з цим виникли помилки.

@rules = {

  'L' => %w[V P],
  'P' => %w[V R],
  'R' => %w[L S],
  'S' => %w[P L],
  'V' => %w[R S]
}

@moves = @rules.keys

def defeats?(move1, move2)
  @rules[move1].include?(move2)
end

def score(move1, move2)
  if move1 == move2
    0
  elsif defeats?(move1, move2)
    1
  else
    -1
  end
end

def move
  player, opponent = ARGV

  case player.to_s.size
  # Throw six lizards in the beginning to confuse opponent
  when 0..5
    'L'
  when 6
    'V'
  when 7
    'S'
  when 8
    'P'
  when 9
    'R'
  else
    analyze_history(player.chars.to_a, opponent.chars.to_a)
  end

end

def analyze_history(player, opponent)
  my_last_move = player.last
  predicted_moves = Hash.new {0}
  opponent_reactions = player.zip(opponent.drop(1))

  # Check whether opponent tended to make a move that would've beaten, lost, or tied my last move
  opponent_reactions.each do |my_move, reaction|
    score = score(reaction, my_move)
    analogous_moves = @moves.select { |move| score == score(move, my_last_move) }
    analogous_moves.each { |move| predicted_moves[move] += 1 }
  end

  # Assume if an opponent has never made a certain move, it never will
  @moves.each { |m| predicted_moves[m] = 0 unless opponent.include?(m) }

  # Pick the move with the best score against opponent's possible moves, weighted by their likelihood, picking randomly for ties
  @moves.shuffle.max_by{ |m| predicted_moves.map { |predicted, freq| score(m, predicted) * freq }.reduce(0,:+) }

end

puts move

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

За винятком того, що перші десять рухів жорстко кодуються: спочатку я роблю вигляд, що знаю лише ящірку, а потім припускаю, що противник завжди кидає щось, щоб бити останнє, що я кинув, поки у мене не вистачить даних для належного аналізу.


4

Java - SelfLoathingBot

BotName: SelfLoathingBot
Compile: Save as 'SelfLoathingBot.java'; compile.
Run:     java SelfLoathingBot [me] [them]

Бот починається випадковим чином, тоді ~ 33%, щоб вийти випадковим чином, або ~ 33%, щоб грати виграшну тактику проти будь-якої з безпосередньо попередніх ігор, з 50% вибором тактики виграшу.

import java.util.Random;

public class SelfLoathingBot {

    static final Random RANDOM = new Random();

    private static char randomPlay() {

        switch (RANDOM.nextInt(5)) {

            case 0 : return 'R';

            case 1 : return 'P';

            case 2 : return 'S';

            case 3 : return 'L';

            default : return 'V';
        }
    }

    private static char antiPlay(String priorPlayString) {

        char[] priorPlays = priorPlayString.toCharArray();

        int choice = RANDOM.nextInt(2);

        switch (priorPlays[priorPlays.length - 1]) {

            case 'R' : return choice == 0 ? 'P' : 'V'; 

            case 'P' : return choice == 0 ? 'S' : 'L';

            case 'S' : return choice == 0 ? 'V' : 'R';

            case 'L' : return choice == 0 ? 'R' : 'S';

            default : return choice == 0 ? 'L' : 'P'; // V        
        }
    }

    public static void main(String[] args) {

        int choice = args.length == 0 ? 0 : RANDOM.nextInt(3);

        char play;

        switch (choice) {

            case 1 :

                // 33.3% chance Play myself
                play = antiPlay(args[0]);
                break;

            case 2 :

                // 33.3% chance Play opponent just in case opponent is screwy like that
                play = antiPlay(args[1]);
                break;

            default :

                // 33.3% chance 100% Random
                play = randomPlay();
        }

        System.out.print(play);
        return;
    }
}

4

Аналітик

Аналітик аналізує деякі речі і робить деякі речі, щоб спробувати побити вас.

компілювати javac Analyst.javaі запускати якjava Analyst

import java.util.Random;

public class Analyst{
    public static void main(String[] args){
        char action = 'S';

        try{
            char[] enemyMoves = null, myMoves = null;

            //first move is random
            if(args.length == 0){
                System.out.print(randomMove());
                System.exit(0);
            //moves 2-3 will beat their last move
            }else if(args[0].length() < 8){
                System.out.print(counterFor(args[1].charAt(args[1].length()-1)));
                System.exit(0);
            //following moves will execute some analyzation stuff
            }else{
                //get previous moves
                myMoves = args[0].toCharArray();
                enemyMoves = args[1].toCharArray();
            }

            //test if they're trying to beat our last move
            if(beats(enemyMoves[enemyMoves.length-1], myMoves[myMoves.length-2])){
                action = counterFor(counterFor(myMoves[myMoves.length-1]));
            }
            //test if they're copying our last move
            else if(enemyMoves[enemyMoves.length-1] == myMoves[myMoves.length-2]){
                action = counterFor(myMoves[myMoves.length-1]);
            }
            //else beat whatever they've done the most of
            else{
                action = counterFor(countMost(enemyMoves));
            }

            //if they've beaten us for the first 40 moves, do the opposite of what ive been doing
            if(theyreSmarter(myMoves, enemyMoves)){
                action = counterFor(action);
            }

        //if you break my program do something random
        }catch (Exception e){
            action = randomMove();
        }

        System.out.print(action);
    }

    private static char randomMove(){
        Random rand = new Random(System.currentTimeMillis());
        int randomMove = rand.nextInt(5);

        switch (randomMove){
            case 0: return 'R';
            case 1: return 'P';
            case 2: return 'S';
            case 3: return 'L';
            default: return 'V';
        }
    }

    private static char counterFor(char move){
        Random rand = new Random(System.currentTimeMillis());
        int moveSet = rand.nextInt(2);

        if(moveSet == 0){
            switch (move){
                case 'R': return 'P'; 
                case 'P': return 'S'; 
                case 'S': return 'R'; 
                case 'L': return 'R'; 
                default: return 'P';
            }
        }else{
            switch (move){
                case 'R': return 'V'; 
                case 'P': return 'L'; 
                case 'S': return 'V'; 
                case 'L': return 'S'; 
                default: return 'L';
            }
        }
    }

    private static boolean beats(char move1, char move2){
        if(move1 == 'R'){
            if((move2 == 'S') || (move2 == 'L')){
                return true;
            }else{
                return false;
            }
        }else if(move1 == 'P'){
            if((move2 == 'R') || (move2 == 'V')){
                return true;
            }else{
                return false;
            }
        }else if(move1 == 'S'){
            if((move2 == 'L') || (move2 == 'P')){
                return true;
            }else{
                return false;
            }
        }else if(move1 == 'L'){
            if((move2 == 'P') || (move2 == 'V')){
                return true;
            }else{
                return false;
            }
        }else{
            if((move2 == 'R') || (move2 == 'S')){
                return true;
            }else{
                return false;
            }
        }
    }

    private static char countMost(char[] moves){
        int[] enemyMoveList = {0,0,0,0,0};

        for(int i=0; i<moves.length; i++){
            if(moves[i] == 'R'){
                enemyMoveList[0]++;
            }else if(moves[i] == 'P'){
                enemyMoveList[1]++;
            }else if(moves[i] == 'S'){
                enemyMoveList[2]++;
            }else if(moves[i] == 'L'){
                enemyMoveList[3]++;
            }else if(moves[i] == 'V'){
                enemyMoveList[4]++;
            }
        }

        int max = 0, maxIndex = 0;
        for(int i=0; i<5; i++){
            if(enemyMoveList[i] > max){
                max = enemyMoveList[i];
                maxIndex = i;
            }
        }

        switch (maxIndex){
            case 0: return 'R';
            case 1: return 'P';
            case 2: return 'S';
            case 3: return 'L';
            default: return 'V';
        }
    }

    private static boolean theyreSmarter(char[] myMoves, char[] enemyMoves){
        int loseCounter = 0;

        if(enemyMoves.length >= 40){
            for(int i=0; i<40; i++){
                if(beats(enemyMoves[i],myMoves[i])){
                    loseCounter++;
                }
            }
        }else{
            return false;
        }

        if(loseCounter > 20){
            return true;
        }else{
            return false;
        }
    }
}

4

Азартний гравець - Python 2

import sys
import random

MODE = 1

moves = 'RSLPV'

def element_sums(a, b):
    return [a[i] + b[i] for i in xrange(len(a))]

def move_scores(p):
    def calc(to_beat):
        return ['LDW'.find('DLLWW'[moves.find(m)-moves.find(to_beat)]) for m in moves]

    return dict(zip(moves, element_sums(calc(p[0]), calc(p[1]))))

def move_chooser(my_history, opponent_history):
    predict = sorted(moves, key=opponent_history.count, reverse=MODE)[-2:]
    scores = move_scores(predict)
    return max(scores, key=lambda k:scores[k])

if __name__ == '__main__':
    if len(sys.argv) == 3:
        print move_chooser(*sys.argv[1:])
    elif len(sys.argv) == 1:
        print random.choice(moves)

Всупереч назви, випадкова випадковість, яка використовується в цій програмі, - це перший тур, коли немає інформації. Натомість вона названа за хибність азартних гравців, переконання, що якщо випадкова подія траплялася рідше в минулому, це швидше відбудеться в майбутньому. Наприклад, якщо 20 разів перевернути справедливу монету, а перші 15 - голови, помилка азартного гравця стверджує, що шанси, що залишилися, перевертаючи хвости, збільшуються. Звичайно, це неправда; Незалежно від попередніх обертів, шанси на отримання монети, що піднімаються, завжди становлять 50%.

Ця програма аналізує історію супротивника, виявляє 2 ходи, які він використовував щонайменше, і припускає, що рух цього супротивника цього разу буде одним із цих двох. Призначаючи 2 до виграшу, 1 до нічиї та 0 до програшу, він знаходить хід з максимальним балом проти цих двох передбачуваних кроків і кидає це.

Брат азартного гравця - Python 2

import sys
import random

MODE = 0

moves = 'RSLPV'

def element_sums(a, b):
    return [a[i] + b[i] for i in xrange(len(a))]

def move_scores(p):
    def calc(to_beat):
        return ['LDW'.find('DLLWW'[moves.find(m)-moves.find(to_beat)]) for m in moves]

    return dict(zip(moves, element_sums(calc(p[0]), calc(p[1]))))

def move_chooser(my_history, opponent_history):
    predict = sorted(moves, key=opponent_history.count, reverse=MODE)[-2:]
    scores = move_scores(predict)
    return max(scores, key=lambda k:scores[k])

if __name__ == '__main__':
    if len(sys.argv) == 3:
        print move_chooser(*sys.argv[1:])
    elif len(sys.argv) == 1:
        print random.choice(moves)

Перемикаючи MODEзмінну на 0, ця програма працюватиме на основі пов'язаної помилки, яку також іноді називають помилкою гравця. У ньому йдеться про те, що якщо випадкова подія траплялася частіше в минулому, то це швидше відбудеться в майбутньому. Наприклад, якщо ви перевернете монету 20 разів, а перші 15 - голови, ця помилка стверджує, що решта фліп, швидше за все, будуть головами, оскільки зараз існує смуга. У режимі 0 ця програма діє так само, за винятком того, що вона передбачає, що опонент кине один з двох ходів, які він кидає найчастіше досі.

Так так, ці дві програми розділені лише одним символом. :)


За якої умови TheGambler змінює РЕЖИМ?
Д-р Р Дізл

@DrRDizzle Це не так, схоже, це подання двох ботів в одну.
Paŭlo Ebermann

2
Чи не була б ця програма ефективнішою, якби MODE переключився, якщо ви втрачаєте більше певної кількості разів поспіль?
Д-р Р Дізл

4

Діенстаг (Python 2)

Моє перше входження Поні, здається, добре справляється з усіма його другими здогадами (потрійне здогадування, ...) та мета-міркуваннями. Але це навіть потрібно?

Отже, ось Дінстаг, маленький друг Поні, який має лише одну з 55 стратегій: передбачте наступний хід суперника і переможете його.

Зрештою, Dienstag виграє або пов'язаний з кожним Ботом у першій десятці поточного лідеру. За винятком Поні, який є.

import sys
if len(sys.argv)<2 or len(sys.argv[1])<2: print 'L'; sys.exit()
hist = [map('RPSVL'.index, p) for p in zip(sys.argv[1], sys.argv[2])]
N = len(hist)
cand = range(N-1)
for l in xrange(1,N):
    cand = ([c for c in cand if c>=l and hist[c-l+1]==hist[-l]] or cand[-1:])
print 'RPSVL'[(hist[cand[-1]+1][1]+(1,3)[N%2==0])%5]

Виконувати як:

python Dienstag.py

Я визнаю, що код трохи затуманений. Якщо хтось хоче пізнати більше про це, я можу додати пояснення.

Редагувати: Ось короткий приклад для пояснення ідеї:

  • Програма отримує власну історію та ходи опонента:

    sys.arg[1] = 'LLVLLVL', sys.arg[2] = 'RPSPSSP'

  • Історія об'єднується в список пар, а ходи переводяться на числа (R = 0, ...):

    hist = [[4, 0], [4, 1], [3, 2], [4, 1], [4, 2], [3, 2], [4, 1]]

  • Кількість відіграних раундів досі визначається:

    N = 7

  • Основна ідея зараз - шукати найдовший неперерваний ланцюг саме останніх кроків у попередній історії. Програма відстежує, де такий ланцюжок закінчується у списку cand(для «кандидатів»). На початку, не перевіряючи, вважається кожна позиція в історії, крім останньої:

    cand = [0, 1, 2, 3, 4, 5]

  • Тепер довжина можливих ланцюгів збільшується поетапно. Для довжини ланцюга l = 1він шукає попередні випадки останньої пари переміщення [4, 1]. Це можна знайти на сторінці історії 1та 3. У candсписку зберігаються лише такі :

    cand = [1, 3]

  • Далі, l = 2він перевіряє, кому з можливих кандидатів передувала друга, яка востаннє рухається [3, 2]. Це стосується лише посади 3:

    cand = [3]

  • Бо l = 3і більше немає попередніх ланцюжків такої довжини, і вони candбули б порожніми. У цьому випадку candзберігається останній елемент :

    cand = [3]

  • Тепер бот припускає, що історія повториться. Останній раз Cain [3, 2], [4, 1]стався, за ним слід [4, 2]. Отже, суперник грав 2(ножиці), який може бути побитий (2+1)%5 = 3(Спок) або (2+3)%5 = 0(скеля). Бот відповідає, першою або другою альтернативою, залежно від того N, непарно чи навіть просто ввести певну дисперсію.

  • Тут 3вибирається хід , який потім перекладається назад:

    print 'V'

Примітка: Dienstag має часову складність O ( N 2 ) для повернення наступного кроку після N раундів. Поні має часову складність O ( N 3 ). Тож у цьому аспекті вони, ймовірно, набагато гірші, ніж у більшості інших записів.


будь ласка. це дивовижний досвід навчання для мене. Я зазвичай живу на землі C # / Java, тому для мене дуже цікаво все божевілля луа, рубін, пітон, хескелл .
Еойн Кемпбелл

Я також спокусився додати додатковий екземпляр Pony до ігор. Це буде як би боротися зі своїм дзеркальним самоврядом у третьому до останнього рівнях смертного бою ;-)
Еойн Кемпбелл

@EoinCampbell :-) Принаймні прямий матч Поні проти Поні був би ідеальною нічиєю. В обох моїх ботах немає елемента випадковості.
Еміль

3

Баш-Скелі

Чи занадто багато цигуна, щоб задати його під час виконання?

bashrocks.sh:

#!/bin/bash
HAND=(R P S L V)
RAND=`od -A n -t d -N 1 /dev/urandom | xargs`
echo ${HAND[ $RAND  % 5 ]}

і запустити його так:

sh bashrocks.sh

5
Прочитавши заголовок, я трохи розчарований, що ви все робите, окрім R. ;)
Мартін Ендер

@mccannf. У мене є деякі проблеми з цим ... Я встановив cygwin і змінив ваші сценарії повністю кваліфікованими шляхами до C: \ Cygwin \ bin для od.exe, xargs.exe & echo.exe. як і раніше отримує наступну помилку. C: / Cygwin / bin / xargs: echo: Немає такого файлу чи каталогу% 5 ") помилка синтаксису: очікується операнд (маркер помилки"
Eoin Campbell

@EoinCampbell - коли ви створюєте файл у Windows, чи можете ви потім запустити dos2unixфайл у cygwin перед його виконанням?
mccannf

впевнений. Я спробую.
Еойн Кемпбелл

Я думаю, що проблема може бути з заявою / dev / urandom
Eoin Campbell

3

Алгоритм

Алгоритм для того, щоб мати його.

Тому що завжди безпечніше щось робити, чим складніше, тим краще.

Ще не зробили серйозної математики, тому цей алгоритм може бути не таким ефективним.

import random, sys

if __name__ == '__main__':

    # Graph in adjacency matrix here
    graph = {"S":"PL", "P":"VR", "R":"LS", "L":"VP", "V":"SR"}
    try:
        myHistory = sys.argv[1]
        opHistory = sys.argv[2]
        choices = ""

        # Insert some graph stuff here. Newer versions may include advanced Math.
        for v in graph:
            if opHistory[-1] == v:
                for u in graph:
                    if u in graph[v]:
                        choices += graph[u]

        print random.choice(choices + opHistory[-1])

    except:
        print random.choice("RPSLV")

Програма Python 2: python algorithm.py


1
Короткий зміст цього алгоритму: подивіться, що противник востаннє грав, а потім випадковим чином відіграйте один із двох ходів, які втратили б проти останнього ходу опонента, якби вони зіграли його знову. Тож краще проти ботів, які не грають один і той же рух двічі поспіль.
Rory O'Kane

Ха-ха. Я не знаю, чи зробив це так. Якщо я не помиляюся, це насправді просто звичний спосіб випадкового вибору будь-якого з 5 ходів. ;)
Векторизований

3

FairBot, Ruby

Почнемо з простого.

puts ['R','P','S','L','V'].sample

Бігай, як

ruby fairbot.rb

маленький друкарський помилок на останньому параметрі "V". виправили це на мій погляд, якщо ви хочете оновити для повноти
Еойн Кемпбелл,

@EoinCampbell дякую, виправлено!
Мартін Ендер

1
Цікавим є той факт, що це рівнозначні шанси на виграш проти ВСІХ стратегій.
Cruncher

3

ViolentBot

Цей бот обирає найжорстокіший варіант на основі попереднього вибору опонентів:

import sys

choice_dict = {"L" : "S", "P" : "S", "R" : "V", "S" : "V", "V" : "L"}

total = len(sys.argv)
if total==1:
    print("L")
    sys.exit()

opponent = sys.argv[2]
opponent_last = opponent[-1]

print(choice_dict[opponent_last])

Виконати як

python ViolentBot.py (me) (opp)

перерви без парам. Traceback (останній дзвінок останній): файл "ViolentBot \ ViolentBot.py", рядок 9, в <module> противник = sys.argv [2] IndexError: список індексів поза діапазоном
Eoin Кемпбелл

перерви з парами. Traceback (останній дзвінок останній): файл "ViolentBot \ ViolentBot.py", рядок 12, у <module> друку (вибір_ виробу [противника_ласт]) KeyError: 'S'
Eoin Кемпбелл

@EoinCampbell: Я додав застереження про вихід для першого запуску, ви повинні мати змогу запустити його зараз.
Кайл Канос

3

Haskell - MonadBot

Я не знаю, чи вважається ghc "в межах розуму", але давайте припустимо, що це так. Стратегія цього бота - протидія найпопулярнішим крокам опонента.

Compile: ghc monadbot.hs
Run:     ./monadbot [Arg1] [Arg2]

Код:

import System.Environment
import Data.List
import Data.Ord

main :: IO ()
main = do
  args <- getArgs
  let moves = if not (null args) then args !! 1 else ""
      fave = if not (null moves) then head $ maximumBy (comparing length) (group $ sort moves) else 'V'
  putChar $ case fave of 'R' -> 'P'
                         'P' -> 'S'
                         'S' -> 'R'
                         'L' -> 'R'
                         'V' -> 'P'
                         _   -> 'V'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.