Остаточний самурайський розбор


37

Примітка. Цю проблему завершено. Це означає, що зелена галочка, яку було присвоєно C5H8NNaO4 за їх запис Спостерігач не буде переміщено до жодної нової відповіді.

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

Вступ

У цьому виклику ви граєте в аркадну гру під назвою The Ultimate Samurai Showdown Ultimate Edition Спеціальна версія 2.0 X Alpha Omega Turbo (або просто Ultimate Samurai Showdown ). Ваші опоненти? Ніхто інший, як інші члени програми Puzzle Puzzle & Code Golf!

Як ви могли очікувати від аркадної гри PPCG, ви не граєте в Ultimate Samurai Showdown безпосередньо, а скоріше пишете програму, яка буде грати для вас. Ця програма буде боротися з програмами, поданими іншими користувачами в поєдинках один на один. Найбільш кваліфікована програма буде коронована Остаточним Самураєм PPCG та отримає зелений галочок легенди.

Опис гри

Цей розділ описує механіку гри.

Стан перемоги

Матч складається з двох самураїв , які стикаються один проти одного. Кожен самурай починає кожен матч з 20 очок потрапляння та 1 честі . Самурай виграє, якщо його супротивник мертвий і він ще живий. Є два методи, за допомогою яких самурай може померти:

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

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

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

Дії

На кожному кроці самурай повинен виконати точно одну з наступних дій:

W

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

B

Самурай чесно кланяється своєму опоненту. Це радує богів, і таким чином самурай здобуде 1 честь. Честь є життєво важливою для успіху вашого самурая, тому що Honor - це, по суті, "ресурс" для цієї гри - все рухається осторонь Bі Wможе зменшити честь. Крім того, якщо самурай набирає 7 Честі або більше, йому надається використання Меча Богів . Наслідки цього описані нижче.
Однак поклонитися опоненту залишає вас відкритими, якщо ваш опонент вирішить вдарити вас мечем, тому будьте обережні, коли ви вирішите поклонитися.

G

Самураї вступають в оборонну позицію і охороняють від будь-яких ударів мечем. Цей хід вдало заблокує всі удари мечами, навіть ті, які зроблені з Мечем Богів .
Однак боги нахмурилися надмірно оборонним самураєм, тож цей хід вимагатиме 1 Честі, якщо дія самураїв на попередньому повороті також охороняла. Інакше вона не споживає честі.

I

Самурай намагається завдати удару супротивнику швидким витяганням меча з його ножниці. Якщо у самурая 7 честі або більше, він використовуватиме Меч Богів замість свого звичайного меча. Цей хід витрачає 1 честь.
Швидка нічия - це швидкий страйк, який виграє повільніші атаки, проте програє проти парирів. Якщо удар вдало підключиться, він нанесе 1 збиток, або 2 збитки Мечем Богів .

P

Самурай намагається проаналізувати будь-яку наступну атаку, а потім розпочати власну атаку. Якщо у самурая 7 честі або більше, він використовуватиме Меч Богів замість свого звичайного меча. Цей хід витрачає 1 честь.
Париж - це хороший маневр проти швидких ударів, але він буде подоланий повільнішими нападами. Якщо удар вдало підключиться, він нанесе 1 збиток, або 2 збитки Мечем Богів .

O

Самурай намагається завдати удару свого опонента повільнішою атакою. Якщо у самурая 7 честі або вище, він використовуватиме Меч Богів замість свого звичайного меча. Цей хід витрачає 1 честь.
Ударний удар може перемогти пари, але він втратить проти швидких ударів. Якщо удар вдало підключиться, він нанесе 1 збиток, або 2 збитки Мечем Богів .

Меч Богів

Самурай з честю 7 або більше здобуває можливість використовувати Меч Богів . Якщо його честь знизиться нижче 7, можливість використання Меча Богів буде відкликана у нього. Меч Богів завдає 2 пошкодження замість 1.

Меч Богів не дозволяє удар перемогти мечем удар , що він не буде звичайно поразку. Наприклад, Меч Богів парирується, як і раніше, звичайним ударом під голову, і a швидкий жеребку Меча Богів не переможе звичайний швидкий нічиї. Дійсно, так званий Меч Богів насправді не настільки сильний - можливо, це космічний жарт, який грають боги ...

Таблиця взаємодії

Фрагмент стека нижче містить таблицю, в якій чітко перераховані всі можливі результати різних комбінацій дій, які можуть здійснити два самураї. Щоб переглянути його, натисніть «Показати фрагмент коду», потім натисніть «Запустити фрагмент коду».

Програмна комунікація

Для полегшення проведення турніру була написана програма контролера, яка грала роль «богів» - вона веде облік честі та здоров’я і відповідно побиває самураїв. У цьому розділі описано, як ваша програма буде спілкуватися з програмою контролера.

Опис вводу

Програма контролера викличе вашу програму з командного рядка так:

<command> <history> <enemy_history> <your_health> <enemy_health> <your_honour> <enemy_honour>

де:

  • <command>це команда, необхідна для запуску вашої програми. Наприклад, якщо ваша програма є у файлі super_sentai.pl, ймовірно, команда perl super_sentai.pl.

  • <history>це історія кроків, які ви зробили. Наприклад, WWBPозначає, що ви чекали двічі, кланялися один раз і парирували один раз.

  • <enemy_history>це історія кроків, які зробив ваш ворог. Наприклад, BBBIце означало б, що твій ворог тричі поклонився і здійснив одну швидку нічию.

  • <your_health> це ваше поточне здоров'я.

  • <enemy_health> - сучасне здоров’я ворога.
  • <your_honour> ваша теперішня честь.
  • <enemy_honour> нинішня честь ворога.

Для першого кроку, historyі enemy_historyбуде порожнім, тому ваша програма буде викликана лише чотирма останніми аргументами на кшталт цього:

<command> <your_health> <enemy_health> <your_honour> <enemy_honour>

Будьте готові до цього!

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

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

Опис виходу

Щоб вибрати дію, ваша програма повинна вивести один з W, B, G, I, P, або Oна стандартний висновок, в залежності від того, які дії ви хочете зробити. Якщо ваша програма нічого не видає протягом 1000 мс, вона буде припинена, а програма буде розглядатися так, ніби вона виводитьсяW .

Якщо ваша програма виводить більше однієї літери, вважатиметься лише перша літера - значить, виведення Parryбуде таким же, як і вихіднеP .

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

Формат подання

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

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

Будь ласка, включіть у подання:

  1. Зрозуміла для людини назва вашої програми для використання у табло. Тут дозволені простори; коми та символи Unicode не є.
  2. Мова, якою написана ваша програма. Будь ласка, уникайте писати на чужих, важкодоступних мовах, таких як TinyMUSH.
  3. Короткий конспект вашої програми. Це може бути опис того, як працює програма, або просто якийсь смаковий текст про вашу програму (якщо ви хочете бути всім секретним), або, можливо, і те й інше.
  4. Команда / s, необхідна для запуску вашої програми. Наприклад, якщо ви писали свою заявку в Java під назвою example.java, ви б надали інструкції по компіляції, javac example.javaа потім виконували інструкціїjava example .
  5. Вихідний код програми.

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

Я також надаю два приклади. Незважаючи на те, що приклади будуть брати участь у турнірі, їх головна мета - уточнити формати подання та введення / виведення для турніру, а не бути серйозними претендентами на титул Ultimate Samurai.

Структура турніру

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

Програма контролю

Програма управління написана на Python 2 і її можна знайти в сховищі Ultimate Samurai Showdown Github . Якщо ви хочете запустити його самостійно, інструкції щодо його запуску містяться у файлі README.md за посиланням. Однак лише турніри, які проводяться на моєму комп’ютері, будуть офіційними, щоб уникнути апаратних розбіжностей, що впливають на результати турніру.

Програма управління буде запущена на портативному комп’ютері під управлінням Arch Linux. У нього процесор Intel Core i7 та 8 Гб оперативної пам’яті. Я докладу зусиль, щоб усі записи працювали на моєму комп’ютері, але я дуже вдячний, якщо ви уникаєте мов, до яких не можна отримати доступ вільно (як без грошових витрат).

Система підрахунку балів

Система підрахунку балів - кругла робіна. Кожна програма зіграє вісім матчів проти кожної іншої програми. Виграш надає програмі 1 бал, програш - не очок, і нічия 0,5 бала. Гра виграє програма з найвищим балом. Якщо відбудеться розіграш, я буду поєдинувати дві найкращі програми один проти одного, щоб визначити переможця.

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

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

Дискваліфікація

Можливо, ваша програма буде дискваліфікована з турніру. Дискваліфікація може статися, якщо:

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

Минулі результати

Детальні результати всіх турнірів розміщені на сторінці wiki .

Останній турнір завершився 2015-07-17 07:20. Ось підсумок результатів:

The Observer: 209.0
Coward: 203.0
Monk: 173.0
Elephant Warrior: 157.0
Iniqy: 157.0
Agent 38: 144.0
Ninja: 138.0
Meiyo Senshi: 138.0
Kakashi: 136.0
Yoshimitsu: 131.0
Hermurai: 121.0
Warrior Princess: 120.0
Gargoyle: 119.5
The Honourable: 119.0
Hebi: 118.5
Predictor: 116.0
Whack-a-mole: 107.0
The Fool: 106.0
The Prophet: 105.0
Copy-san: 97.0
YAGMCSE: 80.0
The Waiter: 66.0
Swordsman: 43.0
Spork Holder: 32.5
Blessed Samurai: 27.5
Attacker: 27.0
The Terminator: 17.0
Master Yi: 16.0

