Caveman Duels (lub: Me szturcham cię ostrym kijem)

151

Jaskiniowiec. Inny jaskiniowiec bierze kij, ale kij był dla mnie. Walka jaskiniowców !


Opis

Jaskiniowiec potrzebuje ostrego patyka, aby dźgnąć innego jaskiniowca. Inny jaskiniowiec również próbuje dźgnąć ostrym kijem. Jaskiniowiec może wyostrzyć kij, szturchać kijem lub blokować kijki.

Jeśli jaskiniowiec wbije drugiego jaskiniowca ostrym kijem, inny jaskiniowiec ucieknie, a ja zwycięstwo. Ale jeśli inny jaskiniowiec sprytnie blokuje się podczas szturchania, nic się nie dzieje, z wyjątkiem tego, że mój kij staje się tępy i muszę ponownie wyostrzyć.

Jaskiniowiec leniwy. Poza tym jaskiniowiec głupi. Jaskiniowiec nie wie, co robić, więc jaskiniowiec potrzebuje wymyślnego programu komputerowego techno, aby powiedzieć jaskiniowcowi, co ma robić.

Wejście

Wkład twojego programu będzie historią wydarzeń, które miały miejsce, w których Soznacza ostrzenie (tj. Jaskiniowiec zaostrzył swój kij), Poznacza poke i Bblok. Dane wejściowe będą historią obu stron (ciebie i przeciwnika), więc ruchy twojego i przeciwnika zostaną oddzielone przecinkiem ( ,).

Przykładowe dane wejściowe:

SPB,SBB

Oznacza to, że gracz wyostrzył swój kij, a następnie szturchnął, a następnie zablokował, a przeciwnik wyostrzył, a następnie zablokował, a następnie ponownie zablokował.

Nie otrzymasz żadnych danych wejściowych w pierwszej turze.

Wynik

Wyjście jest bardzo podobne do wejścia (ponieważ jaskiniowiec nie jest zbyt inteligentny). Twój program powinien wyświetlać dane w Scelu wyostrzenia, Ppoke i Bbloku. Uwzględniany będzie tylko pierwszy znak wyniku, a wszelkie inne dane wejściowe będą traktowane jako Bpolecenie (blok).

  • S: wyostrzyć

    Podczas ostrzenia ostrość kija jaskiniowca wzrasta o 1, a kij dostaje 1 dodatkowe szturchnięcie. Każde dźgnięcie zmniejsza ostrość kija o 1, a jeśli ostrość kija wynosi 0, jest zbyt nudny, aby go szturchać. Ostrość zaczyna się od 0. Jeśli ostrość osiągnie 5, kij jest mieczem! (Patrz poniżej.)

    Jeśli przeciwnik szturchnie podczas ostrzenia (i ma ostrość> 0), przeciwnik wygrywa!

  • P: szturchać

    Podczas szturchania ostrość kija jaskiniowca spada o 1, a ty szturchasz przeciwnika! Jeśli twój przeciwnik ostrzy, wygrywasz! Jeśli przeciwnik szturcha, twój kij uderza w kij przeciwnika i oba stają się matowniejsze (o 1 „jednostkę ostrości”). Jeśli przeciwnik blokuje, nic się nie dzieje poza tym, że twój kij staje się matowy.

    Jeśli szturchasz, gdy ostrość twojego kija wynosi 5 lub więcej, twój kij staje się mieczem i zawsze wygrywasz! (Chyba, że ​​twój przeciwnik również ma miecz i również wybrał P; w takim przypadku oboje stają się bardziej tępi i mogą powrócić do drążków, jeśli ich ostrość spadnie poniżej 5).

    Nie możesz szturchać z ostrością 0. Jeśli to zrobisz, nic się nie wydarzy.

  • B: blok

    Kiedy blokujesz, nic się nie dzieje, gdy przeciwnik szturcha. Jeśli twój przeciwnik nie szturcha, blok nic nie robi.

    Blokowanie nie chroni przed mieczem, nawet jeśli go masz!

Zasady i ograniczenia

Dodatkowe zasady to:

  • Twój program może odczytywać i zapisywać pliki we własnym folderze (bez kradzieży!), Jeśli chcesz zapisać dane, ale nie możesz uzyskać dostępu do niczego poza nim (a jaskiniowcy nie mają połączenia z Internetem na pustkowiu).
    • Ważna uwaga na temat plików : jeśli zapisujesz pliki, pamiętaj, aby zapisać je w katalogu players/YourBotsName/somefile.foo! Bieżący katalog roboczy dla Twojego programu nie będzie należeć do Twojego programu!
  • Jaskiniowcy są uczciwi: jeden program nie może mieć kodu specyficznego dla innego programu, a programy nie mogą sobie nawzajem pomagać. (Możesz mieć wiele programów, ale nie mogą one ze sobą w żaden sposób współdziałać).
  • Sędzia jaskiniowca nie jest cierpliwy. Jeśli jaskiniowcy wykonają więcej niż 100 tur w celu wyłonienia zwycięzcy, sędzia się nudzi i obaj jaskiniowcy przegrywają.

