Duelos de hombre de las cavernas (o: Te pincho con un palo afilado)

151

Hombre de las cavernas loco. Otro hombre de las cavernas toma palo pero el palo fue para mí. Lucha de hombre de las cavernas !


Descripción

El hombre de las cavernas necesita un palo afilado para apuñalar a otro hombre de las cavernas. Otros hombres de las cavernas también intentan apuñalar con un palo afilado. El hombre de las cavernas puede afilar el palo, pinchar con el palo o bloquear los palos.

Si el hombre de las cavernas golpea a otro hombre de las cavernas con un palo afilado, otro hombre de las cavernas se escapará y yo venceré. Pero si otro hombre de las cavernas bloquea inteligentemente cuando estoy hurgando, no pasa nada, excepto que mi palo se vuelve contundente y necesito afilar nuevamente.

Hombre de las cavernas vago. Además, hombre de las cavernas tonto. El hombre de las cavernas no sabe qué hacer, por lo que el hombre de las cavernas necesita un sofisticado programa de computadora tecno para decirle al hombre de las cavernas qué hacer.

Entrada

La entrada de su programa será una historia de los eventos que han sucedido, donde Ssignifica agudizar (es decir, el hombre de las cavernas afiló su bastón), Prepresenta un golpe y Brepresenta un bloque. La entrada será un historial de ambos lados (usted y el oponente), por lo que sus movimientos y los del oponente se separarán con una coma ( ,).

Entrada de ejemplo:

SPB,SBB

Esto significa que el jugador afiló su palo, luego golpeó, bloqueó y el oponente afiló, bloqueó y bloqueó nuevamente.

No recibirá ninguna entrada en el turno 1.

Salida

La salida es muy similar a la entrada (porque el hombre de las cavernas no es muy inteligente). Su programa debe salir Spara enfocar, Ppara empujar y Bpara bloquear. Solo se tendrá en cuenta el primer carácter de salida, y cualquier otra entrada se tratará como un Bcomando (bloque).

  • S: afilar

    Al afilar, la agudeza del palo del hombre de las cavernas aumenta en 1 y el palo recibe 1 empuje adicional. Cada golpe reduce la nitidez del palo en 1, y si la nitidez del palo es 0, es demasiado aburrido para tocar. La nitidez comienza en 0. Si la nitidez llega a 5, ¡el palo es una espada! (Vea abajo.)

    Si el oponente golpea mientras usted está afilando (y tiene una nitidez> 0), ¡el oponente gana!

  • P: empujar

    Al pinchar, la agudeza del palo del hombre de las cavernas se reduce en 1 y golpeas a tu oponente. Si tu oponente está afilando, ¡tú ganas! Si el oponente está empujando, tu palo golpea el palo de tu oponente y ambos se embotan (por 1 "unidad de nitidez"). Si el oponente está bloqueando, no pasa nada excepto que tu palo se vuelve más opaco.

    Si tocas cuando la agudeza de tu palo es 5 o mayor, ¡tu palo se convierte en una espada y siempre ganas! (A menos que tu oponente también tenga una espada y también elija P; en ese caso, ambos se vuelven más opacos y pueden volver a palos si su agudeza cae por debajo de 5).

    No puedes empujar con una nitidez de 0. Si lo haces, no pasará nada.

  • B: bloque

    Cuando bloqueas, no pasa nada cuando tu oponente golpea. Si tu oponente no está hurgando, el bloqueo no hace nada.

    ¡Bloquear no protege contra una espada, incluso si también tienes una!

Reglas y restricciones

Las reglas adicionales son:

  • Su programa puede leer y escribir archivos en su propia carpeta (¡sin robar!) Si desea guardar datos, pero no puede acceder a nada fuera de él (y los hombres de las cavernas no tienen conexión a Internet en el desierto).
    • Nota importante sobre los archivos : si guarda archivos, recuerde guardarlos en el directorio players/YourBotsName/somefile.foo. ¡El directorio de trabajo actual para su programa no será el de su programa!
  • Los hombres de las cavernas son justos: un programa no puede tener un código específico para otro programa, y ​​los programas no pueden ayudarse entre sí. (Es posible que tenga varios programas, pero no pueden interactuar entre sí de ninguna manera).
  • El juez cavernícola no es paciente. Si los hombres de las cavernas toman más de 100 turnos cada uno para decidir un ganador, el juez se aburre y ambos hombres de las cavernas pierden.

Si su programa infringe una regla o no sigue la especificación, el programa se descalifica, se elimina playerlist.txty todos los duelos se reinician desde el principio. Si su programa es descalificado, el líder del hombre de las cavernas (¡yo!) Comentará la publicación de su programa y explicará por qué. Si no está rompiendo ninguna regla, su programa se agregará a la tabla de clasificación. (Si su programa no está en la tabla de clasificación, no hay ningún comentario explicativo en su publicación, y publicó su programa antes de la hora de "Última actualización" a continuación, ¡dígaselo al líder del hombre de las cavernas! ¡Quizás lo olvidó!)