1
Офіціант справляється напрочуд добре. Потрібно виграти виграші проти власника Spork, коли у нього закінчується честь.
StephenTG

Це акуратне завдання. Ви чітко вкладаєте в це багато думок і роботи, і я думаю, що це безумовно окупилося. Відмінна робота. :)
Алекс А.

1
@ C5H8NNaO4 Так, я перевірю наявність оновлень для ботів, перш ніж запустити наступний турнір.
абсент

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

1
@Levi Так! Виробник доставив мені заміну, яка надійшла сьогодні. Там, як ми говоримо, проходить турнір.
абсент

Відповіді:


8

Чернець (Java)

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

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

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

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

Компілювати / Запустити

javac Monk.java
java Monk

public class Monk {
    public static void main(String[] args){
        char  r = 'B';
        double  s = Math.random ();
        int n = Math.max (args [0].length ()- 8, 1);
        int p = args.length > 4 ? Integer.parseInt (args [4]):0;
        int l = Integer.parseInt (args [3]);
        int m = Integer.parseInt (args [2]);
        double d = 1 + (20 - m) / n;
        double e = 1 + (20 - l) / n;

        if (((p>8&&s<.7)||l<11||m<2)&&p>0) {
                r=(s<(.14)||d>=2||e/d<.618)?'G':"OPI".charAt((int)(Math.random()*3));
        }

        System.out.print (r);
    }
}

Ніндзя (Java)

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

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

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

javac Ninja.java
java Ninja

public class Ninja {
    public static void main(String[] args){
        char  r = 'B';
        int n = args [0].length ();
        int p = args.length > 4 ? Integer.parseInt (args [4]):0;
        int m = Integer.parseInt (args [2]);
        int a = n % 3;
        if (p>7) {
           if (m>17) {
                r = "BBI".charAt (a);
           } else if (m>13) {
                r = "BII".charAt (a); 
           } else {
               r  = "GIG".charAt (a);
           }

        } else if (p>0) {
           if (m > 10) {
                    r = "BBI".charAt (a);
           } else {
                r="IGI".charAt (n%2);
           }
        }
        System.out.print (r);
    }
}

Kakashi, The Copycat Ninja (Java)

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

javac Kakashi.java
java Kakashi

public class Kakashi {
    public static void main(String[] args){
        char  r;
        String h = args [1];
        if (h=="W" || Integer.parseInt ( args.length > 4?args [4]:"0") < 1){
                 r = 'B';
        } else if (Math.random ()<.1) {
            r = 'I';
        } else {
            r  = h.charAt ((int) (h.length()==1?0: h.length()-Math.random ()*2));
        }

        System.out.print (r);
    }
}


Мені б хотілося, щоб Какаші міг бути благословенним спілінганом .. Я думав про читання cast.txt. Моделюйте кожен раунд своєї історії проти кожного суперника, який там є. Спробуйте з’ясувати, проти якого противника він бореться, порівнявши змодельовану історію ворогів з реальною історією ворогів. Потім використовуйте цю інформацію, щоб передбачити наступний крок, який зробить опонент, і виберіть найкращий контрмобіль із попередньо визначеного списку. Але я вважаю, що це може зайняти трохи, оскільки у мене зараз супер повільний Інтернет і відсутність навичок Java

Спостерігач, (node.js)

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

Редагувати: Дякуємо @apsillers за те, що вони надали доступ до котла node.js !.

node observer.js

var argv = process.argv;
var history = argv.length>6?argv[2]:"";
var enemyHistory = argv.length>6?argv[3]:"";
var offset = 8 - argv.length;
var my = { health:+argv[4-offset], honor:+argv[6-offset], history:history };
var enemy = { health:+argv[5-offset], honor:+argv[7-offset], history:enemyHistory };
my.godSword = my.honor >= 7;
enemy.godSword = enemy.honor >= 7;
function decide() {
    process.stdout.write(arguments[Math.floor(arguments.length*Math.random())]);
    process.exit();
}

var m = {
    m:{},
    l:function (a,b) {
        if (!this.m[a]) {
           this.m [a] = [];
        }
        this.m[a].push (b);
    },
    p:function (a) {
       for (var k=0;k<a.length;k++)
       for (var j=1;j<a.length;j++)
       for (var i=-1+k; i<a.length-j; i++)this.l (a.slice (i,i+j),a[i+j]);
    },
    a:function (a) {
      if (!this.m[a])return;
      return this.m[a][0|Math.random () * this.m[a].length-1]
    }
}
var g={
   B:"IPO",
   G:"B",
   I:"PG",
   O:"IG",
   P:"OG",
   W:"I"
}
var c,i=0;
m.p(enemy.history);
while (!c && i++<enemy.history.length) {
   c=m.a (enemy.history.slice (i));
}
decide.apply  (0,my.honor < 7?["B"]:g[c].split (''))

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

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

Спостерігач, тепер також охороняє.


[1]: TIL: еякуляція має релігійне значення


Ви зараз # 1 і №3! Приємні боти! :)
apsillers

Вітаємо з перемогою разом із The Observer. Зелений галочок тепер ваш: D
абсент

7

Meiyo Senshi (Java)

Родом з району Хаїдзима про Меййо мало відомо. Вони, як правило, не беруть участь у спортивних іграх, але послали до цього воїна, щоб оцінити своїх суперників.

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

Для компіляції запуску це стандартний спосіб Java:

> javac MeiyoSenshi.java
> java MeiyoSenshi
public class MeiyoSenshi {
    public static void main(String[] args){
        System.out.print(
                Integer.valueOf(args[args.length<5?0:2])>12 ||
                Integer.valueOf(args[args.length<5?2:4])<1  ?
                "B":
                "IPO".charAt((int)(Math.random()*3))
        );
    }
}

7

Держатель Spork (Ruby)

Держатель спорків кланяється на першому повороті, після чого діє випадково. Це одна з двох прикладних записів.

Команда: ruby spork-holder.rb

if ARGV.length == 4
    print "B"
else
    print ["W", "B", "G", "I", "P", "O"].sample
end

Офіціант (баш)

Офіціант чекає тільки на кожному кроці. Це одна з двох прикладних записів.

Команда: echo W

Не потрібен вихідний код.


7

Трус (Node.js)

Я боягуз / Це диво, я смію дихати
Посилений / По ніжному літньому вітрі

  • Перевіряє, чи BXBXBX/ BBBшаблони кланяються (або вдаряють вас), коли ви кланяєтесь.
  • Перевіряє GXGXGXсхеми для поклону, коли ви охороняєте.
  • Якщо його випадковий відважний відкид подолає поріг страху для цього раунду, він спробує вдарити.
    • Наявність Меча Богів робить його сміливішим.
    • Супротивник з Мечем Богів робить його більш страшним.
    • Супротивник, який веде щонайменше на 5 здоров'я або більше, також змушує його трохи злякатися.
  • В іншому випадку він по черзі охороняє і кланяється.

Якщо ви хочете написати подання на Node.js , будь ласка, не соромтеся використовувати мій код котла; все, включаючи decideфункцію, є повністю загальним і вільним.


node coward.js

var argv = process.argv;
var history = argv.length>6?argv[2]:"";
var enemyHistory = argv.length>6?argv[3]:"";
var offset = 8 - argv.length;
var my = { health:+argv[4-offset], honor:+argv[6-offset], history:history };
var enemy = { health:+argv[5-offset], honor:+argv[7-offset], history:enemyHistory };
my.godSword = my.honor >= 7;
enemy.godSword = enemy.honor >= 7;
function decide() {
    process.stdout.write(arguments[Math.floor(arguments.length*Math.random())]);
    process.exit();
}

var enemyGuards = !!enemy.history.match(/G.G.G.$/);
var enemyBows = !!enemy.history.match(/(B.B.B.$)|(BBB$)/);

// open with a bow
if(!my.history) { decide("B"); }

// enemy will likely bow? Hit them with your super sword! (or bow)
if((!enemy.honor || enemyBows)) {
    if(my.godSword) { decide("P","I","O"); }
    else { decide("B"); }
}

// no point in hitting them if they're going to guard
if(enemyGuards) { decide("B"); }

// calculate bravery level
var braveryLevel = 0.3;
braveryLevel += (my.godSword * 0.2) - (enemy.godSword * 0.2);
braveryLevel -= (enemy.health - my.health > 5) * 0.1;

// if we're feeling brave, hit them
if(Math.random() < braveryLevel && my.honor) { decide("P","I","O"); }

// if we didn't just guard, and we're not feeling brave, cower in fear
if(!my.history.match(/G$/)) {
    decide("G");
}

// if we did just guard, and we're feeling cowardly,
//   if we don't have sword of the gods, bow
//   otherwise, do anything except guard
if(!my.godSword) {
    decide("B");
} else {
    decide("B","P","I","O");
}

1
Це важкий бот. Дивовижна котельня; Я одразу скористаюсь цим. Дякую за те, що поділилися :)
C5H8NNaO4

6

Удар-моль (R)

Вдаряє, коли ворог, швидше за все, поклониться, інакше охороняє.