Jeśli Twój program złamie regułę lub nie będzie zgodny ze specyfikacją, zostanie zdyskwalifikowany, usunięty playerlist.txti wszystkie pojedynki rozpoczną się od początku. Jeśli twój program zostanie zdyskwalifikowany, lider jaskiniowca (ja!) Skomentuje post twojego programu i wyjaśni dlaczego. Jeśli nie łamiesz żadnych reguł, Twój program zostanie dodany do tablicy wyników. (Jeśli twojego programu nie ma na tablicy wyników, nie ma komentarza wyjaśniającego do twojego postu, a opublikowałeś swój program przed czasem „Ostatnia aktualizacja” poniżej, powiedz liderowi jaskiniowców! Może on zapomniał.)

W swoim poście podaj:

  • Imię.
  • Polecenie powłoki, aby uruchomić program (np. java MyBot.java, ruby MyBot.rb, python3 MyBot.py, Itd.).
    • Uwaga: dane wejściowe zostaną do tego dołączone jako argument wiersza poleceń.
    • Jaskiniowcy używają Ubuntu 14.04, więc upewnij się, że kod działa (swobodnie) na nim.
  • Numer wersji, jeśli kod działa inaczej w różnych wersjach wybranego języka.
  • Twój kod (oczywiście).
  • Jak skompilować kod, jeśli to konieczne.

Kod kontrolera / testowanie, przykładowy bot

Lider jaskiniowca napisał kod kontrolny w C ++ i opublikował go na repozytorium Github . Możesz tam uruchomić i przetestować swój program.

Bardzo, bardzo prosty program (1 linia!) Jest również zamieszczony w odpowiedziach poniżej .

Punktacja i tabela wyników

Punktacja jest łatwa. Zwycięzca jaskiniowca dostaje punkt. Jaskiniowiec z największą liczbą punktów po 3 pojedynkach z każdym innym jaskiniowcem zostaje nowym przywódcą jaskiniowców!

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

(ta tabela liderów została wygenerowana automatycznie)

Gracze oznaczeni *w pewnym momencie rzucili jakiś błąd lub wyjątek; ci gracze mają również komentarz do swoich postów.

Gracze, którzy nie mogą być zawarte w testach z jakiegokolwiek powodu (ci gracze będą mieć komentarz na swoich stanowiskach wyjaśniając problem): Monkey, Elephant, FacileFibonacci, StudiousSylwester.

Ostatnia aktualizacja: 3 sierpnia 00:15 (UTC).

Klamka
źródło
Dziwi mnie, że nikt nie próbował jeszcze znaleźć strategii minimax. To wydaje się oczywiste.
user2357112,
@ user2357112 Nie sądzę, aby minimax był tutaj poprawą. Mam na myśli, że możesz zaprojektować implementację minimax, ale ponieważ logika jest tak prosta, to samo dokładne zachowanie można wyrazić za pomocą skończonej maszyny stanów. (tzn. bot nigdy nie będzie się wyostrzał, dopóki przeciwnik nie będzie tępy, ponieważ jeśli to zrobi, minimalizujący ruch przeciwnika będzie polegał na szturchaniu i przegrasz, bot zawsze będzie blokował, dopóki nie będziemy mieć miecza, ponieważ maksymalizujący ruch dla naszego bota zawsze będzie być do blokowania itp.)
HuddleWolf
3
Wiele wpisów wydaje się uwzględniać ujemną ostrość w swoich obliczeniach. Reguły, jak napisano, mówią, że nic się nie dzieje, gdy szturchasz z zerową ostrością. Czy to „nic” oznacza również, że twoja ostrość pozostaje zerowa, zamiast być zmniejszona?
Sparr
6
To musi być tutaj: dresdencodak.com/comics/2009-09-22-caveman_science_fiction.jpg Może pobudzi wyobraźnię. :)
Evi1M4chine
2
Czy to jest nadal otwarte? Widzę, że ludzie dodają nowe zgłoszenia, ale nie widzę, aby tabela wyników była aktualizowana.
ASCIIThenANSI

Odpowiedzi:

35

Darwin - C

W każdym razie, kto potrzebuje strategii? Poproś grupę jaskiniowców, aby poszli na siebie i pozwól, aby dobór naturalny zajął się resztą!


Używamy bardzo prostego modelu dla prymitywnego mózgu jaskiniowca: nie ma on pamięci i bierze pod uwagę jedynie ostrość kija jego i przeciwnika. Są one używane jako zmienne dla binarnego wielomianu o pewnym skończonym porządku. Każda akcja (blok, wyostrzenie i zaczepienie) ma przypisany wielomian, którego wynik określa względne prawdopodobieństwo wyboru tej akcji. To prawie wszystko - zacznij od niektórych losowych współczynników i zoptymalizuj iteracyjnie.

Bot:

#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;
}

Skompilować z: gcc darwin.c -odarwin -w -O3. Uruchom z: ./darwin <history>.

Bot odczytuje współczynniki z pliku o nazwie podanej programw players/Darwinkatalogu (inny plik może być określony jako drugi argument wiersza poleceń). Ten program wydaje się dobrze:

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 

Zapisz jako players/Darwin/program.

Poniżej znajduje się program, który generuje programpliki, które mogą być używane przez bota (nie trzeba go kompilować, jeśli używasz programpowyższego pliku):

#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;
}

Skompilować z: gcc genprog.c -ogenprog -w -O3. Uruchom z: ./genprog [output-filename].


Watson

