Caveman Duels (или: я ткну тебя острой палкой)


151

Пещерный человек сумасшедший. Другой пещерный человек взял палку, но палка была для меня. Пещерный Бой !


Описание

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

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

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

вход

Ввод вашей программы будет представлять собой историю событий, которые произошли, где Sобозначает повышение резкости (то есть пещерный человек оттачивал свою палку), Pобозначает удар, и Bобозначает блок. Входными данными будет история обеих сторон (вы и противник), поэтому ходы вашего и противника будут разделены запятой ( ,).

Пример ввода:

SPB,SBB

Это означает, что игрок оттачивал свою палку, затем тыкал, затем блокировал, а противник оттачивал, затем блокировал, а затем снова блокировал.

Вы не получите никакой информации на первом ходу.

Выход

Вывод очень похож на ввод (потому что пещерный человек не очень умен). Ваша программа должна выводить Sрезкость, Pдля poke и Bдля блока. Будет учитываться только первый символ вывода, а любой другой ввод будет рассматриваться как B(блочная) команда.

  • S: точить

    При обострении острота палки пещерного человека увеличивается на 1, и палка получает 1 дополнительный удар. Каждый удар уменьшает остроту палки на 1, а если резкость палки равна 0, слишком скучно для того, чтобы тыкать. Резкость начинается с 0. Если резкость достигает 5, палка - это меч! (Смотри ниже.)

    Если противник тыкает, когда вы точите (и они имеют остроту> 0), противник побеждает!

  • P: тыкать

    Когда тыкаешь, резкость палки пещерного человека падает на 1, а ты тыкаешь своего противника! Если ваш противник обостряется, вы выигрываете! Если противник тыкает, ваша палка ударяет по палке противника, и они оба становятся более тусклыми (на 1 «единицу резкости»). Если противник блокирует, ничего не происходит, кроме того, что ваша палка становится более тупой.

    Если тыкаешь, когда острота твоей палки 5 или больше, твоя палка становится мечом, и ты всегда выигрываешь! (Если только у вашего противника нет меча и он тоже выбрал P; в этом случае они оба становятся тупее и могут вернуться к палкам, если их острота упадет ниже 5.)

    Вы не можете тыкать с точностью до 0. Если вы делаете, ничего не произойдет.

  • B: блок

    Когда вы блокируете, ничего не происходит, когда ваш противник пикает. Если ваш противник не тыкает, блок ничего не делает.

    Блокировка не защищает от меча, даже если он у вас есть!

Правила и ограничения

Дополнительные правила:

  • Ваша программа может читать и записывать файлы в своей собственной папке (без кражи!), Если вы хотите сохранить данные, но вы не можете получить доступ к чему-либо за ее пределами (а пещерные люди не имеют подключения к Интернету в пустыне).
    • Важное примечание к файлам : если вы сохраняете файлы, не забудьте сохранить их в каталоге players/YourBotsName/somefile.foo! Текущий рабочий каталог для вашей программы не будет вашей программой!
  • Пещерные люди справедливы: одна программа не может иметь код, специфичный для другой программы, и программы не могут помочь друг другу. (У вас может быть несколько программ, но они никак не могут взаимодействовать друг с другом.)
  • Судья пещерного человека не терпелив. Если пещерный человек делает более 100 ходов каждый, чтобы определить победителя, судье становится скучно, и оба пещерных человека проигрывают.

Если ваша программа нарушает правило или не соответствует спецификации, программа дисквалифицируется, удаляется playerlist.txtи все дуэли возобновляются с самого начала. Если ваша программа будет дисквалифицирована, лидер пещерного человека (я!) Прокомментирует пост вашей программы и объяснит почему. Если вы не нарушаете никаких правил, ваша программа будет добавлена ​​в список лидеров. (Если вашей программы нет в списке лидеров, в вашем посте нет пояснительного комментария, и вы опубликовали свою программу раньше, чем «Последнее обновление», указанное ниже, сообщите об этом руководителю пещерного человека! Возможно, он забыл об этом.)

В ваш пост, пожалуйста, включите:

  • Имя.
  • Командная оболочка для запуска программы (напр. java MyBot.java, ruby MyBot.rb, python3 MyBot.pyИ т.д.).
    • Примечание: вход будет добавлен в качестве аргумента командной строки.
    • Пещерные люди используют Ubuntu 14.04, поэтому убедитесь, что ваш код работает (свободно) на нем.
  • Номер версии, если ваш код работает по-разному на разных версиях выбранного вами языка.
  • Ваш код (очевидно).
  • Как скомпилировать код, если это необходимо.

Контроллер кода / тестирование, пример бота

Лидер пещерного человека написал контрольный код на C ++ и разместил его в репозитории Github . Вы можете запустить и протестировать свою программу там.

Очень, очень простая программа (1 строка!) Также размещена в ответах ниже .

Скоринг и таблица лидеров

Забить легко. Какой бы пещерный человек ни победил, он получает очко. Пещерный человек с наибольшим количеством очков после 3 поединков против каждого другого пещерного человека становится новым лидером пещерного человека!

150     Watson
147     SpeculativeSylwester
146     Gruntt
141     BashMagnon
126     ChargerMan
125     PrisonRules
124     ViceLeader
122     MultiMarkov
122     CaveDoctor
120     RegExMan
120     Hodor
117     FancyTechnoAlgorithm
116     Semipatient
113     Watcher
108     BobCaves
105     MinimaxMan
104     Oracle
102     MaybeMarkov
97      Nash
95      Sicillian
95      Feint
95      Basilisk
94      SharpMan
93      Darwin
91      Nigel
91      JavaMan
88      Entertainer
88      CarefulBot
85      CaveMonkey
84      SSBBP
82      SirPokealot
79      MasterPoker
77      Unpredictable
76      IllogicalCaveman
75      SharpenBlockPoke
75      HuddleWolfWithStick
72      WoodenShield
68      PokeBackBot
68      PatientBlacksmith
66      PatientWolf
58      MonteCarloMan
58      BlindFury
56      BinaryCaveman
55      PokeBot
55      CavekidBlocks
53      Swordmaster
53      Blocker
52      NakedEarlyNerd
52      ModestCaveman
50      LatePokeBot
40      Trickster
39      SwordLover
38      ForeignCaveman
36      Swordsmith *
28      Touche
27      WantASword
27      FoolMeOnce
24      PeriodicalCavemanCicada
11      Aichmophobic

(этот список лидеров был сгенерирован автоматически)

Игроки, помеченные *какой-то ошибкой или исключением, в какой-то момент; эти игроки также имеют комментарии к своим сообщениям.

Игроки , которые не могли быть включены в тесты по какой - либо причине (эти игроки будут иметь комментарий на своих постах , объясняющих проблему): Monkey, Elephant, FacileFibonacci, StudiousSylwester.

Последнее обновление: 3 августа, 00:15 (UTC).


Я удивлен, что никто, кажется, еще не пытался найти минимаксную стратегию. Это кажется очевидным.
user2357112

@ user2357112 Я не думаю, что минимакс здесь - это улучшение. Я имею в виду, что вы могли бы разработать минимаксную реализацию, но поскольку логика очень проста, то же самое точное поведение можно выразить с помощью конечного автомата. (т.е. бот никогда не будет точить, пока противник не станет скучным, потому что, если это произойдет, минимизирующий ход противника будет тыкать, а вы проиграете, бот будет всегда блокировать, пока у нас не будет меча, потому что максимизирующий ход для нашего бота всегда будет быть в блоке и т. д.)
HuddleWolf

3
Многие из записей, кажется, учитывают отрицательную резкость в своих расчетах. Как написано в правилах, ничего не происходит, когда тыкаешь с нулевой резкостью. Означает ли это «ничто» также, что ваша резкость остается нулевой, а не уменьшенной?
Спарр

6
Это должно быть здесь: dresdencodak.com/comics/2009-09-22-caveman_science_fiction.jpg Возможно, это заставит воображение работать. :)
Evi1M4chine

2
Это все еще открыто? Я вижу людей, добавляющих новые материалы, но я не вижу обновления списка лидеров.
ASCIIThenANSI

Ответы:


35

Дарвин - С

Кому нужна стратегия? Пусть группа пещерных людей встретится, и пусть естественный отбор сделает все остальное!


Мы используем очень простую модель для примитивного мозга нашего пещерного человека: он не имеет памяти и учитывает только остроту его и его оппонента. Они используются в качестве переменных для двоичного полинома некоторого конечного порядка. Каждое действие (блок, резкость и тыкать) имеет связанный многочлен, результат которого определяет относительную вероятность выбора этого действия. Вот и все, что нужно сделать - начать с некоторых случайных коэффициентов и оптимизировать итеративно.

Бот:

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

/* magic numbers */
#define SWORD_SHARPNESS 5
#define PROGRAM_DIM 4 /* polynomial order + 1 */
#define DEFAULT_FILENAME "players/Darwin/program"

typedef double real;
typedef real program[PROGRAM_DIM][PROGRAM_DIM];
typedef program caveman_brain[3];

typedef char action; /* S, B or P */
/* encodes a pair of actions */
#define ACTION_PAIR(a1, a2) (((int)(a1) << (sizeof(action) * 8)) | (a2))

real eval_program(const program p, double x, double y) {
    real v = 0;
    int i, j;

    for (i = 0; i < PROGRAM_DIM; ++i) {
        real w = 0;
        for (j = 0; j < PROGRAM_DIM; ++j)
            w = x * w + p[i][j];
        v = y * v + w;
    }

    if (v < 0)
        v = 0;
    return v;
}
void read_program(FILE* f, program p) {
    int i, j;
    for (i = 0; i < PROGRAM_DIM; ++i) {
        for (j = 0; j < PROGRAM_DIM; ++j) {
            double v;
            fscanf(f, "%lg", &v);
            p[i][j] = v;
        }
    }
}

int blunt(int* s) {
    int temp = *s;
    if (temp)
        --*s;
    return temp;
}
void sharpen(int* s) { ++*s; }
/* takes two sharpness/action pairs and updates the sharpness accordingly.
 * returns negative value if first caveman wins, positive value if second
 * caveman wins and 0 otherwise. */
int act(int* s1, action a1, int* s2, action a2) {
    switch (ACTION_PAIR(a1, a2)) {
        case ACTION_PAIR('B', 'B'): return 0;
        case ACTION_PAIR('B', 'S'): sharpen(s2); return 0;
        case ACTION_PAIR('B', 'P'): return blunt(s2) >= SWORD_SHARPNESS ? 1 :
                                                                          0;
        case ACTION_PAIR('S', 'B'): sharpen(s1); return 0;
        case ACTION_PAIR('S', 'S'): sharpen(s1); sharpen(s2); return 0;
        case ACTION_PAIR('S', 'P'): sharpen(s1); return *s2 > 0 ? 1 : 0;
        case ACTION_PAIR('P', 'B'): return blunt(s1) >= SWORD_SHARPNESS ? -1 :
                                                                          0;
        case ACTION_PAIR('P', 'S'): sharpen(s2); return *s1 > 0 ? -1 : 0;
        case ACTION_PAIR('P', 'P'): {
            int t1 = blunt(s1), t2 = blunt(s2);
            if (t1 >= SWORD_SHARPNESS && t2 < SWORD_SHARPNESS)
                return -1;
            else if (t2 >= SWORD_SHARPNESS && t1 < SWORD_SHARPNESS)
                return 1;
            else
                return 0;
        }
    }
}
/* processes a pair of strings of actions */
int str_act(int* s1, const char* a1, int* s2, const char* a2) {
    for (; *a1 && *a2; ++a1, ++a2) {
        int winner = act(s1, *a1, s2, *a2);
        if (winner)
            return winner;
    }
    return 0;
}

double frandom() { return (double)rand() / RAND_MAX; }

/* chooses an action based on self and opponent's sharpness */
action choose_action(const caveman_brain b, int s1, int s2) {
    double v[3];
    double sum = 0;
    double r;
    int i;
    for (i = 0; i < 3; ++i) {
        v[i] = eval_program(b[i], s1, s2);
        sum += v[i];
    }
    r = frandom() * sum;
    if (r <= v[0])
        return 'B';
    else if (r <= v[0] + v[1])
        return 'S';
    else
        return 'P';
}

/* portable tick-count for random seed */
#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