args <- commandArgs(TRUE)
L <- length(args)
my_health <- as.integer(args[L-3])
enemy_health <- as.integer(args[L-2])
my_honour <- as.integer(args[L-1])
enemy_honour <- as.integer(args[L])
if(L>4){enemy_history <- args[L-4]}else{enemy_history <- ""}
if(my_honour<1){
    out <- "B"
}else if (enemy_honour<=1 | grepl("BB$",enemy_history)){
    out <- sample(c("I","O"),1)
}else{
    out <- "G"
}
cat(out)

Запустити за допомогою Rscript Whack-a-mole.R.


1
Хороша робота, плюс я люблю ім’я.
Алекс А.

3

Слон-воїн (Java)

Воїн-слон - з більш старого, більш природного часу. Він багато бачив і пам’ятає всіх. Він цікавиться прихильністю до богів, поки він оглядає свого супротивника, а потім, як тільки він бере їх у своє серце, він розбирає їх.

Компілювати: javac ElephantWarrior.java
Command:java ElephantWarrior

import java.util.LinkedList;

//Elephants never forget
class ElephantWarrior
{


  static LinkedList<Choice> analysis = new LinkedList<Choice>();

  public static void main(String[] args){
      if(args.length < 6){ respond("B");}   
      String myhis = args[0];
      String enHis = args[1];
      int health = Integer.parseInt(args[2]);
      int enHealth = Integer.parseInt(args[3]);
      int honour = Integer.parseInt(args[4]);
      int enHonour = Integer.parseInt(args[5]);

        //Bow a few times until I know how he operates
        if(enHis.length() <= 5){
            respond("B");
        }

        //Special cases
        //If I'm at 0 honor, better bow
        else if(honour <= 0){
            respond("B");

        }
        else{
          analyze(enHis);

          //Narrow it down to applicable choices
          char hisLast = enHis.toCharArray()[enHis.toCharArray().length - 1];
          LinkedList<Choice> hisOptions = new LinkedList<Choice>();
          for(Choice c: analysis){
              if(c.pattern.toCharArray()[0] == hisLast){
                  hisOptions.add(c);
              }
          }

           //Default to assuming they bow
          char hisNext = 'B';
          int mostLikely = 0;

          //What will they do next?
          for(Choice c : hisOptions){
              if(c != null && c.probability > mostLikely){
                  //System.out.println("Option = " + c.pattern);
                  //System.out.println("Prob = " + c.probability);
                  mostLikely = c.probability;
                  hisNext = c.pattern.toCharArray()[1]; }
          }

          //Now go through potential case
          switch(hisNext){
              case 'W':
                  respond("I");
                  break;
              case 'B': 
                  respond("O");
                  break;
              case 'G':
                  respond("B");
                  break;
              case 'I':
                  if(enHonour  > 0){
                      respond("P");
                  }
                  else{
                      respond("B");
                  }
                  break;
              case 'P':
                  respond("O");
                  break;
              case 'O':
                  respond("I");
                  break;
              default:
                  respond("G");
          }
        }
    }





      static void analyze(String his){

        //Keep track of his previous moves
        char[] shortString = his.substring(1,his.length() - 1).toCharArray();
        char[] longString = his.toCharArray();
        for( int i = 0; i < shortString.length; i++) {
          String pattern = "" + longString[i] + shortString[i];
          boolean exists = false;
          for(Choice c : analysis){
              if(c.pattern.equals(pattern)){
                  exists = true;
                  c.probability++;
              }
          }
          if(!exists){
              analysis.add(new Choice(pattern, 1));
          }
        }
      }

      private static void respond(String s){
            System.out.println(s);
            System.exit(0);
        }

    }

class Choice{
        String pattern;
        int probability;

       Choice(String p, int i){
            pattern = p;
            probability = i;
       }
}

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

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

@katya Це вже виправлено, btw, слід включити до турніру.
Каїн

3

Принцеса-воїн (Джулія)

Це перший виклик короля пагорба, в якому я змагався. Подивимося, як це відбувається.

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


Збережіть як warrior-princess.jlі запустіть з командного рядка так:

julia warrior-princess.jl <arguments>

Якщо у вас немає Юлії, ви можете завантажити її тут . Щоб уникнути проблем, рекомендується остання стабільна версія (тобто не версія для розробки).


type Samurai
    history::String
    health::Int
    honor::Int
end

A = length(ARGS) < 5 ? ["", "", ARGS] : ARGS

me = Samurai(A[1], int(A[3]), int(A[5]))
opponent = Samurai(A[2], int(A[4]), int(A[6]))


if length(me.history) == 0

    # Always begin the match with an honorable bow
    action = "B"

elseif (!ismatch(r"[OIP]", opponent.history) && me.history[end] != 'G') ||
       (me.health < 2 && me.honor > 0)

    # Guard if the enemy has not yet attacked and I did not previously
    # guard, or if my health is low and my honor is sufficient
    action = "G"

elseif me.honor < 2

    # Bow if I'm low on honor
    action = "B"

elseif opponent.honor >= 7 && opponent.history[end]['B', 'W']

    # Assume the enemy will attack with the Sword of the Gods if they
    # most recently bowed or waited
    action = "I"

else
    action = "P"
end

println(action)

1
Ваш перший запис KotH і перший запис Julia KotH коли-небудь, якщо я не помиляюся: вітаю!
планнапус

@plannapus Дякую! : D Можливо, я зроблю з цього звичку.
Алекс А.

3

Гаргуле (Java)

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

Оскільки це запис на Java:

> javac Gargoyle.java
> java Gargoyle
public class Gargoyle { 
    public static void main(String args[]) {
        if (args.length < 5 || Integer.valueOf(args[4]) > 0) {
            System.out.println("IPO".charAt((int)(Math.random()*3)));
        } else if (args[0].charAt(args[0].length()-1) != 'G') {
            System.out.println('G');
        } else {
            System.out.println('B');
        }
    }
}

3

Мечник (C / Java)

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

Версія C:

#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void print_and_exit(char* str)
{
    puts(str);
    exit(0);
}

int main(int argc, char** argv){

    srand(time(NULL));
    char* attack_moves[]={"I", "P", "O"};
    int random_num = rand() % 3;

    if(argc == 5 || atoi(argv[5]) == 0)
        print_and_exit("B");
    else if(argv[2][strlen(argv[2])-1] != 'B' && argv[2][strlen(argv[2])-1] != 'G' && argv[2][strlen(argv[2])-1] != 'W')
        print_and_exit(attack_moves[random_num]);
    else if(argv[1][strlen(argv[1])-1] != 'G')
        print_and_exit("G");

     print_and_exit("B");
}

Встановіть GCC (компілятор) і збережіть код у файл з назвою " Swordsman.c " для компіляції:

gcc Swordsman.c -o Swordsman

Буде створено виконавчий файл з назвою " Меч ". Запустити за допомогою

Swordsman

Версія Java:

public class Swordsman {

    public static void print_and_exit(String str)
    {
        System.out.println(str);
        System.exit(0);
    }
    public static void main(String[] argv) {

        String attack_moves[]={"I", "P", "O"};
        int random_num = (int)(Math.random()*3);

        if(argv.length == 4 || Integer.valueOf(argv[5]) == 0)
            print_and_exit("B");
        else if(argv[2].charAt(argv[2].length()-1) != 'B' && argv[2].charAt(argv[2].length()-1) != 'G' && argv[2].charAt(argv[2].length()-1) != 'W')
            print_and_exit(attack_moves[random_num]);
        else if(argv[1].charAt(argv[1].length()-1) != 'G')
            print_and_exit("G");

         print_and_exit("B");
    }

}

Встановіть javac (компілятор) і збережіть код у файл з назвою " Swordsman.java " для компіляції:

javac Swordsman.java

Файл класу з назвою " Swordsman.class " буде створений. Запустити за допомогою

java Swordsman



Зловмисник (Java)

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

public class Attacker {

    static int position = -1;

    public static void print_and_exit(String str)
    {
        System.out.println(str);
        System.exit(0);
    }
    public static void main(String[] argv) {

        String attack_moves[]={"I", "P", "O"};
        position = (position + 1) % 3;

        if(argv.length != 5 && Integer.valueOf(argv[5]) == 0)
            print_and_exit("B");
        else 
            print_and_exit(attack_moves[position]);
    }

}

Встановіть javac (компілятор) і збережіть код у файл з назвою " Attacker.java " для компіляції команди:

javac Attacker.java

Файл класу з назвою " Attacker.class " буде створений. Запустити за допомогою

java Attacker


Прогноз (C / Java)

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

Версія C:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>

void print_and_exit(char* str)
{
    puts(str);
    exit(0);
}

int main(int argc, char** argv){

    srand(time(NULL));
    int random = rand() % 5;
    char* moves[] = {"B", "G", "I", "P", "O"};

    if(argc == 5)
        print_and_exit(moves[random]);

    if(atoi(argv[5]) <= 0)
        print_and_exit(moves[0]);
    if(atoi(argv[6]) <= 0)
        print_and_exit(moves[4]);
    if(argv[2][strlen(argv[2])-1] == 'G')
        print_and_exit(moves[4]);
    if(argv[1][strlen(argv[1])-1] != 'G')
        print_and_exit(moves[1]);

    if(argv[2][strlen(argv[2])-1] != 'W'){
        char buf[2]={0};
        *buf = argv[2][strlen(argv[2])-1];
        print_and_exit(buf);
    }

    print_and_exit(moves[0]);

}

Встановіть GCC (компілятор) і збережіть код у файл під назвою " Predictor.c " для компіляції:

gcc Predictor.c -o Predictor

