Caveman Duels (or: Me te piquer avec un bâton pointu)

151

Caveman fou. Un autre homme des cavernes prenait un bâton, mais le bâton était pour moi. Caveman combat !


La description

Caveman a besoin d'un bâton pointu pour poignarder un autre homme des cavernes. Un autre homme des cavernes essaie également de poignarder avec un bâton pointu. Un homme des cavernes peut aiguiser un bâton, piquer avec un bâton ou bloquer des bâtons glacés.

Si l'homme des cavernes pique un autre homme des cavernes avec un bâton pointu, un autre homme des cavernes s'enfuit et me gagne. Mais si un autre homme des cavernes bloquait intelligemment quand je cinglais, rien ne se passera si mon bâton ne s’émousse pas et que je dois redresser la peau.

Caveman paresseux. Aussi, homme des cavernes muet. Caveman ne sait pas quoi faire, alors Caveman a besoin d'un programme informatique sophistiqué pour dire à Caveman quoi faire.

Contribution

La contribution de votre programme sera un historique des événements qui se sont produits, où Ssignifie «aiguise» (c'est-à-dire que l'homme des cavernes aiguisé son bâton), Psignifie «poke» et « Bbloc». L'entrée sera une histoire des deux côtés (vous et l'adversaire), de sorte que vos mouvements et ceux de l'adversaire seront séparés par une virgule ( ,).

Exemple d'entrée:

SPB,SBB

Cela signifie que le joueur aiguisé son bâton, puis piqué, puis bloqué, et que l'adversaire aiguisé, puis bloqué, puis bloqué à nouveau.

Vous ne recevrez aucune entrée au tour 1.

Sortie