En su publicación, incluya:

  • Un nombre.
  • Un comando shell para ejecutar el programa (ej. java MyBot.java, ruby MyBot.rb, python3 MyBot.py, Etc.).
    • Nota: la entrada se agregará a esto como un argumento de línea de comando.
    • Los hombres de las cavernas usan Ubuntu 14.04, así que asegúrese de que su código funcione (libremente) en él.
  • Un número de versión, si su código funciona de manera diferente en diferentes versiones de su idioma elegido.
  • Tu código (obviamente).
  • Cómo compilar el código, si es necesario.

Código / prueba del controlador, ejemplo bot

El líder del hombre de las cavernas escribió el código de control en C ++ y lo publicó en un repositorio de Github . Puede ejecutar y probar su programa allí.

Un programa muy, muy simple (¡1 línea!) También se publica en las respuestas a continuación .

Puntuación y tabla de clasificación

Anotar es fácil. El hombre de las cavernas que gana obtiene un punto. ¡El hombre de las cavernas con más puntos después de 3 duelos contra cualquier otro hombre de las cavernas se convierte en el nuevo líder del hombre de las cavernas!

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

(esta tabla de clasificación se generó automáticamente por arte de magia)

Los jugadores marcados con un *lanzamiento arrojaron algún tipo de error o excepción en algún momento; Estos jugadores también tienen un comentario en sus publicaciones.

Los jugadores que no pudieron ser incluidos en las pruebas por cualquier motivo (estos jugadores tendrán un comentario en sus mensajes que explican el problema): Monkey, Elephant, FacileFibonacci, StudiousSylwester.

Última actualización: 3 de agosto 00:15 (UTC).

Pomo de la puerta
fuente
Me sorprende que nadie parezca haber intentado encontrar la estrategia minimax todavía. Parece lo más obvio que hacer.
user2357112
@ user2357112 No creo que minimax sea una mejora aquí. Quiero decir, podrías diseñar una implementación minimax, pero como la lógica es tan simple, el mismo comportamiento exacto se puede expresar con una máquina de estados finitos. (es decir, el bot nunca se agudizará hasta que el oponente esté aburrido porque si lo hace, el movimiento de minimización del oponente será empujar y tú pierdes, el bot siempre se bloqueará hasta que tengamos una espada porque el movimiento de maximización para nuestro bot siempre ser para bloquear, etc.)
HuddleWolf
3
Muchas de las entradas parecen permitir una nitidez negativa en sus cálculos. Las reglas tal como están escritas dicen que no pasa nada cuando tocas con cero nitidez. ¿Eso "nada" también significa que su nitidez se mantiene en cero, en lugar de ser disminuida?
Sparr
66
Esto tiene que estar aquí: dresdencodak.com/comics/2009-09-22-caveman_science_fiction.jpg Tal vez pueda despertar la imaginación. :)
Evi1M4chine
2
¿Sigue abierto? Veo personas que agregan nuevas presentaciones, pero no veo que se actualice la tabla de clasificación.
ASCIIThenANSI

Respuestas:

35

Darwin - C

¿Quién necesita estrategia, de todos modos? ¡Haga que un grupo de hombres de las cavernas se enfrenten y dejen que la selección natural haga el resto!


Utilizamos un modelo muy simple para el cerebro primitivo de un hombre de las cavernas: no tiene memoria y solo tiene en cuenta la agudeza del palo de él y de su oponente. Esos se usan como variables para un polinomio binario de algún orden finito. Cada acción (bloquear, enfocar y pinchar) tiene un polinomio asociado cuyo resultado determina la probabilidad relativa de elegir esta acción. Eso es prácticamente todo lo que hay que hacer: comience con algunos coeficientes aleatorios y optimice de forma iterativa.

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

Compilar con: gcc darwin.c -odarwin -w -O3. Ejecutar con: ./darwin <history>.

El bot lee los coeficientes de un archivo nombrado programen el players/Darwindirectorio (se puede especificar un archivo diferente como un segundo argumento de línea de comandos). Este programa parece funcionar bien:

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 

Guardar como players/Darwin/program.

El siguiente es un programa que genera programarchivos que pueden ser utilizados por el bot (no tiene que ser compilado si usa el programarchivo anterior):

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

Compilar con: gcc genprog.c -ogenprog -w -O3. Ejecutar con: ./genprog [output-filename].


Watson

¿Cuál es el ADN de un hombre de las cavernas ganador? Quizás este chico tiene la respuesta:

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