int main(int argc, const char* argv[]) {
    const char* filename = DEFAULT_FILENAME;
    const char *a1, *a2;
    FILE* f;
    caveman_brain b;
    int s1 = 0, s2 = 0;
    int i;

    srand(tick_count()); rand();

    a1 = argc > 1 ? argv[1] : "";
    if (*a1) {
        a2 = strchr(a1, ',');
        if (a2 == NULL) {
            printf("invalid input!\n");
            return 1;
        }
        ++a2;
    } else
        a2 = a1;

    if (argc > 2)
        filename = argv[2];

    f = fopen(filename, "r");
    if (f == NULL) {
        printf("failed to open `%s'\n", filename);
        return 1;
    }
    for (i = 0; i < 3; ++i)
        read_program(f, b[i]);
    fclose(f);

    str_act(&s1, a1, &s2, a2);
    printf("%c\n", choose_action(b, s1, s2));

    return 0;
}

Компиляция с: gcc darwin.c -odarwin -w -O3. Запуск с: ./darwin <history>.

Бот считывает коэффициенты из файла, указанного programв players/Darwinкаталоге (в качестве второго аргумента командной строки можно указать другой файл). Эта программа, кажется, делает хорошо:

0.286736 0.381578 -0.128122 1.33933 
0.723126 0.380574 1.21659 -0.9734 
0.924371 0.998632 -0.0951554 0.744323 
-0.113888 -0.321772 -0.260496 -0.136341 

0.280292 -0.699782 -0.246245 1.27435 
-1.24563 -0.959822 -0.745656 0.0347998 
-0.917928 -0.384105 0.319008 -0.70434 
0.484375 0.802138 0.0967234 0.638466 

0.406679 0.597322 1.39409 0.902353 
-0.735946 0.742589 0.955567 0.643268 
-0.503946 0.446167 1.002 0.328205 
0.26037 0.113346 0.0517265 -0.223298 

Сохранить как players/Darwin/program.

Ниже приведена программа, которая генерирует programфайлы, которые могут использоваться ботом (не нужно компилировать, если вы используете programфайл выше):

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

/* magic numbers */
#define SWORD_SHARPNESS 5
#define MAX_TURN_COUNT 100
#define PROGRAM_DIM 4 /* polynomial order + 1 */
#define CAVEMAN_COUNT 500
#define GENERATION_COUNT 12
#define DUEL_COUNT 8
#define ERROR_BACKOFF 0.5
#define DEFAULT_FILENAME "players/Darwin/program"

typedef double real;
typedef real program[PROGRAM_DIM][PROGRAM_DIM];
typedef program caveman_brain[3];

typedef char action; /* S, B or P */
/* encodes a pair of actions */
#define ACTION_PAIR(a1, a2) (((int)(a1) << (sizeof(action) * 8)) | (a2))

real eval_program(const program p, double x, double y) {
    real v = 0;
    int i, j;

    for (i = 0; i < PROGRAM_DIM; ++i) {
        real w = 0;
        for (j = 0; j < PROGRAM_DIM; ++j)
            w = x * w + p[i][j];
        v = y * v + w;
    }

    if (v < 0)
        v = 0;
    return v;
}
void write_program(FILE* f, const program p) {
    int i, j;
    for (i = 0; i < PROGRAM_DIM; ++i) {
        for (j = 0; j < PROGRAM_DIM; ++j)
            fprintf(f, "%g ", p[i][j]);
        fprintf(f, "\n");
    }
    fprintf(f, "\n");
}

int blunt(int* s) {
    int temp = *s;
    if (temp)
        --*s;
    return temp;
}
void sharpen(int* s) { ++*s; }
/* takes two sharpness/action pairs and updates the sharpness accordingly.
 * returns negative value if first caveman wins, positive value if second
 * caveman wins and 0 otherwise. */
int act(int* s1, action a1, int* s2, action a2) {
    switch (ACTION_PAIR(a1, a2)) {
        case ACTION_PAIR('B', 'B'): return 0;
        case ACTION_PAIR('B', 'S'): sharpen(s2); return 0;
        case ACTION_PAIR('B', 'P'): return blunt(s2) >= SWORD_SHARPNESS ? 1 :
                                                                          0;
        case ACTION_PAIR('S', 'B'): sharpen(s1); return 0;
        case ACTION_PAIR('S', 'S'): sharpen(s1); sharpen(s2); return 0;
        case ACTION_PAIR('S', 'P'): sharpen(s1); return *s2 > 0 ? 1 : 0;
        case ACTION_PAIR('P', 'B'): return blunt(s1) >= SWORD_SHARPNESS ? -1 :
                                                                          0;
        case ACTION_PAIR('P', 'S'): sharpen(s2); return *s1 > 0 ? -1 : 0;
        case ACTION_PAIR('P', 'P'): {
            int t1 = blunt(s1), t2 = blunt(s2);
            if (t1 >= SWORD_SHARPNESS && t2 < SWORD_SHARPNESS)
                return -1;
            else if (t2 >= SWORD_SHARPNESS && t1 < SWORD_SHARPNESS)
                return 1;
            else
                return 0;
        }
    }
}
/* processes a pair of strings of actions */
int str_act(int* s1, const char* a1, int* s2, const char* a2) {
    for (; *a1 && *a2; ++a1, ++a2) {
        int winner = act(s1, *a1, s2, *a2);
        if (winner)
            return winner;
    }
    return 0;
}

double frandom() { return (double)rand() / RAND_MAX; }
double firandom() { return 2.0 * rand() / RAND_MAX - 1.0; }

/* chooses an action based on self and opponent's sharpness */
action choose_action(const caveman_brain b, int s1, int s2) {
    double v[3];
    double sum = 0;
    double r;
    int i;
    for (i = 0; i < 3; ++i) {
        v[i] = eval_program(b[i], s1, s2);
        sum += v[i];
    }
    r = frandom() * sum;
    if (r <= v[0])
        return 'B';
    else if (r <= v[0] + v[1])
        return 'S';
    else
        return 'P';
}

typedef struct {
    caveman_brain brain;
    int sharpness;
    int score;
} caveman;
void init_caveman(caveman* c, const caveman* m, double e) {
    int p, i, j;
    c->score = 0;
    for (p = 0; p < 3; ++p) {
        for (i = 0; i < PROGRAM_DIM; ++i) {
            for (j = 0; j < PROGRAM_DIM; ++j) {
                c->brain[p][i][j] = m->brain[p][i][j] + firandom() * e;
            }
        }
    }
}
int duel(caveman* c1, caveman* c2) {
    int winner;
    int turn;
    c1->sharpness = c2->sharpness = 0;
    for (turn = 0; turn < MAX_TURN_COUNT; ++turn) {
        winner = act(&c1->sharpness,
                     choose_action(c1->brain, c1->sharpness, c2->sharpness),
                     &c2->sharpness,
                     choose_action(c2->brain, c2->sharpness, c1->sharpness));
        if (winner)
            break;
    }
    if (winner < 0)
        ++c1->score;
    else if (winner > 0)
        ++c2->score;
    return winner;
}

/* portable tick-count for random seed */
#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

int main(int argc, const char* argv[]) {
    const char* filename = DEFAULT_FILENAME;
    FILE* f;
    caveman* cavemen;
    caveman winner;
    int gen;
    double err = 1.0;
    int i;

    srand(tick_count()); rand();
    memset(&winner, 0, sizeof(caveman));

    if ((cavemen = (caveman*)malloc(sizeof(caveman) * CAVEMAN_COUNT)) == NULL) {
        printf("not enough memory!\n");
        return 1;
    }

    for (gen = 0; gen < GENERATION_COUNT; ++gen) {
        int i, j, k;
        const caveman* leader;

        printf("[Gen. %d / %d] ", gen + 1, GENERATION_COUNT);
        fflush(stdout);

        for (i = 0; i < CAVEMAN_COUNT; ++i)
            init_caveman(&cavemen[i], &winner, err);

        for (i = 0; i < CAVEMAN_COUNT; ++i) {
            for (j = i + 1; j < CAVEMAN_COUNT; ++j) {
                for (k = 0; k < DUEL_COUNT; ++k)
                    duel(&cavemen[i], &cavemen[j]);
            }
        }

        leader = cavemen;
        for (i = 1; i < CAVEMAN_COUNT; ++i) {
            if (cavemen[i].score > leader->score)
                leader = &cavemen[i];
        }

        printf("Caveman #%d wins with %d victories in %d duels\n",
               leader - cavemen + 1,
               leader->score, (CAVEMAN_COUNT - 1) * DUEL_COUNT);

        memcpy(&winner, leader, sizeof(caveman));
        err *= ERROR_BACKOFF;
    }

    free(cavemen);

    if (argc > 1)
        filename = argv[1];
    printf("Dumping brain to `%s'\n", filename);
    f = fopen(filename, "w");
    if (f == NULL) {
        printf("failed to open `%s'\n", filename);
        return 1;
    }
    for (i = 0; i < 3; ++i)
        write_program(f, winner.brain[i]);
    fclose(f);

    return 0;
}

Компиляция с: gcc genprog.c -ogenprog -w -O3. Запуск с: ./genprog [output-filename].


Уотсон

Что такое ДНК победившего пещерного человека? Возможно, у этого парня есть ответ:

# That's the actual logic. Initialization goes below.
def run():
    if his_sharpness[-10] - turn / 15 + 1 + turn % 3 - his_sharpness[-6] < 0:
        act(B=0, S=0, P=100) # 7.21% chance
    elif his_sharpness[-6] + 1 - his_sharpness[-2] < 0:
        act(B=0, S=0, P=100) # 4.15% chance
    elif his_history[-3] - my_history[-1] <= 0 and my_sharpness[-1] - turn / 10 <= 0:
        act(B=0, S=100, P=0) # 11.34% chance
    elif his_sharpness[-1] == 0:
        act(B=0, S=100, P=0) # 27.84% chance
    else:
        act(B=100, S=0, P=0) # 49.46% chance

# Boring stuff go here...

import sys, random

# Actions
block, sharpen, poke, idle = range(4)

# Converts textual history to internal format
def convert_history(textual_history):
    return ["BSP".index(action) for action in textual_history]

# Calculates sharpness after performing an action sequence
def calculate_sharpness(history):
    return history.count(sharpen) - history.count(poke)

# Returns a list containing the sharpness at the end of each turn
def sharpness_history(history):
    return [calculate_sharpness(history[:i + 1]) for i in range(len(history))]

# Acts based on the probability distribution (B%, S%, P%)
def act(B, S, P):
    r = random.random() * 100
    print "BSP"[(r >= B) + (r >= B + S)]

# Setup data
textual_history = sys.argv[1] if len(sys.argv) > 1 else ","
my_history, his_history = (convert_history(h) for h in textual_history.split(','))
my_sharpness, his_sharpness = (sharpness_history(h) for h in (my_history, his_history))
turn = len(my_history)
my_history, his_history = ([idle] * 16 + h for h in (my_history, his_history))
my_sharpness, his_sharpness = ([0] * 16 + s for s in (my_sharpness, his_sharpness))

# Make a move
run()

Бежать с: python Watson.py

Уотсон является продуктом генетического алгоритма. В отличие от Дарвина, генетическая база данных на этот раз является реальной программой, написанной на крошечном доменно-специфическом языке (здесь переведено на Python).


Простая последовательность бьет крупных игроков

Этот маленький парень делает удивительно (или, может быть, не так удивительно) хорошо, особенно против лидеров:

import sys
print "Simple Sequence Beats Big Players".split(' ')[
    len(sys.argv[1]) / 2 % 5 if len(sys.argv) > 1 else 0
]

Бежать с: python SSBBP.py


Как мне скомпилировать и запустить это? Кроме того, как уже упоминалось в вопросе, вы можете только читать / записывать файлы в players/Darwinкаталоге.
Дверная ручка

@ Doorknob: исправлено.
DarwinBot

Я получаю эти ошибки компиляции при компиляции этого кода. (Я нахожусь на Ubuntu 14.04.)
Ручка двери

@ Doorknob: исправлено. Должен работать сейчас.
DarwinBot

