Höhlenmensch-Duelle (oder: Ich stoße dich mit einem spitzen Stock an)


151

Höhlenmensch verrückt. Andere Höhlenmenschen nehmen Stock, aber Stock war für mich. Höhlenmensch Kampf !


Beschreibung

Höhlenmenschen brauchen scharfe Stöcke, um andere Höhlenmenschen zu erstechen. Andere Höhlenmenschen versuchen ebenfalls mit spitzen Stöcken zu stechen. Caveman kann Schläger schärfen, mit Schlägern stechen oder knifflige Schläger blockieren.

Wenn ein Höhlenmensch einen anderen Höhlenmenschen mit einem spitzen Stock stößt, rennt ein anderer Höhlenmensch weg und ich habe gewonnen. Aber wenn andere Höhlenmenschen klug blocken, wenn ich stoße, passiert nichts, außer dass mein Stock stumpf wird und ich wieder scharf machen muss.

Höhlenmensch faul. Auch Höhlenmensch dumm. Caveman weiß nicht, was zu tun ist, also braucht Caveman ein ausgefallenes Techno-Computerprogramm, um Caveman zu sagen, was zu tun ist.

Eingang

Die Eingabe Ihres Programms ist eine Historie der Ereignisse, bei denen Sfür Schärfen (dh der Höhlenmensch hat seinen Stock geschärft), Pfür Stoßen und Bfür Blockieren steht. Die Eingabe ist eine Historie beider Seiten (Sie und der Gegner), sodass Ihre und die Bewegungen des Gegners durch ein Komma ( ,) getrennt werden.

Beispiel Eingabe:

SPB,SBB

Dies bedeutet, dass der Spieler seinen Stock geschärft, dann gestoßen und dann geblockt hat und der Gegner geschärft, dann geblockt und dann wieder geblockt hat.

Sie erhalten in Runde 1 keine Eingabe.

Ausgabe

Die Ausgabe ist der Eingabe sehr ähnlich (weil der Höhlenmensch nicht sehr schlau ist). Ihr Programm sollte Szum Schärfen, Pzum Anstoßen und Bzum Blockieren ausgegeben werden . Nur das erste Zeichen der Ausgabe wird berücksichtigt, und jede andere Eingabe wird als B(Block-) Befehl behandelt.

  • S: schärfen

    Beim Schärfen erhöht sich die Schärfe des Höhlenmeisters um 1 und der Stock erhält 1 zusätzlichen Stoß. Jeder Stoß verringert die Schärfe des Stocks um 1, und wenn die Schärfe des Stocks 0 ist, ist es zu langweilig, um damit zu stoßen. Die Schärfe beginnt bei 0. Wenn die Schärfe 5 erreicht, ist der Stab ein Schwert! (Siehe unten.)

    Wenn der Gegner während des Schärfens drückt (und die Schärfe> 0 ist), gewinnt der Gegner!

  • P: stecken

    Beim Stoßen sinkt die Schärfe des Höhlenmeisters um 1 und Sie stoßen Ihren Gegner an! Wenn Ihr Gegner schärft, gewinnen Sie! Wenn der Gegner stößt, trifft Ihr Schläger den Schläger Ihres Gegners und beide werden stumpfer (um 1 "Schärfeeinheit"). Wenn der Gegner blockt, passiert nichts, außer dass Ihr Schläger stumpfer wird.

    Wenn Sie stoßen, wenn die Schärfe Ihres Schlägers 5 oder mehr beträgt, wird Ihr Schläger zum Schwert und Sie gewinnen immer ! (Es sei denn, dein Gegner hat auch ein Schwert und hat ebenfalls gewählt P. In diesem Fall werden beide stumpfer und können zu Stöcken zurückkehren, wenn ihre Schärfe unter 5 fällt.)

    Sie können nicht mit einer Schärfe von 0 stoßen. Wenn Sie dies tun, passiert nichts.

  • B: Block

    Wenn Sie blocken, passiert nichts, wenn Ihr Gegner stößt. Wenn dein Gegner nicht stößt, macht der Block nichts.

    Das Blockieren schützt nicht vor einem Schwert, auch wenn Sie eines haben!

Regeln und Einschränkungen

Zusätzliche Regeln sind:

  • Ihr Programm kann Dateien in einem eigenen Ordner lesen und schreiben (kein Diebstahl!), Wenn Sie Daten speichern möchten, aber auf nichts außerhalb zugreifen können (und Höhlenmenschen haben keine Internetverbindung in der Wildnis).
    • Wichtiger Hinweis zu Dateien : Wenn Sie Dateien speichern, denken Sie daran, diese im Verzeichnis zu speichern players/YourBotsName/somefile.foo! Das aktuelle Arbeitsverzeichnis für Ihr Programm wird nicht das Ihres Programms sein!
  • Höhlenmenschen sind fair: Ein Programm kann keinen Code haben, der für ein anderes Programm spezifisch ist, und Programme können sich nicht gegenseitig helfen. (Möglicherweise haben Sie mehrere Programme, die jedoch in keiner Weise miteinander interagieren können.)
  • Der Höhlenrichter ist nicht geduldig. Wenn die Höhlenmenschen mehr als 100 Runden brauchen, um einen Gewinner zu ermitteln, langweilt sich der Richter und beide Höhlenmenschen verlieren.