Буде створено виконуваний файл під назвою " Прогноз ". Запустити за допомогою

Predictor

Версія Java:

public class Predicator{

    public static void print_and_exit(String str)
    {
        System.out.println(str);
        System.exit(0);
    }

    public static void main(String[] argv){

        int random = (int)(Math.random() * 5);
        String moves[] = {"B", "G", "I", "P", "O"};

        if(argv.length == 4)
            print_and_exit(moves[random]);
        else if(Integer.valueOf(argv[5]) <= 0)
            print_and_exit(moves[0]);
        else if(Integer.valueOf(argv[6]) <= 0)
            print_and_exit(moves[4]);
        else if(argv[2].charAt((argv[2].length())-1) == 'G')
            print_and_exit(moves[4]);
        else if(argv[1].charAt((argv[1].length())-1) != 'G')
            print_and_exit(moves[1]);
        else if(argv[2].charAt((argv[1].length())-1) != 'W'){
                    print_and_exit(""+argv[2].charAt((argv[2].length())-1));
        }
        else
            print_and_exit(moves[0]);
    }
}

Встановіть javac (компілятор) і збережіть код у файл під назвою " Predicator.java " для компіляції:

javac Predicator.java

Файл класу з назвою " Predicator.class " буде створений. Запустити за допомогою

java Predicator


Не впевнений, наскільки ефективними будуть ці боти, оскільки у мене немає інтерпретатора python2, щоб перевірити його.


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

Здається, що нападник здається ArrayIndexOutOfBoundsExceptionна першій черзі, змушуючи його чекати на першій черзі. Крім цього він функціонує.
абсент

@Katya та Geobits, виправлено. Дякуємо, що помітили його.
Spikatrix

Під час запуску segmentation fault (core dumped)
прогноктора

@ C5H8NNaO4 Виправлена ​​проблема. Оновлений код для всіх трьох ботів. Має працювати нормально зараз. Дякуємо, що вказали на це! :-D
Spikatrix

2

Майстер Йі (Python)

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

import sys, random

class MasterYi(object):
    def __init__(self):
        self.attack = lambda: random.choice(['I','P','O'])
        self.bow   = "B"
        self.guard = "G"
        self.wait  = "W"
        if len(sys.argv)>6:
            self.hist = sys.argv[1]; self.ohist = sys.argv[2]
            self.hp   = sys.argv[3]; self.ohp   = sys.argv[4]
            self.hon  = sys.argv[5]; self.ohon  = sys.argv[6]
        else:
            self.hist = [];          self.ohist = []
            self.hp   = sys.argv[1]; self.ohp   = sys.argv[2]
            self.hon  = sys.argv[3]; self.ohon  = sys.argv[4]
        self.last  = self.hist  and self.hist[-1]  or "W"
        self.olast = self.ohist and self.ohist[-1] or "W"
        self.oGuarder = len(self.ohist)>4 and self.ohist[-4]==self.ohist[-2]=="G"

    def move(self):
        if self.hon < 1: return self.bow
        if self.olast == "G": return self.attack
        if self.hon > 6:
            if self.oGuarder: return self.bow
            if self.ohon > 6: return self.guard
            if self.ohon < 7: return self.attack
            return self.attack
        if self.ohon > 6: return self.guard
        return self.bow

Yi = MasterYi()
print(Yi.move())

Для запуску: Збережіть як MasterYi.py

python MasterYi.py <args>

2

Копія-сан (C)

Копіює кожен хід свого опонента. Досить впевнений, що він гарантовано програє. Збірка:gcc copy-san.c

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    if (argc == 5) {
        putchar('B');
    } else {
        char *enemy_hist = argv[2];
        size_t len = strlen(enemy_hist);
        putchar(enemy_hist[len - 1]);
    }
    putchar('\n');
    return 0;
}

2

Хебі (Java)

Хебі слідує Шляху змії.

Змії не потребують благословення богів.

Змія стримує свої удари; як хвилі на пляжі, те, що входить, відступає тому, як воно прийшло.

Змія ніколи не чекає.

Змія не має почуття придатності, інакше це було б написано на Python.

Інструкції з експлуатації:

> javac hebi.java
> java hebi

Орган коду:

public class hebi{

    public static void main(String args[]){

        if( (args.length < 5) || (args[0].length() % 18 == 0) ) System.out.println( "IPO".charAt((int)(Math.random()*3)) );
        else{

            int hist_size = args[0].length();

            if      (hist_size % 3 == 1) System.out.println("G");
            else if (hist_size % 3 == 2) System.out.println("B");
            else{

                if     (hist_size % 18 ==  9) System.out.println(args[0].charAt(hist_size -  3));
                else if(hist_size % 18 == 12) System.out.println(args[0].charAt(hist_size -  9));
                else if(hist_size % 18 == 15) System.out.println(args[0].charAt(hist_size - 15));
                else{

                    char move_head = args[0].charAt( (hist_size / 18) * 18 );
                    char move_mid;
                    if( hist_size % 18 == 3 ){
                        if     ( move_head == 'I' ) move_mid = "PO".charAt((int)(Math.random()*2));
                        else if( move_head == 'O' ) move_mid = "IP".charAt((int)(Math.random()*2));
                        else                        move_mid = "OI".charAt((int)(Math.random()*2));
                        System.out.println(move_mid);
                    }
                    else{
                        move_mid = args[0].charAt( ((hist_size / 18) * 18) + 3 );
                        char move_tail;

                        if( move_head == 'I' ){
                            if( move_mid == 'P' ) move_tail = 'O';
                            else                  move_tail = 'P';
                        }else if( move_head == 'P' ){
                            if( move_mid == 'O' ) move_tail = 'I';
                            else                  move_tail = 'O';
                        }else{
                            if( move_mid == 'I' ) move_tail = 'P';
                            else                  move_tail = 'I';
                        }

                        System.out.println( move_tail );

                    }

                }

            }

        }

    }

}

2

Почесний (Java)

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

скласти:

> javac TheHonourable.java
> java TheHonourable

Джерело:

public class TheHonourable {
    public static void main(String[] args) {
        char move;

        if (args.length < 5) {
            move = 'B';
        } else if (Integer.valueOf(args[5]) >= Integer.valueOf(args[4])){
            move = 'B';
        } else {
            move =  (args[0].endsWith("G")) ?
                    "IPO".charAt((int)(Math.random()*3)) :
                    "GIPO".charAt((int)(Math.random()*4));
        }

        System.out.print(move);
    }
}

1

Блаженний самурай (Пітон)

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

import sys
import random
class BlessedSamurai(object):
    def __init__(self):
        if len(sys.argv) < 7:
            print("B")
        else:
            self.attack = ['O', 'I', 'P']
            self.hp = sys.argv[3]
            self.ohp = sys.argv[4]
            self.hon = sys.argv[5]
            self.last = sys.argv[1][-1]
            print(self.move())

    def move(self):
        #check if I have low health or should rush the kill
        if (self.hp < 5 or self.ohp < 5) and self.hon > 0:
            return(random.choice(self.attack))
        # charge honour to get SOTG
        elif self.hon < 7:
            return 'B'
        #Alternate guarding and attacking
        else:
            if self.last == 'G':
                return(random.choice(self.attack))
            return 'G'
Sam = BlessedSamurai()

Для запуску:
Збережіть як BlessedSamurai.py

python BlessedSamurai.py <args>

4
Вашій програмі потрібно надрукувати хід.
mbomb007

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

Я використовував подібний формат до того, що він робив. @Stranjyr, поглянь на те, що я зробив для отримання аргументів.
mbomb007

Дякую вам обом! Зараз у мене немає доступу до інтерпретатора python, але я думаю, що виправили проблеми. Я якось зовсім пропустив, що перший набір інструкцій не матиме історії.
Stranjyr

Привіт, у вас була невелика помилка у вашій програмі: "глобальне ім'я" останнє "не визначено". Оскільки це невелика помилка, яку я змінив, lastі, self.lastздається, вирішує проблему.
абсент

1

Гермурай (C ++)

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

#include <stdio.h>
#include <string>
#include <sstream>

using namespace std;

char getLastAttack(string enemy_history)
{
    size_t found = enemy_history.find_last_of("IPO");
    if(found == string::npos)
    {
        return 'I';
    }

    return enemy_history[found];
}

int main(int argc, const char * argv[])
{
    if(argc != 7){
        printf("B");
        return 0;
    }

    string enemy_history(argv[2]);

    int ho;
    string honour(argv[5]);
    stringstream(honour) >> ho;

    if(ho > 20){
        char atk = getLastAttack(enemy_history);
        printf("%c", atk);
        return 0;
    }

    char lastMove = enemy_history[enemy_history.length()-1];
    if(lastMove == 'W' || lastMove == 'G')
        lastMove = 'B';
    printf("%c", lastMove);
    return 0;
}

Iniqy (C ++)

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

#include <stdio.h>
#include <string>
#include <sstream>

using namespace std;

char getLastAttack(string enemy_history)
{
    size_t found = enemy_history.find_last_of("IPO");
    if(found == string::npos)
    {
        return 'I';
    }

    return enemy_history[found];
}