La sortie est très similaire à l'entrée (parce que l'homme des cavernes n'est pas très intelligent). Votre programme doit générer des résultats Spour affiner, Ppour poke et Bpour bloquer. Seul le premier caractère de la sortie sera pris en compte et toute autre entrée sera traitée comme une Bcommande (bloc).

  • S: aiguiser

    Lors de l'affûtage, la netteté du bâton de l'homme des cavernes augmente de 1 et le bâton reçoit 1 poke supplémentaire. Chaque poke réduit la netteté du stick de 1, et si la netteté du stick est 0, elle est trop terne pour que l'on puisse la piquer. La netteté commence à 0. Si la netteté atteint 5, le bâton est une épée! (Voir ci-dessous.)

    Si l’adversaire pique pendant que vous affilez (et qu’il a une netteté> 0), l’opposant gagne!

  • P: poussée

    Lorsque vous piquez, la netteté du bâton de l'homme des cavernes diminue de 1 et vous piquez votre adversaire! Si votre adversaire est en train d'affûter, vous gagnez! Si l'adversaire pique, votre bâton frappe le bâton de votre adversaire et ils deviennent tous les deux plus ternes (de 1 "unité de netteté"). Si l'adversaire bloque, rien ne se passe si ce n'est que votre bâton devient plus terne.

    Si vous piquez quand la netteté de votre bâton est de 5 ou plus, votre bâton devient une épée et vous gagnez toujours ! (À moins que votre adversaire ait aussi choisi une épée et l'ait choisi P; dans ce cas, ils deviennent tous les deux plus ternes et peuvent redevenir des bâtons si leur acuité est inférieure à 5.)

    Vous ne pouvez pas piquer avec une netteté de 0. Si vous le faites, rien ne se passera.

  • B: bloquer

    Lorsque vous bloquez, rien ne se passe lorsque votre adversaire pique. Si votre adversaire ne pique pas, bloquer ne fait rien.

    Le blocage ne protège pas contre une épée, même si vous en avez aussi une!

Règles et contraintes

Les règles supplémentaires sont:

  • Votre programme peut lire et écrire des fichiers dans son propre dossier (pas de vol!) Si vous voulez sauvegarder des données, mais vous ne pouvez accéder à rien en dehors de celui-ci (et les hommes des cavernes n'ont pas de connexion Internet dans le désert).
    • Remarque importante sur les fichiers : Si vous enregistrez des fichiers, n'oubliez pas de les enregistrer dans le répertoire players/YourBotsName/somefile.foo! Le répertoire de travail actuel de votre programme ne sera pas celui de votre programme!
  • Les cavernes sont justes: un programme ne peut pas avoir de code spécifique pour un autre programme, et les programmes ne peuvent pas s'aider les uns les autres. (Vous pouvez avoir plusieurs programmes, mais ils ne peuvent en aucun cas interagir.)
  • Le juge des cavernes n'est pas patient. Si les hommes des cavernes effectuent plus de 100 tours chacun pour déterminer le vainqueur, le juge s'ennuie et les deux hommes des cavernes perdent.

Si votre programme enfreint une règle ou ne respecte pas la spécification, il est disqualifié, supprimé playerlist.txtet tous les duels recommencent depuis le début. Si votre programme est disqualifié, le responsable des hommes des cavernes (moi!) Commentera le message de votre programme et expliquera pourquoi. Si vous ne respectez pas les règles, votre programme sera ajouté au classement. (Si votre programme n'est pas dans le classement, il n'y a pas de commentaire explicatif sur votre message, et vous avez posté votre programme avant l'heure "Dernière mise à jour" ci-dessous, dites au chef des hommes des cavernes! Peut-être qu'il l'a oublié.)

Dans votre message, veuillez inclure:

  • Un nom.
  • Une commande shell pour exécuter votre programme (ex. java MyBot.java, ruby MyBot.rb, python3 MyBot.py, Etc.).
    • Remarque: l'entrée sera ajoutée à cela en tant qu'argument de ligne de commande.
    • Les hommes des cavernes utilisent Ubuntu 14.04, alors assurez-vous que votre code fonctionne (librement) dessus.
  • Un numéro de version, si votre code fonctionne différemment selon les versions de la langue choisie.
  • Votre code (évidemment).
  • Comment compiler le code, si nécessaire.

Code du contrôleur / test, exemple de bot

Le chef des hommes des cavernes a écrit le code de contrôle en C ++ et l'a posté sur un dépôt Github . Vous pouvez y exécuter et tester votre programme.

Un programme très, très simple (1 ligne!) Est également affiché dans les réponses ci-dessous .

Score et classement

La notation est facile. Celui qui gagne gagne un point. L'homme des cavernes avec le plus de points après 3 duels contre un autre homme des cavernes devient le nouveau leader des hommes des cavernes!

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

(ce classement a été généré automatiquement)

Les joueurs marqués d'un ont *lancé une erreur ou une exception à un moment donné; ces joueurs ont également un commentaire sur leurs messages.

Les joueurs qui ne pouvaient pas être inclus dans les essais pour une raison quelconque (ces joueurs auront un commentaire sur leurs messages expliquant le problème): Monkey, Elephant, FacileFibonacci, StudiousSylwester.

Dernière mise à jour: 3 août à 00h15 (UTC).

Poignée de porte
la source
Je suis surpris que personne ne semble avoir encore tenté de trouver la stratégie minimax. Cela semble être une chose évidente à faire.
user2357112
@ user2357112 Je ne pense pas que minimax soit une amélioration ici. Je veux dire, vous pourriez concevoir une implémentation minimax, mais comme la logique est si simple, le même comportement peut être exprimé avec une machine à états finis. (c.-à-d. que le bot n'affûtera jamais tant que l'adversaire ne sera pas terne car s'il le fait, le coup minimisant de l'adversaire sera de pousser et vous perdrez, le bot bloquera toujours jusqu'à ce que nous ayons une épée car le coup maximisant de notre bot sera toujours être à bloquer, etc.)
HuddleWolf
3
De nombreuses entrées semblent permettre une netteté négative dans leurs calculs. Les règles écrites disent que rien ne se passe lorsque vous piquez avec une netteté nulle. Est-ce que cela "rien" signifie également que votre netteté reste à zéro, au lieu d'être décrémentée?
Sparr
6
Cela doit être ici: dresdencodak.com/comics/2009-09-22-caveman_science_fiction.jpg Peut-être que cela stimulera l'imagination. :)
Evi1M4chine
2
Est-ce toujours ouvert? Je vois des gens ajouter de nouvelles soumissions, mais je ne vois pas le classement mis à jour.
ASCIIThenANSI

Réponses:

35

Darwin - C

Qui a besoin de stratégie, de toute façon? Demandez à un groupe de cavernes de se battre et laissez la sélection naturelle faire le reste!


Nous utilisons un modèle très simple pour le cerveau primitif de l'homme des cavernes: il n'a pas de mémoire et ne prend en compte que la finesse de son bâton et celui de son adversaire. Celles-ci sont utilisées comme variables pour un polynôme binaire d'un ordre fini. Chaque action (bloquer, accentuer et piquer) est associée à un polynôme dont le résultat détermine la probabilité relative de choisir cette action. C’est à peu près tout ce qu’il ya à faire - commencez par quelques coefficients aléatoires et optimisez-le de manière itérative.

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

Compiler avec: gcc darwin.c -odarwin -w -O3. Exécuter avec: ./darwin <history>.

Le bot lit les coefficients dans un fichier nommé programdans le players/Darwinrépertoire (un autre fichier peut être spécifié en tant que second argument de ligne de commande). Ce programme semble bien réussir:

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 

Enregistrer sous players/Darwin/program.

Voici un programme qui génère des programfichiers pouvant être utilisés par le bot (il n’est pas nécessaire de les compiler si vous utilisez le programfichier ci-dessus):

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

Compiler avec: gcc genprog.c -ogenprog -w -O3. Exécuter avec: ./genprog [output-filename].


Watson

Quel est l'ADN d'un homme des cavernes gagnant? Peut-être que ce gars a la réponse:

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

Courir avec: python Watson.py

Watson est le produit d'un algorithme génétique. Contrairement à Darwin, la donnée génétique est cette fois un programme réel, écrit dans un minuscule langage spécifique à un domaine (traduit ici en Python).


La séquence simple bat les gros joueurs

Ce petit gars est étonnamment bien (ou peut-être pas si étonnant), surtout contre les leaders:

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

Courir avec: python SSBBP.py

DarwinBot
la source
Comment compiler et exécuter ceci? En outre, comme indiqué dans la question, vous ne pouvez lire / écrire que des fichiers du players/Darwinrépertoire.
Poignée de porte
@Doorknob: corrigé.
DarwinBot
Je reçois ces erreurs de compilation lors de la compilation de ce code. (Je suis sous Ubuntu 14.04.)
Poignée de porte
@Doorknob: corrigé. Devrait travailler maintenant.
DarwinBot
Je vais maintenant undefined reference to `fmax'. --Edit-- Peu importe, j'en ai bien besoin -lm.
Poignée de porte
50

Caveman imprévisible

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!

Cet homme des cavernes choisit chaque tour au hasard, mais je lui ai expliqué très simplement que certaines actions n’ont tout simplement pas de sens parfois. N'hésitez pas à copier ce code si vous souhaitez exprimer une logique différente.

C'est Ruby, enregistrez sous le nom 'impredictable.rb' et exécutez-le avec ruby unpredictable.rb

histocrate
la source
En fait, je pense que cela no 'Block'devrait également l'être si mon adversaire a une épée.
njzk2
Le premier non-blocage couvre en fait cela: un bâton pointu n'est pas une épée.
Histocrat
2
Pourquoi ne pas utiliser unlesspour les déclarations no 'Block'et no 'Poke'? ( no 'Block' unless he.has_pointy_stick)
wchargin
25

Cave Doctor - Lua

"Moi, je perds face aux nouveaux étrangers, je les ai assommés pour les étudier"

Quand vous avez vu autant de patients que le médecin des cavernes, vous commencez à comprendre véritablement le psychisme de l'homme des cavernes (ou du moins, j'espère). Le jeu Cave Doctor est une stratégie pure, il attend les coups qu'il bloque pour tenter de désarmer son adversaire, mais il ne laissera pas cet adversaire s'approcher de la fabrication d'une épée. Il essaie de prédire quand il est prudent d'aiguiser pour ne pas perdre le dessus.

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

Courir avec: lua CaveDoctor.lua

Lien
la source
3
Cela ne perd que deux fois dans le classement actuel? oO
moitié du
La révision 5 génère de nombreuses erreurs. La révision 4 est donc celle incluse dans la série d’essais en cours.
Poignée de porte
@Doorknob Je pense avoir résolu tous les problèmes, de toute façon, il n'y avait qu'un changement dans la logique réelle.
Nexus
20

ForeignCaveman

ForeignCaveman n'a aucune idée de ce que vous venez de dire. Il fait juste ... des trucs.

javac ForeignCaveman.java ensuite java ForeignCaveman

public class ForeignCaveman {

    public static void main(String[] args) {
        int m = (int) (Math.random()*3);
        switch(m) {
            case 0: System.out.println('B'); 
                    break;
            case 1: System.out.println('P'); 
                    break;
            case 2: System.out.println('S'); 
                    break;
        }
   }
}
Kevin L
la source
11
Cela a probablement bien trop de votes positifs
Kevin L
19

Vice-chef

Poignée de porte ♦ est leader. Moi veux être leader! Suivez le programme super intelligent pour devenir leader!

Compiler: javac ViceLeader.javaExécuter: java ViceLeader.

public class ViceLeader {

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

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

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

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

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

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

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

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

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

    private static boolean isSharpener(String history) {
        if (history.length() < 3) {
            return false;
        }
        for (int i = history.length() - 1; i > history.length() - 3; i--) {
            if (history.charAt(i) != 'S') {
                return false;
            }
        }
        return true;
    }
}
CommonGuy
la source
Pourquoi ce n'est pas if (enemySharpness <= 4 || mySharpness >= 5)vs ==?
durron597
@ durron597 Parce que je ne veux attaquer que l'ennemi s'il peut fabriquer une épée lors du prochain tour (ce qu'il fera probablement). VizeLeader ne pique pas souvent, il le fait au bon moment .
CommonGuy
Mais vous avez une épée et votre adversaire ne ...
durron597
@ durron597 Non, c'est une instruction OR. Cela signifie "piquez l'adversaire si j'ai une épée OU s'il aura bientôt une épée".
CommonGuy
7
Oh mon Dieu. Il est temps de prendre une autre tasse de café :) Ou de nouvelles lentilles de contact
durron597
15

Peut-être Markov 2.1

Je pense qu’il utilise les chaînes de Markov pour prédire ce que fera l’autre homme des cavernes, mais j’ai seulement regardé brièvement la page wikipedia sur les chaînes de Markov et décidé qu’il y avait trop de texte.

Il essaie de rester en vie pendant 30 rounds, puis crée une table avec les prochains changements d'état et réagit à ce que pense l'autre homme des cavernes.

Le code contient beaucoup d'instructions inutiles, mais il fonctionne assez bien.

MODIFIER

Détecté une faille dans la logique. Maintenant, il fait quelque chose quand il a une épée.

$ python3 players/MaybeMarkov/MaybeMarkov.py

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

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

all_actions = SHARPEN, POKE, BLOCK
always = 1

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

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

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

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

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


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

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

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

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

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

if turns > 97:
    do(POKE)

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

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

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

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

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

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

counts = itemgetter(1)

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

react_on(prediction)
Lennart_96
la source
14

PériodiqueCicadaCaveman

Cet homme des cavernes assez intelligent a étudié un certain Bug et s'est rendu compte que personne ne peut adapter son style de vie pour tirer parti du nombre premier Cicada.

Il cache / bloque pendant la plus grande partie de sa vie, mais pique parfois. Bien sûr, il est vulnérable aux épées, et passe tout un cycle avec un bâton non affûté, mais affûter votre bâton quand il est totalement émoussé? C'est exactement ce que les autres attendent de lui ... pas cette cigale

compiler: mcs program.cs pour exécuter mono program.exe

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

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

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

  }

}

Edit: Changé la netteté - code ... si je poke soit je gagne ou mon bâton devient plus terne

Edit2: Ajouté dans la suggestion de Bobs

Edit: Modifié pour ne toucher que lorsque Netteté 2, si le bâton est à zéro, l’autre type peut fabriquer une épée.

Mikey Mouse
la source
1
Je cours sur Ubuntu; cela compilera-t-il sous Mono? Si oui, comment puis-je le compiler et comment l'exécuter?
Poignée de porte
Pour être honnête, je ne sais pas. Je suis sur le point de me diriger vers le lit. Je peux le réécrire pour Java demain matin au travail. Le code Java devrait être presque identique.
Mikey Mouse
5
@Doorknob mcs program.csle compilera, mono programl'exécutera, mais vous devrez remplacer le foo.Dump();s par System.Console.WriteLine(foo);(ou ajouter une méthode d'extension public static void Dump(this string value) { System.Console.WriteLine(value); }).
Bob
@Bob Merci mon pote, j'ai ajouté votre méthode d'extension.
Mikey Mouse
Désolé, le nom de fichier par défaut mcsgénéré est <filename>.exe, par exemple program.cs, deviendrait program.exe. Donc, la commande run serait mono program.exe. (Je n'avais pas accès au mono lors de mon précédent commentaire.)
Bob
14

FancyTechnoAlgorithm

Un algorithme de techno de fantaisie pour le programme informatique de techno de fantaisie.

Caveman continue à perdre la bataille. Caveman en colère. Alors homme des cavernes aller à l'école d'informatique apprendre faire algorithme.

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"

Programme Python 2. Courir:python fancytechnoalgorithm.py

Vectorisé
la source
Cela casse lorsqu'il n'y a pas d'entrée (c'est-à-dire au premier tour). Je ne sais pas comment vous voulez gérer cela, alors je vais devoir l'exclure de la première série d'essais.
Bouton de porte
@Doorknob Pour la première entrée, s'agit-il de "," ou ""? Je suppose que c'est le dernier de cela.
Vectorisé le
Pour la première entrée, il n'y aura pas d'argument (il sera exécuté comme python StickSharpener.py).
Poignée de porte
@Doorknob je l'ai édité. Ne vois si cela fonctionne maintenant.
Vectorisé le
D'accord merci! Je vais l'inclure dans la prochaine série d'essais.
Poignée de porte
14

L'observateur

Il surveille les mouvements de ses adversaires, les laissant toujours montrer leur main avant qu'il ne frappe. Il est particulièrement préparé pour ceux qui négligent de travailler vers une épée.

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

Nom de fichier: watcher.py

Courir: python watcher.py

Basilic

Cherche à détruire ceux qui le regardent de trop près. Fait constamment mieux que l'Observateur, mais son bilan sera généralement pire.

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

Nom de fichier: basilisk.py

Courir: python basilisk.py

Nash

Cherche à rendre les choix de son adversaire sans importance, en choisissant chaque coup avec une probabilité que les risques et les avantages en découlent

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

Ce n'est pas tout à fait l'équilibre de Nash (mon générateur de stratégie a une certaine instabilité), mais c'est proche.

Par curiosité, voici les estimations de la probabilité de victoire de ce bot dans chaque état de jeu:

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

Nom de fichier: nash.py

Courir: python nash.py

Feinte

Ouvre avec une attaque rapide, pour tester les défenses de son adversaire.

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

Nom de fichier: feint.py

Courir: python feint.py

LatePokeBot

Le petit frère de PokeBot. Ne montre jamais de faiblesse, mais essaie de se battre comme son grand frère.

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

Nom de fichier: latepokebot.py

Courir: python latepokebot.py

Brilliand
la source
Il te manquait un :au basilic; J'ai réglé ça pour vous
Bouton de porte
Cette présentation a jeté une sorte d'erreur ou d'exception à un moment donné; vous voudrez peut-être envisager de résoudre ce problème avant la prochaine ronde d'essais. (celle du basilic)
Bouton de porte
@Doorknob J'ai choisi la séquence de départ pour Basilisk en examinant les hypothèses émises par The Watcher et Cave Doctor et en recherchant une séquence qui aurait pour effet de les anéantir. Cela enfreint-il la règle "les hommes des cavernes sont justes"?
Brilliand
Allez Nash! Gagnez exactement la moitié de vos matchs contre tous les bots assez intelligents pour éviter les options P = 0!
Aschepler
12

PokeBot

Écrit en rubis.

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

Courez avec ruby pokebot.rb.

Ce bot n'est pas très intelligent. il parle de ce que l'homme des cavernes moyen ferait tout seul de toute façon.

Poignée de porte
la source
9

PatientWolf v2.0

Accentue si émoussé, pique si l'ennemi aura une épée au prochain tour ou si l'ennemi est émoussé, bloque autrement.

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

Courir avec

perl patientwolf.pl

EDIT: merci à @sylwester pour avoir signalé un bug

Killmous
la source
Comme vous n'obtenez qu'un seul argument avec les deux historiques séparés par une virgule, vous le analysez incorrectement. Par exemple. PatientWolf.pl SB,SPfait un Pdepuis qu'il pense qu'il a un bâton pointu.
Sylwester
@ Sylwester, ce n'est pas correct. La première ligne assigne le premier argument à $ me et le second à $ him
killmous le
Le programme CavemanDuel n'utilise pas deux arguments, un seul. par exemple. perl patientwolf.pl "SB,SP". Tu devrais faire my($me,$him) = split/,/ $ARGV[0];et if( @ARGV ) {print "S";exit}.
Sylwester
@ Sylwester ok je vois où tu veux en venir. Ce n'était pas clair ni du point de vue de l'OP ni du coup d'œil rapide que j'avais jeté sur le code du contrôleur. Je vais arranger ça bientôt
killmous
9

Cavalier binaire

Aiguiser, Stab, Répéter

Basé sur l'idée que le blocage est pour les poules mouillées, cet homme des cavernes alterne entre les deux options restantes.

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

Compiler avec javac BinaryCaveman.java

Courir avec java BinaryCaveman

EDIT: Adventures in String Arrays ..... args.length () renvoie une erreur. args.length renvoie toujours 1. args [0] .length () renvoie les longueurs de la première chaîne du tableau.

EDIT 2: Mise à jour grâce à l'aide de Doorknob, Brilliand et Sylwester. Merci les gars.

Red_Shadow
la source
@ MartinBüttner J'ai oublié de diviser les arguments - 1 sur 2 pour obtenir uniquement le nombre de soumissions passées par un seul joueur. Corrigé ça. Je ne peux pas comprendre la soumission de Dorknob, le rubis est pratiquement du charabia pour moi. Est-ce qu'il commence toujours par affûter?
Red_Shadow
Oui, il vérifie simplement si son dernier mouvement était Pou Set fait le contraire. Et s'il n'y a pas encore d'histoire, il prétend que l'histoire le serait P,(ce qui le conduit ensuite à le faire en Spremier).
Martin Ender
Deux approches différentes aboutissant au même résultat. Est-ce que c'est contre les règles?
Red_Shadow
Probablement pas, je vous le ferais savoir.
Martin Ender
2
@ Doorknob Je pense que cela devrait être args[0].length(), pas args.length.
Brilliand
8

CavekidBlocks

Un enfant des cavernes pleurant et apeuré peut ressembler à une proie facile. Ne laissez pas son joli visage vous tromper parce qu'il sait bloquer.

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

Courir avec python3 cavekidblocks.py

ChargerMan

Cet homme des cavernes est très conservateur. Essayera de charger son arme et attaque uniquement en cas de besoin.

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)

Courir avec python3 chargerman.py

Filou

Trickster ne sait pas se battre, alors il essaie de semer la confusion chez un autre homme des cavernes.

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

Courir avec python3 trickster.py

Malheureusement, après le commit acc74 , Trickster ne fonctionne plus comme prévu.

Wendelbsilva
la source
4
Ce programme de filou est diabolique
Nexus
@Nexus, je le pensais aussi. Malheureusement, Trickster ne réussit pas bien dans les duels.
wendelbsilva
7

Hodor

Hodor n'est pas très agressif. Il aime rester dans son bouclier à moins d'une bonne occasion de faire la grève.

compiler avec: javac Hodor.javaet courir avec: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);
    }
}

Edit: mise à jour du code mineur

Qwix
la source
Cette présentation a jeté une sorte d'erreur ou d'exception à un moment donné; vous voudrez peut-être envisager de résoudre ce problème avant la prochaine ronde d'essais.
Poignée de porte
1
Essayez avec SB,BB. Hodor se comporte aussi mal quand les autres hommes des cavernes se comportent mal au premier tour.
Sylwester
7

Sylwester spéculatif - Perl5

Sylwester spéculatif veut éliminer les chercheurs d’épées en regardant les schémas et piquer quand il ya une chance que l’adversaire aiguise et aiguise quand l’opposant est le plus susceptible de bloquer. Cependant, il ne le fera pas s’il aurait pu deviner que lui-même sera aigu au prochain coup et que nous sommes encore plus prudents lorsque nous décidons d’aiguiser.

Quand son adversaire est émoussé, il essaie d’être agressif, mais finira par économiser pour une épée quand cela semble stérile.

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

Pour fonctionner sur linux, ajoutez simplement ceci dans playerlist.txt:

perl players/SpeculativeSylwester/SpeculativeSylwester.pl

Facile Fibonacci - Schéma R6RS

En plus du premier coup, Facile Fibonacci bloque lorsque le tour est un nombre de Fibonacci (à partir de 0) et remplit le reste avec PPSS..et change lorsque 8 passe à une séquence infinie de PSSvictoire avec une épée.

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

Pour exécuter, installez simplement ikarus avec apt-get install ikaruset ajoutez ceci dans playerlist.txt:

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

Sylwester studieux - Perl5

Studious Sylwester utilise la même tactique que Sylwester spéculatif, mais il examine également les jeux précédents pour déterminer où il aurait pu faire un mauvais choix.

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

Pour fonctionner sur linux, ajoutez simplement ceci à playerlist.txt

perl players/StudiousSylwester/StudiousSylwester.pl

Édition studieuse

Je ne peux pas reproduire les problèmes que vous avez rencontrés avec le fait que vous n'êtes $0pas le chemin complet du script Perl lorsqu'il est exécuté avec perl. J'ai également retiré vos modifications et je ne vois aucun changement dans la src de CavemanDuels et c'est la même chose que j'ai exécutée plus de 20 fois sans le problème que vous signalez. Je commence à craindre que vous ayez pu trouver le script en tant que script bash au lieu de l'exécuter en tant qu'exécutable ou en tant qu'argument pour Perl. J'ai besoin de plus d'informations pour savoir à coup sûr. En guise de test, j'ai fait ceci et vous pouvez faire la même chose pour voir si vous obtenez le même résultat:

echo '#!/usr/bin/perl
print "$0\n\n";' > testcmd.pl;
perl ./testcmd.pl;           # outputs ./testcmd.pl
bash -c "perl ./testcmd.pl"; # outputs ./testcmd.pl
bash -c ./testcmd.pl;        # outputs an error since it's not executable
chmod 755 ./testcmd.pl;
./testcmd.pl;                # outputs ./testcmd.pl
bash -c ./testcmd.pl;        # outputs ./testcmd.pl since it's executable
Sylwester
la source
Scheme ne semble pas vouloir coopérer avec moi sur ma machine et je n’ai donc pas pu tester celle de Fibonacci. Je continuerai d'essayer de le faire fonctionner, mais ce serait formidable si vous pouviez le traduire dans une autre langue.
Poignée de porte
Le studieux ne semble pas non plus fonctionner, car il $0est bashappelé à partir d'une ligne de commande bash (comme le fait le contrôleur). Vous pouvez simplement coder players/StudiousSylwester/foo.txt, cependant.
Poignée de porte
@Doorknob J'ai ajouté comment installer ikaruset j'ai ajouté mes réflexions sur $0Studious.
Sylwester
6

Swordsmith

Besoin d'un bâton pointu. Si vous avez un bâton pointu, piquez. Moi pas de douleur.

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

Enregistrer sous swordsmith.f90et compiler avec gfortran -o swordsmith swordsmith.f90, exécuter comme tout exécutable normal: ./swordsmith.

Kyle Kanos
la source
Cela semble imprimer un espace (``) avant la sortie réelle. Je ne sais pas comment résoudre ce problème, je vais donc devoir exclure cette soumission de la première série d'essais.
Poignée de porte
De plus, j'ai corrigé votre chemin de fichier; s'avère que le répertoire de travail actuel quand ils sont lancés n'est pas celui de votre programme. Oh, et si par "nouvelle instance", vous entendez "chaque jeu", je ne peux pas le faire car cela nécessiterait un boîtier spécial du programme du contrôleur; vous voudrez peut-être faire cela dans votre propre code.
Poignée de porte
@Doorknob: J'ai mis à jour mon code: la sortie est un seul caractère, elle supprime un fichier déjà existant au premier lancement et le fichier se trouve dans le répertoire du lecteur.
Kyle Kanos
D'accord merci! Cette soumission est maintenant incluse dans le classement.
Poignée de porte
@Doorknob: Cool! Suce que je ne suis pas le premier. Aussi: je suis sûr que les utilisateurs de Fortran sont comme les vampires, alors je suis sûr que vous allez bientôt commencer à coder en Fortran! Muahahahaha!
Kyle Kanos
5

PatientBlacksmith

Ce bot est écrit en R, utilisez-le Rscript PatientBlacksmith.Rpour le déclencher.

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)

Mesure la netteté du bâton de l’adversaire: bloque quand il est tranchant, prend le temps d’affûter autrement. Lorsque la netteté atteint 5, piquez jusqu'à ce que la netteté disparaisse.

planificateur
la source
Cela casse quand aucune entrée n’est donnée (c’est-à-dire au premier tour); Je ne sais pas comment résoudre ce problème, je vais donc devoir l'exclure du premier tour.
Poignée de porte
@Doorknob corrigé.
Plannapus
5

Règles de la prison, Haskell

Cavewoman pense que l'homme des cavernes et les autres hommes des cavernes devraient parler, partager leur bâton. Mais, hé ho, si doit se battre, combattez les règles de la prison. Trouver le patron et attaquer.

Vice-chef Alpha Caveman maintenant; que l'homme des cavernes doit combattre. D'autres hommes se battent plus tard. Si mon homme des cavernes perd, ne vous inquiétez pas; il trop poilu de toute façon.

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

Écrit en Haskell (programme fonctionnel!), Enregistrez-le sous prisonrules.hs , puis compilez-le avec:

ghc prisonrules.hs

Et courez comme:

prisonrules [history]
comperendinous
la source
4

Je l'appelle JavaMan

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

note: je n'ai pas l'intention de jouer au golf de code .. mais si vous êtes un golfeur et que les espaces / lignes supplémentaires font saigner vos yeux .. n'hésitez pas à le changer

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;
    }
}
utilisateur2813274
la source
4
Les soumissions pour les défis King of the Hill ne sont pas destinées au golf, alors ne vous inquiétez pas. ;)
Martin Ender
J'ai changé son nom en JavaMan, parce que "Caveman" est un peu trop générique pour figurer dans le classement. J'espère que ça vous va; sinon, changez-le en autre chose.
Poignée de porte
1
Cela casse quand aucune entrée n’est donnée (c’est-à-dire au premier tour); Je ne sais pas comment vous voulez gérer cela, alors je vais devoir l'exclure de la première série d'essais.
Bouton de porte
Corrigé, et le changement de nom me
convient très bien
1
Je pense que vous avez commis une erreur en analysant l'état, les deux actions "moi" et "ennemi" ont les mêmes mouvements: États [0]
Roy van Rijn
4

Pensées profondes, C

Code de l'homme des cavernes. Caveman pense. Homme des cavernes faire.

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

Je fais des tests. Plus de pensées mieux.

Zakipu
la source
1
+1 pour l'homme des cavernes var noms et commentaires: P aussi, beau programme c:
chat
3

Nigel

Nigel est un vieil homme des cavernes patient et défensif qui préfère être tactique que d'attaquer.

C'est un script PHP, appel avec php nigel.php

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

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

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

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

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

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

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

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

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

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

?>
ArcticanAudio
la source
3

Aichmophobic - Lua

Il vous frappera de temps en temps, mais seulement jusqu'à ce que le bâton devienne trop tranchant. Lorsque cela se produit, il panique et se courbe en position fœtale.

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)

Exécutez-le avec:

lua aichmophobic.lua

William Barbosa
la source
2
Votre sortie doit être en majuscule. J'ai corrigé ça pour toi. (Aussi, j'ai mal orthographié le nom de cette soumission environ mille fois.: P)
Bouton de porte
3

Bob Caves

Bob Caves est l'un des gars les plus intelligents de sa grotte. Il a appris à compter avec une main (l'autre est occupée à tenir son bâton). Il a connu les Jeux olympiques de l'âge de pierre et a voulu y participer.

Sa stratégie principale est de bloquer et d'aiguiser son bâton jusqu'à ce qu'il ait un beau bâton pointu ou que l'autre homme des cavernes en ait un aussi. Dans ce cas, Bob Caves tente de le toucher!

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

}

Compiler avec javac BobCaves.javaet courir avecjava BobCaves

Edit: Bob compte maintenant quand il y a un bloc! (merci à Mikey Mouse ). En outre, il tranchant son bâton lorsque l'autre bâton d'homme des cavernes est émoussé.

Edit 2: Méthode de comptage améliorée (merci encore à Mikey).

Edit 3: Rendre Bob légèrement plus agressif.

Averroes
la source
2
Bob oublie l'effet Poke: bloque la netteté du manche. Trois "S" ne collent pas trois fois. Chaque "P" dans s signifie bâton non affûté. Huh huh huh ... "Pee" blague homme des cavernes ...
Mikey Mouse
@ MikeyMouse Bob est d'accord. Bob rendra visite au sorcier pour améliorer sa technique. Bob reconnaissant!
Averroes
1
Le docteur de sorcière apprend à Bob. Mais il oublie de mentionner le scénario Poke: Poke. Stick deviens émoussé alors aussi. Bob n'a pas besoin d'envisager de déplacer l'adversaire. Si Bob Poke, s'en tenir à émousser. Soit émoussé: poke adverse, sur bloc adverse ou sur la tête de l'adversaire. Si c'est l'adversaire Head, Bob gagne et peut danser autour de la grotte avec un manche émoussé.
Mikey Mouse
1
@ MikeyMouse Bob sait compter. Bob a besoin d'apprendre à lire. Merci encore!
Averroes
3

Gruntt

Gruntt est défensif. Gruntt analyse d'autres mouvements d'hommes des cavernes pour savoir comment les piquer. Puis il les pique droit dans les yeux. Gruntt n'est pas un gentil homme des cavernes.

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

}

Compiler avec javac Gruntt.javaet courir avecjava Gruntt

Averroes
la source
Cela jette un ArrayOutOfBoundsExceptionau premier tour et génère parfois plusieurs actions lors des autres tours.
Poignée de porte
@Doorknob Ops! Fixe, merci!
Averroes
3

Est-ce un oiseau? Est-ce un avion? C'est RegExMan!

Il essaie d'analyser vos séquences super-ennuyeuses avec son RegEx-power primitif spécial!

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

Écrit en Python 2.7, exécuté avec python RegExMan.py [history]

Chiffrer
la source
3

Sicillien

Mais c'est si simple! Tout ce que je dois faire est de deviner ce que je sais d’autre homme des cavernes: est-il le genre d’homme des cavernes qui bloquerait, affûterait ou piquerait? Maintenant, un homme des cavernes habile pourrait frapper ou bloquer, car il saurait que seul un grand imbécile aiguiserait et s'exposerait à l'attaque. Je ne suis pas un grand imbécile, je ne peux donc clairement pas affûter. Mais les autres hommes des cavernes doivent savoir que je ne suis pas un grand imbécile et que j’aurais compté sur cela, afin que je ne puisse clairement pas cingler ou bloquer!

Courir avec:

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;
    }
}
Amwallis
la source
3

bash-magnon

Les Bash-Magnons étaient robustes et puissants. Le corps était généralement lourd et solide avec une forte musculature. Le front était plutôt droit que incliné, comme chez le Néandertal, et ne présentait que de légers passages. Le visage était court et large. Le menton était proéminent. La capacité cérébrale était d’environ 1 600 centimètres cubes (98 pouces cubes), plus grande que la moyenne de l’homme moderne. Cependant, des recherches récentes suggèrent que les dimensions physiques de ce que l'on appelle "Bash-Magnon" ne sont pas suffisamment différentes de celles des humains modernes pour justifier une désignation distincte.

Moi j'ai un cerveau, je m'en souviens.

Ceci est un auto-exécutable ./bash-magnon.sh

#!/bin/bash

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

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

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

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

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

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

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

set $(max "$B B" "$(max "$P P" "$S S")" )
echo $2
Emmanuel
la source
1+ Vous avez évidemment le bon outil pour le travail et vos noms d'hommes des cavernes sont assez amusants :) (
Sylwester
@ Sylwester Merci c'est mon premier +1. J'ai d'abord essayé de créer un automate homéostatique inspiré par ce que le premier cybernéticien a senti comme son propre équilibre, puis j'ai abandonné et créé un script bash.
Emmanuel
2

PokeBackBot

Simplement adapté de PokeBot:

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

Courir avec ruby pokebackbot.rb.

Ceci utilise la stratégie la plus simple suivante et bloque "patiemment" pendant un round avant d'attaquer.

Martin Ender
la source
3
@PeterTaylor J'ai lu cela comme n'être pas autorisé à changer de stratégie en prenant l'empreinte digitale de l'adversaire. Si ma soumission ne peut vaincre qu'une autre soumission, cela n'affectera pas vraiment le score des autres soumissions, et ma propre soumission s'en tirera probablement très mal. En outre, s'il n'y a qu'une soumission et qu'une seconde est écrite, cette seconde est susceptible de battre la première (parce que sinon, pourquoi s'embêter) - est-ce que cela suffit à qualifier de "spécifique pour un autre programme"? Mon bot va battre n'importe quel bot qui commence avec SPS(ce qui semble raisonnable), mais jusqu'à présent, PokeBot était le seul autour.
Martin Ender
2

Maître des Epées

Écrit en Python 3.4 (fonctionne avec Python 3.x)

Essaie d'obtenir une épée aussi vite que possible, mais attaque si elle a une chance de la toucher (netteté> 0) et si l'ennemi peut la blesser aussi (netteté de l'ennemi> 0).
Bloque que si n'a pas de netteté et ennemi pourrait attaquer.

Commencer avec:

python3 swordmaster.py MOVES

(supposé que vous enregistrez sous swordmaster.py)

Code rapide et moche:

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

(Définir dgsur Truepour activer les messages de débogage)

Chill0r
la source
1
Astuce: Ne le laissez pas se combattre - ça va interblocage avec S, P, S, P...
chill0r
J'ai trouvé que cela arrive aussi avec le mien. À moins d’examiner l’histoire ou d’utiliser un degré d’aléatoire, vous vous retrouverez coincé dans un cycle.
Pharap
2

FoolMeOnce.py

Enregistrez les mouvements de chaque joueur pour le premier duel, puis rejouez avec exactement les mêmes mouvements. Si l'algorithme de l'ennemi est non aléatoire, nous ne pouvons prédire le même résultat et frapper que lorsque nous savons que nous allons gagner.

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)

Écrit en python 3, vous devrez donc probablement utiliser python3. FoolMeOnce.py Au premier tour, je ne suis pas sûr que nous obtenions une chaîne vide ou juste une virgule. Il est donc possible que quelques ajustements soient nécessaires.

tzazy
la source
J'ai corrigé le chemin de votre fichier - le répertoire de travail actuel n'est pas celui de votre programme.
Poignée de porte
En jouant avec le testeur CavemanDuel, j'ai remarqué que FoolMeOnce obtenait des points bien meilleurs si j'utilisais plus de threads (j'ai testé 16 threads contre 4). Avec 4 fils, il obtient ~ 25 points, avec 16, il obtient ~ 34.
wendelbsilva
Bizarre, je ne sais pas pourquoi.
Tzazy