Я сейчас получаю undefined reference to `fmax'. - Редактировать-- Неважно, мне действительно нужно -lm.
Ручка двери

50

Непредсказуемый пещерный человек

me, he = (ARGV[0] || ' , ').split(',')

@possible_actions = %w[Sharpen Poke Block]

class String

  def sharpness
    @sharpness ||= count('S') - count('P')
  end

  def has_pointy_stick
    (1..4).cover? sharpness
  end

  def has_sword
    sharpness >= 5
  end

  def scary
    sharpness > 0
  end

end

def no action
  @possible_actions.delete(action)
end

def do!
  puts @possible_actions.sample[0]
end

no 'Block' if not he.has_pointy_stick

no 'Poke' if not me.scary

no 'Sharpen' if me.has_sword

no 'Block' if me.has_sword

do!

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

Это Ruby, сохраните его как unpredictable.rb и запустите ruby unpredictable.rb


На самом деле, я думаю, что так и no 'Block'должно быть, если у моего противника есть меч.
njzk2

Первый «Блок» на самом деле охватывает это: острая палка - это не меч.
гистократ

2
Почему вы не используете unlessдля no 'Block'и no 'Poke'заявления? ( no 'Block' unless he.has_pointy_stick)
wchargin

25

Пещерный Доктор - Луа

«Я проигрываю новым иностранцам, нокаутирую их изучать»

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

caveman={havePointyStick=function (t)     
   local pointy=0   
   for i in t.stick:gmatch("[SP]") do
    if i=="S" then 
      pointy=pointy+1
    elseif pointy>0 then
      pointy=pointy-1
    end   
   end 
 t.sharp=pointy>0
 t.lastmove=t.stick:sub(t.stick:len())
 return pointy 
 end,
    Stupid=function (stick)--I put way to much effort in this...
      o = {} 
      setmetatable(o, caveman)
      o.smartness=0
      o.stick=stick
      caveman.__index = caveman
      return o
    end,
     Smart= function (stick)
      o ={} 
      setmetatable(o, caveman)
      o.smartness=100
      o.stick=stick
      caveman.__index = caveman
      return o
    end
       }


    if arg[1]==nil then  
       print("S")
    else   
      split=arg[1]:find(",")  
      me=caveman.Smart(arg[1]:sub(0,split-1)) 
      he=caveman.Stupid(arg[1]:sub(split+1)) 
      mesharp=me:havePointyStick()  
      hesharp=he:havePointyStick()
      if not he.sharp and mesharp<5 then print("S")--Go for the sword  
      elseif mesharp>4 or me.stick:len()>93 then
         if (mesharp>0) then print("P")--We're losing/about to win or time's running out
         else print("S")--uh-oh
         end
      else 
         u,g,h=he.stick:match("(B+)S+(B+)S+(B+)$")
         g,u,h=he.stick:match("(P+)S+(P+)S+(P+)$")
         if u~=nil and u==g and g==h then 
            if not me.sharp then print("S")
            else print("P")
            end
         elseif me.stick:match("SBSB$")~=nil then print("B")
         elseif he.stick:len()>7 and he.stick:match("P")==nil and me.lastmove~="S" then print("S")
         else
         b,u,h=he.stick:match("(B*)(S+)(B*)$")
         if u~=nil then
             if (h:len()>3 and me.lastmove=="B") or (b:len()>h:len() and b:len()>0 and h:len()>0) then print("S")
             else print("B")
             end
          else print("B")
          end   
      end   
   end 
end

Бежать с: lua CaveDoctor.lua


3
Это только проиграет дважды в текущем списке лидеров? oO
полугодие

Редакция 5 выдает кучу ошибок, поэтому ревизия 4 включена в текущий раунд испытаний.
Ручка двери

@ Doorknob Я думаю, я исправил все из них, в любом случае было только одно изменение в реальной логике.
Nexus

20

ForeignCaveman

ForeignCaveman понятия не имеет, что вы только что сказали. Он просто ... делает вещи.

javac ForeignCaveman.java тогда java ForeignCaveman

public class ForeignCaveman {

    public static void main(String[] args) {
        int m = (int) (Math.random()*3);
        switch(m) {
            case 0: System.out.println('B'); 
                    break;
            case 1: System.out.println('P'); 
                    break;
            case 2: System.out.println('S'); 
                    break;
        }
   }
}

11
Это, вероятно, имеет слишком много голосов против того, насколько это плохо
Кевин Л.

19

Вице-лидер

Дверная ручка ♦ является лидером. Мне хочется быть лидером! Следуйте супер интеллектуальной программе, чтобы стать лидером!

Компиляция: javac ViceLeader.javaRun: java ViceLeader.

public class ViceLeader {

    public static void main(String[] args) {
        if (args.length == 0 || !args[0].contains(",")) {
            System.out.print("S");
            return;
        }
        String[] history = args[0].split(",");
        int mySharpness = getSharpness(history[0]);
        int enemySharpness = getSharpness(history[1]);

        // enough sharpness to strike until end of game
        if (100 - history[0].length() <= mySharpness) {
            System.out.print("P");
            return;
        }

        // sharpen while secure
        if (enemySharpness == 0) {
            System.out.print("S");
            return;
        }

        // enemy blocks the whole time and I didn't use this tactic on last turn
        if (isBlocker(history[1]) && history[0].charAt(history[0].length() - 1) != 'S') {
            System.out.print("S");
            return;
        }

        // TAKE HIM OUT!
        if (enemySharpness == 4 || mySharpness >= 5) {            
            System.out.print("P");
            return;
        }

        // enemy sharpens the whole time => sharpen to strike on next turn
        if (isSharpener(history[1])) {
            System.out.print("S");
            return;
        }

        System.out.print("B");
    }

    private static int getSharpness(String history) {
        int sharpness = 0;
        for (char move : history.toCharArray()) {
            if (move == 'S') {
                sharpness++;
            } else if ((move == 'P' && sharpness > 0) || move == '^') {
                sharpness--;
            }
        }
        return sharpness;
    }

    private static boolean isBlocker(String history) {
        if (history.length() < 3) {
            return false;
        }
        for (int i = history.length() - 1; i > history.length() - 3; i--) {
            if (history.charAt(i) != 'B') {
                return false;
            }
        }
        return true;
    }

    private static boolean isSharpener(String history) {
        if (history.length() < 3) {
            return false;
        }
        for (int i = history.length() - 1; i > history.length() - 3; i--) {
            if (history.charAt(i) != 'S') {
                return false;
            }
        }
        return true;
    }
}

Почему это не if (enemySharpness <= 4 || mySharpness >= 5)против ==?
durron597

@ durron597 Потому что я хочу атаковать врага, только если он сможет сделать меч на следующем ходу (что он, скорее всего, сделает). VizeLeader не совать часто, он делает это в нужное время .
CommonGuy

Но у вас есть меч, а у вашего противника нет ...
durron597

@ durron597 Нет, это оператор OR. Это означает «ткните противника, если у меня есть меч ИЛИ если у него скоро будет меч».
CommonGuy

7
О мой Бог. Время получить еще одну чашку кофе :) Или новые контактные линзы
durron597

15

Может быть Марков 2.1

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

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

Код содержит много ненужных операторов, но он работает довольно хорошо.

РЕДАКТИРОВАТЬ

Обнаружен недостаток в логике. Теперь он действительно что-то делает, когда у него есть меч.

$ python3 players/MaybeMarkov/MaybeMarkov.py

import sys, itertools
from operator import itemgetter
from collections import defaultdict

SHARPEN, POKE, BLOCK, HALP = 'SPB?'

all_actions = SHARPEN, POKE, BLOCK
always = 1

def do(action):
    print(action)
    exit(0)

if len(sys.argv) < 2:
    do(SHARPEN)

class status:
    def __init__(self, actions):
        self.step = len(actions)
        self.last = actions[-1]
        self.sh = self.sharpness = actions.count(SHARPEN) - actions.count(POKE)
        self.dull = self.sharpness <= 0
        self.has_sword = self.sharpness >= 5
        self.actions = actions
        self.ratio = {act:actions.count(act)/self.step for act in all_actions}
        self.can_do = set(all_actions)

        if self.dull:
            self.can_do.remove(POKE)

    def can(self, action):
        return action in self.can_do


me, he = map(status, sys.argv[-1].split(','))
turns = me.step

if he.has_sword:
    if me.can(POKE)                :do(POKE)
    if always                      :do(SHARPEN)

if me.has_sword:
    if he.last != POKE and me.last == BLOCK :do(POKE)
    if he.can(POKE)                :do(BLOCK)
    if always                      :do(POKE)

if not he.can(POKE)                :do(SHARPEN)

if turns <= 4                      :do(BLOCK)
if turns < 30:
    if he.ratio[SHARPEN] == 1:
        if me.can(POKE)            :do(POKE)
        if always                  :do(SHARPEN)
    if always                      :do(BLOCK)

if turns > 97:
    do(POKE)

def react_on(action):
    do({
        HALP    : BLOCK,
        SHARPEN : POKE,
        POKE    : BLOCK,
        BLOCK   : SHARPEN
    }[action])

states = tuple(itertools.product(all_actions, all_actions))
change = defaultdict(lambda:defaultdict(lambda:0))
count  = defaultdict(lambda:0)

for i in range(1, turns):
    prev = me.actions[i-1], he.actions[i-1]
    now  = me.actions[i]  , he.actions[i]
    change[prev][now] += 1
    count[prev] += 1

current = change[me.last, he.last]
prediction = HALP

if len(current) is 0:
    do(BLOCK)

if len(current) is 1:
    if tuple(current.values())[0] > turns / 7:
        prediction = tuple(current.keys())[0][1]

counts = itemgetter(1)

if len(current) > 1:
    key1, value1 = max(current.items(), key=counts)
    current[key1] *= 0.9
    key2, value2 = max(current.items(), key=counts)
    if key1 == key2:
        prediction = key1[1]

react_on(prediction)

14

PeriodicalCicadaCaveman

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

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

скомпилировать: mcs program.cs для запуска mono program.exe

public class PeriodicalCicadaCaveman
{
  const int Periodic = 13; //Could be 17
  public static void Main(string[] args)
  {
    if (args.Length == 0) 
    {
          System.Console.WriteLine("S");
          return;
    }
    var arg1 = args[0];
    if(arg1.Length == 0) 
    {
        //Always start with a sharp stick
        System.Console.WriteLine("S");
        return;
    }
    var myHistory = arg1.Split(',')[0];
    var theirHistory = arg1.Split(',')[1];
    int sharpness = 0;
    int timeElapsed =  myHistory.Length;

    for(int i = 0; i < timeElapsed; i++)
    {
        if(myHistory[i] == 'S')  
        {
            sharpness++;
        }
        if(myHistory[i] == 'P')
        {
            sharpness--;
        }
    }

    if((myHistory.Length % 13) == 0 
            || timeElapsed > 90 // Running out of time! To hell with the routine
        )
    {
        //The Secada strikes!
        if(sharpness > 1)
        {
            System.Console.WriteLine("P");
            return;
        }
        else
        {
            System.Console.WriteLine("S"); 
            return;
        }
    }
    System.Console.WriteLine("B"); 

  }

}

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

Edit2: добавлено в предложении Бобса

Изменить: Изменено только тыкать, когда на 2 резкости, если палка когда-либо на нуле, другой парень может сделать меч.


1
Я бегу на Ubuntu; это будет компилироваться под Mono? Если да, то как мне его скомпилировать и как его запустить?
Дверная ручка

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

5
@Doorknob mcs program.csскомпилирует его, mono programзапустит, но вам нужно заменить foo.Dump();s на System.Console.WriteLine(foo);(или добавить метод расширения public static void Dump(this string value) { System.Console.WriteLine(value); }).
Боб

@Bob Спасибо, приятель, я добавил в твой метод расширения.
Майки Маус

Извините, фактическое имя файла по умолчанию mcsсоздает <filename>.exe, например program.cs, станет program.exe. Таким образом, команда запуска будет mono program.exe. (У меня не было доступа к моно во время моего предыдущего комментария.)
Боб

14

FancyTechnoAlgorithm

Необычный техно алгоритм для необычной техно компьютерной программы.

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

import random, sys  # Need import some advanced techno code

if __name__ == '__main__':  # If fancy techno computer program is main

    try:  # Me try use fancy techno algorithm!

        me, he     = sys.argv[1].split(",")
        mePointy   = me.count("S") - me.count("P")
        hePointy   = he.count("S") - he.count("P")
        meCanPoke  = mePointy > 0
        heCanPoke  = hePointy > 0
        meHasSword = mePointy >= 5
        heHasSword = hePointy >= 5
        meScary    = meCanPoke + meHasSword 
        heScary    = heCanPoke + heHasSword

        # Me donno fancy coding math algoritm.
        # Math confuse. Me code work, me happy.
        if he[-6:] == "SB"*3:
            print "SP"[meCanPoke]
        elif (len(he) > 30 and he[-3:].count("B") > 2) or \
             (hePointy > 2 and he.count("SSBB") > 0 and he.count("BBS") > 0):
            if meHasSword:
                print "P"
            else:
                print "SB"[me[-1] == "S"]
        elif hePointy > 3 and he.count("BBS") > 2:
            print "SP"[me[-1] == "S"]
        else:
            print random.choice(\
                [["S", "SP", "P" ],\
                 ["B", "B" , "P" ],\
                 ["S", "P" , "P" ]][heScary][meScary])

    except:  # Fancy techno algorithm Failed... Me just sharpen.
        print "S"

Программа Python 2. Бежать:python fancytechnoalgorithm.py


Это прерывается, когда нет ввода (т.е. при первом повороте). Я не знаю, как вы хотите справиться с этим, поэтому мне придется исключить это из первого раунда тестирования.
Дверная ручка

@ Doorknob Для первого ввода это "," или ""? Я думаю, это последний из этого.
Векторизовано

Для первого ввода не будет никаких аргументов (он будет запущен как python StickSharpener.py).
Дверная ручка

@ Doorknob Я отредактировал это. Посмотрите, работает ли это сейчас.
Векторизовано

Хорошо, спасибо! Я включу это в следующий раунд испытаний.
Ручка двери

14

Наблюдатель

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

import sys, random

if len(sys.argv) > 1:
    history_self, history_other = sys.argv[1].split(',')
else:
    history_self = history_other = ""

def sharpness(history):
    ret = 0
    for action in history:
        if action == 'S':
            ret += 1
        elif action == 'P' and ret > 0:
            ret -= 1
    return ret

def weighted_random(dict):
    i = random.randrange(sum(dict.values()))
    for k, v in dict.items():
        i -= v
        if i < 0:
            return k

def action(history_self, history_other):
    sharpness_self = sharpness(history_self)
    sharpness_other = sharpness(history_other)
    if sharpness_self >= 5:
        return 'P'
    elif sharpness_other == 0:
        return 'S'  #Guaranteed safe
    elif sharpness_other == 1:
        #If the opponent isn't interested in a sword, time is on our side
        block_count = len(history_self) - len(history_self.rstrip('B'))
        if block_count > 3 and random.randrange(block_count) > 3:
            return 'S'
        else:
            return 'B'
    elif sharpness_other >= 5:
        return 'S'
    else:
        #Search for a weakness
        for i in range(10, 2, -1):
            if history_other[-i:] == history_other[-i*2:-i]:
                predicted_action = history_other[-i]
                if predicted_action == 'S':
                    if sharpness_self > 0:
                        return 'P'
                    else:
                        return 'S'
                elif predicted_action == 'B':
                    return 'S'
                elif predicted_action == 'P':
                    return 'B'
        #Presumably the opponent is random - respond with some educated randomness
        if sharpness_self == 0:
            return random.choice(['S','S','B'])
        return weighted_random({
            'S': sharpness_self,
            'B': 1,
            'P': sharpness_other,
        })

if __name__ == "__main__":
    print(action(history_self, history_other))

Имя файла: watcher.py

Бежать: python watcher.py

василиск

Стремится уничтожить тех, кто смотрит на него слишком внимательно. Последовательно побеждает наблюдателя, но, вероятно, будет хуже в целом.

import sys, random

if len(sys.argv) > 1:
    history_self, history_other = sys.argv[1].split(',')
else:
    history_self = history_other = ""

def sharpness(history):
    ret = 0
    for action in history:
        if action == 'S':
            ret += 1
        elif action == 'P' and ret > 0:
            ret -= 1
    return ret

def action(history_self, history_other):
    sharpness_self = sharpness(history_self)
    sharpness_other = sharpness(history_other)
    if sharpness_self >= 5:
        return 'P'
    elif len(history_self) < 13:
        return 'SBBSBPSBBSBPP'[len(history_self)]
    elif 5 + 5 * sharpness_self < random.randrange(len(history_self)):
        return 'S'
    elif sharpness_other == 0:
        if sharpness_self == 0 or random.randrange(sharpness_self) == 0:
            return 'S'
        else:
            return 'P'
    elif sharpness_other == sharpness_self:
        return 'P'
    else:
        return 'B'

if __name__ == "__main__":
    print(action(history_self, history_other))

Имя файла: basilisk.py

Бежать: python basilisk.py

Nash

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

import sys, random

if len(sys.argv) > 1:
    history_self, history_other = sys.argv[1].split(',')
else:
    history_self = history_other = ""

movemap = [ [(1.000000,0.000000),(0.473863,0.526137),(0.394636,0.605364),(0.490512,0.509488),(1.000000,0.000000)],
        [(0.695328,0.000000,0.304672),(0.275953,0.582347,0.141700),(0.192635,0.700391,0.106974),(0.196343,0.689662,0.113995),(0.289968,0.544619,0.165413)],
        [(0.570635,0.000000,0.429365),(0.236734,0.570126,0.193139),(0.167197,0.687133,0.145670),(0.173139,0.667169,0.159693),(0.264911,0.475316,0.259773)],
        [(0.490512,0.000000,0.509488),(0.196309,0.578888,0.224803),(0.135744,0.692358,0.171898),(0.140638,0.663397,0.195965),(0.220709,0.426989,0.352302)],
        [(1.000000,0.000000,0.000000),(0.147944,0.636760,0.215296),(0.089478,0.737358,0.173165),(0.087259,0.704604,0.208137),(0.128691,0.435655,0.435655)]  ]

def sharpness(history):
    ret = 0
    for action in history:
        if action == 'S':
            ret += 1
        elif action == 'P' and ret > 0:
            ret -= 1
    return ret

def action(history_self, history_other):
    sharpness_self = sharpness(history_self)
    sharpness_other = sharpness(history_other)
    if sharpness_self >= 5:
        return 'P'
    elif sharpness_other >= 5:
        return 'S'
    moves = movemap[sharpness_self][sharpness_other]
    v = random.random()
    if v < moves[0]:
        return 'S'
    elif v < moves[0] + moves[1]:
        return 'B'
    else:
        return 'P'

if __name__ == "__main__":
    print(action(history_self, history_other))

Это не совсем равновесие Нэша (у моего генератора стратегий есть некоторая нестабильность), но оно близко.

Ради любопытства ниже приведены оценки вероятности победы этого бота в каждом игровом состоянии:

map = [ [0.50000000,0.26337111,0.15970733,0.08144046,0.00000000,0.00000000],
        [0.73662889,0.50000000,0.37879183,0.28035985,0.16622410,0.00000000],
        [0.84029267,0.62120817,0.50000000,0.39441630,0.26038353,0.00000000],
        [0.91855954,0.71964015,0.60558370,0.50000000,0.35246401,0.00000000],
        [1.00000000,0.83377590,0.73961647,0.64753599,0.50000000,0.00000000],
        [1.00000000,1.00000000,1.00000000,1.00000000,1.00000000,0.50000000] ]

Имя файла: nash.py

Бежать: python nash.py

Финт

Открывается быстрой атакой, чтобы проверить защиту противника.

import sys, random

if len(sys.argv) > 1:
    history_self, history_other = sys.argv[1].split(',')
else:
    history_self = history_other = ""

def sharpness(history):
    ret = 0
    for action in history:
        if action == 'S':
            ret += 1
        elif action == 'P' and ret > 0:
            ret -= 1
    return ret

def action(history_self, history_other):
    sharpness_self = sharpness(history_self)
    sharpness_other = sharpness(history_other)
    if sharpness_self >= 5:
        return 'P'
    elif len(history_self) < 2:
        return 'SP'[len(history_self)]
    elif history_other[1] == 'P':
        # Fierce fight
        if sharpness_self == 0:
            return 'S'
        elif history_self[-(1 + history_self.count('P'))] == 'S':
            return 'P'
        else:
            return 'B'
    else:
        # Smart guy
        if sharpness_other == 1:
            return 'B'
        elif history_self[-1] != 'S' or history_self[-4:] == 'BSBS':
            return 'S'
        elif history_other.count('S') > history_other.count('B'):
            return 'P'
        else:
            return 'B'

if __name__ == "__main__":
    print(action(history_self, history_other))

Имя файла: feint.py

Бежать: python feint.py

LatePokeBot

Маленький брат PokeBot. Никогда не проявляет слабости, но пытается бороться, как его старший брат.

import sys, random

if len(sys.argv) > 1:
    history_self, history_other = sys.argv[1].split(',')
else:
    history_self = history_other = ""

def sharpness(history):
    ret = 0
    for action in history:
        if action == 'S':
            ret += 1
        elif action == 'P' and ret > 0:
            ret -= 1
    return ret

def action(history_self, history_other):
    sharpness_self = sharpness(history_self)
    return 'SSP'[sharpness_self]

if __name__ == "__main__":
    print(action(history_self, history_other))

Имя файла: latepokebot.py

Бежать: python latepokebot.py


Вы скучали :по Василиску; Я исправил это для тебя
дверная ручка

Это представление вызвало какую-то ошибку или исключение в какой-то момент; Возможно, вы захотите исправить это до следующего раунда испытаний. (
Василийский

@ Doorknob Я выбрал начальную последовательность для Василиска, посмотрев на предположения, сделанные «Наблюдателем» и «Пещерным доктором», и нашел последовательность, которая могла бы сделать эти предположения ошибочными. Это нарушает правило "пещерные люди справедливы"?
Brilliand

Иди, Нэш! Выиграйте ровно половину своих матчей против всех достаточно умных ботов, чтобы избежать опций P = 0!
aschepler

12

PokeBot

Написано на Ruby.

puts((ARGV.shift || "P,").match(/(.),/)[1] == "P" ? "S" : "P")

Беги с ruby pokebot.rb.

Этот бот не очень умный; это делает то, что обычный пещерный человек все равно будет делать сам.


9

PatientWolf v2.0

Точит, если скучно, тыкает, если у врага будет меч на следующем ходу, или если враг скучен, блокирует иначе.

my ($me,$him) = split(/,/,$ARGV[0]);
if(!defined $me) {
    print "S";
    exit;
}
my $mysharpness =()= ($me =~ /S/g);
$mysharpness -= ($me =~ /P/g);
my $opponentsharpness =()= ($him =~ /S/g);
$opponentsharpness -= ($him =~ /P/g);
if($mysharpness == 0) {
    print "S";
} elsif($opponentsharpness <= 0 || $opponentsharpness == 4) {
    print "P";
} else {
    print "B";
}

Бежать с

perl patientwolf.pl

РЕДАКТИРОВАТЬ: спасибо @sylwester за указание на ошибку


Поскольку вы получаете только один аргумент с обеими историями, разделенными запятой, вы неправильно его анализируете. Например. PatientWolf.pl SB,SPделает, Pтак как он думает, что у него острая палка.
Сильвестр

@ Сильвестр, это не правильно. Первая строка присваивает первый аргумент $ me, а второй аргумент - $ ему
killmous

Программа CavemanDuel не использует два аргумента, только один. например. perl patientwolf.pl "SB,SP", Вы должны сделать my($me,$him) = split/,/ $ARGV[0];и if( @ARGV ) {print "S";exit}.
Сильвестр

@ Сильвестр, хорошо, я понимаю, к чему ты клонишь. Это не было ясно из OP или из-за быстрого взгляда, который я бросил на код контроллера. Я исправлю это в ближайшее время
убийственный

9

Бинарный пещерный человек

Резкость, удар, повторение

Основываясь на идее, что блокировка предназначена для баб, этот пещерный человек чередует два оставшихся варианта.

public class BinaryCaveman { 

    public static void main(String[] args) {
        int timelapse = 0;
        if(args.length>0)
        {
            timelapse = ((args[0].length() - 1) / 2);
        }
        switch(timelapse % 2) 
        {
            case 0: System.out.println('S'); 
                    break;
            case 1: System.out.println('P'); 
                    break;
        }
    }
}

Компилировать с javac BinaryCaveman.java

Бежать с java BinaryCaveman

РЕДАКТИРОВАТЬ: Приключения в строковых массивах ..... args.length () выдает ошибку. args.length всегда возвращает 1. args [0] .length () возвращает длину первой строки в массиве.

РЕДАКТИРОВАТЬ 2: Обновлено благодаря помощи от Doorknob, Brilliand и Sylwester. Спасибо, парни.


@ MartinBüttner Я забыл разделить аргументы - 1 на 2, чтобы получить количество прошлых представлений только одним игроком. Исправлено. Я не могу понять подчинение Дорнкоба, рубин для меня - практически бред. Всегда ли он начинается с заточки?
Red_Shadow

Да, он просто проверяет, был ли его последний ход, Pили Sделает наоборот. И если истории еще нет, он притворяется, что история будет P,(что затем побуждает его сделать в Sпервую очередь).
Мартин Эндер

Два разных подхода, которые приводят к одному и тому же результату. Это против правил?
Red_Shadow

Наверное, нет, я просто дал бы вам знать.
Мартин Эндер

2
@ Doorknob Думаю, так и должно быть args[0].length(), нет args.length.
Brilliand

8

CavekidBlocks

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

import sys, math, random
def count(a):
    s = 0
    for i in range(len(a)):
        if a[i] == 'P': s-=1
        elif a[i] == 'S': s+=1
        if s < 0: s = 0
    return s
kid = []
scary_adult = []
what2do = 'Sharpen the Stick! Why not? Adult may be doing the same. DONT trust adults!'
if len(sys.argv) > 1:
    kid, scary_adult = sys.argv[1].split(",")
    kid_stick_sharpness = count( kid )
    scary_adult_stick_sharpness = count( scary_adult )
    if (scary_adult_stick_sharpness >= 2):
        what2do = "Block! Block! Block! Adult's stick looks scary sharp."
    elif (kid_stick_sharpness > 0):
        what2do = 'Point your Stick to the adult. It may scary him.'
    else:
        what2do = 'Sharpen the Stick!'

    # Roll d20 for a courage check.
    dice = random.randint(1,20)
    if (dice > 15): what2do = 'Poke the adult! Critical Hit!'
    elif (dice <= 5): what2do = 'Block! Block! Block!'
print(what2do[0])

Бежать с python3 cavekidblocks.py

ChargerMan

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

import sys, math, random
def countSharpness(a):
    s = 0
    for i in range(len(a)):
        if a[i] == 'P': s-=1
        elif a[i] == 'S': s+=1
        if s < 0: s = 0
    return s
def getHistory():
    me = ""
    him = ""
    if len(sys.argv) > 1:
        me, him = sys.argv[1].split(",")
    return me,him
if __name__ == '__main__':
    me, him = getHistory()
    me_s = countSharpness(me)
    him_s = countSharpness(him)
    answer = 'B'
    # First Case
    if (len(me) == 0):
        answer = 'S'
    # I have a sword
    elif (me_s == 5):
        answer = 'P'
    # Cant let he gets a sword
    elif (him_s == 4):
        answer = 'P'
    # His sword is dull
    elif (him_s == 0):
        # He may try to sharp
        # Cant attack? Sharp my stick
        if (me_s == 0): answer = 'S'
        else:
            if (random.randint(0,33) != 0): answer = 'S'
            else: answer = 'P'
    elif (len(him) % 5 == 0):
        # Decide what to do based on the
        # opponent last 3 movements.
        hist = him[-3:]
        # Does he like to block?
        if (hist.count('B') >= 2): answer = 'S'
    print(answer)

Бежать с python3 chargerman.py

обманщик

Трикстер не знает, как бороться, поэтому он пытается сбить с толку другого пещерного человека.

import sys, math
a = "PPS"
i = 0
if (len(sys.argv) > 1): i = math.floor(((len(sys.argv[1])-1)/2) % 3)
print(a[i])

Бежать с python3 trickster.py

К сожалению, после коммита acc74 Trickster больше не работает, как планировалось.


4
Эта программа-обманщик зла
Nexus

@Nexus Я тоже так думаю. К сожалению, в дуэлях у Трикстера не все в порядке.
wendelbsilva

7

Hodor

Ходор не очень агрессивен. Он любит оставаться в своем щите, если нет хорошей возможности нанести удар.

скомпилировать с: javac Hodor.javaи запустить с:java Hodor

код:

public class Hodor {
    public static void main(String[] args){

        String previousMoves = null;

        //account for no input
        if(args.length == 0){
            System.out.print('S');
            System.exit(0);
        }else{
            previousMoves = args[0];
        }

        //declare variables
        char action = 'S';
        int enemySharpens = 0, enemyPokes = 0, myPokes = 0, mySharpens = 0;
        String[] movesArray = previousMoves.split(",");
        char[] enemyMoves = movesArray[1].toCharArray(), myMoves = movesArray[0].toCharArray();

        //determine enemy sharpness
        for(int i=0; i<enemyMoves.length; i++){
            if(enemyMoves[i] == 'S'){
                enemySharpens++;
            }else if(enemyMoves[i] == 'P'){
                enemyPokes++;
            }
        }

        //block if opponent can poke, else sharpen
        if(enemySharpens - enemyPokes > 0){
            action = 'B';
        }else{
            action = 'S';
        }

        //determine my sharpness
        for(int i=0; i<movesArray[0].length(); i++){
            if(myMoves[i] == 'P'){
                myPokes++;
            }else if(myMoves[i] == 'S'){
                mySharpens++;
            }
        }

        //poke as much as possible if the game is about to end
        if((mySharpens-myPokes) > (100-enemyMoves.length)){
            action = 'P';
        }

        try{
            //sharpen if opponent blocks 2 times in a row and I didn't just sharpen
            if((enemyMoves[enemyMoves.length-1] == 'B') && (enemyMoves[enemyMoves.length-2] == 'B') && (myMoves[myMoves.length-1] != 'S')){
                action = 'S';
            }
            //poke if opponent sharpens twice in a row
            if((enemyMoves[enemyMoves.length-1] == 'S') && (enemyMoves[enemyMoves.length-2] == 'S')){
                action = 'P';
            }
            //poke if the opponent just sharpened/blocked then poked, has a blunt stick, and my stick isn't blunt
            if((enemyMoves[enemyMoves.length-2] != 'P') && (enemyMoves[enemyMoves.length-1] == 'P') && (enemySharpens-enemyPokes == 0) && (mySharpens - myPokes > 0)){
                action = 'P';
            }
        }catch (ArrayIndexOutOfBoundsException e){
            //not enough info
        }

        //poke if we have a sword
        if(mySharpens-myPokes > 4){
            action = 'P';
        }

        System.out.print(action);
    }
}

Изменить: незначительное обновление кода


Это представление вызвало какую-то ошибку или исключение в какой-то момент; Возможно, вы захотите исправить это до следующего раунда испытаний.
Ручка двери

1
Попробуй с SB,BB. Когда другие пещерные люди плохо себя ведут в первый ход, Ходор тоже плохо себя ведет.
Сильвестр

7

Спекулятивный Сильвестр - Perl5

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

Что касается, когда противник тупой, он пытается быть агрессивным, но в конечном счете начнет копить на меч, когда это кажется бесплодным.

#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

## Valid operations
my $SHARPEN = "S";
my $POKE    = "P";
my $BLOCK   = "B";

## It will also print resolution to stderr
my $VERBOSE = 0;

my $first_move = not @ARGV;
my ($me, $you) = split(',', $ARGV[0]) unless( $first_move );

## What do I do?
me_do($SHARPEN, "beginning") if $first_move;
me_do($POKE, "end is near") if  almost_over() || sword($me);
me_do($SHARPEN, "you sword") if !sword($me) && sword($you);
me_do($POKE, "you repeat") if consecutive_sharpens($you) && sharp($me);
me_do(blunt_move(), "you blunt stick") if not sharp($you); 
me_do(aggressive_move(), "me think you sharpen") if sharpen_next($you) && !sharpen_next($me);
me_do($SHARPEN, "me think you block") if you_block_next() && very_little_chance_me_sharpen_next();
me_do($BLOCK, "me have no idea you do");

sub almost_over {
  sharp($me) >= (100 - length($you));
}

sub sharp {
  my $history = shift;
  my $sharp = 0;
  foreach my $s ( split('',$history) ) {
    $sharp++ if( $s eq "S");
    $sharp-- if( $s eq "P" && $sharp > 0);
  }
  return $sharp;
}

sub sword {
  my $me = shift;
  sharp($me) >= 5;
}

sub num_pokes {
  my $me = shift;
  $me =~ s/[^P]//g; #/ SO highlight bug?
  length($me);
}

sub consecutive_sharpens {
  my $you = shift;
  $you =~ m/SS+$/
}

sub sharpen_next {
  my $you = shift;
  $you =~ /([^S]+)S\1S\1$/;
}

sub you_block_next {
  $you =~ /([^B]+B*)B\1B\1$/ || $you =~ /B{4}$/;
}

sub very_little_chance_me_sharpen_next {
  $me !~ /S$/ && ( $me !~ /([^S]+)S\1$/ || $me =~ /^SB+SB+$/ ); 
}

sub blunt_move {
  my $sword_move = sword($me) ? $POKE : $SHARPEN;
  ( $me =~ m/(?:PS){5,}/ || sharp($me)*7 < num_pokes($me) ? $sword_move : aggressive_move() );
}

sub aggressive_move {
  sharp($me)? $POKE : $SHARPEN;
}

sub me_do {
  my ($stick_operation, $reason) = @_;
  my $arg = ( $first_move ? "" : "$me,$you" );
  my $resolution = "$stick_operation me do because $reason ($arg)";
  print "$resolution\n";
  err($resolution);
  exit;
}

sub err {
  my($str) = @_;
  print STDERR "SpeculativeSylwester:$str\n" if $VERBOSE;
}

Для запуска на Linux просто добавьте это в playerlist.txt:

perl players/SpeculativeSylwester/SpeculativeSylwester.pl

Facile Fibonacci - схема R6RS

Помимо первого хода, Facile блокирует Фибоначчи, когда на терне есть число Фибоначчи (начиная с 0), и заполняет остаток PPSS..и изменяется, когда проходит 8, к бесконечной последовательности, PSSчтобы выиграть мечом.

#!r6rs
(import (rnrs base)
        (only (rnrs) fold-left display command-line))

(define %SHARPEN "S")
(define %POKE    "P")
(define %BLOCK   "B")

(define (fibonacci? n)
  (let loop ((a 1) (b 1))
    (cond ((> a n) #f)
          ((= a n) #t)
          (else (loop b (+ a b))))))

(define (poke? num-sp)
  (if (< num-sp 8)
      (even? (div num-sp 2))
      (= 2 (mod num-sp 3))))

(define (split-string x)
  (let ((len (div (string-length x) 2)))
    (substring x 0 len)))

(define (num-sp x)
  (fold-left (lambda (a x)
               (if (eqv? x #\B) a (+ a 1)))
               0
               (string->list x)))

(define (advanced-strategy me)
  (cond ((fibonacci? (string-length me)) %BLOCK)
        ((poke? (num-sp me)) %POKE)
        (else %SHARPEN)))

(define (decide args)
  (if (= (length args) 1)
      %SHARPEN
      (advanced-strategy (split-string (cadr args)))))

;; The dirty imperative code:
(display (decide (command-line)))

Для запуска просто установите ikarus apt-get install ikarusи добавьте его в playerlist.txt:

ikarus --r6rs-script players/FacileFibonacci/FacileFibonacci.scm

Studious Sylwester - Perl5

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

#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

## Valid operations
my $SHARPEN = "S";
my $POKE    = "P";
my $BLOCK   = "B";

## It will also print resolution to stderr
my $VERBOSE = 0;

my $path = $0; # "players/StudiousSylwester/StudiousSylwester.pl";
my $first_move = not @ARGV;
my ($me, $you) = split(',', $ARGV[0]) unless( $first_move );

## What do I do?
me_do($SHARPEN, "beginning") if $first_move;
me_do(consult_history($POKE, "end is near")) if  almost_over() || sword($me);
me_do(consult_history($SHARPEN, "you sword")) if sword($you);
me_do(consult_history($POKE, "you repeat")) if consecutive_sharpens($you) && sharp($me);
me_do(consult_history(blunt_move(), "you blunt stick")) if not sharp($you);
me_do(consult_history(aggressive_move(), "me think you sharpen")) if sharpen_next($you) && !sharpen_next($me);
me_do(consult_history($SHARPEN, "me think you block")) if you_block_next() && very_little_chance_me_sharpen_next();
me_do(consult_history($BLOCK, "me have no idea you do"));

sub almost_over {
  sharp($me) >= (100 - length($you));
}

sub sharp {
  my $history = shift;
  my $sharp = 0;
  foreach my $s ( split('', $history) ) {
    $sharp++ if( $s eq "S");
    $sharp-- if( $s eq "P" && $sharp > 0);
  }
  return $sharp;
}

sub sword {
  my $me = shift;
  sharp($me) >= 5;
}

sub num_pokes {
  my $me = shift;
  $me =~ s/[^P]//g; #/ SO highlight bug?
  length($me);
}


sub consecutive_sharpens {
  my $you = shift;
  $you =~ m/SS+$/
}

sub sharpen_next {
  my $you = shift;
  $you =~ /([^S]+)S\1S\1$/;
}

sub you_block_next {
  $you =~ /([^B]+B*)B\1B\1$/ || $you =~ /B{4}$/;
}

sub very_little_chance_me_sharpen_next {
  $me !~ /S$/ && ( $me !~ /([^S]+)S\1$/ || $me =~ /^SB+SB+$/ );
}

sub blunt_move {
  my $sword_move = sword($me) ? $POKE : $SHARPEN;
  ( $me =~ m/(?:PS){5,}/ || sharp($me)*7 < num_pokes($me) ? $sword_move : aggressive_move() );
}

sub aggressive_move {
  sharp($me)? $POKE : $SHARPEN;
}


sub consult_history {
  my ($suggested_move, $why) = @_;
  my $mylen = length($me);

  # By demanding 5 or more there are 81 (- illegals)
  # different possibilities. Below that and
  # we are shooting in the dark.
  return @_ if( $mylen <= 4 );

  my $override = $suggested_move;
  my @lines = ();
  my %matches      = (P => 0, B=> 0, S=> 0);
  my %match_prefix = (P => 0, B=> 0, S=> 0);
  my $file = "$path.prefix";
  my $sem = "$path.sem";
  my $found_session = 0;

  # Since Judge is running multiple instances at the same time we flock
  open(LOCK, "> $sem") || die ("$path error while open $sem: $!");
  flock(LOCK, 2);

  if( -e $file ) {
    open(FH, $file) || die("$path: error while open $file: $!");

    my $prevyou = substr($you,0,-1);
    while(my $ln = <FH>){
      if ( $ln =~ m/^$me(.).*,$you(.?).*$/ ) {
         # Match that ends here is either a win or a loss depending on my choice
     my $key = ($2 eq "" ? ( $1 eq $POKE ? $SHARPEN : $POKE ) : $2);
     $matches{$key}++;
     $match_prefix{$1}++;
      }
      if( $ln =~ m/^$me,$prevyou$/ ) {
        $found_session++;
    next;
      }
      $found_session++ if( $ln =~ m/^$me.*,$prevyou.*$/ );
      push @lines,$ln;
    }
  }

  my $num_matches = (grep { $matches{$_} != 0 } keys %matches);
  unless( $num_matches || $found_session || $mylen == 5 ) {
    err("WARNING: You have not started this game from the beginning. This will not be a valid outcome! ($me,$you)");
  }

  if( $num_matches == 1 ) {
    my $match_val = (grep { $matches{$_} != 0 } keys %matches)[0];
    if( $match_val eq $BLOCK && !sharp($me)) {
      $override = $SHARPEN;
      $why = "me know u block";
    } elsif ( $match_val eq $SHARPEN ) {
      $override =  aggressive_move();
      $why = "me know u sharpen";
    } elsif ( $match_val eq $POKE && !sword($me) ) { 
      $override = $BLOCK;
      $why = "me know u poke";
    }

  } elsif($num_matches > 1 && $mylen > 6 ) {
    # if the chances are overwelming we are not poked we might as well sharpen
    # if we are wrong here we loose
    if( $matches{$POKE} * 4 < ($matches{$BLOCK}+$matches{$SHARPEN}) && !sword($me)){
      $override = $SHARPEN;
      $why = "me think u block/sharpen";
    }
    # if chances for sharpening is higher than poke/block we go for it with any stick
    if( $matches{$SHARPEN} > 2*($matches{$BLOCK}+$matches{$POKE}) && sharp($me) ) {
      $override = $POKE;
      $why = "me think u sharpen";
    }

    # if the chances for poke is overwelming, we might consider blocking
    if( $matches{$POKE} > 2*($matches{$BLOCK}+$matches{$SHARPEN}) && !sword($me)){
      $override = $BLOCK;
      $why = "me think u poke";
    }
  }

  unless ( $match_prefix{$override} ) {
    open( FH, "> $file") ||     die("$path: error while open $file: $!");
    push @lines, "$me$override,$you\n";
    foreach my $line ( sort @lines ) {
      print FH $line;
    }
  }

  my $stats = join("",map {"$_=>$matches{$_} "} keys %matches);

  if( $override ne $suggested_move ) {
     $why .= ". stats: $stats, original choice: $suggested_move";
  }

  close FH;
  close LOCK;

  return ( $override, $why );
}

sub me_do {
  my ($stick_operation, $reason) = @_;
  my $arg = ( $first_move ? "" : "$me,$you" );
  my $resolution = "$stick_operation me do because $reason ($arg)";
  print "$resolution\n";
  err($resolution);
  exit;
}

sub err {
  my($str) = @_;
  print STDERR "StudiousSylwester:$str\n" if $VERBOSE;
}

Для запуска на Linux просто добавьте это в playerlist.txt

perl players/StudiousSylwester/StudiousSylwester.pl

Прилежное редактирование

Я не могу воспроизвести проблемы, которые у вас возникли $0из-за отсутствия полного пути к скрипту perl, когда он запускается с perl. Я также вытащил ваши изменения и не вижу никаких изменений в CavemanDuels src. Это то же самое, что я выполнял более 20 раз без проблем, о которых вы сообщаете. Я начинаю опасаться, что вы могли бы использовать скрипт как скрипт bash вместо того, чтобы запускать его во время выполнения или в качестве аргумента для perl. Мне нужно больше информации, чтобы знать наверняка. В качестве теста я сделал это, и вы можете сделать то же самое, чтобы увидеть, если вы получите тот же результат:

echo '#!/usr/bin/perl
print "$0\n\n";' > testcmd.pl;
perl ./testcmd.pl;           # outputs ./testcmd.pl
bash -c "perl ./testcmd.pl"; # outputs ./testcmd.pl
bash -c ./testcmd.pl;        # outputs an error since it's not executable
chmod 755 ./testcmd.pl;
./testcmd.pl;                # outputs ./testcmd.pl
bash -c ./testcmd.pl;        # outputs ./testcmd.pl since it's executable

Схема, похоже, не хочет сотрудничать со мной на моей машине, поэтому я не смог проверить Фибоначчи. Я буду продолжать пытаться заставить его работать, но было бы здорово, если бы вы могли перевести его на другой язык.
Дверная ручка

Прилежный также, похоже, не работает, потому что $0вызывается bashиз командной строки bash (что делает контроллер). Вы можете просто жестко закодировать players/StudiousSylwester/foo.txt.
дверная ручка

@ Doorknob Я добавил, как установить, ikarusи я добавил свои мысли $0для Studious.
Сильвестр

6

мечей

Нужна острая палка. Если есть острая палка, ткните. Я не чувствую боли.

program Swordsmith
   implicit none
   integer :: mySharp,ierr,arg_count
   logical :: lExist
   character(38) :: filename = "players/Swordsmith/SwordsmithSharp.txt"

! check argument counts for initialization of storage file
   arg_count = command_argument_count()
   if(arg_count == 0) then
      inquire(file=filename,exist=lExist)
      mySharp = 0
      if(lExist) then
         open(unit=10,file=filename,status='replace')
      else
         open(unit=10,file=filename,status='new')
      endif
      write(10,*) mySharp
      close(10)
   endif

! open, read, & close the file for mySharp
   open(unit=10,file=filename,status='old')
   read(10,*) mySharp
   close(10)

! make decision
   if(mySharp < 5) then
      print '(a1)',"S"
      open(unit=10,file=filename,status='replace')
      mySharp = mySharp + 1
      write(10,*) mySharp
      stop
   endif
   print '(a1)',"P"
end program Swordsmith

Сохранить как swordsmith.f90и компилировать с gfortran -o swordsmith swordsmith.f90, выполнить , как и любой нормальный исполняемый файл: ./swordsmith.


Это появляется для печати пробела (``) перед реальным выводом. Я понятия не имею, как это исправить, поэтому мне придется исключить это представление из первого раунда тестирования.
Ручка двери

Также я исправил ваш путь к файлу; получается, что текущий рабочий каталог, когда они запускаются , не является вашей программой. Да, и если под «новым экземпляром» вы подразумеваете «каждую игру», я не могу этого сделать, потому что для этого потребуется специальный корпус программы контроллера; Вы можете сделать это в своем собственном коде.
Ручка двери

@ Doorknob: я обновил свой код: вывод представляет собой один символ, он удаляет уже существующий файл при первом запуске, и файл находится в каталоге проигрывателя.
Кайл Канос

Хорошо, спасибо! Это представление теперь включено в таблицу лидеров.
Ручка двери

@ Doorknob: Круто! Отстой, что я не первый. Кроме того: я почти уверен, что пользователи Fortran похожи на вампиров, поэтому я уверен, что вы скоро начнете писать код на Fortran! Muahahahaha!
Кайл Канос

5

PatientBlacksmith

Этот бот написан на R, используйте Rscript PatientBlacksmith.Rдля его запуска.

args <- commandArgs(TRUE)
if(length(args)){
    input <- strsplit(strsplit(args,split=",")[[1]],"")
    me <- input[[1]]
    opponent <- input[[2]]
    sharpness <- 0
    for(i in seq_along(opponent)){
        if(opponent[i]=="S") sharpness <- sharpness + 1
        if(opponent[i]=="P") sharpness <- sharpness - 1
        }
    out <- ifelse(sharpness>0,"B","S")
    bfree <- me[me!="B"]
    r <- rle(bfree) #run length encoding
    S_sequence <- r$length[r$value=="S"]
    P_sequence <- r$length[r$value=="P"]
    if(!length(P_sequence)) P_sequence <- 0
    if(tail(S_sequence,1)==5 & tail(P_sequence,1)!=5) out <- "P"
}else{out <- "S"}
cat(out)

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


Это прерывается, когда не вводится (т.е. при первом повороте); Я не знаю, как это исправить, поэтому мне придется исключить это из первого раунда тестирования.
Дверная ручка

@ Doorknob исправлено.
plannapus

5

Тюремные правила, Хаскелл

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

Вице-лидер Альфа Пещерный человек сейчас; тот, кто пещерный человек должен сражаться. Другие пещерные люди сражаются позже. Если мой пещерный человек проиграет, не волнуйтесь; он слишком волосатый в любом случае.

import System.Environment


-- Tell caveman next move

next move
    | end with sharp stick  = poke with (what have)
    | they no poky          = sharpen stick
    | me have sword         = poke with sword
    | soon them have sword  = try poke or sharpen
    | soon have own sword   = fear pokes
    | think them want sword = sharpen stick
    | getting bored now     = sharpen stick
    | otherwise             = block poky stick


-- How fancy techno computer program know?

    where
        end with sharp stick = pokiness my stick >= moves before fight boring
        they no poky  = pokiness their stick == 0
        me have sword = pokiness my stick >= 5
        soon "them" have sword = pokiness their stick == 4
        soon have "own" sword  = pokiness my stick == 4
        try poke or sharpen = if pokiness my stick > 0
                              then poke with stick
                              else sharpen stick
        fear pokes = count 2 (block poky stick) and (sharpen stick)
        think them want sword = pokiness their stick == 3
        getting bored now = those last 2 mine same

        what have
            | me have sword = sword
            | otherwise     = stick



-- Rest not for caveman - only techno computer

        moves before time up = time - (length . fst $ move)

        and   = my
        mine  = my
        my    = fst move
        their = snd move

        before = "before"
        bored  = "bored"
        boring = "boring"
        have   = "have"
        no     = "no"
        now    = "now"
        own    = "own"
        pokes  = "pokes"
        same   = "same"
        sharp  = "sharp"
        them   = "them"
        want   = "want"


fight = 100


main = do
    movesHistoryEtc <- getArgs
    putStrLn . next . basedOn $ movesHistoryEtc


basedOn = movesOfEachCaveman . history

history []    = ""
history (h:_) = h

movesOfEachCaveman "" = ("", "")
movesOfEachCaveman h  = (\(a, b) -> (a, tail b)) . span (/= ',') $ h


sharpened = 'S'
poked     = 'P'
blocked   = 'B'

times m = length . filter (== m)


with  = "WITH"
poky  = "POKY"
sword = "SWORD"
stick = "STICK"

sharpen stick    = "SHARPEN " ++ stick
block poky stick = "BLOCK " ++ poky ++ " " ++ stick
poke with stick  = "POKE " ++ with ++ " " ++ stick


pokiness stick is = foldl countPokiness 0 stick

countPokiness pokyPoints 'P'
    | pokyPoints > 0         = pokyPoints - 1
    | otherwise              = 0
countPokiness pokyPoints 'S' = pokyPoints + 1
countPokiness pokyPoints  _  = pokyPoints


allLast n x xs = all (== x) $ take n . reverse $ xs

those previous n moves same = ((length moves) >= n)
                           && (allLast n (last moves) moves)

count n firstMoves moveHistory lastMove = if allLast n fm moveHistory
                                          then lastMove
                                          else firstMoves
    where fm = head firstMoves

Написан на Haskell (зайдите в функциональное программирование!), Так что сохраните его как Prisonrules.hs , а затем скомпилируйте с:

ghc prisonrules.hs

И запустить как:

prisonrules [history]

4

Я называю его JavaMan

compile: javac JavaMan.java
run: java JavaMan SPB,SBB

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

public class JavaMan
{
    public static void main(String[] args)
    {
        // input: SPB,SBB
        // me, enemy
        // S: sharpen, P: poke, B: block

        if (args.length == 0)
        {
            System.out.println("S");
        }
        else
        {
            String[] states = args[0].split(",");
            Player me = new Player(states[0].toCharArray());
            Player enemy = new Player(states[1].toCharArray());  //fixed thanks to Roy van Rijn

            if (me.hasSword())
            {
                System.out.println("P");
            }
            else if (!enemy.canPoke())
            {
                if (me.canPoke() && (Math.random() * 95) < states[0].length())
                {
                    System.out.println("P");
                }
                else
                {
                    System.out.println("S");
                }
            }
            else if (enemy.hasSword())
            {
                if (me.canPoke())
                {
                    System.out.println("P");
                }
                else
                {
                    System.out.println("S");
                }

            }
            else if (enemy.canPoke())
            {
                if (me.canPoke())
                {
                    if ((Math.random() * 95) < states[0].length())
                    {
                        System.out.println("P");
                    }
                    else
                    {
                        System.out.println("B");
                    }
                }
                else
                {
                    if ((Math.random() * 95) < states[0].length())
                    {
                        System.out.println("S");
                    }
                    else
                    {
                        System.out.println("B");
                    }
                }
            }
            else
            {
                System.out.println("S");
            }
        }
    }

}

class Player
{
    int sharpLevel;

    public Player(char[] state)
    {
        sharpLevel = 0;
        for (char c : state)
        {
            switch (c)
            {
            case 'S':
                sharpLevel++;
                break;
            case 'P':
                sharpLevel--;
                break;
            case 'B':
                break;
            default:
                System.out.println(c);
            }
        }
    }

    public boolean hasSword()
    {
        return sharpLevel > 4;
    }

    public boolean canPoke()
    {
        return sharpLevel > 0;
    }
}

4
Заявки на участие в соревнованиях King of the Hill не предназначены для игры в гольф, так что не волнуйтесь. ;)
Мартин Эндер

Я изменил его имя на JavaMan, потому что "Caveman" слишком общий, чтобы быть в списке лидеров. Надеюсь, с тобой все в порядке; если нет, просто измените его на что-то другое.
Дверная ручка

1
Это прерывается, когда не вводится (т.е. при первом повороте); Я не знаю, как вы хотите справиться с этим, поэтому мне придется исключить это из первого раунда тестирования.
Дверная ручка

Исправлено, и смена имени меня
устраивает

1
Я думаю, у вас есть ошибка при разборе состояния, и «я», и «враг» получают одинаковые ходы: states [0]
Рой ван Рейн

4

Глубокие Мысли, C

Код пещерного человека. Пещерный человек думаю. Пещерный человек.

// DeepThoughts.c
#include <stdio.h>  // Me need for plan
#include <string.h> // Me need for memory

// Me count sharps. If me still here, pokes no work
int is_pointy(char *past){
    int pointy = 0;     // Stick dull
    while(*past){
        switch(*past ++){
            case 'S': pointy ++; break;
            case 'P': if(pointy > 0) pointy --;
        }
    }
    return pointy;
}

// Me brain
int main(int argc, char *argv[]){
    int me_pointy = 0;  // Is 0, stick dull. Is 5, has sword
    int you_pointy = 0; // Same to you
    int me_last;        // Me last plan
    int you_last;       // Same to you
    char *you;          // You past
    int when;           // Time
    int me_plan;        // Me deep thought

    // Me remember
    if(argc > 1){
        you = strchr(argv[1], ',');     // Me find you past in me arg
        *you ++ = 0;
        when = strlen(argv[1]);         // Time is passing
        me_pointy = is_pointy(argv[1]); // Me look at me past
        you_pointy = is_pointy(you);    // Same to you
        me_last = argv[1][when - 1];    // Why me do that?
        you_last = you[when - 1];       // Same to you
    }

    // Me has deep thoughts. Me make plan
    if(me_pointy >= 5) me_plan = 'P';       // Me has sword
    else if(you_pointy == 0) me_plan = 'S'; // Me safe. You stick dull
    else if(when == 1) me_plan = 'P';       // Me shoot first (more thought)
    else if(me_pointy == 1 && when < 42) me_plan = 'B';  // Me try for sharper (deeper thought)
    else if(me_pointy > 0) me_plan = 'P';   // Me stick not dull
    else if(me_last == 'P') me_plan = 'B';  // Me in trouble
    else me_plan = 'S';                     // Me cross toes

    // Me do plan
    putchar(me_plan);
    return 0;
}

Я делаю тестирование. Больше мыслей лучше.


1
+1 за имена и комментарии пещерного человека var: P Также хорошая программа c:
cat

3

Найджел

Найджел - терпеливый, оборонительный старый пещерный человек, который скорее будет тактичным, чем изо всех сил атакует.

Это скрипт PHP, позвоните с php nigel.php

<?php
// Seed the random number generator
srand(time());

// Simple function output chosen move
function move($m)
{
    echo $m;
    echo "\n";
    exit;
}

// Make stick sharp if first move
if (sizeof($argv) == 1)
    move("S");

// Grab the list of moves
$moves = explode(",", $argv[1]);    
$mySharpness = 0;
$opSharpness = 0;

// Loop through all previous moves and calculate sharpness
for ($i=0; $i<strlen($moves[0]); $i++)
{
    $myMove = substr ($moves[0], $i, 1);
    $opMove = substr ($moves[1], $i, 1);
    if ($myMove == "S")     $mySharpness++;
    if ($opMove == "S")     $opSharpness++; 
    if ($myMove == "P" && $mySharpness > 0)     $mySharpness--;
    if ($opMove == "P" && $opSharpness > 0)     $opSharpness--;     
}

// We somehow have a sword.. ATTACK!
if ($mySharpness > 4)
    move("P");

// Opponent is blunt, guarenteed upgrade!
if ($opSharpness < 1)
    move("S");          

// If we're sharp, either block or poke, unless OP is near a sword
if ($mySharpness > 0)
{
    // Oppenent is halfway to a sword.. ATTACK!
    if ($opSharpness > 2)
        move("P");  

    if (rand(0,1) == 0)     move("P");
    else                    move("B");
}

// If we're blunt, either sharpen or block
else
{
    if (rand(0,1) == 0)     move("S");
    else                    move("B");  
}

?>

3

Айхмофобия - Луа

Он будет иногда тыкать тебя, но только до тех пор, пока какая-нибудь палка не станет слишком острой. Когда это произойдет, он запаникует и свернется в позу плода.

if arg[1] == nil then
  response = "S"
elseif not arg[1]:match('SSSSS') == nil then
  --PANIC
  response = "B"
else  
  --Minds his own business and goes where he pleases
  math.randomseed(os.time())
  local rand = math.random();

  response = rand > 0.6 and "P" or "S"
end

print(response)

Запустите это с:

lua aichmophobic.lua


2
Ваш вывод должен быть прописными буквами; Я исправил это для тебя. (Кроме того, я неправильно написал название этого представления около тысячи раз.: P)
Ручка двери

3

Боб Пещеры

Боб Кейвс - один из самых умных парней в своей пещере. Он научился считать одной рукой (другая занята удерживанием палки). Он знал об этой олимпиаде каменного века и хотел участвовать.

Его основная стратегия - блокировать и оттачивать свою палку, пока у него не появится хорошая острая палка, или у другого пещерного человека тоже есть острая палка. В этом случае Боб Кейвс пытается ткнуть его!

import java.util.Random;

public class BobCaves {

    public static void main(String[] args) {
        int mySharpness = 0;
    int otherSharpness = 0;

    //Boc counts
    if (args.length > 0) {
        String[] ss = args[0].split(",");
        mySharpness = howSpiky(ss[0]);
        otherSharpness = howSpiky(ss[1]);
    }
    // Bob thinks!
    Random rn = new Random();
    if (mySharpness == 0 && otherSharpness == 0){
        System.out.println( "S");
    }
    if (otherSharpness == 0 && mySharpness < 5 && mySharpness > 0){
        if (rn.nextBoolean()){
            System.out.println("P");
        } else {
            System.out.println("S");
        }
    } 

    if (mySharpness >= 5 || (otherSharpness >= 2 && mySharpness > 0)) {
        System.out.println("P");
    }

    if (rn.nextInt(5) > 3) {
        System.out.println("S");
    } 

    System.out.println("B");
    }

    private static int howSpiky(String s1) {
        int count = 0;
        char[] c1 = s1.toCharArray();
        for (int i = 0; i < c1.length; i++) {
        if (c1[i] == 'S') {
                count++;
            } else if (c1[i] == 'P'){
                count --;
            }
        }
        return count;
    }

}

Скомпилировать javac BobCaves.javaи запустить сjava BobCaves

Изменить: Боб теперь считает, когда есть какой-либо блок! (спасибо Мики Маусу ). Также он заострит свою палку, когда другая палка пещерного человека тупа.

Редактировать 2: Улучшен метод подсчета (еще раз спасибо Мики).

Изменить 3: сделать Боб немного более агрессивным.


2
Боб забыл подсчитать эффект Poke: Block на резкость собственной палки. Три буквы "S" не означают, что трость в три раза острее. Каждая буква «Р» означает незаточенную палочку. Ха-ха-ха ... "Пи" пещерный человек шутит ...
Майки Маус

@MikeyMouse Боб соглашается. Боб посетит знахаря, чтобы улучшить его технику. Боб благодарен!
Аверроэс

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

1
@MikeyMouse Боб знает, как считать. Бобу нужно научиться читать. Еще раз спасибо!
Аверроэс

3

Gruntt

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

public class Gruntt {

public static void main(String[] args) {
    System.out.println(whatToDo(args));
}

private static String whatToDo(String[] args){
    int mySharpness = 0;
    int otherSharpness = 0;

    if (args.length > 0) {
        String[] ss = args[0].split(",");
        mySharpness = howSpiky(ss[0]);
        otherSharpness = howSpiky(ss[1]);
    } else {
        return "S";
    }

    if (mySharpness >= 5){
        return "P";
    }

    String res = wowoo(args[0].split(",")[1]);
    if ("P".equals(res) && mySharpness > 0) {
        return "P";
    } else if ("P".equals(res) && mySharpness == 0) {
        return "S";
    } else if ("S".equals(res) && !args[0].split(",")[0].endsWith("S")) {
        return "S";
    }

    if (otherSharpness == 4 && !args[0].split(",")[0].endsWith("P")){
        return "P";
    }

    if (otherSharpness == 0){
        return "S";
    }

    return "B";

}

private static int howSpiky(String s1) {
    int count = 0;
    char[] c1 = s1.toCharArray();
    for (int i = 0; i < c1.length; i++) {
    if (c1[i] == 'S') {
            count++;
        } else if (c1[i] == 'P'){
            count --;
        }
    }
    return count;
}

private static String wowoo(String s){
    String s1 = "";
    String s2 = "";

    if (s.length() >= 4){
        s1 = s.substring(s.length() - 4);
    }

    if (s.length() >= 3){
        s2 = s.substring(s.length() - 3);
    }

    if ("SPSP".equals(s1)){
        return "P";
    } else if ("SSS".equals(s2)){
        return "P";
    } else if ("BBBB".equals(s1)){
        return "S";
    } else if ("SBSB".equals(s1)){
        return "P";
    }

    return null;
}

}

Скомпилировать javac Gruntt.javaи запустить сjava Gruntt


Это создает ArrayOutOfBoundsExceptionпервый ход и иногда выдает несколько действий на других ходах.
Дверная ручка

@ Doorknob Ops! Исправлено, спасибо!
Аверроэс

3

Это птица? Это самолет? Это RegExMan!

Он пытается проанализировать ваши супер-скучные последовательности с его особой первобытной мощью RegEx!

#!/usr/bin/env python
import sys, re

def whatAmIDoing(opnHist, meSharp, opnSharp) :

    match = re.search(r"([PSB]{3,})\1$", opnHist)    ### Super RegEx ftw!

    if meSharp >= 5 :
        return "P"
    if opnSharp == 4 and meSharp > 0 :
        return "P"
    if match :
        opnStrat = match.group()
        if opnStrat[0] == "S" :
            if meSharp > 0 :
                return "P"
            else :
                return "S"
        elif opnStrat[0] == "B" :
            return "S"
    if opnSharp <= 0 :
        return "S"
    return "B"

try :
    hist = sys.argv[1].split(",")
    sharp = map(lambda h : h.count("S") - h.count("P"), hist)
    answer = whatAmIDoing(hist[1], *sharp)
except Exception :
    answer = "S"
finally :
    print(answer)

Написан на Python 2.7, работает с python RegExMan.py [history]


3

Sicillian

Но это так просто! Все, что мне нужно сделать, это божественное из того, что я знаю о другом пещерном человеке: он тот самый пещерный человек, который будет блокировать, обострять или тыкать? Теперь умный пещерный человек ткнет или заблокирует, потому что он будет знать, что только великий дурак будет точить и подвергать себя нападению. Я не большой дурак, поэтому я не могу четко обострить. Но другой пещерный человек должен знать, что я не великий дурак, и рассчитывал бы на это, поэтому я явно не могу тыкать или блокировать!

Бежать с:

javac Sicillian.java
java Sicillian

Код:

public class Sicillian {

    public static void main(String[] args) {

        if (args.length == 0) System.out.println("S");
        else {
            //get and analyze history
            String[] history = args[0].split(",");
            Caveman vizzini = new Caveman(history[0].toCharArray());
            Caveman fool = new Caveman(history[1].toCharArray());
            Think divine = new Think(history[0].toCharArray(),history[1].toCharArray());

            //The Sicillian always thinks and makes a logical decision before acting...
            char onlyAFool = divine.clearly(vizzini.getSharpness(),fool.getSharpness());

            //Never go in against a Sicillian when death is on the line!
            if(onlyAFool == 'S') {
                if(!vizzini.weaponless()) poke();
                else sharpen();
            }
            else if(onlyAFool == 'P') {
                if(vizzini.hasSword()) poke();
                else block();
            }
            else if(onlyAFool == 'B') sharpen();

            else {          // Inconceivable!

                //if he's a sharpener, poke him where it hurts!
                if(fool.isSharpener()) {
                    if(vizzini.getSharpness() >= 2) poke();  //don't ever go weaponless, else you give him the advantage
                    else sharpen();
                }               
                //if he's a blocker, get sword and break through his defense
                else if(fool.isDefensive()) {
                    if(vizzini.hasSword()) poke();
                    else sharpen();
                }
                // fool doesn't have a disposition to do anything in particular
                else {
                    //he could be sharpening and blocking to get a sword in which case his sharpness will be higher
                    //or a random, which will average a lower sharpness
                    if (fool.getSharpness() <= 2) { //assume random
                        if(vizzini.hasSword()) poke();
                        else if(fool.weaponless()) sharpen();
                        else block();
                    }
                    else {
                        if(vizzini.hasSword()) poke();
                        else if(vizzini.getSharpness() > fool.getSharpness()) sharpen();    //we can win race to sword
                        else if(vizzini.getSharpness() >= 2 || (!vizzini.weaponless() && fool.onEdge())) poke();
                        else sharpen();
                    }
                }
            }           
        }
    }   //end of main

    private static void poke() {
        System.out.println("P");
    }
    private static void block() {
        System.out.println("B");
    }
    private static void sharpen() {
        System.out.println("S");
    }
}
class Think {
    private char[][] cleverman = new char[6][6];    //tracks what the enemy does in a particular situation 
    private int mySharpness;
    private int enemySharpness;
    public Think(char[] myAction, char[] enemyAction) {
        //init variables
        mySharpness = 0;
        enemySharpness = 0;

        for(int i = 0; i < myAction.length; i++) {
            //remember what enemy did last time
            cleverman[mySharpness][enemySharpness] = enemyAction[i];
            //System.out.println("When I was at ("+mySharpness+") and he was at ("+enemySharpness+") he did ("+enemyAction[i]+")");

            //calculate my sharpness
            if(myAction[i] == 'S') mySharpness++;
            else if(myAction[i] == 'P') mySharpness--;
            if(mySharpness < 0) mySharpness = 0; //ensure multiple pokes don't create a negative sharpness
            //calculate my enemy's sharpness
            if(enemyAction[i] == 'S') enemySharpness++;
            else if(enemyAction[i] == 'P') enemySharpness--;
            if(enemySharpness < 0) enemySharpness = 0; //ensure multiple pokes don't create a negative sharpness
        }   
    }
    public char clearly(int myAction, int enemyAction) {
        if(myAction > 5) myAction = 5;
        if(enemyAction > 5) enemyAction = 5;
        return cleverman[myAction][enemyAction];
    }
}
class Caveman {
    private int sharpness;
    private int disposition;    //Finite State Machine: how inclined the caveman is toward blocking (0) or sharpening (4)
    public Caveman(char[] action) {
        sharpness = 0;
        disposition = 1;        //assume a slightly defensive disposition
        for (int i = 0; i < action.length; i++) {
            if(action[i] == 'S') {
                sharpness++;
                disposition++;
            }
            else if(action[i] == 'P') sharpness--;
            else disposition--;                     //blocking
            if(sharpness < 0) sharpness = 0; //ensure multiple pokes don't create a negative sharpness
            if(disposition > 4) disposition = 4;
            else if(disposition < 0) disposition = 0;
        }
    }
    public int getSharpness() {
        return sharpness;
    }
    public boolean weaponless() {
        return sharpness == 0;
    }
    public boolean hasSword() {
        return sharpness >= 5;
    }
    public boolean onEdge() {
        return sharpness == 4;
    }
    public boolean isDefensive() {
        return disposition == 0;
    }
    public boolean isSharpener() {
        return disposition == 4;
    }
    public int getDisposition() {
        return disposition;
    }
}

3

Баш-магнонное

Баш-магноны были крепко сложены и мощны. Тело в целом было тяжелым и крепким с сильной мускулатурой. Лоб был довольно прямым, а не наклонным, как у неандертальцев, и с небольшими бровями. Лицо было коротким и широким. Подбородок был видным. Объем мозга был около 1600 кубических сантиметров (98 кубических дюймов), что больше, чем в среднем для современного человека. Однако недавние исследования показывают, что физические размеры так называемого «Баш-Магнона» не достаточно отличаются от современных людей, чтобы оправдать отдельное обозначение.

У меня есть мозг, я помню.

Это исполняемый файл ./bash-magnon.sh

#!/bin/bash

function min () {
 [[ $1 -gt $2 ]] && echo $2 || echo $1
}

function max () {
[[ ${1%% *} -gt ${2%% *} ]] && echo $1 || echo $2
}

declare -A brain
declare -i C S P B me he
he=0
me=0
C=0
S=0; B=0; P=0

left=${1%%,*}
right=${1##*,}
while  : 
do

    [[ "${right:$C:1}" ]] && brain[$he$me]=${right:$C:1}
    case "${left:$C:1}${right:$C:1}" in
    BB) true;;
    BP) ((he--));;
    BS) ((he++));;
    PP) ((he--)); ((me--));;
    PB) ((me--));;
    PS|SP) exit;;
    SB) ((me++));;
    SS) ((me++)); ((he++));;
    "") break;;
    esac
    me=$(max 0 $me)
    me=$(min 9 $me)
    he=$(max 0 $he)
    he=$(min 9 $he)
    ((C++))
done

[[ $me$he =  *[5-9] ]] && ((P+=2))
[[ $me$he =  [5-9]* ]] && ((P+=2))
[[ $me$he =  [1-9]0 ]] && ((P+=2))
[[ $me$he =  00 ]] && ((S+=2))
[[ $me$he =  [1-4]4 ]] && ((P+=2))
[[ $me$he =  0[1-4] ]] && ((S+=1))
[[ $me$he =  0* ]] && ((B+=1))

case "${brain["$he$me"]}" in 
S) ((P+=2));;
B) ((S+=2));;
P) ((B+=2));;
*) ((B++));;
esac

set $(max "$B B" "$(max "$P P" "$S S")" )
echo $2

1+ У вас, очевидно, есть подходящий инструмент для работы, и ваши имена пещерных людей довольно забавны :) (хотя лично мне рыба нравится больше)
Сильвестр

@Sylwester Спасибо, это мой первый +1. Сначала я попытался создать гомеостатический автомат, вдохновленный тем, что сделал первый кибернетик, что-то, что ощущает его собственный баланс, затем я сдался и сделал сценарий bash.
Эммануэль

2

PokeBackBot

Просто адаптировано из PokeBot:

puts 'SBPB'[(ARGV.shift || ',').split(',', 2)[0].length % 4]

Беги с ruby pokebackbot.rb.

Это использует следующую простейшую стратегию и блокирует «терпеливо» на один раунд перед атакой.


3
@PeterTaylor Я читал, что мне нельзя менять стратегию, основываясь на отпечатках пальцев противника. Если моя заявка может превзойти только одну другую, это не повлияет на оценку других заявок, и моя собственная заявка, вероятно, будет очень плохой. Кроме того, если есть только одна заявка и написана вторая, эта вторая, вероятно, превзойдет первую (потому что иначе зачем беспокоиться) - одно это квалифицируется как «специфичное для другой программы»? Мой бот SPSпревзойдет любого бота, который начинается с (что кажется разумным), но пока PokeBot был единственным из них.
Мартин Эндер

2

Мастер меча

Написан на Python 3.4 (работает с Python 3.x)

Пытается получить меч как можно быстрее, но атакует, если у него есть шанс поразить его (острота> 0), и враг может нанести ему тоже вред (острота противника> 0).
Блокирует только если не имеет резкости и враг может атаковать.

Начните с:

python3 swordmaster.py MOVES

(предполагается, что вы сохраните его как swordmaster.py)

Быстрый и некрасивый код:

import sys, random
dg = False
if len(sys.argv) > 1:
    ow,ot = sys.argv[1].split(',')
else:
    ow = ot = ""
def gs(m):
    ow = 0
    ot = 0
    i = 0
    ms = m[0]
    mo = m[1]
    for _ in mo:
        if ms[i] == 'S':
            ow += 1
        elif ms[i] == 'P' and mo[i] in ['P','B']:
            ow -= 1
        if mo[i] == 'S':
            ot += 1
        elif mo[i] == 'P' and ms[i] in ['P','B']:
            ot -= 1
        if dg:
            print("Own: {}, Other: {}".format(ow,ot))
        i += 1
    return [ow, ot]

def sm(sh):
    if (type(sh) != list) and dg:
        raise ValueError('Invalid sh type.')
    ow, ot = sh
    if ow >= 5:
        ret = 'P'
    elif ow >= 0 and ot == 0:
        ret = 'S'
    elif ow > 0 and ot > 0:
        ret = 'P'
    elif ow == 0 and ot > 0:
        ret = 'B'
    else:
        ret = random.choice(['S','B','P']) #Should not happen
    return ret

if __name__ == "__main__":
    print(sm(gs([ow,ot])))

(Установите dgдля Trueвключения отладочных сообщений)


1
Подсказка: Не позволяйте ей сражаться себя - это будет тупик с S, P, S, P...
chill0r

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

2

FoolMeOnce.py

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

import os
import sys
import random

def getLastMove(player, turn):
    path = 'players/FoolMeOnce/'+player+str(turn)+'.txt'
    if os.path.isfile(path):
        with open(path, 'r') as f:
            return f.read()
    else:
        return 'nofile'

def sharpness(history):
    sharpness = 0
    for c in history:
        if c is 'S':
            sharpness+=1
        elif c is 'P' and sharpness > 0:
            sharpness-=1
    return sharpness

def takeTurn(choice, history, turn):
    print(choice)
    with open('players/FoolMeOnce/me'+str(turn)+'.txt', 'w') as f:
        f.write(choice)
    #also record their last choice
    choice = history[-1]
    with open('players/FoolMeOnce/them'+str(turn)+'.txt', 'w') as f:
        f.write(choice)

#if its the first turn, always sharpen
if(len(sys.argv) == 1):
    print('S')

else:
    history = sys.argv[1].split(',')
    meSharp = sharpness(history[0])
    themSharp = sharpness(history[1])
    turn = len(history[0])

    #read opponents move and our move for this turn from last duel
    them = getLastMove('them', turn);
    me = getLastMove('me', turn);

    #if this is first duel, fool me once
    if(them is 'nofile' or me is 'nofile'):
        if themSharp is 0 and meSharp >0:
            takeTurn(random.SystemRandom().choice('PS'), history, turn)
        else:
            takeTurn('B', history, turn)

    #if we could have played a winning move, do it. otherwise do what we did last time
    elif(them is 'S' and meSharp > 0):
        takeTurn('P', history, turn)
    else:
        takeTurn(me, history, turn)

Написан на python 3, поэтому, скорее всего, вам придется использовать python3 FoolMeOnce.py. В первом раунде я не уверен, получим ли мы пустую строку или просто запятую, поэтому могут потребоваться некоторые настройки.


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

Играя с тестером CavemanDuel, я заметил, что FoolMeOnce получит намного больше очков, если я использую больше потоков (я протестировал 16 потоков против 4). С 4 потоками он получает ~ 25 баллов, с 16 - ~ 34.
wendelbsilva

Странно, я понятия не имею, почему это будет.
цазы
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.