int main(int argc, const char * argv[])
{
    if(argc != 7){
        printf("B");
        return 0;
    }

    string history(argv[1]);
    string enemy_history(argv[2]);
    string health(argv[3]);
    string enemy_health(argv[4]);
    string honour(argv[5]);
    string enemy_honour(argv[6]);

    int he, enemy_he, ho, enemy_ho;
    stringstream(health) >> he;
    stringstream(enemy_health) >> enemy_he;
    stringstream(honour) >> ho;
    stringstream(enemy_honour) >> enemy_ho;

    if(ho > 6 || ((he < 6 || enemy_he < 6) && ho > 0))
    {
        char atk = getLastAttack(enemy_history);
        printf("%c", atk);
        return 0;
    }


    printf("B");
    return 0;
}

Обидва написані на C ++. Для складання:

g++ iniqy.cpp -o iniqy

Для роботи в Linux: ./iniqy

Для роботи в Windows: iniqy.exe


1

Термінатор (рубін)

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

responses = {
  ?W => %w(B I),
  ?B => %w(I O),
  ?G => %w(B B),
  ?I => %w(G P),
  ?P => %w(B O),
  ?O => %w(G I)
}

if ARGV.size > 4
  pool = ARGV[1].chars.map{ |c| responses[c] }.flatten
  puts pool.sample
else
  puts %w(O I P B).sample
end

1

Агент 38 [1] (C)

Як продукт широкої генетичної маніпуляції, агент 38 має тілесність і гостроту психіки супер [2] -самурая і, безумовно, перевершує всі його безпорадні [потрібні цитати] недоліки [потрібне цитування] конкурентів.


//Agent 38
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#ifdef _WIN32
#include <Windows.h>
unsigned int tick_count(){
    return GetTickCount();
}
#else
#include <sys/time.h>
unsigned int tick_count(){
    struct timeval t;
    gettimeofday(&t, NULL);
    return 1000 * t.tv_sec + t.tv_usec / 1000;
}
#endif