Corre con: python Watson.py

Watson es el producto de un algoritmo genético. A diferencia de Darwin, el dato genético esta vez es un programa real, escrito en un pequeño lenguaje específico de dominio (aquí traducido a Python).


La secuencia simple supera a los grandes jugadores

A este pequeño amigo le va sorprendentemente (o, tal vez, no tan sorprendentemente) bien, especialmente contra los líderes:

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

Corre con: python SSBBP.py

DarwinBot
fuente
¿Cómo compilo y ejecuto esto? Además, como se menciona en la pregunta, solo puede leer / escribir archivos en el players/Darwindirectorio.
Pomo de la puerta
@Pomo de puerta: corregido.
DarwinBot
Recibo estos errores de compilación al compilar este código. (Estoy en Ubuntu 14.04.)
Pomo de la puerta
@ Pomo de puerta: corregido. Debería funcionar ahora.
DarwinBot
Ahora me estoy poniendo undefined reference to `fmax'. --Editar-- No importa, realmente lo necesitaba -lm.
Pomo de la puerta
50

Hombre de las cavernas impredecible

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!

Este hombre de las cavernas elige al azar cada ronda, pero le he explicado muy simplemente que ciertas acciones simplemente no tienen sentido a veces. Siéntase libre de copiar este código si desea expresar una lógica diferente.

Este es Ruby, guárdelo como 'unpredictable.rb' y ejecútelo con ruby unpredictable.rb

histocrat
fuente
En realidad, creo que no 'Block'también debería ser si mi oponente tiene una espada.
njzk2
El primer no 'Bloque' en realidad cubre eso: un palo puntiagudo no es una espada.
histocrat
2
¿Por qué no usas unlesspara las declaraciones no 'Block'y no 'Poke'? ( no 'Block' unless he.has_pointy_stick)
wchargin
25

Doctor de las cavernas - Lua

"Perdí con los nuevos extranjeros, los noqueé para estudiarlos"

Cuando haya visto tantos pacientes como el médico de las cavernas, comenzará a comprender realmente la psique del hombre de las cavernas (o eso espero). El juego del doctor de las cavernas es pura estrategia, espera golpes que bloquea en un intento de desarmar a su oponente, pero no permitirá que ese oponente se acerque a hacer una espada. Intenta predecir cuándo es seguro afilar para no perder la ventaja.

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

Corre con: lua CaveDoctor.lua

Nexo
fuente
3
¿Esto solo pierde dos veces en la clasificación actual? oO
justo el
La revisión 5 arroja muchos errores, por lo que la revisión 4 es la que se incluye en la ronda actual de pruebas.
Pomo de la puerta
@Doorknob Creo que los arreglé todos, de todos modos solo hubo un cambio en la lógica real.
Nexus
20

ExtranjeroCaveman

ForeignCaveman no tiene idea de lo que acabas de decir. Él solo ... hace cosas.

javac ForeignCaveman.java entonces 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
fuente
11
Esto probablemente tiene demasiados votos a favor por lo mal que lo hace
Kevin L
19

Vice-líder

Pomo de la puerta ♦ es el líder. ¡Quiero ser líder! ¡Sigue el programa súper inteligente para convertirte en líder!

Compilar: javac ViceLeader.javaEjecutar: 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
fuente
¿Por qué no es esto if (enemySharpness <= 4 || mySharpness >= 5)vs ==?
durron597
@ durron597 Porque solo quiero golpear al enemigo si puede hacer una espada en el próximo turno (lo que probablemente hará). VizeLeader no toca con frecuencia, lo hace en el momento adecuado .
CommonGuy
Pero tienes una espada y tu oponente no ...
durron597
@ durron597 No, es una declaración OR. Significa "golpear al oponente si tengo una espada O si pronto tendrá una espada".
CommonGuy
77
Oh Dios. Es hora de tomar otra taza de café :) O nuevas lentes de contacto
durron597
15

Quizás Markov 2.1

Creo que utiliza las cadenas de Markov para predecir lo que hará el otro hombre de las cavernas, pero solo miré brevemente la página de Wikipedia sobre las cadenas de Markov y decidí que tenía demasiado texto.

Intenta mantenerse con vida durante 30 rondas y luego construye una tabla con los cambios de estado actuales y siguientes, y reacciona a lo que cree que hará el otro hombre de las cavernas.

El código contiene muchas declaraciones innecesarias, pero funciona bastante bien.

EDITAR

Detectado un defecto en la lógica. Ahora en realidad hace algo cuando tiene una espada.

$ 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
fuente
14

PeriodicalCicadaCaveman

Este hombre de las cavernas bastante inteligente ha estudiado cierto error y se dio cuenta de que nadie puede ajustar su estilo de vida para aprovechar el número primo Cicada.

Se esconde / bloquea durante la mayor parte de su vida, pero ocasionalmente se asoma. ¿Seguro que es vulnerable a las espadas y pasa un ciclo completo con un palo sin punta, pero afilando su palo cuando es totalmente contundente? Eso es exactamente lo que los demás esperan de él ... no esta cigarra

para compilar: mcs program.cs para ejecutar 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"); 

  }

}

Editar: Cambié la nitidez: código ... si pincho, gano o mi palo se vuelve más opaco

Edit2: agregado en la sugerencia de Bobs

Editar: se cambió para empujar solo cuando está en la nitidez 2, si el palo alguna vez está en cero, el otro tipo podría hacer una espada.

Mikey Mouse
fuente
1
Estoy corriendo en Ubuntu; ¿esto compilará bajo Mono? Si es así, ¿cómo lo compilo y cómo lo ejecuto?
Pomo de la puerta
Para ser sincero, no lo sé. Estoy a punto de irme a la cama. Puedo reescribirlo en Java mañana por la mañana en el trabajo. El código Java debería ser casi idéntico.
Mikey Mouse
55
@Doorknob mcs program.cslo compilará, mono programlo ejecutará, pero deberá reemplazar el foo.Dump();s con System.Console.WriteLine(foo);(o agregar un método de extensión public static void Dump(this string value) { System.Console.WriteLine(value); }).
Bob
@Bob Gracias amigo, he agregado tu método de extensión.
Mikey Mouse
Lo sentimos, el nombre de archivo predeterminado real que se mcsgenera es <filename>.exe, por ejemplo, program.cssería program.exe. Entonces el comando de ejecución sería mono program.exe. (No tenía acceso a mono en el momento de mi comentario anterior)
Bob
14

FantasíaTechnoAlgoritmo

Un sofisticado algoritmo techno para el sofisticado programa de computadora techno.

El hombre de las cavernas sigue perdiendo la batalla. Hombre de las cavernas enojado. Entonces, el hombre de las cavernas va a la escuela de computación y aprende el algoritmo.

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"

Programa Python 2. Correr:python fancytechnoalgorithm.py

Vectorizado
fuente
Esto se rompe cuando no hay entrada (es decir, en el primer turno). No sé cómo quieres manejar eso, así que tendré que excluirlo de la primera ronda de pruebas.
Pomo de la puerta
@Doorknob Para la primera entrada, ¿es "," o ""? Supongo que es lo último de eso.
Vectorizado
Para la primera entrada, no habrá argumentos (se ejecutará como python StickSharpener.py).
Pomo de la puerta
@Doorknob Lo he editado. A ver si funciona ahora.
Vectorizado
¡OK gracias! Incluiré esto en la próxima ronda de ensayos.
Pomo de la puerta
14

El vigilante

Él observa los movimientos de su oponente, siempre dejándolos mostrar su mano antes de atacar. Está particularmente preparado para aquellos que descuidan trabajar hacia una espada.

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

Nombre del archivo: watcher.py

Correr: python watcher.py

Basilisco

Busca destruir a quienes lo miran demasiado de cerca. Consistentemente vence al Observador, pero probablemente le irá peor en general.

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

Nombre del archivo: basilisk.py

Correr: python basilisk.py

Nash

Busca hacer irrelevantes las elecciones de su oponente, eligiendo cada movimiento con una probabilidad que explique sus riesgos y recompensas

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

Este no es exactamente el equilibrio de Nash (mi generador de estrategias tiene cierta inestabilidad), pero está cerca.

En aras de la curiosidad, estas son las estimaciones de la probabilidad de que este bot gane en cada estado del juego:

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

Nombre del archivo: nash.py

Correr: python nash.py

Finta

Se abre con un ataque rápido, para probar las defensas de su oponente.

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

Nombre del archivo: feint.py

Correr: python feint.py

LatePokeBot

El hermano pequeño de PokeBot. Nunca muestra debilidad, pero trata de pelear como su hermano mayor.

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

Nombre del archivo: latepokebot.py

Correr: python latepokebot.py

Brilliand
fuente
Te faltaba un :en Basilisco; Lo arreglé para usted
Pomo de la puerta
Esta presentación arrojó algún tipo de error o excepción en algún momento; es posible que desee considerar arreglar eso antes de la próxima ronda de pruebas. (el Basilisco)
Pomo de la puerta
@Doorknob Elegí la secuencia de inicio de Basilisk mirando las suposiciones hechas por The Watcher y Cave Doctor y encontrando una secuencia que haría que esas suposiciones salieran mal. ¿Eso viola la regla de "los hombres de las cavernas son justos"?
Brilliand
¡Ve a Nash! ¡Gana exactamente la mitad de tus partidas contra todos los bots lo suficientemente inteligentes como para evitar tus opciones P = 0!
aschepler
12

PokeBot

Escrito en rubí.

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

Corre con ruby pokebot.rb .

Este bot no es muy inteligente; hace lo que el hombre de las cavernas promedio haría solo de todos modos.

Pomo de la puerta
fuente
9

PatientWolf v2.0

Afila si está aburrido, empuja si el enemigo tendrá una espada el próximo turno o si el enemigo está apagado, bloquea de lo contrario.

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

Corre con

perl patientwolf.pl

EDITAR: gracias a @sylwester por señalar un error

killmous
fuente
Como solo obtienes un argumento con ambas historias separadas por comas, lo estás analizando incorrectamente. P.ej. PatientWolf.pl SB,SPhace un Pya que piensa que tiene un palo afilado.
Sylwester
@Sylwester eso no es correcto. La primera línea asigna el primer argumento a $ me y el segundo argumento a $ él
killmous
El programa CavemanDuel no usa dos argumentos, solo uno. p.ej. perl patientwolf.pl "SB,SP". Deberías hacer my($me,$him) = split/,/ $ARGV[0];y if( @ARGV ) {print "S";exit}.
Sylwester
@Sylwester ok, veo a qué te refieres. Eso no estaba claro por el OP o por la rápida mirada que le había arrojado al código del controlador. Lo arreglaré en breve
killmous
9

Hombre de las cavernas binario

Afilar, apuñalar, repetir

Basado en la idea de que el bloqueo es para mariquitas, este hombre de las cavernas alterna entre las dos opciones 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;
        }
    }
}

Compilar con javac BinaryCaveman.java

Corre con java BinaryCaveman

EDITAR: Adventures in String Arrays ..... args.length () arroja un error. args.length siempre devuelve 1. args [0] .length () devuelve las longitudes de la primera cadena en la matriz.

EDIT 2: actualizado gracias a la ayuda de Doorknob, Brilliand y Sylwester. Gracias chicos.

Sombra_roja
fuente
@ MartinBüttner Olvidé dividir args: 1 por 2 para obtener solo el número de envíos pasados ​​de un solo jugador. Arreglado eso. No puedo entender la sumisión de Dorknob, Ruby es prácticamente un galimatías para mí. ¿Su siempre comienza con el afilado?
Red_Shadow
Sí, solo comprueba si su último movimiento fue Po Shace lo contrario. Y si aún no hay historia, él finge que la historia lo sería P,(lo que luego lo lleva a hacer Sprimero).
Martin Ender
Dos enfoques diferentes que resultan en la misma salida. ¿Eso va en contra de las reglas?
Red_Shadow
Probablemente no, solo te lo haría saber.
Martin Ender
2
@Pomo de la puerta Creo que debería ser args[0].length(), no args.length.
Brilliand
8

CavekidBlocks

Un niño de las cavernas llorando y asustado puede parecer una presa fácil. No dejes que su cara bonita te engañe porque él sabe cómo bloquear.

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

Corre con python3 cavekidblocks.py

ChargerMan

Este hombre de las cavernas es muy conservador. Intentará cargar su arma y solo atacará cuando sea necesario.

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)

Corre con python3 chargerman.py

Embaucador

Trickster no sabe cómo pelear, por lo que intenta confundir a otro hombre de las cavernas.

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

Corre con python3 trickster.py

Desafortunadamente, después del commit acc74 , Trickster ya no funciona según lo planeado.

Wendelbsilva
fuente
44
Ese programa tramposo es malvado
Nexus
@Nexus, aunque yo también. Desafortunadamente, Trickster no está bien en los duelos.
wendelbsilva
7

Hodor

Hodor no es muy agresivo. Le gusta permanecer en su escudo a menos que haya una buena oportunidad para atacar.

compilar con: javac Hodor.javay ejecutar con:java Hodor

código:

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

Editar: actualización de código menor

Qwix
fuente
Esta presentación arrojó algún tipo de error o excepción en algún momento; es posible que desee considerar solucionar eso antes de la próxima ronda de ensayos.
Pomo de la puerta
1
Tratar con SB,BB. Cuando otros hombres de las cavernas se portan mal en el primer turno, Hodor también se porta mal.
Sylwester
7

Sylwester especulativo - Perl5

Sylwester especulativo quiere eliminar a los buscadores de espadas mirando los patrones y empujando cuando existe la posibilidad de que el oponente se agudice y se agudice cuando el oponente tenga más probabilidades de bloquear. Sin embargo, no lo hará si existe la posibilidad de que hubiera adivinado que él mismo se agudizará en el próximo movimiento y somos aún más cautelosos cuando decidimos afilar.

En cuanto a cuando el oponente es contundente, intenta ser agresivo, pero eventualmente comenzará a ahorrar para una espada cuando eso parezca infructuoso.

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

Para ejecutar en Linux simplemente agregue esto en playerlist.txt:

perl players/SpeculativeSylwester/SpeculativeSylwester.pl

Fácil Fibonacci - Esquema R6RS

Además del primer movimiento, Facile Fibonacci bloquea cuando el turno es un número de Fibonacci (a partir de 0) y llena el resto con PPSS..y cambia cuando pasa el 8 a una secuencia interminable de PSSganar con una espada.

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

Para ejecutar simplemente instale ikarus con apt-get install ikarusy agregue esto en playerlist.txt:

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

Sylwester estudioso - Perl5

El estudioso Sylwester usa la misma táctica que el especulativo Sylwester, pero también mira los juegos anteriores para determinar dónde podría haber tomado una decisión equivocada.

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

Para ejecutar en Linux simplemente agregue esto a playerlist.txt

perl players/StudiousSylwester/StudiousSylwester.pl

Edición estudiosa

No puedo reproducir los problemas que tuvo al $0no ser la ruta completa al script perl cuando se ejecuta con perl. También he retirado sus cambios y no veo cambios en el src CavemanDuels y es lo mismo que he estado ejecutando más de 20 veces sin el problema que está informando. Estoy empezando a temer que podría haber obtenido el script como un script bash en lugar de ejecutarlo mientras es ejecutable o como un argumento para Perl. Necesito más información para saber con certeza. Como prueba, hice esto y puedes hacer lo mismo para ver si obtienes el mismo resultado:

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
fuente
Scheme no parece querer cooperar conmigo en mi máquina, por lo que no he podido probar el Fibonacci. Seguiré intentando que funcione, pero sería genial si pudieras traducirlo a otro idioma.
Pomo de la puerta
El estudioso tampoco parece funcionar, porque $0es bashcuando se llama desde una línea de comando bash (que hace el controlador). Sin players/StudiousSylwester/foo.txtembargo, podrías simplemente codificar .
Pomo de la puerta
@Doorknob Agregué cómo instalar ikarusy agregué mis pensamientos sobre $0Studious.
Sylwester
6

Herrero

Necesito un palo afilado. Si tiene un palo afilado, empuje. Yo no siento dolor.

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

Guardar como swordsmith.f90y compilar con gfortran -o swordsmith swordsmith.f90ejecutar como lo haría con cualquier ejecutable normales: ./swordsmith.

Kyle Kanos
fuente
Esto parece imprimir un espacio (``) antes de la salida real. No tengo idea de cómo solucionarlo, así que tendré que excluir esta presentación de la primera ronda de pruebas.
Pomo de la puerta
Además, he corregido la ruta del archivo; Resulta que el directorio de trabajo actual cuando se ejecutan no es el de su programa. Ah, y si por "nueva instancia" quieres decir "cada juego", no puedo hacer eso porque eso requeriría una carcasa especial del programa controlador; es posible que desee hacer eso en su propio código.
Pomo de la puerta
@Doorknob: He actualizado mi código: la salida es un solo carácter, elimina un archivo ya existente en la primera ejecución y el archivo está en el directorio del reproductor.
Kyle Kanos
¡OK gracias! Esta presentación ahora está incluida en la tabla de clasificación.
Pomo de la puerta
@Doorknob: ¡Genial! Apesta que no soy el primero. Además: estoy bastante seguro de que los usuarios de Fortran son como vampiros, ¡así que estoy bastante seguro de que pronto comenzarás a codificar en Fortran! Muahahahaha!
Kyle Kanos
5

PacienteHerrero

Este bot está escrito en R, úsalo Rscript PatientBlacksmith.Rpara activarlo.

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)

Mide la agudeza del palo del oponente: bloquea cuando está afilado, de lo contrario, tome tiempo para afilarlo. Cuando la propia nitidez alcance 5, empuje hasta que la nitidez desaparezca.

plannapus
fuente
Esto se rompe cuando no se le da entrada (es decir, en el primer turno); No sé cómo solucionarlo, así que tendré que excluirlo de la ronda 1 de pruebas.
Pomo de la puerta
@Doorknob corregido.
plannapus
5

Reglas de la prisión, Haskell

La mujer de las cavernas piensa que el hombre de las cavernas y otros hombres de las cavernas deberían hablar, compartir el palo. Pero, oye, si debes luchar, lucha contra las reglas de la prisión. Encuentra jefe y ataca.

ViceLeader Alpha Caveman ahora; que el hombre de las cavernas debe luchar. Otros hombres de las cavernas luchan más tarde. Si mi hombre de las cavernas pierde, no se preocupe; él también peludo de todos modos.

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

Escrito en Haskell (¡vaya a la programación funcional!), Así que guárdelo como prisonrules.hs , luego compile con:

ghc prisonrules.hs

Y correr como:

prisonrules [history]
competitivo
fuente
4

Lo llamo JavaMan

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

nota: no tengo la intención de jugar golf de código ... pero si eres golfista y los espacios / líneas adicionales hacen que tus ojos sangren ... no dudes en cambiarlo

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;
    }
}
usuario2813274
fuente
44
Los envíos para los desafíos de King of the Hill no están destinados a jugar golf, así que no se preocupe. ;)
Martin Ender
He cambiado su nombre a JavaMan, porque "Caveman" es un poco demasiado genérico para estar en la clasificación. Espero que esté bien contigo; si no, simplemente cámbielo a otra cosa.
Pomo
1
Esto se rompe cuando no se le da entrada (es decir, en el primer turno); No sé cómo quieres manejar eso, así que tendré que excluirlo de la primera ronda de pruebas.
Pomo de la puerta
Solucionado, y el cambio de nombre está bien para mí
usuario2813274
1
Creo que tiene un error al analizar el estado, tanto 'yo' como 'enemigo' obtienen los mismos movimientos: estados [0]
Roy van Rijn
4

Pensamientos profundos, C

Código de hombre de las cavernas. El hombre de las cavernas piensa. Hombre de las cavernas hacer.

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

Yo hago las pruebas. Más pensamientos mejor.

Zakipu
fuente
1
+1 para los nombres y comentarios del hombre de las cavernas: P También, buen programa c:
gato
3

Nigel

Nigel es un viejo hombre de las cavernas defensivo y paciente que prefiere ser táctico antes que atacar.

Es un script PHP, llame con 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
fuente
3

Aichmophobic - Lua

De vez en cuando te empuja, pero solo hasta que el palo se afila demasiado. Cuando esto suceda, entrará en pánico y se enrollará en posición fetal.

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)

Ejecútalo con:

lua aichmophobic.lua

William Barbosa
fuente
2
Su salida tiene que estar en mayúsculas; Lo he arreglado para ti. (Además, escribí mal el nombre de esta presentación unas mil veces.: P)
Pomo de la puerta
3

Cuevas de Bob

Bob Caves es uno de los tipos más inteligentes de su cueva. Ha aprendido a contar con una mano (la otra está ocupada sosteniendo su palo). Él sabía de estos Juegos Olímpicos de la Edad de Piedra y quería participar.

Su estrategia principal es bloquear y afilar su palo hasta que tenga un buen palo afilado o el otro hombre de las cavernas también tenga uno afilado. ¡En este caso, Bob Caves intenta empujarlo!

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

}

Compilar javac BobCaves.javay ejecutar conjava BobCaves

Editar: ¡Bob ahora cuenta cuando hay algún bloque! (gracias a Mikey Mouse ). También afilará su bastón cuando el otro bastón cavernícola sea romo.

Edición 2: Método de conteo mejorado (gracias nuevamente a Mikey).

Edición 3: Hacer a Bob un poco más agresivo.

Averroes
fuente
2
Bob olvida el efecto de conteo de Poke: Block en la nitidez del palo. Tres "S" en s no significan palo 3 veces afilado. Cada "P" en s significa palo sin punta. Huh huh huh ... "Pee" broma del hombre de las cavernas ...
Mikey Mouse
@MikeyMouse Bob está de acuerdo. Bob visitará al médico brujo para mejorar su técnica. Bob agradecido!
Averroes
1
El médico brujo le enseña bien a Bob. Pero él olvida mencionar Poke: escenario Poke. Stick se embota entonces también. Bob no necesita considerar el movimiento del oponente. Si Bob Poke, el palo se vuelve contundente. Ya sea contundente: golpe del oponente, bloqueo del oponente o en la cabeza del oponente. Si está en la cabeza del oponente, Bob gana y puede bailar alrededor de la cueva con un palo contundente.
Mikey Mouse
1
@MikeyMouse Bob sabe contar. Bob necesita aprender a leer. ¡Gracias de nuevo!
Averroes
3

Gruntt

Gruntt está a la defensiva. Gruntt analiza otros movimientos de hombres de las cavernas para saber cómo empujarlos. Luego los empuja directamente a los ojos. Gruntt no es un buen hombre de las cavernas.

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

}

Compilar javac Gruntt.javay ejecutar conjava Gruntt

Averroes
fuente
Esto arroja un ArrayOutOfBoundsExceptionen el primer turno, y a veces genera múltiples acciones en otros turnos.
Pomo de la puerta
@Doorknob Ops! Fijo, gracias!
Averroes
3

¿Es un pajaro? ¿Es un avión? ¡Es RegExMan!

¡Intenta analizar tus secuencias súper aburridas con su poder especial RegEx primitivo!

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

Escrito en Python 2.7, ejecute con python RegExMan.py [history]

Cifrar
fuente
3

Siciliano

¡Pero es tan simple! Todo lo que tengo que hacer es divino por lo que sé de otro hombre de las cavernas: ¿es él el tipo de hombre de las cavernas que bloquearía, afilaría o golpearía? Ahora, un hombre de las cavernas inteligente golpearía o bloquearía, porque sabría que solo un gran tonto se agudizaría y se expondría a los ataques. No soy un gran tonto, por lo que claramente no puedo agudizar. Pero otro hombre de las cavernas debe saber que no soy un gran tonto, y habría contado con eso, ¡así que claramente no puedo empujar ni bloquear!

Corre con:

javac Sicillian.java
java Sicillian

Código:

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
fuente
3

bash-magnon

Los Bash-magnons fueron robustos y potentes. El cuerpo era generalmente pesado y sólido con una musculatura fuerte. La frente era bastante recta en lugar de inclinarse como en los neandertales, y solo con ligeros fruncidos. La cara era corta y ancha. El mentón era prominente. La capacidad cerebral era de aproximadamente 1.600 centímetros cúbicos (98 pies cúbicos), mayor que el promedio de los humanos modernos. Sin embargo, investigaciones recientes sugieren que las dimensiones físicas del llamado "Bash-Magnon" no son lo suficientemente diferentes de los humanos modernos como para justificar una designación separada.

Tengo un cerebro, me acuerdo.

Este es un auto ejecutable ./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
fuente
1+ Obviamente tienes la herramienta adecuada para el trabajo y los nombres de tus hombres de las cavernas son bastante divertidos :) (Personalmente, me gusta más el pescado)
Sylwester
@Sylwester Gracias, ese es mi primer +1. Primero intenté hacer un autómata homeostático inspirado en lo que hizo el primer cibernético algo que siente su propio equilibrio, luego me di por vencido y escribí un script bash.
Emmanuel
2

PokeBackBot

Simplemente adaptado de PokeBot:

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

Corre con ruby pokebackbot.rb .

Utiliza la siguiente estrategia más simple y bloquea "pacientemente" durante una ronda antes de atacar.

Martin Ender
fuente
3
@PeterTaylor Leí que no se me permite cambiar mi estrategia basada en las huellas digitales del oponente. Si mi presentación solo puede vencer a otra presentación, eso realmente no afectará el puntaje de otras presentaciones, y mi propia presentación probablemente irá muy mal. Además, si solo hay una presentación y se escribe una segunda, es probable que la segunda supere a la primera (porque de lo contrario, ¿por qué molestarse?), ¿Eso solo califica como "específico para otro programa"? Mi bot superará a cualquier bot que comience con SPS(lo que parece razonable), pero hasta ahora PokeBot era el único.
Martin Ender
2

Maestro de la espada

Escrito en Python 3.4 (funciona con Python 3.x)

Trata de obtener una espada lo más rápido posible, pero ataca si tiene la posibilidad de golpearlo (agudeza> 0) y el enemigo también podría lastimarla (agudeza del enemigo> 0).
Bloquea solo si no tiene agudeza y el enemigo puede atacar.

Empezar con:

python3 swordmaster.py MOVES

(asumí que lo guardas como swordmaster.py )

Código rápido y feo:

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

(Configurar dgpara Truehabilitar mensajes de depuración)

chill0r
fuente
1
Un consejo: No deje que se batalla en sí - que va marcador con S, P, S, P...
chill0r
Encontré que esto también pasa con el mío. A menos que examine la historia o use un grado de aleatoriedad, seguramente se quedará atrapado en un ciclo.
Pharap
2

FoolMeOnce.py

Guarda los movimientos de cada jugador para el primer duelo, luego repite con los mismos movimientos. Si el algoritmo del enemigo no es aleatorio, podemos predecir el mismo resultado y atacar solo cuando sabemos que ganaremos.

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)

Escrito en python 3, lo más probable es que tengas que usar python3 FoolMeOnce.py. En la primera ronda, no estoy seguro de si obtenemos una cadena vacía o solo una coma, por lo que es posible que se necesiten algunos ajustes.

tzazy
fuente
He arreglado la ruta del archivo; resulta que el directorio de trabajo actual no es el de su programa.
Pomo de la puerta
Mientras jugaba con el probador CavemanDuel, noté que FoolMeOnce obtiene mejores puntos si uso más hilos (probé 16 hilos contra 4). Con 4 hilos obtiene ~ 25 puntos, con 16 obtiene ~ 34.
wendelbsilva
Extraño, no tengo idea de por qué sería eso.
tzazy