Jakie jest DNA zwycięskiego jaskiniowca? Być może ten koleś ma odpowiedź:

# 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()

Biegnij z: python Watson.py

Watson jest produktem algorytmu genetycznego. W przeciwieństwie do Darwina, tym razem genetyczny układ odniesienia jest faktycznym programem napisanym w małym, specyficznym dla domeny języku (tutaj przetłumaczonym na Python).


Prosta sekwencja pokonuje dużych graczy

Ta mała koleżanka robi zaskakująco (a może nie tak zaskakująco) dobrze, szczególnie przeciwko liderom:

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

Biegnij z: python SSBBP.py

DarwinBot
źródło
Jak to skompilować i uruchomić? Ponadto, jak wspomniano w pytaniu, możesz tylko odczytywać / zapisywać pliki w players/Darwinkatalogu.
Klamka
@Doorknob: naprawiono.
DarwinBot
Pojawiają się te błędy kompilacji podczas kompilacji tego kodu. (Jestem na Ubuntu 14.04.)
Klamka
@Doorknob: Naprawiono. Powinien działać teraz.
DarwinBot
Teraz dostaję undefined reference to `fmax'. - Edytuj-- Nieważne, naprawdę potrzebowałem -lm.
Klamka
50

Nieprzewidywalny jaskiniowiec

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!

Jaskiniowiec wybiera losowo każdą rundę, ale wyjaśniłem mu bardzo prosto, że niektóre działania po prostu czasem nie mają sensu. Skopiuj ten kod, jeśli chcesz wyrazić inną logikę.

To jest Ruby, zapisz jako „nieprzewidywalny.rb” i uruchom z ruby unpredictable.rb

histocrat
źródło
Właściwie tak no 'Block'też powinno być, jeśli mój przeciwnik ma miecz.
njzk2
Pierwszy „blok” nie obejmuje tego: spiczasty kij nie jest mieczem.
histokrata
2
Dlaczego nie używasz unlessinstrukcji no 'Block'i no 'Poke? ( no 'Block' unless he.has_pointy_stick)
wchargin
25

Cave Doctor - Lua

„Przegrywam z nowymi obcokrajowcami, znokautowałem ich na studia”

Kiedy zobaczysz tylu pacjentów, co lekarz jaskiniowy, zaczynasz naprawdę rozumieć psychikę jaskiniowca (a przynajmniej tak mam nadzieję). Gra w jaskiniowego doktora jest czystą strategią, czeka na zaczepy, które blokuje, próbując rozbroić swojego przeciwnika, ale nie pozwala temu przeciwnikowi zbliżyć się do wykonania miecza. Próbuje przewidzieć, kiedy można bezpiecznie wyostrzyć, aby nie stracić przewagi.

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

Biegnij z: lua CaveDoctor.lua

Ogniwo
źródło
3
Przegrywa to tylko dwukrotnie w bieżącej tabeli wyników? oO
justhalf
Wersja 5 generuje wiele błędów, więc wersja 4 to ta, która została uwzględniona w bieżącej rundzie prób.
Klamka
@Doorknob Myślę, że naprawiłem je wszystkie, i tak była tylko jedna zmiana w logice.
Nexus
20

ForeignCaveman

ForeignCaveman nie ma pojęcia, co właśnie powiedziałeś. On po prostu ... robi rzeczy.

javac ForeignCaveman.java następnie 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;
        }
   }
}
Kevin L.
źródło
11
To prawdopodobnie ma zbyt wiele pozytywnych opinii na to, jak źle to robi
Kevin L
19

Wice lider

Klamka ♦ jest liderem. Chcę być liderem! Śledź super inteligentny program, aby stać się liderem!

Skompilować: javac ViceLeader.javaUruchom: 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;
    }
}
CommonGuy
źródło
Dlaczego to nie if (enemySharpness <= 4 || mySharpness >= 5)vs ==?
durron597,
@ durron597 Ponieważ chcę szturchać wroga tylko wtedy, gdy uda mu się zrobić miecz w następnej turze (co najprawdopodobniej zrobi). VizeLeader nie szturcha często, robi to we właściwym czasie .
CommonGuy
Ale masz miecz, a twój przeciwnik nie ...
durron597,
@ durron597 Nie, to instrukcja OR. To znaczy „szturchnij przeciwnika, jeśli mam miecz LUB jeśli wkrótce będzie miał miecz”.
CommonGuy
7
O Boże. Czas na kolejną filiżankę kawy :) Lub nowe soczewki kontaktowe
durron597
15

Może Markov 2.1

Myślę, że używa Łańcuchów Markowa do przewidywania, co zrobi drugi jaskiniowiec, ale tylko krótko spojrzałem na stronę wikipedii o Łańcuchach Markowa i zdecydowałem, że ma za dużo tekstu.

Próbuje pozostać przy życiu przez 30 rund, a następnie buduje stół ze zmianami stanu obecnego i następnego i reaguje na to, co myśli inny jaskiniowiec.

Kod zawiera wiele niepotrzebnych instrukcji, ale działa całkiem dobrze.

EDYTOWAĆ

Wykryto lukę w logice. Teraz robi coś, gdy ma miecz.

$ 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)
Lennart_96
źródło
14

PeriodicalCicadaCaveman

Ten raczej sprytny jaskiniowiec zbadał pewnego robaka i zdał sobie sprawę, że nikt nie może dostosować swojego stylu życia, aby skorzystać z pierwszej liczby cykady.

Ukrywa / blokuje przez większość swojego życia, ale czasami szturcha. Jasne, że jest wrażliwy na Miecze i spędza cały cykl z nieostrym kijem, ale ostrzenie kija, gdy jest całkowicie tępe? Dokładnie tego oczekują inni ... nie ta Cykada

do kompilacji: mcs program.cs, aby uruchomić mono program.exe

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

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

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

  }

}

Edycja: Zmieniono ostrość - kod ... jeśli szturchnę albo wygram, albo mój kij stanie się ciemniejszy

Edycja2: Dodano w sugestii Bobs

Edycja: Zmieniono tak, aby szturchać tylko przy ostrości 2, jeśli drążek ma zawsze zero, drugi facet może zrobić miecz.

Mikey Mouse
źródło
1
Używam Ubuntu; czy to się skompiluje pod Mono? Jeśli tak, to jak go skompilować i jak uruchomić?
Klamka
Szczerze mówiąc, nie wiem. Właśnie zmierzam do łóżka. Mogę przepisać go na Javę jutro rano w pracy. Kod Java powinien być prawie identyczny.
Mikey Mouse,
5
@Doorknob mcs program.csgo skompiluje, mono programuruchomi, ale musisz zastąpić foo.Dump();s System.Console.WriteLine(foo);(lub dodać metodę rozszerzenia public static void Dump(this string value) { System.Console.WriteLine(value); }).
Bob
@Bob Dzięki kolego, dodałem do twojej metody rozszerzenia.
Mikey Mouse
Niestety, rzeczywista domyślna nazwa pliku mcsgeneruje to <filename>.exe, np. program.csStałaby się program.exe. Tak więc polecenie uruchomienia byłoby mono program.exe. (Nie miałem dostępu do mono w momencie mojego wcześniejszego komentarza.)
Bob
14

FancyTechnoAlgorytm

Fantazyjny algorytm techno dla fantazyjnego programu komputerowego techno.

Jaskiniowiec wciąż przegrywa bitwę. Jaskiniowiec zły. Więc jaskiniowiec idzie do szkoły komputerowej i uczy się algorytmu.

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"

Program Python 2. Biegać:python fancytechnoalgorithm.py

Vectorized
źródło
Zrywa się, gdy nie ma danych wejściowych (tj. W pierwszym zakręcie). Nie wiem, jak chcesz sobie z tym poradzić, więc będę musiał wykluczyć to z pierwszej rundy testów.
Klamka
@Doorknob Na pierwsze wejście, czy to „,” czy „”? Wydaje mi się, że z tego wynika to drugie.
Vectorized
Przy pierwszym wejściu nie będzie żadnych argumentów (zostanie uruchomiony jako python StickSharpener.py).
Klamka
@Doorknob Zredagowałem to. Sprawdź, czy teraz działa.
Vectorized
W porządku, dzięki! Uwzględnię to w następnej rundzie prób.
Klamka
14

Obserwator

Obserwuje ruchy przeciwnika, zawsze pozwalając mu pokazać rękę, zanim uderzy. Jest szczególnie przygotowany dla tych, którzy zaniedbują pracę nad mieczem.

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))

Nazwa pliku: watcher.py

Biegać: python watcher.py

Bazyliszek

Stara się zniszczyć tych, którzy patrzą na niego zbyt uważnie. Konsekwentnie pokonuje Strażnika, ale prawdopodobnie ogólnie będzie gorzej.

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))

Nazwa pliku: basilisk.py

Biegać: python basilisk.py

Nash

Stara się, aby wybory przeciwnika były nieistotne, wybierając każdy ruch z prawdopodobieństwem uwzględniającym ryzyko i nagrody

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))

To nie jest równowaga Nasha (mój generator strategii ma pewną niestabilność), ale jest blisko.

Dla ciekawości, oto szacunki prawdopodobieństwa wygranej tego bota w każdym stanie gry:

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] ]

Nazwa pliku: nash.py

Biegać: python nash.py

Zwód

Otwiera się szybkim atakiem, aby przetestować obronę przeciwnika.

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))

Nazwa pliku: feint.py

Biegać: python feint.py

LatePokeBot

Młodszy brat PokeBota. Nigdy nie wykazuje słabości, ale próbuje walczyć jak jego starszy brat.

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))

Nazwa pliku: latepokebot.py

Biegać: python latepokebot.py

Brilliand
źródło
Brakowało ci :bazyliszka; Naprawiłem to dla ciebie
Klamka
To zgłoszenie rzuciło jakiś błąd lub wyjątek w pewnym momencie; możesz zastanowić się nad ustaleniem tego przed następną rundą prób. (Bazyliszek)
Klamka
@Doorknob Wybrałem sekwencję początkową bazyliszka, patrząc na założenia The Watcher i Cave Doctor i znajdując sekwencję, która sprawiłaby, że te założenia byłyby bardzo błędne. Czy to narusza zasadę „jaskiniowcy są sprawiedliwi”?
Brilliand
Idź Nash! Wygraj dokładnie połowę swoich meczów ze wszystkimi botami wystarczająco inteligentnymi, aby uniknąć opcji P = 0!
aschepler
12

PokeBot

Napisane w Ruby.

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

Uruchom z ruby pokebot.rb.

Ten bot nie jest zbyt inteligentny; i tak robi to, co przeciętny jaskiniowiec zrobiłby sam.

Klamka
źródło
9

PatientWolf v2.0

Ostrzy, jeśli jest tępy, szturcha, jeśli w następnej turze wróg będzie miał miecz lub jeśli wróg jest tępy, blokuje inaczej.

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";
}

Biegnij z

perl patientwolf.pl

EDYCJA: dzięki @sylwester za wskazanie błędu

zabójca
źródło
Ponieważ otrzymujesz tylko jeden argument z dwiema historiami oddzielonymi przecinkiem, analizujesz go nieprawidłowo. Na przykład. PatientWolf.pl SB,SProbi, Pponieważ uważa, że ​​ma ostry kij.
Sylwester
@Sylwester, który nie jest poprawny. Pierwszy wiersz przypisuje pierwszy argument $ me, a drugi argument $ mu
killmous
Program CavemanDuel nie używa dwóch argumentów, tylko jeden. na przykład. perl patientwolf.pl "SB,SP". Powinieneś zrobić my($me,$him) = split/,/ $ARGV[0];i if( @ARGV ) {print "S";exit}.
Sylwester
@Sylwester ok Widzę o co ci chodzi. Nie było to jasne z OP ani z szybkiego spojrzenia, które rzuciłem na kod kontrolera. Naprawię to wkrótce
zabójczy
9

Binary Caveman

Wyostrz, dźgnij, powtórz

Opierając się na pomyśle, że blokowanie jest dla maminsynek, ten jaskiniowiec na przemian między dwiema pozostałymi opcjami.

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;
        }
    }
}

Połącz z javac BinaryCaveman.java

Biegnij z java BinaryCaveman

EDYCJA: Przygody w tablicach łańcuchowych ..... args.length () generuje błąd. args.length zawsze zwraca 1. args [0] .length () zwraca długość pierwszego łańcucha w tablicy.

EDYCJA 2: Zaktualizowano dzięki pomocy Doorknob, Brilliand i Sylwester. Dzięki chłopaki.

Red_Shadow
źródło
@ MartinBüttner Zapomniałem podzielić argumenty - 1 na 2, aby uzyskać tylko liczbę poprzednich zgłoszeń przez jednego gracza. Naprawiono to. Nie rozumiem uległości Dorknoba, rubin jest dla mnie praktycznie bełkotem. Czy zawsze zaczyna się od ostrzenia?
Red_Shadow
Tak, po prostu sprawdza, czy jego ostatni ruch był Plub Srobi coś przeciwnego. A jeśli nie ma jeszcze historii, udaje, że historia byłaby P,(co następnie prowadzi go do zrobienia w Spierwszej kolejności).
Martin Ender
Dwa różne podejścia, które dają ten sam wynik. Czy to wbrew zasadom?
Red_Shadow
Prawdopodobnie nie, po prostu dam ci znać.
Martin Ender,
2
@Doorknob myślę, że powinno być args[0].length(), nie args.length.
Brilliand
8

CavekidBlocks

Płaczący i przestraszony jaskiniowiec może wyglądać na łatwą zdobycz. Nie daj się zwieść jego ładnej twarzy, bo on umie blokować.

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])

Biegnij z python3 cavekidblocks.py

ChargerMan

Ten jaskiniowiec jest bardzo konserwatywny. Spróbuje naładować swoją broń i atakuje tylko w razie potrzeby.

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)

Biegnij z python3 chargerman.py

Oszust

Trickster nie wie, jak walczyć, więc próbuje zmylić innego jaskiniowca.

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])

Biegnij z python3 trickster.py

Niestety, po zatwierdzeniu acc74 , Trickster nie działa już zgodnie z planem.

wendelbsilva
źródło
4
Ten program oszustów jest zły
Nexus,
@Nexus Też tak myślałem. Niestety Trickster nie radzi sobie dobrze w pojedynkach.
wendelbsilva
7

Hodor

Hodor nie jest bardzo agresywny. Lubi pozostać w tarczy, chyba że istnieje dobra okazja do ataku.

skompiluj z: javac Hodor.javai uruchom z:java Hodor

kod:

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);
    }
}

Edycja: drobna aktualizacja kodu

Qwix
źródło
To zgłoszenie rzuciło jakiś błąd lub wyjątek w pewnym momencie; możesz zastanowić się nad ustaleniem tego przed następną rundą prób.
Klamka
1
Spróbuj z SB,BB. Kiedy inni jaskiniowcy źle zachowują się w pierwszej turze, Hodor też źle się zachowuje.
Sylwester
7

Spekulacyjny Sylwester - Perl5

Spekulacyjny Sylwester chce wyeliminować poszukiwaczy miecza, patrząc na wzory i szturchać, gdy istnieje szansa, że ​​przeciwnik wyostrzy się i wyostrzy, gdy przeciwnik najprawdopodobniej zablokuje. Nie zrobi tego jednak, jeśli istnieje szansa, że ​​zgadłby, że on sam wyostrzy się w następnym ruchu, a my będziemy jeszcze bardziej ostrożni, kiedy zdecydujemy się na wyostrzenie.

Jeśli zaś przeciwnik jest tępy, stara się być agresywny, ale w końcu zacznie oszczędzać na miecz, gdy wydaje się to bezowocne.

#!/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;
}

Aby uruchomić na Linuksie, po prostu dodaj to w playerlist.txt:

perl players/SpeculativeSylwester/SpeculativeSylwester.pl

Facile Fibonacci - R6RS Schemat

Oprócz pierwszego ruchu Facile Fibonacciego blokuje, gdy turą jest liczba Fibonacciego (zaczynając od 0) i wypełnia resztę PPSS..i zmienia się, gdy przechodzi 8 do nieskończonej sekwencji PSSwygranych mieczem.

#!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)))

Aby uruchomić wystarczy zainstalować ikarus apt-get install ikarusi dodać to w playerlist.txt:

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

Studious Sylwester - Perl5

Ostrożny Sylwester stosuje tę samą taktykę jak Spekulacyjny Sylwester, ale analizuje także poprzednie gry, aby ustalić, gdzie mógł wybrać zły wybór.

#!/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;
}

Aby uruchomić na Linuksie, po prostu dodaj to do playerlist.txt

perl players/StudiousSylwester/StudiousSylwester.pl

Ostrożna edycja

Nie mogę odtworzyć problemów, które miałeś z $0tym, że nie byłeś pełną ścieżką do skryptu perl, gdy jest on uruchamiany z perlem. Wyciągnąłem również twoje zmiany i nie widzę żadnych zmian w CavemanDuels src i tak samo działam ponad 20 razy bez zgłaszanego problemu. Zaczynam się obawiać, że skrypt mógł zostać pobrany jako skrypt bash zamiast uruchamiać go podczas wykonywania lub jako argument dla Perla. Potrzebuję więcej informacji, aby wiedzieć na pewno. Jako test zrobiłem to i możesz zrobić to samo, aby zobaczyć, czy uzyskasz ten sam wynik:

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
Sylwester
źródło
Schemat nie chce ze mną współpracować na moim komputerze, więc nie byłem w stanie przetestować Fibonacciego. Będę starał się, aby działał, ale byłoby wspaniale, gdybyś mógł przetłumaczyć go na inny język.
Klamka
Uważny też nie działa, ponieważ $0jest bashwywoływany z linii poleceń bash (co robi kontroler). Możesz jednak po prostu kodować players/StudiousSylwester/foo.txt.
Klamka
@Doorknob Dodałem sposób instalacji ikarusi dodałem swoje przemyślenia $0do Studious.
Sylwester,
6

Miecznik

Potrzebujesz ostrego kija. Jeśli masz ostry kij, szturchnij. Nie odczuwam bólu.

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

Zapisz jako swordsmith.f90i skompilować gfortran -o swordsmith swordsmith.f90, uruchomić tak jak każdy normalny wykonywalnego: ./swordsmith.

Kyle Kanos
źródło
Wydaje się, że drukuje spację (``) przed rzeczywistym wyjściem. Nie mam pojęcia, jak to naprawić, więc będę musiał wykluczyć to zgłoszenie z pierwszej rundy testów.
Klamka
Poprawiłem także ścieżkę do pliku; okazuje się, że bieżący katalog roboczy po uruchomieniu nie należy do twojego programu. Aha, a jeśli przez „nową instancję” masz na myśli „każdą grę”, nie mogę tego zrobić, ponieważ wymagałoby to specjalnego umieszczenia programu kontrolera; możesz to zrobić we własnym kodzie.
Klamka
@Doorknob: Zaktualizowałem swój kod: wyjście jest pojedynczym znakiem, usuwa już istniejący plik przy pierwszym uruchomieniu, a plik znajduje się w katalogu odtwarzacza.
Kyle Kanos
W porządku, dzięki! To zgłoszenie jest teraz uwzględnione w tabeli wyników.
Klamka
@Doorknob: Cool! Bani, że nie jestem pierwszy. Ponadto: jestem prawie pewien, że użytkownicy Fortrana są jak wampiry, więc jestem pewien, że wkrótce zaczniesz kodować w Fortran! Muahahahaha!
Kyle Kanos
5

PacjentBlackmith

Ten bot jest napisany w języku R, użyj go, Rscript PatientBlacksmith.Raby go uruchomić.

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)

Mierzy ostrość drążka przeciwnika: blokuje, gdy jest ostry, w przeciwnym razie poświęć trochę czasu. Kiedy własna ostrość osiągnie 5, szturchaj, aż ostrość zniknie.

plannapus
źródło
Zrywa się, gdy nie otrzyma żadnych danych wejściowych (tj. W pierwszej turze); Nie wiem, jak to naprawić, więc będę musiał wykluczyć go z pierwszej rundy testów.
Klamka
@Doorknob poprawiony.
plannapus
5

Reguły więzienne, Haskell

Jaskiniowiec uważa, że ​​jaskiniowiec i inny jaskiniowiec powinni rozmawiać, dzielić kij. Ale, hej ho, jeśli trzeba walczyć, walcz z więziennymi zasadami. Znajdź bossa i zaatakuj.

ViceLeader Alpha Caveman teraz; z którym jaskiniowiec musi walczyć. Inni jaskiniowcy walczą później. Jeśli mój jaskiniowiec przegra, nie martw się; i tak jest owłosiony.

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

Napisane w Haskell (przejdź do programowania funkcjonalnego!), Więc zapisz jako prisonrules.hs , a następnie skompiluj z:

ghc prisonrules.hs

I działaj jako:

prisonrules [history]
wszechstronny
źródło
4

Nazywam go JavaMan

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

Uwaga: Nie zamierzam grać w golfa kodowego ... ale jeśli jesteś golfistą, a spacje / dodatkowe linie powodują krwawienie oczu .. możesz to zmienić

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;
    }
}
użytkownik 2813274
źródło
4
Zgłoszenia do wyzwań King of the Hill nie są przeznaczone do gry w golfa, więc nie martw się. ;)
Martin Ender
Zmieniłem jego nazwę na JavaMan, ponieważ „Caveman” jest nieco zbyt ogólny, aby znaleźć się w tabeli liderów. Mam nadzieję, że to w porządku. jeśli nie, po prostu zmień to na coś innego.
Klamka
1
Zrywa się, gdy nie otrzyma żadnych danych wejściowych (tj. W pierwszej turze); Nie wiem, jak sobie z tym poradzić, więc będę musiał wykluczyć to z pierwszej rundy testów.
Klamka
Naprawiono, a zmiana nazwy jest dla mnie w porządku
2813274
1
Myślę, że popełniłeś błąd podczas analizowania stanu, zarówno „ja”, jak i „wróg” wykonują te same ruchy: stany [0]
Roy van Rijn
4

Głębokie myśli, C.

Kod jaskiniowca. Jaskiniowiec myśli. Jaskiniowiec zrobić.

// 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;
}

Ja robię testy. Więcej myśli lepiej.

Zakipu
źródło
1
+1 za nazwy i komentarze jaskiniowców var: P Również fajny program c:
kot
3

Nigel

Nigel jest cierpliwym, defensywnym starym jaskiniowcem, który wolałby być taktyczny niż walczyć w ataku.

To skrypt PHP, zadzwoń z 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");  
}

?>
ArcticanAudio
źródło
3

Aichmophobic - Lua

Czasami cię szturcha, ale tylko do momentu, gdy jakiś kij stanie się zbyt ostry. Kiedy to nastąpi, wpadnie w panikę i zwinie się w pozycję embrionalną.

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)

Uruchom z:

lua aichmophobic.lua

William Barbosa
źródło
2
Twój wynik musi być pisany wielkimi literami; Naprawiłem to dla ciebie. (Również błędnie przeliterowałem nazwę tego zgłoszenia około tysiąc razy.: P)
Klamka
3

Bob Caves

Bob Caves jest jednym z najmądrzejszych facetów w jego jaskini. Nauczył się liczyć jedną ręką (druga zajmuje się trzymaniem kija). Znał Olimpiadę Epoki Kamienia i chciał wziąć udział.

Jego główną strategią jest blokowanie i wyostrzanie kija, aż będzie miał fajny, ostry patyk lub inny jaskiniowiec też będzie ostry. W tym przypadku Bob Caves próbuje go szturchnąć!

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;
    }

}

Kompiluj javac BobCaves.javai uruchamiaj zjava BobCaves

Edycja: Bob liczy się teraz, gdy jest jakiś blok! (dzięki Mikey Mouse ). Ostrzy też kij, gdy drugi kij jaskiniowca jest tępy.

Edycja 2: Ulepszona metoda liczenia (ponownie dzięki Mikey).

Edycja 3: Uczynienie Boba nieco bardziej agresywnym.

Averroes
źródło
2
Bob zapomina zliczyć efekt Poke: Block na własnej ostrości. Trzy „S” w sztyfcie nie oznaczają 3 razy ostre. Każde „P” oznacza nieostrzony kij. Huh huh huh ... Żart w jaskini „siusiu” ...
Mikey Mouse
@MikeyMouse Bob zgadza się. Bob odwiedzi szamana, aby ulepszyć swoją technikę. Bob wdzięczny!
Averroes
1
Szaman dobrze uczy Boba. Ale zapomniał wspomnieć o scenariuszu Poke: Poke. Stick też się stępił. Bob nie musi rozważać ruchu przeciwnika. Jeśli Bob Poke, kij się stępi. Albo tępo: przeciwnik szturcha, na bloku przeciwnika lub na głowie przeciwnika. Na Głowie przeciwnika Bob wygrywa i może tańczyć wokół jaskini tępym kijem.
Mikey Mouse
1
@MikeyMouse Bob umie liczyć. Bob musi nauczyć się czytać. Dzięki jeszcze raz!
Averroes
3

Gruntt

Gruntt jest defensywny. Gruntt analizuje inne ruchy jaskiniowców, aby wiedzieć, jak je szturchać. Potem szturcha je prosto w oko. Gruntt nie jest miłym jaskiniowcem.

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;
}

}

Kompiluj javac Gruntt.javai uruchamiaj zjava Gruntt

Averroes
źródło
To rzuca znak ArrayOutOfBoundsExceptionw pierwszej turze, a czasami generuje wiele akcji w innych turach.
Klamka
@Doorknob Ops! Naprawiono, dziękuję!
Averroes
3

Czy to ptak? Czy to samolot? To RegExMan!

Próbuje analizować twoje super nudne sekwencje za pomocą swojej wyjątkowej mocy 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)

Napisane w Pythonie 2.7, uruchamiane z python RegExMan.py [history]

Szyfr
źródło
3

Sycylijski

Ale to takie proste! Wszystko, co muszę zrobić, to boskość z tego, co wiem o innym jaskiniowcu: czy to taki jaskiniowiec, który blokuje, wyostrza lub szturcha? Teraz sprytny jaskiniowiec szturchał lub blokował, ponieważ wiedziałby, że tylko wielki głupiec wyostrzy się i wystawi na atak. Nie jestem wielkim głupcem, więc wyraźnie nie mogę wyostrzyć. Ale inny jaskiniowiec musi wiedzieć, że nie jestem wielkim głupcem i liczyłbym na to, więc wyraźnie nie mogę szturchać ani blokować!

Biegnij z:

javac Sicillian.java
java Sicillian

Kod:

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;
    }
}
amwallis
źródło
3

bash-magnon

Bash-magnony były solidnie zbudowane i potężne. Ciało było ogólnie ciężkie i solidne z silną muskulaturą. Czoło było raczej proste, a nie ukośne, jak u neandertalczyków, z tylko niewielkimi brwiami. Twarz była niska i szeroka. Podbródek był wydatny. Pojemność mózgu wynosiła około 1600 centymetrów sześciennych (98 cu in), więcej niż średnia dla współczesnych ludzi. Jednak ostatnie badania sugerują, że fizyczne wymiary tak zwanego „Bash-Magnon” nie różnią się wystarczająco od współczesnych ludzi, aby uzasadnić odrębne oznaczenie.

Mam mózg, pamiętam.

Jest to plik wykonywalny ./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
Emmanuel
źródło
1+ Oczywiście masz odpowiednie narzędzie do pracy, a twoje jaskiniowe imiona są dość zabawne :) (Osobiście bardziej lubię ryby)
Sylwester
@Sylwester Dziękuję, to moja pierwsza +1. Najpierw próbowałem stworzyć automaty homeostatyczne zainspirowane tym, co zrobił pierwszy cybernetycy coś, co wydaje się być równowagą, potem poddałem się i napisałem skrypt bash.
Emmanuel
2

PokeBackBot

Po prostu zaadaptowany z PokeBot:

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

Uruchom z ruby pokebackbot.rb.

Wykorzystuje następną najprostszą strategię i blokuje „cierpliwie” przez jedną rundę przed atakiem.

Martin Ender
źródło
3
@PeterTaylor Przeczytałem, że nie wolno mi zmieniać strategii na podstawie odcisków palców przeciwnika. Jeśli moje zgłoszenie może pokonać tylko jedno inne zgłoszenie, tak naprawdę nie wpłynie to na wynik innych zgłoszeń, a moje własne zgłoszenie prawdopodobnie źle się sprawdzi. Co więcej, jeśli jest tylko jedno zgłoszenie, a napisane jest drugie, to drugie prawdopodobnie pobije pierwsze (bo inaczej, po co zawracać sobie głowę) - czy to samo kwalifikuje się jako „specyficzne dla innego programu”? Mój bot pokona każdego bota, który zaczyna SPS(co wydaje się rozsądne), ale jak dotąd PokeBot był jedynym w okolicy.
Martin Ender
2

Mistrz miecza

Napisane w Python 3.4 (współpracuje z Python 3.x)

Próbuje zdobyć miecz tak szybko, jak to możliwe, ale atakuje, jeśli ma szansę go trafić (ostrość> 0), a wróg może go zranić (ostrość wroga> 0).
Blokuje tylko wtedy, gdy nie ma ostrości, a wróg może atakować.

Zacząć od:

python3 swordmaster.py MOVES

(zakładając, że zapiszesz jako swordmaster.py)

Szybki i brzydki kod:

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])))

(Ustaw, dgaby Truewłączyć wiadomości debugowania)

chill0r
źródło
1
Podpowiedź: nie pozwól, by walczyć sam - będzie to z impasu S, P, S, P...
chill0r
Odkryłem, że tak się dzieje również z moim. O ile nie przeanalizujesz historii lub nie wykorzystasz pewnego stopnia losowości, z pewnością utkniesz w cyklu.
Pharap
2

FoolMeOnce.py

Zachowaj ruchy każdego gracza na pierwszy pojedynek, a następnie powtórz dokładnie te same ruchy. Jeśli algorytm wroga nie jest przypadkowy, możemy przewidzieć ten sam wynik i uderzyć tylko wtedy, gdy wiemy, że wygramy.

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)

Napisane w Pythonie 3, więc najprawdopodobniej będziesz musiał użyć python3 FoolMeOnce.py W pierwszej rundzie nie jestem pewien, czy otrzymamy pusty ciąg, czy tylko przecinek, więc mogą być potrzebne poprawki.

tzazy
źródło
Naprawiłem twoją ścieżkę do pliku - okazuje się, że bieżący katalog roboczy nie należy do twojego programu.
Klamka
Podczas zabawy testerem CavemanDuel zauważyłem, że FoolMeOnce uzyskuje znacznie lepsze punkty, jeśli użyję więcej wątków (przetestowałem 16 wątków na 4). Z 4 wątkami dostaje ~ 25 punktów, z 16 dostaje ~ 34.
wendelbsilva
Dziwne, nie mam pojęcia, dlaczego tak jest.
tzazy