float program[5][4][4][4][4]={
    {{{{-1.192779,0.693321,-1.472931,-0.054087},{0.958562,0.557915,0.883166,-0.631304},{-0.333221,1.410731,0.496346,0.087134},{0.459846,0.629780,-0.479042,-0.025909}},{{0.547976,1.059051,-0.748062,-0.675350},{-0.607591,-0.152156,-0.400350,-0.685337},{1.686450,0.628706,0.312865,0.324119},{1.652558,0.403733,-0.456481,-0.081492}},{{0.371629,-0.036948,-0.982682,0.065115},{1.360809,0.681294,0.505074,0.782737},{-0.545192,0.954937,-0.727853,0.273542},{-0.575777,1.615253,-0.064885,-0.516893}},{{0.577015,-0.112664,0.456595,-0.007560},{-0.660930,-0.738453,0.668093,1.716388},{1.972322,0.108558,0.535114,-0.337916},{0.640208,-0.019680,-0.769389,0.873087}}},{{{-0.021140,-0.095956,-0.098309,-0.280295},{-0.926284,1.724028,0.278855,0.678060},{0.153006,-1.860947,-0.577699,-1.931683},{-0.187152,0.529719,-1.164157,0.125499}},{{0.582208,-0.835029,-0.329857,0.088176},{-0.030797,0.389396,0.584636,-0.025866},{-0.736538,1.624658,0.690493,0.387515},{0.973253,-0.530825,1.934379,-0.872921}},{{0.812884,0.138399,-1.452478,-1.504340},{-0.119595,0.986078,-0.993806,1.102894},{0.848321,-0.268764,0.876110,0.782469},{0.948619,-0.557342,0.749764,-0.712915}},{{-1.195538,0.783784,-1.973428,-0.873207},{0.085426,-0.241360,-0.534561,-0.372105},{0.029696,-0.906821,0.932227,-0.834607},{0.764903,-0.276117,-1.346102,-0.093012}}},{{{0.168113,0.855724,1.817381,-0.547482},{0.468312,0.923739,-0.723461,0.798782},{-0.875978,-0.942505,-0.684104,-0.046389},{0.893797,-0.071382,0.283264,0.811233}},{{0.391760,0.309392,-0.045396,-0.977564},{0.085694,0.257926,-0.775461,0.060361},{0.486737,-0.175236,0.806258,-0.196521},{0.691731,-0.070052,0.636548,0.464838}},{{0.532747,-1.436236,-0.900262,-0.697533},{0.566295,0.650852,0.871414,-0.566183},{-0.075736,-0.886402,0.245348,-0.438080},{-0.811976,0.022233,-0.685647,0.323351}},{{-1.864578,1.141054,1.636157,-0.455965},{0.592333,0.890900,-0.259255,0.702826},{0.404528,0.905776,0.917764,0.051214},{0.761990,0.766907,-0.595618,-0.558207}}},{{{0.209262,-1.126957,-0.517694,-0.875215},{0.264791,0.338225,0.551586,0.505277},{0.183185,0.782227,0.888956,0.687343},{0.271838,0.125254,1.071891,-0.849511}},{{0.261293,-0.445399,0.170976,-0.401571},{0.801811,0.045041,-0.990778,-0.013705},{-0.343000,-0.913162,0.840992,0.551525},{-0.526818,-0.231089,0.085968,0.861459}},{{0.540677,-0.844281,-0.888770,0.438555},{0.802355,-0.825937,0.472974,-0.719263},{-0.648519,1.281454,0.470129,-0.538160},{-0.851015,0.985721,-0.993719,0.558735}},{{1.164560,-0.302101,0.953803,0.277318},{0.886169,0.623929,1.274299,-0.559466},{-0.948670,0.807814,-1.586962,-0.502652},{-0.069760,1.387864,-0.423140,0.285045}}}},
    {{{{0.747424,-0.044005,0.402212,-0.027484},{0.785297,0.169685,0.734339,-0.984272},{-0.656865,-1.397558,0.935961,-0.490159},{-0.099856,-0.293917,0.129296,-0.920536}},{{0.546529,-0.488280,-0.516120,-1.112775},{0.155881,-0.103160,0.187689,0.485805},{0.918357,0.829929,0.619437,0.877277},{0.389621,0.360045,0.434281,0.456462}},{{-0.803458,-0.525248,-0.467349,0.714159},{-0.648302,-0.005998,-0.812863,0.205664},{0.591453,0.653762,-0.227193,-0.946375},{0.080461,0.311794,0.802115,-1.115836}},{{-0.495051,-0.869153,-0.179932,0.925227},{-1.950445,1.908723,-0.378323,-0.472620},{-0.688403,-1.470251,1.991375,-1.698926},{-0.955808,-0.260230,0.319449,-1.368107}}},{{{-0.029073,-0.622921,-1.095426,-0.764465},{-0.362713,-0.123863,0.234856,-0.772613},{0.697097,0.103340,0.831709,0.529785},{0.103735,-0.526333,-0.084778,0.696831}},{{-0.670775,0.289993,-0.082204,-1.489529},{0.336070,0.322759,0.613241,0.743160},{0.298744,-1.193191,0.848769,-0.736213},{0.472611,-0.830342,0.437290,-0.467557}},{{-0.529196,-0.245683,0.809606,-0.956047},{-1.725613,0.187572,0.528054,-0.996271},{-0.330207,0.206237,0.218373,0.187079},{0.243388,0.625787,-0.388859,0.439888}},{{-0.802928,-0.811282,0.788538,0.948829},{0.966371,1.316717,0.004928,0.832735},{-0.226313,0.364653,0.724902,-0.579910},{-0.544782,-0.143865,0.069256,-0.020610}}},{{{-0.393249,0.671239,-0.481891,0.861149},{-0.662027,-0.693554,-0.564079,-0.477654},{0.070920,-0.052125,-0.059709,0.473953},{-0.280146,-0.418355,0.703337,0.981932}},{{-0.676855,0.102765,-0.832902,-0.590961},{1.717802,0.516057,-0.625379,-0.743204},{-0.170791,-0.813844,-0.269250,0.707447},{0.057623,0.472053,-0.211435,0.147894}},{{-0.298217,0.577550,1.845773,0.876933},{0.617987,0.502801,0.951405,0.122180},{0.924724,-0.166798,0.632685,-0.466165},{-0.834315,-0.864180,-0.274019,0.568493}},{{0.669850,-0.961671,0.790462,0.738113},{-0.534215,-0.556158,0.653896,0.031419},{0.065819,0.220394,0.153365,-0.373006},{0.886610,-0.742343,1.282099,0.198137}}},{{{0.092579,-0.026559,-1.121547,0.143613},{-0.289030,0.265226,-0.350741,-0.897469},{-0.918046,0.038521,-1.515900,0.488701},{-0.759326,-1.782885,-1.787784,0.249131}},{{-0.849816,-0.857074,-0.843467,-0.153686},{0.998653,0.356216,0.926775,0.300663},{-0.749890,-0.003425,-0.607109,0.317334},{-0.561644,0.446478,-0.898901,0.711265}},{{0.232020,-0.445016,0.618918,0.162098},{0.381030,-0.036170,0.084177,0.766972},{0.493139,0.189652,-0.511946,-0.273525},{0.863772,-0.586968,0.829531,-0.075552}},{{0.191787,-0.627198,0.975013,-0.448483},{-0.197885,0.151927,-0.558646,-1.308541},{-0.582967,1.207841,0.746132,0.245631},{0.314827,-0.702463,-0.301494,0.787569}}}},
    {{{{0.670028,-1.825749,-0.739187,0.482428},{0.175521,-0.020120,-0.154805,0.187004},{0.971728,-0.160181,-0.164031,-0.868147},{-0.954732,-0.175713,0.791116,0.294173}},{{-0.958337,-0.843157,-0.472882,0.273517},{-0.999058,0.824762,-0.223130,-0.150628},{0.393747,-0.301297,0.095572,-0.798950},{-0.119787,0.746673,0.955094,0.259353}},{{0.951590,0.225539,0.503282,0.668746},{-0.384898,-0.979592,-0.005485,-0.191883},{-0.692369,-0.642401,-0.825598,0.171933},{-0.321919,-0.498635,0.449704,0.780842}},{{-0.387902,0.522435,0.565608,0.166193},{-0.799671,-0.295871,-0.702573,-0.151006},{0.040550,-0.468503,0.651076,0.636352},{-0.839299,-0.090651,0.428761,0.187043}}},{{{-0.369823,0.377011,0.422936,0.284752},{-0.181514,-0.701449,0.748768,0.540533},{0.734381,0.149410,-0.867043,-0.397142},{-0.770904,-0.581897,-1.578306,-0.402638}},{{0.859015,-0.540358,0.202715,-0.975354},{-0.773629,-0.382342,-0.022498,-0.129286},{-0.901210,-0.641866,1.219216,0.731525},{0.740457,0.858546,-0.408661,-0.364897}},{{-0.830865,-1.370657,-1.226303,-0.392147},{-0.810554,-0.975232,-0.717845,-0.825379},{-0.150096,-0.664533,0.347084,0.243443},{-0.447383,0.842164,1.491342,0.380295}},{{-0.383958,0.811219,0.160459,0.841601},{1.631515,0.371637,0.110000,0.467783},{-0.689356,-0.004289,-0.081057,-0.317243},{0.092451,-0.181268,-0.575747,-0.580061}}},{{{0.908549,-0.013975,-0.880165,-0.938937},{-0.225713,0.449478,0.372569,-0.229889},{0.255711,-0.264752,0.307982,0.260505},{0.314966,-0.540905,0.743032,-0.078475}},{{-0.307472,-1.268296,0.020383,1.798401},{-0.150954,0.909716,-0.407903,0.379046},{0.621853,-0.003629,-0.582697,0.614618},{-0.122843,-0.627133,-0.217968,0.608322}},{{0.071923,0.807315,0.538905,-0.630660},{0.495641,0.240202,-0.920822,-0.258533},{-1.760363,-0.448525,-0.351553,-0.551666},{0.152720,0.900531,0.061966,-0.544377}},{{0.648923,0.450945,-1.530020,1.570190},{0.536210,0.078454,0.577168,0.464872},{-0.888258,-0.950748,0.781474,0.958593},{0.463631,0.319614,-0.248374,-0.413144}}},{{{0.293463,0.236284,1.721511,0.107408},{-0.790508,-0.072027,-0.559467,-0.955839},{-0.777662,-0.169876,0.896220,0.776105},{0.003944,-0.745496,-0.236446,-0.824604}},{{-1.770746,-0.051266,-0.174258,0.003074},{-0.339553,-0.868807,-0.032754,-0.494847},{-0.896712,0.957339,-0.003444,-1.582125},{-0.699883,0.626691,0.799635,-0.542343}},{{-0.635123,-0.755960,0.576373,-0.899530},{-0.393745,0.718900,0.312400,0.511415},{-0.647565,0.368431,0.214726,0.892693},{-0.511960,-0.513262,0.885908,-0.536478}},{{-0.590074,0.623328,0.268674,-0.401391},{0.308868,-0.869862,0.233132,0.243337},{-0.242908,-0.557192,-0.728454,0.867029},{0.156435,-0.805308,-0.815392,-1.437798}}}},
    {{{{0.613484,1.454566,-0.363858,0.634053},{0.535096,-0.641079,-0.607553,0.852559},{0.959100,-0.398621,0.375819,0.385756},{-0.601982,0.494128,0.809699,0.608804}},{{-1.390871,-0.943062,1.556671,0.966501},{-0.013242,0.152716,-0.089592,0.230793},{0.933785,0.119358,0.057387,0.502033},{-0.332925,0.537509,-0.081436,-0.701995}},{{-0.435117,0.996885,0.646630,-0.092342},{0.004343,-0.737514,-0.716187,-0.946819},{0.814258,-0.766971,-0.488162,-0.531619},{-0.923069,0.683915,-0.023809,-1.242992}},{{-0.909155,-0.166488,-0.159273,-0.908121},{-0.783871,-0.522598,0.691845,-0.164065},{1.255966,0.051373,-0.566025,0.820081},{0.186583,0.266032,-0.793747,-0.510092}}},{{{0.890639,0.970042,-0.507885,-0.029557},{-0.771142,-0.875802,0.400070,-1.264247},{-0.881146,0.570950,-0.051624,0.347612},{0.312110,-0.374885,0.600112,0.388460}},{{-0.417107,-0.309284,-0.128477,0.689671},{-0.695866,1.254585,-0.381883,-0.313415},{0.433565,0.919626,0.159180,-0.657310},{-1.396139,0.346053,0.108768,0.061238}},{{-0.776695,0.084491,0.045357,0.312823},{-0.379268,1.217006,-0.014838,-1.032272},{-1.251344,-0.366283,-0.124786,0.729754},{0.979936,0.669519,-0.900018,-0.596954}},{{-0.998834,0.593942,0.375639,-0.627459},{0.297281,0.400240,0.839707,0.960262},{-0.872143,0.574040,-0.559580,-1.965570},{-0.559218,-0.778780,-0.955526,-0.253380}}},{{{-1.919625,-1.911049,0.025035,0.754917},{-0.110993,0.535933,-0.572788,-0.856476},{-0.810836,-0.496261,1.128368,1.758826},{-0.564368,-1.849772,-0.251560,0.635528}},{{0.768196,-0.934122,0.207228,0.884610},{-0.356145,0.265792,-0.835582,0.377675},{-0.410745,0.613212,0.245560,-0.873826},{1.725191,-0.263344,-0.077167,-0.976379}},{{-0.736299,-0.109476,0.044512,-0.004005},{0.692230,0.316670,0.267247,-1.076821},{-0.903184,0.189762,-0.674111,0.219113},{0.639162,1.347521,0.428823,-0.765664}},{{-0.509165,0.458806,-0.851011,0.455027},{-0.218564,-0.063492,0.889320,-0.762062},{0.145950,0.985037,-0.489372,-0.879851},{0.352346,-0.127275,0.896496,-0.596037}}},{{{0.402678,1.479855,0.089187,0.967153},{-0.431225,0.402980,0.883584,-0.900324},{0.262233,-0.647278,0.637005,0.142678},{-0.003253,-0.671924,0.969458,-0.316752}},{{0.345185,-0.477503,-0.326822,-0.106251},{0.239521,1.617125,0.632651,0.969976},{-1.015183,-0.676629,0.955842,0.134925},{-0.319063,-0.493157,-0.488088,0.713008}},{{-0.468621,1.301292,-1.826501,1.138666},{0.170247,-0.661171,0.895204,-0.400700},{-0.077645,-0.978179,-0.245724,0.245282},{-0.258300,0.287261,-0.006274,0.549716}},{{-0.932247,-0.274950,0.920451,0.016237},{0.888865,-0.845248,1.661716,-0.108960},{0.712357,0.586609,-0.867356,0.355058},{-0.540912,0.892622,0.302627,0.247194}}}},
    {{{{0.817578,0.719047,0.438903,0.637398},{0.750466,-0.911799,-0.609606,0.358541},{-1.782979,-0.851717,-0.802122,0.735913},{0.490604,-0.417822,-0.332074,0.836756}},{{-0.650232,-0.442026,0.874916,0.705671},{0.217602,-0.755841,0.573944,0.279365},{-0.713729,0.358880,-0.308992,0.778297},{0.832099,-0.916695,-0.887834,1.041483}},{{1.019467,1.099488,-0.130674,-0.241995},{0.792572,0.756977,0.518186,0.070411},{-0.815779,-0.790757,-1.027439,-0.163698},{0.721461,-0.403364,0.656609,-0.367364}},{{-0.279333,-0.742041,0.515832,-0.408114},{0.834577,0.736056,0.900594,0.276357},{0.726000,0.464991,-0.569281,0.098139},{-0.582324,0.875666,-0.681556,-0.903009}}},{{{1.300969,-0.798351,0.107230,1.611284},{0.239211,0.418231,-0.795764,-0.398818},{-0.939666,1.768175,-0.297023,-0.064087},{-0.239119,-0.365132,0.864138,0.595560}},{{1.898313,-0.343816,1.066256,0.876655},{-0.053636,0.544756,-0.937927,0.189233},{0.445371,-0.656790,-0.675091,0.753163},{-0.293330,-0.002717,0.341173,0.095493}},{{0.951658,0.513912,-0.678347,-0.981140},{-0.020791,0.571138,-0.890648,0.881789},{-1.783345,0.909598,-0.393155,0.240630},{-0.057908,-0.237435,-0.124993,-0.754091}},{{-0.014153,0.127172,0.097134,0.538952},{0.167943,0.786395,0.946153,-0.762513},{-0.562758,0.675657,-0.226395,0.979761},{0.850214,0.818309,0.397074,-0.372059}}},{{{0.803316,-0.659538,-1.987864,-0.186366},{-0.259213,0.315848,-0.427898,0.326521},{-0.168181,-0.620898,0.562309,0.722064},{-1.949690,0.307720,-0.147760,0.603492}},{{0.898339,0.986228,0.724530,0.105193},{0.066046,0.037689,-0.553543,0.597864},{0.296553,0.165199,0.500125,-0.395978},{0.790120,-1.873361,0.354841,-0.187812}},{{-0.559746,0.357012,0.373903,-0.113564},{-0.671918,-0.919720,0.258328,-0.283453},{0.008365,0.597272,0.355827,0.391287},{0.355297,-0.631888,0.221383,1.448221}},{{0.259199,-0.491776,0.721151,0.391427},{0.494000,0.652814,-0.153306,-0.615687},{0.142167,-0.601161,0.281702,0.563390},{0.904019,1.284241,0.901663,0.244620}}},{{{-0.664638,-0.564596,0.839897,0.153358},{-0.506883,0.822337,-0.974957,-0.098112},{-0.962870,-0.274566,0.418039,-0.020525},{-0.965969,0.954587,-0.250493,-0.031592}},{{-0.966475,0.455338,0.868491,0.723032},{-0.002141,0.021922,-0.131429,-0.601106},{-1.240003,1.483318,1.612920,-0.653210},{-0.505979,0.005588,-0.087506,-0.705789}},{{-0.203137,0.765652,-0.132974,-0.900534},{0.731132,0.133467,-1.086363,0.600763},{1.795911,-0.411613,-1.990494,0.405937},{0.729332,-0.119175,-0.979213,0.362346}},{{-0.049014,0.228577,-1.728796,-0.898348},{-0.540969,1.245881,-0.820859,0.285859},{0.430751,-0.373652,0.034535,0.434466},{0.365354,0.243261,0.910114,1.497873}}}}
};
float eval_polynomial(float variables[4],int program_index,int variable_index,int indices[4]){
    if(variable_index==4)return program[program_index][indices[0]][indices[1]][indices[2]][indices[3]];
    float result=0,base=1;
    for(int power=0;power<4;++power){
        indices[variable_index]=power;
        result+=base*eval_polynomial(variables,program_index,variable_index+1,indices);
        base*=variables[variable_index];
    }
    return result;
}
int main(int argc,char *argv[]){
    srand(tick_count());
    rand();
    float variables[4],probability[5],total=0;
    int i,indices[4],temp;
    for(i=0;i<4;++i){
        sscanf(argv[i-4+argc],"%d",&temp);
        variables[i]=temp;
    }
    temp=variables[1];
    variables[1]=variables[2];
    variables[2]=temp;
    if(variables[1]==0){ //bow if our honour is 0
        putchar('B');
        return 0;
    }

    variables[0]/=20;variables[2]/=20;
    variables[1]=1/(variables[1]+1);variables[3]=1/(variables[3]+1);
    for(i=0;i<5;++i){
        probability[i]=eval_polynomial(variables,i,0,indices);
        if(probability[i]<0)probability[i]=0;
        total+=probability[i];
        probability[i]=total;
    }
    total*=(float)rand()/RAND_MAX;
    for(i=0;i<5;++i)if(total<probability[i]){
        putchar("BGIPO"[i]);
        return 0;
    }
    putchar('B');
    return 0;
}