Wenn Ihr Programm gegen eine Regel verstößt oder nicht der Spezifikation entspricht, wird das Programm disqualifiziert, entfernt playerlist.txtund alle Duelle werden von Anfang an neu gestartet . Wenn Ihr Programm disqualifiziert wird, kommentiert der Caveman-Leiter (ich!) Den Beitrag Ihres Programms und erklärt, warum. Wenn Sie keine Regeln brechen, wird Ihr Programm zur Bestenliste hinzugefügt. (Wenn sich Ihr Programm nicht in der Bestenliste befindet, gibt es keinen erklärenden Kommentar zu Ihrem Beitrag und Sie haben Ihr Programm vor der unten angegebenen "Zuletzt aktualisiert" -Zeit gepostet. Sagen Sie es dem Höhlenmenschenführer! Vielleicht hat er es vergessen.)

Bitte fügen Sie Ihrem Beitrag Folgendes bei:

  • Ein Name.
  • Ein Shell - Befehl ausführt Ihr Programm (ex. java MyBot.java, ruby MyBot.rb, python3 MyBot.py, Etc.).
    • Hinweis: Die Eingabe wird als Befehlszeilenargument angehängt.
    • Die Höhlenmenschen verwenden Ubuntu 14.04, stellen Sie also sicher, dass Ihr Code (frei) darauf funktioniert.
  • Eine Versionsnummer, wenn Ihr Code in verschiedenen Versionen der von Ihnen gewählten Sprache unterschiedlich funktioniert.
  • Dein Code (offensichtlich).
  • So kompilieren Sie den Code, falls erforderlich.

Controller Code / Testing, Beispiel Bot

Der Caveman-Anführer schrieb den Kontrollcode in C ++ und stellte ihn auf ein Github-Repo . Dort können Sie Ihr Programm ausführen und testen.

Ein sehr, sehr einfaches Programm (1 Zeile!) Finden Sie auch in den folgenden Antworten .

Wertung und Bestenliste

Die Wertung ist einfach. Welcher Höhlenmensch gewinnt, bekommt einen Punkt. Der Höhlenmensch mit den meisten Punkten nach 3 Duellen gegen jeden anderen Höhlenmenschen wird der neue Höhlenmenschenführer!

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

(Diese Rangliste wurde automatisch magisch generiert)

Spieler, die mit einem gekennzeichnet sind, *haben irgendwann einen Fehler oder eine Ausnahme geworfen. Diese Spieler haben auch einen Kommentar zu ihren Beiträgen.

Spieler , die nicht mehr in den Tests aus irgendeinem Grunde aufgenommen werden (diese Spieler einen Kommentar über ihre Beiträge haben das Problem zu erklären): Monkey, Elephant, FacileFibonacci, StudiousSylwester.

Letzte Aktualisierung: 3. August 00:15 (UTC).


Ich bin überrascht, dass noch niemand versucht hat, die Minimax-Strategie zu finden. Es scheint das Naheliegende zu sein.
user2357112

@ user2357112 Ich denke nicht, dass Minimax hier eine Verbesserung ist. Sie könnten eine Minimax-Implementierung entwerfen, aber da die Logik so einfach ist, kann dasselbe exakte Verhalten mit einer Finite-State-Maschine ausgedrückt werden. (dh der Bot schärft niemals, bis der Gegner stumpf ist, denn wenn dies der Fall ist, ist die Minimierungsbewegung des Gegners ein Stoßen, und Sie verlieren, der Bot blockiert immer, bis wir ein Schwert haben, da die Maximierungsbewegung für unseren Bot immer ist zu blocken sein, etc.)
HuddleWolf

3
Viele der Einträge scheinen eine negative Schärfe in ihren Berechnungen zuzulassen. Die Regeln, wie sie geschrieben sind, besagen, dass nichts passiert, wenn Sie mit einer Schärfe von Null stoßen. Bedeutet das "nichts" auch, dass Ihre Schärfe Null bleibt, anstatt dekrementiert zu werden?
Sparr

6
Dies muss hier sein: dresdencodak.com/comics/2009-09-22-caveman_science_fiction.jpg Vielleicht regt es die Fantasie an. :)
Evi1M4chine

2
Ist das noch offen? Ich sehe Leute, die neue Beiträge hinzufügen, aber ich sehe nicht, dass die Bestenliste aktualisiert wird.
ASCIIThenANSI

Antworten:


35

Darwin - C

Wer braucht schon Strategie? Lassen Sie eine Gruppe Höhlenmenschen aufeinander los und lassen Sie die natürliche Auslese den Rest erledigen!


Wir verwenden ein sehr einfaches Modell für das primitive Gehirn unseres Höhlenmenschen: Es hat kein Gedächtnis und berücksichtigt nur die Schärfe des Stocks seines und seines Gegners. Diese werden als Variablen für ein binäres Polynom einer endlichen Ordnung verwendet. Jeder Aktion (Blockieren, Schärfen und Anstoßen) ist ein Polynom zugeordnet, dessen Ergebnis die relative Wahrscheinlichkeit für die Auswahl dieser Aktion bestimmt. Das ist so ziemlich alles - beginnen Sie mit einigen zufälligen Koeffizienten und optimieren Sie iterativ.

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

Kompilieren mit: gcc darwin.c -odarwin -w -O3. Führen Sie mit: ./darwin <history>.

Der Bot liest die Koeffizienten aus einer programim players/DarwinVerzeichnis angegebenen Datei (eine andere Datei kann als zweites Befehlszeilenargument angegeben werden). Dieses Programm scheint gut zu funktionieren:

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 

Speichern unter players/Darwin/program.

Das folgende Programm generiert programDateien, die vom Bot verwendet werden können (muss nicht kompiliert werden, wenn Sie die programobige Datei verwenden):

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

Kompilieren mit: gcc genprog.c -ogenprog -w -O3. Führen Sie mit: ./genprog [output-filename].


Watson

Was ist die DNA eines siegreichen Höhlenbewohners? Vielleicht hat dieser Typ die Antwort:

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

