Дуелі з печерами (або: Мене тикають гострою палицею)


151

Печеринка божевільна. Інший печерний чоловік тримався, але палка була для мене. Бій за печер !


Опис

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

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

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

Вхідні дані

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

Приклад введення:

SPB,SBB

Це означає, що гравець заточував свою палицю, потім тикав, потім блокував, а опонент загострював, потім блокував, потім знову блокував.

Ви не отримаєте жодного входу на черзі 1.

Вихідні дані

Вихід дуже схожий на вхід (тому що печерний чоловік не дуже розумний). Ваша програма повинна виводити Sна різкість, Pна трюк та 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 Я не думаю, що minimax - це поліпшення. Я маю на увазі, ви могли б спроектувати виконання minimax, але оскільки логіка настільки проста, таку саму точну поведінку можна виразити і з машиною з кінцевим станом. . бути для блокування тощо)
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

@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
Це лише двічі програють у нинішній лідері? оо
justhalf

Версія 5 припускає купу помилок, тому версія 4 - це та, що входить до поточного раунду випробувань.
Дверна ручка

@Doorknob Я думаю, що я все виправив, в будь-якому випадку була лише одна зміна фактичної логіки.
Nexus

20

Іноземний кавалер

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 Ні, це заява АБО. Це означає "ткнути супротивника, якщо у мене меч АБО, якщо він скоро матиме меч".
CommonGuy

7
О боже. Час отримати ще одну чашку кави :) Або нові контактні лінзи
durron597

15

Можливо, Марков 2.1

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

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

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

EDIT

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

$ 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

ПеріодичнаCicadaCaveman

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

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

для компіляції: mcs program.cs для запуску моно 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. Отже команда run була б mono program.exe. (У мене не було доступу до моно на момент попереднього коментаря.)
Боб

14

Фантастичний технічний алгоритм

Фантастичний техно алгоритм для фантазійної комп'ютерної програми техно.

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

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

@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

Неш

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

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

Це подання кинуло якусь помилку чи виняток у якийсь момент; Ви можете розглянути, як це виправити до наступного раунду випробувань. (Василіск один)
Дверна ручка

@Doorknob Я вибрав початкову послідовність для Basilisk, переглянувши припущення, які висловлювали The Watcher and Cave Doctor, і знайшов послідовність, яка зробила б ці помилки неправильними. Чи це порушує правило "печерні люди справедливі"?
Brilliand

Іди Неш! Виграйте рівно половину своїх матчів проти всіх ботів, досить розумних, щоб уникнути Ваших P = 0 варіантів!
aschepler

12

PokeBot

Написано в Рубі.

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

EDIT: спасибі @sylwester за вказівку на помилку


Оскільки ви отримуєте лише один аргумент з обома історіями, розділеними комою, ви неправильно їх аналізуєте. Напр. PatientWolf.pl SB,SPробить, Pоскільки вважає, що має гостру палицю.
Сільвестер

@Sylwester це неправильно. Перший рядок присвоює перший аргумент $ мені, а другий аргумент - $ him
убивчий

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

@Sylwester добре, я бачу, до чого ти потрапляєш. Це не було зрозуміло з ОП або з швидкого погляду, який я кинув на код контролера. Я скоро це
виправлю

9

Бінарний печер

Точити, колоти, повторити

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

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

EDIT: Пригоди в рядкових масивах ..... args.length () видає помилку. args.length завжди повертає 1. args [0] .length () повертає довжини першого рядка в масиві.

EDIT 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

Ходор

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

компілювати з: 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, просто додайте це в playlist.txt:

perl players/SpeculativeSylwester/SpeculativeSylwester.pl

Фактична Фібоначчі - схема R6RS

Окрім першого кроку, Facile Fibonac блокує, коли поворот - це число Фібоначчі (починаючи з 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і додайте це до playlist.txt:

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

Вивчений сильвестер - 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 просто додайте це до playlist.txt

perl players/StudiousSylwester/StudiousSylwester.pl

Студійна редакція

Я не можу відтворити проблеми, які ви мали з тим, щоб $0не бути повним шляхом до сценарію perl, коли він запускається з perl. Я також вніс ваші зміни, і я не бачу змін у сервісі CavemanDuels, і це те саме, що я працював 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студії.
Сільвестер

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! Муахахахаха!
Кайл Канос

5

Пацієнт-коваль

Цей бот написаний на 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, натискайте, поки різкість не зникне.


Це порушується, якщо не вводиться (тобто при першому повороті); Я не знаю, як це виправити, тому мені доведеться виключити це з 1 раунду тестування.
Дверна ручка

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

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 (перейдіть на функціональне програмування!), Тож збережіть як zatvorrules.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
Це порушується, якщо не вводиться (тобто при першому повороті); Я не знаю, як ви хочете впоратися з цим, тому мені доведеться виключити це з першого раунду тестування.
Дверна ручка

Виправлено, і зміна імені зі мною добре
користувач2813274

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

4

Глибокі думки, С

Печерний код. Печерна людина думає. Печеру робити.

// 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 для імен та коментарів печерного чоловіка: P Також приємна програма c:
кіт

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: Блокуйте різкість власного паличка. Три "S" s в s не означає, що палиця 3 рази гостро. Кожен "P" в s означає незаточену паличку. А-а-а-а-а ... Жарт "Пе," печера ...
Майкі Маус

@MikeyMouse Боб погоджується. Боб відвідає лікаря відьом для вдосконалення своєї техніки. Боб вдячний!
Averroes

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

1
@MikeyMouse Bob знає, як рахувати. Боб повинен навчитися читати. Знову дякую!
Averroes

3

Грюнт

Грюнтт - оборонний. Грюнт аналізує інші рухи печерних людей, щоб знати, як їх тикати. Потім він тикає їм прямо в очі. Грюнт - не милий печерик.

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 Оп! Виправлено, дякую!
Аверрое

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

Сицилійська

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

Виконати з:

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

bash-magnon

Баш-магнони були міцно побудовані та потужні. Тіло було загалом важким і твердим із сильною мускулатурою. Лоб був досить прямим, а не похилим, як у неандертальців, і лише з невеликими проділами. Обличчя було коротке і широке. Підборіддя було видатним. Ємність мозку становила приблизно 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

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

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

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

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

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