[1] Повністю нерелевантна кількість [2] Гарантована правда 1% часу


YAGMCSE

Методи Монте-Карло, схоже, демонструють гідну гру, тож ось ще один загальний запис імітації Монте-Карло!

На відміну від більшості інших публікацій цього конкурсу, цей запис використовує велику кількість імітацій випадкових ігор, і тому для оптимальної продуктивності потрібно використовувати прапор -O3.

Складіть програму командою: gcc monte.c -o monte -O3 -std = c99

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef _WIN32
#include <Windows.h>
unsigned int tick_count(){
    return GetTickCount();
}
#else
#include <sys/time.h>
unsigned int tick_count(){
    struct timeval t;
    gettimeofday(&t, NULL);
    return 1000 * t.tv_sec + t.tv_usec / 1000;
}
#endif

const int turn_limit=500;
enum Move{
    WAIT,BOW,GUARD,QUICK,PARRY,OVERHEAD
};
struct Player{
    int health,honour;
    enum Move lastMove;
};
typedef struct Player Player;
//<command> <history> <enemy_history> <your_health> <enemy_health> <your_honour> <enemy_honour>
//<command> <your_health> <enemy_health> <your_honour> <enemy_honour>
int damage_table[6][6][2]={
    {{0,0},{0,0},{0,0},{1,0},{1,0},{1,0}}, //P1 is waiting
    {{0,0},{0,0},{0,0},{1,0},{1,0},{1,0}}, //P1 is bowing
    {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}, //P1 is guarding
    {{0,1},{0,1},{0,0},{0,0},{1,0},{0,1}}, //P1 is using quick draw
    {{0,1},{0,1},{0,0},{0,1},{0,0},{1,0}}, //P1 is parrying
    {{0,1},{0,1},{0,0},{1,0},{0,1},{0,0}} //P1 is using overhead attack
};
enum Move decode_move(char x){
    switch(x){
        case 'W': return WAIT; break;
        case 'B': return BOW; break;
        case 'G': return GUARD; break;
        case 'I': return QUICK; break;
        case 'P': return PARRY; break;
        case 'O': return OVERHEAD; break;
    }
    return WAIT;
}
struct SimulationStat{
    enum Move first_me_move;
    int win,draw,lose,compound;
};
int stat_compare(const void*a,const void*b){
    return ((struct SimulationStat*)b)->compound-((struct SimulationStat*)a)->compound;
}
struct SimulationStat monte_carlo(int num_iters,enum Move first_me_move,Player original_me,Player original_opponent){
    struct SimulationStat simulation_result={first_me_move,0,0,0};

    for(int iter=0;iter<num_iters;++iter){
    Player me=original_me,opponent=original_opponent;
        int turn,game_result;
        for(turn=0;turn<turn_limit;++turn){
            enum Move me_move,opponent_move=rand()%(OVERHEAD-BOW+1)+BOW;
            if(turn==0)me_move=first_me_move;
            else me_move=rand()%(OVERHEAD-BOW+1)+BOW;

            //update honour for guarding
            if(me.lastMove==GUARD&&me_move==GUARD)--me.honour;
            if(opponent.lastMove==GUARD&&opponent_move==GUARD)--opponent.honour;

            int me_attacking=me_move==QUICK||me_move==PARRY||me_move==OVERHEAD,opponent_attacking=opponent_move==QUICK||opponent_move==PARRY||opponent_move==OVERHEAD;

            //update health of players
            me.health-=damage_table[me_move][opponent_move][0]*(1+(opponent.honour>=7));
            opponent.health-=damage_table[me_move][opponent_move][1]*(1+(me.honour>=7));

            //update honour for attacking (Sword of the Gods is revoked after the player attacks with an original honour value of 7)
            if(me_attacking)--me.honour;
            if(opponent_attacking)--opponent.honour;

            //printf("%d %d\n",me.health,me.honour);
            //printf("%d %d\n",opponent.health,opponent.honour);

            //check if any of the terminating conditions are met
            //c. both players fall off the graces of the gods (me.honour<0&&opponent.honour<0)
            if(me.honour<0&&opponent.honour<0){
                game_result=0; //draw
                break;
            }
            //a. player 1 falls off the graces of the gods (me.honour<0)
            else if(me.honour<0){
                game_result=-1; //loss
                break;
            }
            //b. player 2 falls off the graces of the gods (opponent.honour<0)
            else if(opponent.honour<0){
                game_result=1; //win
                break;
            }
            //d. both players are dead (me.health<0&&opponent.health<0)
            else if(me.health<0&&opponent.health<0){
                game_result=0; //draw
                break;
            }
            //e. player 1 is dead (me.health<0)
            else if(me.health<0){
                game_result=-1; //loss
                break;
            }
            //f. player 2 is dead (opponent.health<0)
            else if(opponent.health<0){
                game_result=1; //win
                break;
            }
        }
        //both players get struck down by the guards for being boring
        if(turn==turn_limit)game_result=0; //draw

        if(game_result==1)++simulation_result.win;
        else if(game_result==0)++simulation_result.draw;
        else ++simulation_result.lose;
    }
    return simulation_result;
}
int main(int argc,char*argv[]){
    //const int num_iters=200000,num_shortlist_iters=1000000;
    const int num_iters=20000,num_shortlist_iters=55000;

    srand(tick_count());
    Player me,opponent;
    if(argc==5){
        sscanf(argv[1],"%d",&me.health);
        sscanf(argv[2],"%d",&opponent.health);
        sscanf(argv[3],"%d",&me.honour);
        sscanf(argv[4],"%d",&opponent.honour);
        me.lastMove=WAIT;
        opponent.lastMove=WAIT;
    }else{
        sscanf(argv[3],"%d",&me.health);
        sscanf(argv[4],"%d",&opponent.health);
        sscanf(argv[5],"%d",&me.honour);
        sscanf(argv[6],"%d",&opponent.honour);
        me.lastMove=decode_move(argv[1][strlen(argv[1])-1]);
        opponent.lastMove=decode_move(argv[2][strlen(argv[2])-1]);
    }

    struct SimulationStat results[6];
    results[0].first_me_move=WAIT;
    results[0].win=0;
    results[0].draw=0;
    results[0].lose=num_iters;
    results[0].compound=-num_iters*2-1000; //waiting is worse than any other action

    for(enum Move first_me_move=BOW;first_me_move<=OVERHEAD;++first_me_move){
        results[first_me_move]=monte_carlo(num_iters,first_me_move,me,opponent);
        struct SimulationStat *cur=&results[first_me_move];
        cur->compound=cur->win*4+cur->draw*1-cur->lose*2;
    }
    qsort(results,OVERHEAD-WAIT+1,sizeof(*results),stat_compare);

    for(int i=0;i<OVERHEAD-BOW+1;++i){
        struct SimulationStat *cur=&results[i];
//        fprintf(stderr,"%c: %f%% win, %f%% draw, %f%% lose => %d\n","WBGIPO"[cur->first_me_move],(double)cur->win/num_iters*100.,(double)cur->draw/num_iters*100.,(double)cur->lose/num_iters*100.,cur->compound);
    }

    for(int i=0;i<2;++i){
        results[i]=monte_carlo(num_shortlist_iters,results[i].first_me_move,me,opponent);
        struct SimulationStat *cur=&results[i];
        cur->compound=cur->win*2+cur->draw*1;
    }
    qsort(results,2,sizeof(*results),stat_compare); 

    for(int i=0;i<2;++i){
        struct SimulationStat *cur=&results[i];
//        fprintf(stderr,"%c: %f%% win, %f%% draw, %f%% lose => %d\n","WBGIPO"[cur->first_me_move],(double)cur->win/num_shortlist_iters*100.,(double)cur->draw/num_shortlist_iters*100.,(double)cur->lose/num_shortlist_iters*100.,cur->compound);
    }
    putchar("WBGIPO"[results[0].first_me_move]);
    return 0;
}