Laufen mit: python Watson.py

Watson ist das Produkt eines genetischen Algorithmus. Im Gegensatz zu Darwin ist das genetische Datum dieses Mal ein aktuelles Programm, das in einer winzigen domänenspezifischen Sprache geschrieben ist (hier in Python übersetzt).


Einfache Sequenz schlägt große Spieler

Dieser kleine Kerl macht sich überraschend (oder vielleicht auch nicht so überraschend) gut, besonders gegen die Führer:

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

Laufen mit: python SSBBP.py


Wie kompiliere ich das und führe es aus? Wie in der Frage erwähnt, können Sie außerdem nur Dateien im players/DarwinVerzeichnis lesen / schreiben .
Türklinke

@Doorknob: behoben.
DarwinBot

Ich erhalte diese Kompilierungsfehler, wenn ich diesen Code kompiliere. (Ich bin auf Ubuntu 14.04.)
Türklinke

@Doorknob: Behoben. Sollte jetzt funktionieren.
DarwinBot

Ich bekomme jetzt undefined reference to `fmax'. --Edit-- Egal, ich brauchte in der Tat -lm.
Türklinke

50

Unberechenbarer Höhlenmensch

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!

Dieser Höhlenmensch wählt jede Runde nach dem Zufallsprinzip aus, aber ich habe ihm sehr einfach erklärt, dass bestimmte Aktionen manchmal einfach keinen Sinn ergeben. Fühlen Sie sich frei, diesen Code zu kopieren, wenn Sie eine andere Logik ausdrücken möchten.

Das ist Ruby, speichere es als 'unpredictable.rb' und starte es mit ruby unpredictable.rb


Eigentlich no 'Block'sollte das ja auch sein, wenn mein Gegner ein Schwert hat.
njzk2

Der erste no 'Block' deckt das eigentlich ab: Ein spitzer Stock ist kein Schwert.
Histokrat

2
Warum verwenden Sie nicht unlessfür die no 'Block'und no 'PokeAussagen? ( no 'Block' unless he.has_pointy_stick)
wchargin

25

Höhlenarzt - Lua

"Ich verliere gegen neue Ausländer, habe sie rausgeschmissen, um sie zu studieren."

Wenn Sie so viele Patienten wie den Höhlenarzt gesehen haben, beginnen Sie, die Psyche des Höhlenmenschen wirklich zu verstehen (hoffe ich zumindest). Das Spiel des Höhlenarztes ist reine Strategie, er wartet auf Stöße, die er blockiert, um seinen Gegner zu entwaffnen, aber er lässt diesen Gegner nicht in die Nähe eines Schwertes kommen. Er versucht vorherzusagen, wann es sicher ist, zu schärfen, damit er nicht die Oberhand verliert.

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

Laufen mit: lua CaveDoctor.lua


3
Diese verlieren nur zweimal in der aktuellen Bestenliste? oO
Hälfte des

Revision 5 wirft eine Reihe von Fehlern auf, sodass Revision 4 in der aktuellen Testrunde enthalten ist.
Türklinke

@Doorknob Ich glaube, ich habe alle behoben, es gab sowieso nur eine Änderung an der eigentlichen Logik.
Nexus

20

ForeignCaveman

ForeignCaveman hat keine Ahnung, was Sie gerade gesagt haben. Er macht nur ... Sachen.

javac ForeignCaveman.java dann java ForeignCaveman

public class ForeignCaveman {

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

11
Dies hat wahrscheinlich viel zu viele positive Stimmen für wie schlimm es tut
Kevin L

19

Vize-Leiter

Türklinke ♦ ist führend. Ich will Anführer sein! Folge dem super intelligenten Programm, um führend zu werden!

Kompilieren: javac ViceLeader.javaRun: java ViceLeader.

public class ViceLeader {

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

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

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

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

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

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

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

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

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

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

Warum ist das nicht if (enemySharpness <= 4 || mySharpness >= 5)vs ==?
Durron597

@durron597 Weil ich den Feind nur stechen will, wenn er in der nächsten Runde ein Schwert machen kann (was er höchstwahrscheinlich tun wird). VizeLeader stochert nicht oft, es macht es zur richtigen Zeit .
CommonGuy

Aber Sie haben ein Schwert und Ihr Gegner nicht ...
Durron597

@ durron597 Nein, es ist eine OR-Anweisung. Es bedeutet "Stupse den Gegner an, wenn ich ein Schwert habe ODER wenn er bald ein Schwert haben wird".
CommonGuy

7
Oh, meine Güte. Zeit für eine neue Tasse Kaffee :) Oder neue Kontaktlinsen
durron597

15

Vielleicht Markov 2.1

Ich denke, es verwendet Markov-Ketten, um vorherzusagen, was der andere Höhlenmensch tun wird, aber ich habe nur kurz auf die Wikipedia-Seite über Markov-Ketten geschaut und festgestellt, dass sie zu viel Text enthält.

Es versucht, 30 Runden am Leben zu bleiben und baut dann eine Tabelle mit den aktuellen und nächsten Statusänderungen auf und reagiert auf die Erwartungen, die der andere Höhlenmensch erfüllen wird.

Der Code enthält eine Menge unnötiger Anweisungen, funktioniert aber ziemlich gut.

BEARBEITEN

Erkannte einen Fehler in der Logik. Jetzt macht es tatsächlich etwas, wenn es ein Schwert hat.

$ python3 players/MaybeMarkov/MaybeMarkov.py

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

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

all_actions = SHARPEN, POKE, BLOCK
always = 1

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

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

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

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

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


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

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

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

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

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

if turns > 97:
    do(POKE)

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

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

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

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

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

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

counts = itemgetter(1)

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

react_on(prediction)

14

PeriodicalCicadaCaveman

Dieser ziemlich kluge Höhlenmensch hat einen bestimmten Bug studiert und festgestellt, dass niemand seinen Lebensstil anpassen kann, um die Primzahl Cicada auszunutzen.

Es verbirgt sich für den größten Teil seines Lebens, stößt aber gelegentlich an. Sicher, es ist anfällig für Schwerter und verbringt einen ganzen Zyklus mit einem ungeschärften Stock, aber den Stock schärfen, wenn es total stumpf ist? Genau das erwarten die anderen von ihr ... nicht diese Zikade

Kompilieren: mcs program.cs um mono program.exe auszuführen

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

  }

}

Edit: Änderte den sharpness-- Code ... wenn ich drücke, gewinne ich oder mein Stock wird langweiliger

Edit2: In Bobs Vorschlag hinzugefügt

Bearbeiten: Wurde dahingehend geändert, dass nur bei Schärfe 2 gestoßen wird. Wenn der Stock jemals auf Null steht, kann der andere Typ ein Schwert herstellen.


1
Ich laufe auf Ubuntu; Wird dies unter Mono kompiliert? Wenn ja, wie kompiliere ich es und wie führe ich es aus?
Türklinke

Um ehrlich zu sein, ich weiß es nicht. Ich gehe gerade ins Bett. Ich kann es morgen früh bei der Arbeit auf Java umschreiben. Der Java-Code sollte fast identisch sein.
Mikey Mouse

5
@Doorknob mcs program.cskompiliert es, mono programführt es aus, aber Sie müssen das foo.Dump();s durch System.Console.WriteLine(foo);(oder eine Erweiterungsmethode hinzufügen public static void Dump(this string value) { System.Console.WriteLine(value); }) ersetzen .
Bob

@ Bob Danke Kumpel, ich habe deine Erweiterungsmethode hinzugefügt.
Mikey Mouse

Sorry, der eigentlich mcsgenerierte Standarddateiname ist <filename>.exe, program.cswürde zB werden program.exe. Der Befehl run wäre also mono program.exe. (Zum Zeitpunkt meines vorherigen Kommentars hatte ich keinen Zugriff auf Mono.)
Bob

14

FancyTechnoAlgorithm

Ein ausgefallener Techno-Algorithmus für das ausgefallene Techno-Computerprogramm.

Höhlenmensch verlieren den Kampf. Höhlenmensch wütend. Also Höhlenmensch zur Computerschule gehen lernen, Algorithmus zu machen.

import random, sys  # Need import some advanced techno code

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

    try:  # Me try use fancy techno algorithm!

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

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

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

Python 2-Programm. Zu rennen:python fancytechnoalgorithm.py


Dies bricht ab, wenn keine Eingabe erfolgt (dh bei der ersten Abbiegung). Ich weiß nicht, wie Sie damit umgehen wollen, deshalb muss ich es von der ersten Testrunde ausschließen.
Türklinke

@Doorknob Bei der ersten Eingabe ist es "," oder ""? Ich denke, es ist das letztere davon.
Vectorized

Für die erste Eingabe gibt es keine Argumente (es wird ausgeführt als python StickSharpener.py).
Türklinke

@Doorknob Ich habe es bearbeitet. Mal sehen, ob es jetzt funktioniert.
Vectorized

Gut, danke! Ich werde dies in die nächste Versuchsrunde aufnehmen.
Türklinke

14

Der Beobachter

Er beobachtet die Bewegungen seines Gegners und lässt ihn immer seine Hand zeigen, bevor er zuschlägt. Er ist besonders auf diejenigen vorbereitet, die es versäumen, auf ein Schwert hinzuarbeiten.

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

Dateiname: watcher.py

Zu rennen: python watcher.py

Basilisk

Versucht, diejenigen zu zerstören, die ihn zu genau ansehen. Konsequent schlägt der Watcher, wird aber insgesamt wohl schlechter abschneiden.

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

Dateiname: basilisk.py

Zu rennen: python basilisk.py

Nash

Versucht, die Entscheidungen seines Gegners irrelevant zu machen, indem jeder Zug mit einer Wahrscheinlichkeit ausgewählt wird, die die Risiken und Chancen des Gegners berücksichtigt

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

Dies ist nicht ganz das Nash-Gleichgewicht (mein Strategie-Generator hat eine gewisse Instabilität), aber es ist nah.

Aus Gründen der Neugier sind hier die Schätzungen, wie wahrscheinlich es ist, dass dieser Bot in jedem Spielzustand gewinnt:

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

Dateiname: nash.py

Zu rennen: python nash.py

Finte

Öffnet mit einem schnellen Angriff, um die Abwehrkräfte seines Gegners zu testen.

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

Dateiname: feint.py

Zu rennen: python feint.py

LatePokeBot

PokeBots kleiner Bruder. Zeigt nie Schwäche, sondern versucht wie sein großer Bruder zu kämpfen.

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

Dateiname: latepokebot.py

Zu rennen: python latepokebot.py


Sie haben ein :in Basilisk vermisst ; Ich habe das für dich behoben
Türklinke

Diese Vorlage warf irgendwann einen Fehler oder eine Ausnahme auf. Vielleicht möchten Sie dies vor der nächsten Versuchsrunde beheben. (der Basilisk)
Türklinke

@Doorknob Ich habe die Startsequenz für Basilisk ausgewählt, indem ich mir die Annahmen von The Watcher und Cave Doctor angesehen habe und eine Sequenz gefunden habe, die dazu führen würde, dass diese Annahmen schlimm schief gehen. Verstößt das gegen die Regel "Höhlenmenschen sind fair"?
Brilliand

Geh nach Nash! Gewinne genau die Hälfte deiner Matches gegen alle Bots, die schlau genug sind, um deinen P = 0-Optionen auszuweichen!
Aschepler

12

PokeBot

Geschrieben in Ruby.

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

Laufen Sie mit ruby pokebot.rb.

Dieser Bot ist nicht sehr schlau; es geht darum, was ein durchschnittlicher Höhlenmensch sowieso alleine tun würde.


9

PatientWolf v2.0

Schärft, wenn langweilig, stößt, wenn der Feind in der nächsten Runde ein Schwert hat, oder wenn der Feind langweilig ist, blockt er sonst.

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

Laufen Sie mit

perl patientwolf.pl

EDIT: Danke an @sylwester für den Hinweis auf einen Fehler


Da Sie nur ein Argument mit beiden durch Komma getrennten Historien erhalten, analysieren Sie es falsch. Z.B. PatientWolf.pl SB,SPtut ein, Pda es denkt, es hat einen scharfen Stock.
Sylwester

@ Sylwester das stimmt nicht. Die erste Zeile weist $ me das erste Argument und $ him das zweite Argument zu
killmous

Das CavemanDuel-Programm verwendet nicht zwei Argumente, sondern nur ein Argument. z.B. perl patientwolf.pl "SB,SP". Sie sollten my($me,$him) = split/,/ $ARGV[0];und tun if( @ARGV ) {print "S";exit}.
Sylwester

@ Sylwester ok ich verstehe, worauf du hinaus willst. Das war nicht klar aus dem OP oder aus dem kurzen Blick, den ich auf den Controller-Code geworfen hatte. Ich werde das in Kürze beheben
killmous

9

Binärer Höhlenmensch

Schärfen, Stechen, Wiederholen

Basierend auf der Idee, dass das Blockieren für Weichlinge ist, wechselt dieser Höhlenmensch zwischen den beiden verbleibenden Optionen.

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

Kompilieren mit javac BinaryCaveman.java

Laufen Sie mit java BinaryCaveman

BEARBEITEN: Adventures in String Arrays ..... args.length () löst einen Fehler aus. args.length gibt immer 1 zurück. args [0] .length () gibt die Längen der ersten Zeichenfolge im Array zurück.

EDIT 2: Dank der Hilfe von Doorknob, Brilliand und Sylwester aktualisiert. Danke Leute.


@ MartinBüttner Ich habe vergessen, args - 1 durch 2 zu teilen, um nur die Anzahl der letzten Einsendungen eines einzelnen Spielers zu erhalten. Das wurde behoben. Ich kann Dorknobs Unterwerfung nicht verstehen, Rubin ist für mich praktisch ein Geschwätz. Beginnt er immer mit dem Schärfen?
Red_Shadow

Ja, er prüft nur, ob sein letzter Zug das Gegenteil war Poder Sist. Und wenn es noch keine Geschichte gibt, gibt er vor, die Geschichte wäre es P,(was ihn dann dazu veranlasst, es Szuerst zu tun ).
Martin Ender

Zwei verschiedene Ansätze, die zur gleichen Ausgabe führen. Verstößt das gegen die Regeln?
Red_Shadow

Wahrscheinlich nicht, ich würde es dich nur wissen lassen.
Martin Ender

2
@Doorknob Ich denke es sollte args[0].length()nicht sein args.length.
Brilliand

8

CavekidBlocks

Ein weinendes und verängstigtes Höhlenkind mag wie eine leichte Beute aussehen. Lass dich nicht von seinem hübschen Gesicht täuschen, denn er weiß, wie man blockt.

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

Laufen Sie mit python3 cavekidblocks.py

ChargerMan

Dieser Höhlenmensch ist sehr konservativ. Will versuchen, seine Waffe aufzuladen und greift nur an, wenn es nötig ist.

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)

Laufen Sie mit python3 chargerman.py

Betrüger

Trickster weiß nicht, wie man kämpft, also versucht er, andere Höhlenmenschen zu verwirren.

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

Laufen Sie mit python3 trickster.py

Leider funktioniert Trickster nach dem Commit acc74 nicht mehr wie geplant.


4
Das Trickster-Programm ist böse
Nexus

@Nexus hab ich aber auch so. Leider läuft Trickster in den Duellen nicht gut.
Wendelbsilva

7

Hodor

Hodor ist nicht sehr aggressiv. Er bleibt gerne in seinem Schild, es sei denn, es gibt eine gute Gelegenheit zum Streik.

kompiliere mit: javac Hodor.javaund starte mit:java Hodor

Code:

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

Bearbeiten: kleinere Code-Aktualisierung


Diese Vorlage warf irgendwann einen Fehler oder eine Ausnahme auf. Vielleicht möchten Sie dies vor der nächsten Versuchsrunde beheben.
Türklinke

1
Versuchen Sie es mit SB,BB. Wenn sich andere Höhlenmenschen in der ersten Runde schlecht benehmen, benimmt sich auch Hodor schlecht.
Sylwester

7

Spekulativer Sylwester - Perl5

Der spekulative Sylwester möchte Schwertsucher ausschalten, indem er sich die Muster ansieht und anstößt, wenn die Chance besteht, dass der Gegner schärft und schärft, wenn es am wahrscheinlichsten ist, dass der Gegner blockt. Dies wird er jedoch nicht tun, wenn die Möglichkeit besteht, dass er vermutet hat, dass er sich im nächsten Zug schärft, und wir sind noch vorsichtiger, wenn wir uns für eine Schärfung entscheiden.

Wenn der Gegner stumpf ist, versucht er, aggressiv zu sein, wird aber irgendwann anfangen, für ein Schwert zu sparen, wenn dies fruchtlos erscheint.

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

Um unter Linux zu laufen, füge dies einfach in die playerlist.txt ein:

perl players/SpeculativeSylwester/SpeculativeSylwester.pl

Facile Fibonacci - R6RS-Schema

Neben dem ersten Zug blockt Facile Fibonacci, wenn der Zug eine Fibonacci-Zahl ist (ab 0) und füllt den Rest mit PPSS..und wechselt, wenn 8 zu einer endlosen Folge von PSS, um mit einem Schwert zu gewinnen.

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

Um es zu starten, installiere einfach ikarus mit apt-get install ikarusund füge dies in die playerlist.txt ein:

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

Studious Sylwester - Perl5

Der fleißige Sylwester wendet die gleiche Taktik an wie der spekulative Sylwester, sieht sich jedoch auch frühere Spiele an, um festzustellen, wo er möglicherweise eine falsche Wahl getroffen hat.

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

Um unter Linux zu laufen, füge dies einfach zu playerlist.txt hinzu

perl players/StudiousSylwester/StudiousSylwester.pl

Fleißig bearbeiten

Ich kann die Probleme nicht reproduzieren, die Sie hatten, $0wenn Sie nicht den vollständigen Pfad zum Perl-Skript angegeben haben, wenn es mit Perl ausgeführt wird. Ich habe auch Ihre Änderungen übernommen und sehe keine Änderungen in CavemanDuels src. Es ist dasselbe, das ich mehr als 20 Mal ausgeführt habe, ohne das Problem, das Sie melden. Ich beginne zu befürchten, dass Sie das Skript als Bash-Skript erstellt haben, anstatt es während der Ausführung oder als Argument für Perl auszuführen. Ich brauche mehr Informationen, um es genau zu wissen. Als Test habe ich das gemacht und Sie können das Gleiche tun, um zu sehen, ob Sie das gleiche Ergebnis erzielen:

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

Scheme scheint nicht mit mir auf meinem Computer zusammenarbeiten zu wollen, daher konnte ich den Fibonacci nicht testen. Ich werde weiterhin versuchen, es zum Laufen zu bringen, aber es wäre großartig, wenn Sie es in eine andere Sprache übersetzen könnten.
Türklinke

Das fleißige scheint auch nicht zu funktionieren, denn es $0wird bashvon einer Bash-Befehlszeile aufgerufen (was der Controller tut). Sie könnten jedoch nur hart codieren players/StudiousSylwester/foo.txt.
Türklinke

@Doorknob Ich habe hinzugefügt, wie zu installieren ikarusund ich habe meine Gedanken $0für Studious hinzugefügt.
Sylwester

6

Schwertschmied

Brauche spitzen Stock. Wenn Sie einen scharfen Stock haben, stecken Sie ihn an. Mir tut es nicht weh.

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

Speichern unter swordsmith.f90und kompilieren mit gfortran -o swordsmith swordsmith.f90, führen wie jedes normale ausführbare Datei: ./swordsmith.


Dies scheint ein Leerzeichen (``) vor der tatsächlichen Ausgabe zu drucken. Ich habe keine Ahnung, wie ich das beheben kann, daher muss ich diese Einsendung von der ersten Testrunde ausschließen.
Türklinke

Außerdem habe ich Ihren Dateipfad korrigiert. Es stellt sich heraus, dass das aktuelle Arbeitsverzeichnis, wenn es ausgeführt wird, nicht das Ihres Programms ist. Oh, und wenn mit "neuer Instanz" "jedes Spiel" gemeint ist, kann ich das nicht tun, da dies ein spezielles Gehäuse für das Steuerungsprogramm erfordern würde. Möglicherweise möchten Sie dies in Ihrem eigenen Code tun.
Türklinke

@Doorknob: Ich habe meinen Code aktualisiert: Ausgabe ist ein einzelnes Zeichen, es löscht eine bereits vorhandene Datei beim ersten Ausführen und die Datei befindet sich im Player-Verzeichnis.
Kyle Kanos

Gut, danke! Diese Einreichung ist jetzt in der Bestenliste enthalten.
Türklinke

@Doorknob: Cool! Scheiße, dass ich nicht der Erste bin. Außerdem: Ich bin mir ziemlich sicher, dass Fortran-Benutzer wie Vampire sind, also bin ich mir ziemlich sicher, dass Sie bald mit dem Codieren in Fortran beginnen werden! Muahahahaha!
Kyle Kanos

5

Patientenschmied

Dieser Bot ist in R geschrieben, um ihn Rscript PatientBlacksmith.Rauszulösen.

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)

Misst die Stockschärfe des Gegners: Blockiert, wenn sie scharf ist, nehmen Sie sich Zeit, um sie zu schärfen. Wenn die eigene Schärfe 5 erreicht, stupsen Sie, bis die Schärfe nachlässt.


Dies bricht ab, wenn keine Eingabe erfolgt (dh in der ersten Runde). Ich weiß nicht, wie ich das Problem beheben soll, daher muss ich es aus Runde 1 der Tests ausschließen.
Türklinke

@Doorknob korrigiert.
Plannapus

5

Gefängnisordnung, Haskell

Die Höhlenforscherin denkt, Höhlenmensch und andere Höhlenmenschen sollten reden und sich den Stock teilen. Aber hey ho, wenn kämpfen muss, kämpfe gegen Gefängnisregeln. Finde den Boss und greife an.

ViceLeader Alpha Caveman jetzt; Der Höhlenmensch muss kämpfen. Andere Höhlenmenschen kämpfen später. Wenn mein Höhlenmensch verliert, keine Sorge; Er ist sowieso zu haarig.

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

Geschrieben in Haskell (gehe zur funktionalen Programmierung!), Speichere also als prisonrules.hs und kompiliere dann mit:

ghc prisonrules.hs

Und laufe als:

prisonrules [history]

4

Ich nenne ihn JavaMan

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

Hinweis: Ich habe nicht die Absicht, Codegolf zu spielen. Aber wenn Sie ein Golfer sind und die Leerzeichen / zusätzlichen Linien Ihre Augen zum Bluten bringen, können Sie dies jederzeit ändern

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

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

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

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

}

class Player
{
    int sharpLevel;

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

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

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

4
Einsendungen für King of the Hill-Herausforderungen sind nicht zum Golfen gedacht, also keine Sorge. ;)
Martin Ender

Ich habe den Namen in JavaMan geändert, weil "Caveman" etwas zu allgemein ist, um in der Bestenliste zu stehen. Hoffentlich ist das okay für dich; Wenn nicht, ändern Sie es einfach in etwas anderes.
Türklinke

1
Dies bricht ab, wenn keine Eingabe erfolgt (dh in der ersten Runde). Ich weiß nicht, wie Sie damit umgehen wollen, deshalb muss ich es von der ersten Testrunde ausschließen.
Türknauf

Behoben, und die Namensänderung ist in Ordnung mit mir
user2813274

1
Ich glaube, Sie haben einen Fehler beim Parsen des Staates. Sowohl "ich" als auch "der Feind" bewegen sich gleich: states [0]
Roy van Rijn

4

Tiefe Gedanken, C

Höhlenmann-Code. Höhlenmensch denken. Höhlenmensch.

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

Ich teste. Mehr Gedanken besser.


1
+1 für die Höhlenmenschen var Namen und Kommentare: P Auch schönes Programm c:
Katze

3

Nigel

Nigel ist ein geduldiger, defensiver alter Höhlenmensch, der lieber taktisch vorgeht, als alles in Angriff zu nehmen.

Es ist ein PHP-Skript, rufen Sie mit php nigel.php

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

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

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

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

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

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

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

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

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

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

?>

3

Aichmophobic - Lua

Er wird dich gelegentlich stupsen, aber nur bis der Stock zu scharf wird. In diesem Fall gerät er in Panik und rollt sich in die fetale Position.

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)

Führen Sie es mit:

lua aichmophobic.lua


2
Ihre Ausgabe muss in Großbuchstaben erfolgen. Ich habe das für dich behoben. (Außerdem habe ich den Namen dieser Einreichung ungefähr tausend Mal falsch geschrieben.: P)
Türklinke

3

Bob Caves

Bob Caves ist einer der klügsten Typen in seiner Höhle. Er hat gelernt, mit einer Hand zu zählen (die andere ist damit beschäftigt, seinen Stock zu halten). Er hat von dieser Steinzeitolympiade gewusst und wollte mitmachen.

Seine Hauptstrategie ist es, seinen Stock zu blockieren und zu schärfen, bis er einen schönen spitzen Stock hat oder der andere Höhlenmensch auch einen spitzen. In diesem Fall versucht Bob Caves ihn zu stoßen!

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

}

Kompiliere mit javac BobCaves.javaund starte mitjava BobCaves

Edit: Bob zählt jetzt, wenn es einen Block gibt! (Danke an Mikey Mouse ). Auch wird er seinen Stock scharf machen, wenn der andere Höhlenmenschenstock stumpf ist.

Edit 2: Verbesserte Zählmethode (nochmals danke an Mikey).

Edit 3: Bob etwas aggressiver machen.


2
Bob vergiss den Zähleffekt von Poke: Blockiere die eigene Stockschärfe. Drei "S" in "S" bleiben nicht 3-mal scharf. Jedes "P" in s bedeutet ungeschärfter Stab. Huh huh huh ... "Pee" Höhlenmenschen Witz ...
Mikey Mouse

@ MikeyMouse Bob stimmt zu. Bob wird den Hexendoktor aufsuchen, um seine Technik zu verbessern. Bob dankbar!
Averroes

1
Der Hexendoktor bringt Bob Gutes bei. Aber er vergisst zu erwähnen, Poke: Poke-Szenario. Stick wird dann auch stumpf. Bob muss den Zug des Gegners nicht berücksichtigen. Wenn Bob Poke, bleib stumpf. Entweder stumpf auf: Gegner stoßen, Gegner blocken oder Gegner am Kopf. Wenn er auf den gegnerischen Kopf trifft, gewinnt Bob und kann mit einem stumpfen Stock in der Höhle herumtanzen.
Mikey Mouse

1
@MikeyMouse Bob weiß, wie man zählt. Bob muss lesen lernen. Danke noch einmal!
Averroes

3

Gruntt

Gruntt ist defensiv. Gruntt analysiert andere Höhlenmenschen, um zu wissen, wie man sie steckt. Dann sticht er sie direkt ins Auge. Gruntt ist kein netter Höhlenmensch.

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

}

Kompiliere mit javac Gruntt.javaund starte mitjava Gruntt


Dies löst ArrayOutOfBoundsExceptionin der ersten Runde eine aus und gibt manchmal mehrere Aktionen in anderen Runden aus.
Türklinke

@Doorknob Ops! Behoben, danke!
Averroes

3

Ist es ein Vogel? Ist es ein Flugzeug? Es ist RegExMan!

Er versucht mit seiner besonderen RegEx-Urkraft Ihre überaus langweiligen Sequenzen zu analysieren!

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

In Python 2.7 geschrieben, laufe mit python RegExMan.py [history]


3

Sizilianisch

Aber es ist so einfach! Alles, was ich tun muss, ist, was ich von einem anderen Höhlenmenschen kenne: Ist er der Typ Höhlenmensch, der blockieren, schärfen oder stoßen würde? Jetzt würde ein kluger Höhlenmensch stoßen oder blocken, weil er wusste, dass nur ein großer Dummkopf sich schärfen und angreifen würde. Ich bin kein großer Dummkopf, also kann ich eindeutig nicht schärfen. Aber andere Höhlenmenschen müssen wissen, dass ich kein großer Dummkopf bin und damit gerechnet hätte, damit ich eindeutig nicht stupsen oder blocken kann!

Laufen mit:

javac Sicillian.java
java Sicillian

Code:

public class Sicillian {

    public static void main(String[] args) {

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

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

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

            else {          // Inconceivable!

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

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

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

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

3

Bash-Magnon

Bash-Magnonen waren robust gebaut und leistungsstark. Der Körper war im Allgemeinen schwer und fest mit einer starken Muskulatur. Die Stirn war eher gerade als abfallend wie bei Neandertalern und nur leicht runzelig. Das Gesicht war kurz und breit. Das Kinn war hervorstehend. Das Gehirnvolumen lag mit rund 1.600 Kubikzentimetern über dem Durchschnitt des modernen Menschen. Jüngste Forschungsergebnisse legen jedoch nahe, dass die physikalischen Abmessungen des sogenannten "Bash-Magnon" sich nicht ausreichend von den heutigen Menschen unterscheiden, um eine separate Bezeichnung zu rechtfertigen.

Ich habe ein Gehirn, ich erinnere mich.

Dies ist eine selbst ausführbare Datei ./bash-magnon.sh

#!/bin/bash

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

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

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

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

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

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

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

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

1+ Sie haben offensichtlich das richtige Werkzeug für den Job und Ihre Höhlenmenschennamen sind ziemlich amüsant :) (Ich persönlich mag Fisch aber besser)
Sylwester

@ Sylwester Danke, das ist meine erste +1. Ich habe zuerst versucht, einen homöostatischen Automaten zu erstellen, der sich an dem orientiert, was der erste Kybernetiker tat, und dann habe ich aufgegeben und ein Bash-Skript erstellt.
Emmanuel

2

PokeBackBot

Einfach angepasst von PokeBot:

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

Laufen Sie mit ruby pokebackbot.rb.

Dies verwendet die nächst einfachere Strategie und blockt "geduldig" für eine Runde, bevor angegriffen wird.


3
@PeterTaylor Ich habe gelesen, dass es nicht erlaubt ist, meine Strategie zu ändern, wenn man den Gegner mit dem Finger abdruckt. Wenn meine Einsendung nur eine andere Einsendung schlagen kann, hat dies keine wirklichen Auswirkungen auf die Punktzahl der anderen Einsendungen, und meine eigene Einsendung wird wahrscheinlich sehr schlecht abschneiden. Wenn es nur eine Einsendung gibt und eine zweite geschrieben wird, ist es wahrscheinlich, dass diese zweite Einsendung die erste schlägt (weil sonst, warum sich die Mühe macht) - gilt das allein als "spezifisch für ein anderes Programm"? Mein Bot wird jeden Bot schlagen, der damit beginnt SPS(was vernünftig erscheint), aber bisher war PokeBot der einzige, der es gab.
Martin Ender

2

Schwertmeister

In Python 3.4 geschrieben (funktioniert mit Python 3.x)

Versucht, ein Schwert so schnell wie möglich zu bekommen, greift aber an, wenn es eine Chance hat, ihn zu treffen (Schärfe> 0), und der Feind könnte es auch verletzen (Schärfe des Feindes> 0).
Blockt nur, wenn keine Schärfe vorhanden ist und der Feind angreifen kann.

Beginnen mit:

python3 swordmaster.py MOVES

(angenommen, Sie speichern es als swordmaster.py)

Schneller und hässlicher Code:

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

(Stellen Sie dgzu TrueDebug - Nachrichten aktivieren)


1
Tipp: Lassen Sie es sich nicht kämpfen - es mit Deadlock werde S, P, S, P...
chill0r

Ich habe festgestellt, dass dies auch bei mir passiert. Wenn Sie nicht die Geschichte untersuchen oder einen gewissen Grad an Zufälligkeit anwenden, sind Sie gezwungen, in einem Zyklus festzustecken.
Pharap

2

FoolMeOnce.py

Speichern Sie die Züge jedes Spielers für das erste Duell und spielen Sie dann mit genau den gleichen Zügen. Wenn der Algorithmus des Gegners nicht zufällig ist, können wir dasselbe Ergebnis vorhersagen und nur dann zuschlagen, wenn wir wissen, dass wir gewinnen werden.

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)

In Python 3 geschrieben, daher müssen Sie höchstwahrscheinlich python3 verwenden. FoolMeOnce.py In der ersten Runde bin ich mir nicht sicher, ob wir eine leere Zeichenfolge oder nur ein Komma erhalten, daher sind möglicherweise einige Anpassungen erforderlich.


Ich habe Ihren Dateipfad repariert - es stellt sich heraus, dass das aktuelle Arbeitsverzeichnis nicht das Ihres Programms ist.
Türklinke

Während ich mit dem CavemanDuel-Tester spielte, bemerkte ich, dass FoolMeOnce weitaus bessere Punkte erzielt, wenn ich mehr Threads verwende (ich habe 16 Threads gegen 4 getestet). Mit 4 Threads bekommt es ~ 25 Punkte, mit 16 bekommt es ~ 34.
Wendelbsilva

Komisch, ich habe keine Ahnung, warum das so ist.
Tzazy
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.