1
Він, здається, кланяється лише з будь-якої причини. Ви можете поглянути на це
C5H8NNaO4

@ C5H8NNaO4 Дякую за повідомлення про цю серйозну помилку. Моя редакція повинна виправити помилку.
Картопля

YAGMCSE, здається, робить лише GBWWWWW...абоBWWWW
C5H8NNaO4

@ C5H8NNaO4 Це дивно. Я не в змозі повторити згадані вами результати. Суперник YAGMCSE постійно вклонявся / охороняв / чекав?
Картопля

Так, він кланявся перші 7 турів. Ось Pastebin
C5H8NNaO4

1

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

ScroogeBot - Python 2

Цей бот вклониться, якщо він має одну честь. Інакше він перекине монету.

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

Команда: python scroogebot.py

import random, sys
# If he has more than one honor...
if int(sys.argv[5]) > 1:
    #Flip a coin.
    coin = random.choice(['heads','tails'])
    #If the coin lands on heads...
    if coin == 'heads':
        #Attack!
        print random.choice(['I','O','P'])
    #If the coin lands on tails...
    else:
        #Don't attack!
        print random.choice(['G','B'])
#If he has 1 honor...
else:
    #Bow!
    print "B"

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

0

Йосіміцу (JS)

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

var attacks = ['I','P','O'];
var pasive = ['B','W'];
var argv = process.argv;
var playerHistory = argv.length>6?argv[2].split(''):[];
var enemyHistory = argv.length>6?argv[3].split(''):[];
var offset = 8 - argv.length;
var my = { health:+argv[4-offset], honor:+argv[6-offset], history:playerHistory };
var enemy = { health:+argv[5-offset], honor:+argv[7-offset], history:enemyHistory };
my.godSword = my.honor >= 7;
enemy.godSword = enemy.honor >= 7;

enemy.lastMove = enemyHistory.pop();
enemy.secondToLast = enemyHistory.pop();

enemy.didAttack = !!attacks.indexOf(enemy.lastMove);

my.lastMove = playerHistory.pop();

function decide() {
    process.stdout.write(arguments[Math.floor(arguments.length*Math.random())]);
    process.exit();
}

chooseAnAttack = function(){ decide.apply(this,attacks); };

if( ( pasive.indexOf( enemy.lastMove ) && my.honor < 15 ) || (my.honor < 7 && enemy.health > 10) || my.honor === 1 ){
    if( Math.random * 15 < my.honor ){
        chooseAnAttack();
    } else {
        decide('B');
    }
} else if( enemy.honor < 2 ){
    chooseAnAttack();
} else if( enemy.didAttack ){

    if( attacks.indexOf( enemy.secondToLast ) ){
        decide('G');
    } else if( pasive.indexOf( enemy.secondToLast ) ){
        chooseAnAttack();
    } else if( enemy.secondToLast == 'G' ){
        decide('B');
    }

} else if( enemy.lastMove = 'G' ) {
    chooseAnAttack();
} else if( enemy.lastMove === 'W' ){
    if( attacks.indexOf( enemy.secondToLast ) ){
        decide('G');
    } else if( pasive.indexOf( enemy.secondToLast ) ){
        chooseAnAttack();
    } else if( enemy.secondToLast == 'G' ){
        decide('B');
    }
}

0

Дурень (С)

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

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

const char commands[] =
{
    'W', 'B', 'G', 'I', 'P', 'O'
};

char select_candidate(const char c[])
{
    unsigned i = 0;
    int n_candidates = 0;
    char candidates[sizeof(commands)];

    for (; i < sizeof(commands); i++)
        if (c[i])
            candidates[n_candidates++] = c[i];

    /* There are no candidates for actions, so the fool blindly attacks his opponent, hoping for the best */
    return n_candidates == 0 ? 'I' : candidates[rand() % n_candidates];
}

int main(int argc, char *argv[])
{
    unsigned i = 0;
    int honour;
    char candidates[sizeof(commands)];
    char last_action;

    srand(time(NULL));

    memcpy(candidates, commands, sizeof(commands));

    /* It's the first round, the fool selects a random action except for waiting */
    if (argc != 7)
    {
        candidates[0] = 0;
        putchar(select_candidate(candidates));
        return 0;
    }

    last_action = argv[1][strlen(argv[1]) - 1];
    honour = atoi(argv[5]);

    if (honour == 0)
    {
        /* The fool realises he will meet his doom if he performs any of the following moves */
        /* and removes them from his list of possible actions */
        candidates[3] = 0;
        candidates[4] = 0;
        candidates[5] = 0;

        /* Only omit the blocking action if the last action was blocking */
        if (last_action == 'G')
            candidates[2] = 0;
    } else if (honour >= 7) {

        /* If the fool has the opportunity to abuse power, he will */
        candidates[0] = 0;
        candidates[1] = 0;
    }

    /* However unintellegent, the fool decides never to repeat the same move twice */
    for (; i < sizeof(commands); i++)
    {
        if (candidates[i] == last_action)
        candidates[i] = 0;
    }

    /* The fool randomly selects a possible action and hopes for the best */
    putchar(select_candidate(candidates));

    return 0;
}


Пророк (С)

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main(int argc, char* argv[])
{
    char* hist;
    char* enemy_hist;
    int hist_len;
    int enemy_hist_len;
    int health;
    int enemy_health;
    int honour;
    int enemy_honour;

    if (argc != 7)
    {
        /* Always start with guarding */
        putchar('G');
        return 0;
    }

    srand(time(NULL));

    /* Grab the command-line values */
    hist         = argv[1];
    enemy_hist   = argv[2];
    health       = atoi(argv[3]);
    enemy_health = atoi(argv[4]);
    honour       = atoi(argv[5]);
    enemy_honour = atoi(argv[6]);

    hist_len = strlen(hist);
    enemy_hist_len = strlen(enemy_hist);

    /* Looks like the enemy is starving for honour. */
    /* This means that they have to bow, so attack them,  */
    /* But only if we have the honour to do so. */
    if (enemy_honour == 0 && honour > 0)
    {
        putchar('O');
        return 0;
    } else if (honour == 0) {
        /* We have to bow */
        putchar('B');
        return 0;
    } else if (honour <= 3) {
        /* We have low honour, attack if the enemy has no honour, otherwise bow to restore some of our honour */
        putchar(enemy_honour == 0 ? ((rand() % 2) ? 'I' : 'O') : 'B');
        return 0;
    }

    switch (enemy_hist[enemy_hist_len - 1])
    {
        /* The enemy has previously performed a passive action, so they will likely attack this round */
        case 'W':
        case 'B':
        case 'G':
            putchar(hist[hist_len - 1] == 'G' ? 'P' : 'G'); /* Protect ourselves, using `guard` if we did not use it last turn */
            return 0;

        default:
            if (enemy_hist_len >= 2)
            {
                switch (enemy_hist[enemy_hist_len - 2])
                {
                    case 'I':
                    case 'P':
                    case 'O':
                        /* The enemy has attacked for the last 2 turns, they will likely rest now */
                        putchar((rand() % 2) ? 'I' : 'O');
                        return 0;

                    default:
                        /* Low health, block an incoming attack */
                        if (health <= 5)
                        {
                            putchar(hist[hist_len - 1] == 'G' ? 'P' : 'G');
                            return 0;
                        } else {
                            /* Choose randomly to bow or attack */
                            int decision = rand() % 3;
                            putchar(decision == 2 ? 'B' : decision == 1 ? 'I' : 'O');
                            return 0;
                        }
                }
            } else {
                /* Attack! */
                putchar((rand() % 2) ? 'I' : 'O');
                return 0;
            }
    }

    /* If somehow we get to this point, parry */
    putchar('P');
    return 0;
}


Компіляція

Обидві програми написані на мові С і можуть бути складені за допомогою gcc:

gcc fool.c -o fool
gcc prophet.c -o prophet


Біг

* нікс

./fool <args>
./prophet <args>

Windows

fool.exe <args>
prophet.exe <args>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.