Caveman Duels (o: Me ti colpisco con un bastone affilato)


151

Uomo delle caverne pazzo. L'altro uomo delle caverne prende il bastone ma il bastone era per me. Lotta del cavernicolo !


Descrizione

Il cavernicolo ha bisogno di un bastone affilato per pugnalare un altro uomo delle caverne. Anche altri cavernicoli cercano di pugnalare con un bastone affilato. Il cavernicolo può affilare il bastone, colpire con il bastone o bloccare i bastoncini.

Se l'uomo delle caverne colpisce gli altri uomini delle caverne con un bastone affilato, altri uomini delle caverne scappano e io vado alla vittoria. Ma se un altro uomo delle caverne si blocca in modo intelligente quando frugando, non succede nulla tranne il mio bastone che diventa smussato e devo affilare di nuovo.

Uomo delle caverne pigro. Inoltre, uomo delle caverne stupido. Uomo delle caverne non sa cosa fare, quindi l'uomo delle caverne ha bisogno di un programma informatico techno per dire a l'uomo delle caverne cosa fare.

Ingresso

L'input del tuo programma sarà una storia degli eventi che sono accaduti, dove Ssta per affilare (cioè l'uomo delle caverne ha affilato il suo bastone), Psta per colpire e Bsta per blocco. L'input sarà una cronologia di entrambe le parti (tu e l'avversario), quindi le tue mosse e quelle dell'avversario saranno separate da una virgola ( ,).

Esempio di input:

SPB,SBB

Ciò significa che il giocatore ha affilato il suo bastone, poi ha colpito, quindi bloccato, e l'avversario ha affilato, quindi bloccato, quindi bloccato di nuovo.

Non riceverai alcun input al turno 1.

Produzione

L'output è molto simile all'input (perché l'uomo delle caverne non è molto intelligente). Il tuo programma dovrebbe produrre output Sper sharpen, Ppoke e Bblock. Verrà preso in considerazione solo il primo carattere dell'output e qualsiasi altro input verrà trattato come un Bcomando (a blocchi).

  • S: Affilare

    Durante l'affilatura, la nitidezza del bastone del cavernicolo aumenta di 1 e il bastone ottiene 1 colpo in più. Ogni colpo riduce la nitidezza dello stick di 1 e se la nitidezza dello stick è 0, è troppo noioso per colpire. La nitidezza inizia da 0. Se la nitidezza arriva a 5, lo stick è una spada! (Vedi sotto.)

    Se l'avversario colpisce mentre stai affilando (e hanno una nitidezza> 0), l'avversario vince!

  • P: poke

    Quando colpisci, la nitidezza del bastone del cavernicolo scende di 1 e colpisci il tuo avversario! Se il tuo avversario si sta acuendo, vinci! Se l'avversario sta colpendo, il tuo bastone colpisce il bastone del tuo avversario ed entrambi diventano più opachi (di 1 "unità di nitidezza"). Se l'avversario sta bloccando, non succede nulla se non che il tuo bastone diventa più opaco.

    Se colpisci quando la nitidezza del tuo bastone è 5 o maggiore, il tuo bastone diventa una spada e vinci sempre ! (A meno che anche il tuo avversario non abbia una spada e abbia anche scelto P; in quel caso, entrambi diventano più opachi e possono tornare ai bastoni se la loro nitidezza scende al di sotto di 5.)

    Non puoi colpire con una nitidezza di 0. Se lo fai, non succederà nulla.

  • B: blocco

    Quando blocchi, non succede nulla quando il tuo avversario colpisce. Se il tuo avversario non sta colpendo, il blocco non fa nulla.

    Il blocco non protegge da una spada, anche se ne hai anche una!

Regole e vincoli

Regole aggiuntive sono:

  • Il vostro programma in grado di leggere e scrivere file nella sua propria cartella (non rubare!) Se si desidera salvare i dati, ma non è possibile accedere a qualsiasi cosa al di fuori di esso (e uomini delle caverne non hanno connessione ad internet nel deserto).
    • Nota importante sui file : se salvi i file, ricordati di salvarli nella directory players/YourBotsName/somefile.foo! La directory di lavoro corrente per il tuo programma non sarà quella del tuo programma!
  • I cavernicoli sono giusti: un programma non può avere un codice specifico per un altro programma e i programmi non possono aiutarsi a vicenda. (Potresti avere più programmi, ma non possono interagire tra loro in alcun modo.)
  • Il giudice cavernicolo non è paziente. Se i cavernicoli effettuano più di 100 turni ciascuno per decidere un vincitore, il giudice si annoia ed entrambi i cavernicoli perdono.

Se il tuo programma infrange una regola o non segue le specifiche, il programma viene squalificato, rimosso playerlist.txte tutti i duelli ricominciano dall'inizio. Se il tuo programma viene squalificato, il leader del cavernicolo (io!) Commenterà il post del tuo programma e spiegherà perché. Se non stai infrangendo alcuna regola, il tuo programma verrà aggiunto alla classifica. (Se il tuo programma non è nella classifica, non ci sono commenti esplicativi sul tuo post e hai pubblicato il tuo programma prima del tempo "Ultimo aggiornamento" qui sotto, dillo al leader del cavernicolo! Forse l'ha dimenticato.)

Nel tuo post, ti preghiamo di includere:

  • Un nome.
  • Un comando di shell per eseguire il programma (es. java MyBot.java, ruby MyBot.rb, python3 MyBot.py, Etc.).
    • Nota: l'input verrà aggiunto a questo come argomento della riga di comando.
    • I cavernicoli usano Ubuntu 14.04, quindi assicurati che il tuo codice funzioni (liberamente) su di esso.
  • Un numero di versione, se il codice funziona in modo diverso su versioni diverse della lingua scelta.
  • Il tuo codice (ovviamente).
  • Come compilare il codice, se necessario.

Codice controller / test, esempio bot

Il leader del cavernicolo ha scritto il codice di controllo in C ++ e lo ha pubblicato su un repository Github . È possibile eseguire e testare il programma lì.

Un programma molto, molto semplice (1 riga!) È anche pubblicato nelle risposte di seguito .

Punteggio e classifica

Il punteggio è facile. Qualunque vince l'uomo delle caverne ottiene un punto. Il cavernicolo con il maggior numero di punti dopo 3 duelli contro ogni altro uomo delle caverne diventa il nuovo leader del cavernicolo!

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

(questa classifica è stata generata automaticamente per magia)

I giocatori segnati con un *tiro hanno lanciato qualche tipo di errore o eccezione ad un certo punto; questi giocatori hanno anche un commento sui loro post.

I giocatori che non hanno potuto essere inclusi nelle prove per qualsiasi motivo (questi giocatori avranno un commento sul loro posti che spiegano il problema): Monkey, Elephant, FacileFibonacci, StudiousSylwester.

Ultimo aggiornamento: 3 ago 00:15 (UTC).


Sono sorpreso che nessuno sembra aver ancora tentato di trovare la strategia minimax. Sembra la cosa ovvia da fare.
user2357112

@ user2357112 Non penso che minimax sia un miglioramento qui. Voglio dire, potresti progettare un'implementazione minimax, ma poiché la logica è così semplice, lo stesso comportamento esatto può essere espresso con una macchina a stati finiti. (vale a dire che il robot non si affilerà mai fino a quando l'avversario non è noioso perché se lo fa, la mossa minimizzante dell'avversario sarà colpire e tu perderai, il robot si bloccherà sempre fino a quando non avremo una spada perché la mossa massimizzante per il nostro bot sarà sempre essere per bloccare, ecc.)
HuddleWolf

3
Molte voci sembrano consentire una nitidezza negativa nei loro calcoli. Le regole scritte dicono che non succede nulla quando colpisci con nitidezza zero. Questo "niente" significa anche che la nitidezza rimane zero, anziché essere diminuita?
Sparr,

6
Questo deve essere qui: dresdencodak.com/comics/2009-09-22-caveman_science_fiction.jpg Forse farà andare avanti l'immaginazione. :)
Evi1M4chine,

2
È ancora aperto? Vedo persone che aggiungono nuovi invii, ma non vedo l'aggiornamento della classifica.
ASCIIThenANSI

Risposte:


35

Darwin - C

Chi ha bisogno di strategia, comunque? Chiedi a un gruppo di uomini delle caverne di incontrarsi e lascia che la selezione naturale faccia il resto!


Usiamo un modello molto semplice per il cervello primitivo del cavernicolo: non ha memoria e tiene conto solo della nitidezza del bastone suo e del suo avversario. Quelle sono usate come variabili per un polinomio binario di un certo ordine finito. Ogni azione (blocco, nitidezza e poke) ha un polinomio associato il cui risultato determina la probabilità relativa di scegliere questa azione. È praticamente tutto quello che c'è da fare --- inizia con alcuni coefficienti casuali e ottimizza iterativamente.

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

Compilare con: gcc darwin.c -odarwin -w -O3. Corri con: ./darwin <history>.

Il bot legge i coefficienti da un file denominato programnella players/Darwindirectory (un secondo file può essere specificato come secondo argomento della riga di comando). Questo programma sembra funzionare bene:

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 

Salva come players/Darwin/program.

Di seguito è riportato un programma che genera programfile che possono essere utilizzati dal bot (non è necessario compilarlo se si utilizza il programfile sopra):

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

Compilare con: gcc genprog.c -ogenprog -w -O3. Corri con: ./genprog [output-filename].


Watson

Qual è il DNA di un uomo delle caverne vincente? Forse questo ragazzo ha la risposta:

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

Corri con: python Watson.py

Watson è il prodotto di un algoritmo genetico. A differenza di Darwin, questa volta il dato genetico è un vero programma, scritto in un linguaggio specifico per piccoli domini (qui tradotto in Python).


La sequenza semplice batte i grandi giocatori

Questo piccolo amico fa sorprendentemente (o forse non così sorprendentemente) bene, specialmente contro i leader:

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

Corri con: python SSBBP.py


Come compilo ed eseguo questo? Inoltre, come indicato nella domanda, è possibile solo leggere / scrivere file nella players/Darwindirectory.
Maniglia della porta

@Doorknob: risolto.
DarwinBot,

Ricevo questi errori di compilazione durante la compilazione di questo codice. (Sono su Ubuntu 14.04.)
Maniglia della porta

@Doorknob: risolto. Dovrebbe funzionare ora.
DarwinBot,

Ora sto ricevendo undefined reference to `fmax'. --Modifica-- Non importa, ne avevo davvero bisogno -lm.
Maniglia della porta

50

Uomo delle caverne imprevedibile

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!

Questo uomo delle caverne sceglie casualmente ogni round, ma gli ho spiegato semplicemente che certe azioni a volte non hanno senso. Sentiti libero di copiare questo codice se vuoi esprimere una logica diversa.

Questo è Ruby, salva come 'imprevedibile.rb' e corri con ruby unpredictable.rb


In realtà, penso che no 'Block'dovrebbe essere anche se il mio avversario ha una spada.
njzk2,

Il primo no 'Block' in realtà lo copre: un bastoncino appuntito non è una spada.
istocratico

2
Perché non usi unlessper le dichiarazioni no 'Block'e no 'Poke'? ( no 'Block' unless he.has_pointy_stick)
wchargin,

25

Cave Doctor - Lua

"Io perdo con nuovi stranieri, li ho buttati fuori per studiarli"

Quando hai visto tanti pazienti come il dottore delle caverne, inizi a capire veramente la psiche dell'uomo delle caverne (o almeno così spero). Il gioco del dottore delle caverne è una strategia pura, aspetta dei colpi che blocca nel tentativo di disarmare il suo avversario, ma non lascerà che l'avversario si avvicini a fare una spada. Cerca di prevedere quando è sicuro affinare in modo da non perdere il sopravvento.

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

Corri con: lua CaveDoctor.lua


3
Questo perde solo due volte nella classifica attuale? oO
solo il

La revisione 5 genera numerosi errori, quindi la revisione 4 è quella inclusa nell'attuale ciclo di prove.
Maniglia della porta

@Doorknob Penso di averli risolti tutti, comunque c'era solo una modifica alla logica attuale.
Nexus,

20

ForeignCaveman

ForeignCaveman non ha idea di quello che hai appena detto. Lui ... fa solo cose.

javac ForeignCaveman.java poi java ForeignCaveman

public class ForeignCaveman {

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

11
Questo probabilmente ha troppi voti per quanto male lo fa
Kevin L

19

Vice-capo

Doorknob ♦ è leader. Voglio essere leader! Segui il programma super intelligente per diventare leader!

Compilare: javac ViceLeader.javaRun: java ViceLeader.

public class ViceLeader {

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

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

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

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

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

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

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

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

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

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

Perché non è questo if (enemySharpness <= 4 || mySharpness >= 5)vs ==?
durron597,

@ durron597 Perché voglio colpire il nemico solo se riesce a fare una spada nel turno successivo (cosa che molto probabilmente farà). VizeLeader non colpisce spesso, lo fa al momento giusto .
CommonGuy

Ma hai una spada e il tuo avversario non ...
durron597

@ durron597 No, è un'istruzione OR. Significa "colpire l'avversario se ho una spada O se presto avrà una spada".
CommonGuy

7
Oh, mio ​​Dio. È ora di prendere un'altra tazza di caffè :) O nuove lenti a contatto
durron597

15

Forse Markov 2.1

Penso che utilizzi Markov Chains per prevedere cosa farà l'altro cavernicolo, ma ho solo guardato brevemente la pagina di Wikipedia su Markov Chains e ho deciso che aveva troppo testo.

Cerca di rimanere in vita per 30 round, quindi crea un tavolo con i cambiamenti di stato attuali e successivi e reagisce a ciò che pensa che l'altro cavernicolo farà.

Il codice contiene molte dichiarazioni non necessarie, ma funziona abbastanza bene.

MODIFICARE

Rilevato un difetto nella logica. Ora fa effettivamente qualcosa quando ha una spada.

$ python3 players/MaybeMarkov/MaybeMarkov.py

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

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

all_actions = SHARPEN, POKE, BLOCK
always = 1

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

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

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

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

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


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

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

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

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

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

if turns > 97:
    do(POKE)

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

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

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

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

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

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

counts = itemgetter(1)

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

react_on(prediction)

14

PeriodicalCicadaCaveman

Questo uomo delle caverne piuttosto intelligente ha studiato un certo Bug e si è reso conto che nessuno può adattare il proprio stile di vita per sfruttare il numero primo Cicada.

Si nasconde / blocca per gran parte della sua vita, ma a volte colpisce. Sicuramente è vulnerabile alle Spade e trascorre un intero ciclo con un bastone non affilato, ma affilando il tuo bastone quando è totalmente smussato? È esattamente quello che gli altri si aspettano da questo ... non questa cicala

compilare: mcs program.cs per eseguire 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"); 

  }

}

Modifica: ho cambiato la nitidezza-- codice ... se colpisco o vinco o il mio bastone diventa più opaco

Modifica2: aggiunto nel suggerimento di Bob

Modifica: modificato per colpire solo con nitidezza 2, se lo stick è sempre a zero, l'altro ragazzo potrebbe fare una spada.


1
Sono in esecuzione su Ubuntu; sarà compilato in Mono? In tal caso, come lo compilo e come lo eseguo?
Maniglia della porta

Ad essere sincero, non lo so. Sto per andare a letto. Posso riscriverlo a Java domani mattina al lavoro. Il codice Java dovrebbe essere quasi identico.
Mikey Mouse,

5
@Doorknob mcs program.cslo compilerà, mono programlo eseguirà, ma dovrai sostituire la foo.Dump();s con System.Console.WriteLine(foo);(o aggiungere un metodo di estensione public static void Dump(this string value) { System.Console.WriteLine(value); }).
Bob,

@Bob Grazie amico, ho aggiunto il tuo metodo di estensione.
Mikey Mouse,

Siamo spiacenti, il nome file predefinito effettivo mcsgenerato è <filename>.exe, ad esempio program.csdiventerebbe program.exe. Quindi il comando di esecuzione sarebbe mono program.exe. (Non avevo accesso al mono al momento del mio commento precedente.)
Bob

14

FancyTechnoAlgorithm

Un algoritmo di fantasia techno per il programma di fantasia computer techno.

Il cavernicolo continua a perdere la battaglia. Cavernicolo arrabbiato. Quindi l'uomo delle caverne va alla scuola di computer e impara a creare l'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"

Programma Python 2. Correre:python fancytechnoalgorithm.py


Questo si interrompe quando non c'è input (cioè al primo turno). Non so come tu voglia gestirlo, quindi dovrò escluderlo dal primo round di test.
Maniglia della porta

@Doorknob Per il primo input, è "," o ""? Immagino sia da quest'ultimo.
Vectorized

Per il primo input, non ci saranno argomenti (verrà eseguito come python StickSharpener.py).
Maniglia della porta

@Doorknob L'ho modificato. Vedi se funziona ora.
Vectorized

Va bene grazie! Lo includerò nel prossimo round di prove.
Maniglia della porta

14

L'osservatore

Guarda i movimenti del suo avversario, lasciando sempre che mostrino la loro mano prima di colpire. È particolarmente preparato per coloro che trascurano di lavorare verso una spada.

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

Nome del file: watcher.py

Correre: python watcher.py

Basilisco

Cerca di distruggere coloro che lo guardano troppo da vicino. Batte costantemente l'Osservatore, ma probabilmente peggiorerà nel complesso.

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

Nome del file: basilisk.py

Correre: python basilisk.py

Nash

Cerca di rendere irrilevanti le scelte del suo avversario, scegliendo ogni mossa con una probabilità che rappresenti i suoi rischi e benefici

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

Questo non è proprio l'equilibrio di Nash (il mio generatore di strategia ha una certa instabilità), ma è vicino.

Per curiosità, ecco le stime della probabilità che questo bot vinca in ogni stato di gioco:

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

Nome del file: nash.py

Correre: python nash.py

Finta

Si apre con un attacco rapido, per testare le difese del suo avversario.

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

Nome del file: feint.py

Correre: python feint.py

LatePokeBot

Il fratellino di PokeBot. Non mostra mai debolezza, ma cerca di combattere come suo fratello maggiore.

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

Nome del file: latepokebot.py

Correre: python latepokebot.py


Ti mancava un :a Basilisco; L'ho risolto per te
Maniglia della porta

Questa presentazione ha gettato qualche tipo di errore o eccezione ad un certo punto; potresti voler esaminare come risolverlo prima del prossimo round di prove. (quello di Basilisco)
Maniglia della porta

@Doorknob Ho scelto la sequenza di partenza per Basilisk guardando le ipotesi fatte da The Watcher e Cave Doctor e trovando una sequenza che avrebbe fatto sbagliare quelle assunzioni. Ciò viola la regola "i cavernicoli sono giusti"?
Brilliand,

Go Nash! Vinci esattamente metà delle tue partite contro tutti i robot abbastanza intelligenti da evitare le tue opzioni P = 0!
aschepler,

12

PokeBot

Scritto in Ruby.

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

Corri con ruby pokebot.rb.

Questo bot non è molto intelligente; fa quello che farebbe un uomo delle caverne medio da solo.


9

PatientWolf v2.0

Affila se è noioso, colpisce se il nemico avrà una spada il prossimo turno o se il nemico è noioso, blocca altrimenti.

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

Corri con

perl patientwolf.pl

EDIT: grazie a @sylwester per aver segnalato un bug


Dato che ottieni solo un argomento con entrambe le storie separate da virgola, lo stai analizzando erroneamente. Per esempio. PatientWolf.pl SB,SPfa Pda quando pensa di avere un bastone affilato.
Sylwester,

@Sylwester non è corretto. La prima riga assegna il primo argomento a $ me e il secondo argomento a $ lui
killmous

Il programma CavemanDuel non utilizza due argomenti, solo uno. per esempio. perl patientwolf.pl "SB,SP". Dovresti fare my($me,$him) = split/,/ $ARGV[0];e if( @ARGV ) {print "S";exit}.
Sylwester,

@Sylwester ok, vedo a cosa stai arrivando. Ciò non era chiaro dall'OP o dalla rapida occhiata che avevo lanciato al codice del controller. Lo aggiusterò tra poco
killmous

9

Cavernicolo binario

Affilare, pugnalare, ripetere

Basato sull'idea che il blocco è per femminucce, questo uomo delle caverne si alterna tra le due opzioni rimanenti.

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

Compila con javac BinaryCaveman.java

Corri con java BinaryCaveman

EDIT: Adventures in String Arrays ..... args.length () genera un errore. args.length restituisce sempre 1. args [0] .length () restituisce le lunghezze della prima stringa nell'array.

EDIT 2: aggiornato grazie all'aiuto di Doorknob, Brilliand e Sylwester. Grazie ragazzi.


@ MartinBüttner Ho dimenticato di dividere args - 1 per 2 per ottenere solo il numero di invii passati da un singolo giocatore. Risolto questo. Non riesco a capire la tesi di Dorknob, il rubino è praticamente incomprensibile per me. Il suo inizia sempre con l'affilatura?
Red_Shadow il

Sì, controlla solo se la sua ultima mossa è stata Po Sfa l'opposto. E se non c'è ancora storia, finge che la storia sarebbe P,(il che poi lo porta a fare Sprima).
Martin Ender,

Due approcci diversi che producono lo stesso risultato. È contro le regole?
Red_Shadow il

Probabilmente no, ti farei solo sapere.
Martin Ender,

2
@Doorknob Penso che dovrebbe essere args[0].length(), no args.length.
Brilliand,

8

CavekidBlocks

Un bambino delle caverne piangente e spaventato può sembrare una preda facile. Non lasciarti ingannare dal suo bel viso perché sa come bloccare.

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

Corri con python3 cavekidblocks.py

ChargerMan

Questo uomo delle caverne è molto conservatore. Proverà a caricare la sua arma e attaccherà solo quando necessario.

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)

Corri con python3 chargerman.py

imbroglione

Trickster non sa come combattere, quindi cerca di confondere l'altro cavernicolo.

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

Corri con python3 trickster.py

Sfortunatamente, dopo il commit acc74 , Trickster non funziona più come previsto.


4
Quel programma di imbroglioni è malvagio
Nexus,

@Nexus L'ho pensato anch'io. Sfortunatamente Trickster non sta andando bene nei duelli.
wendelbsilva,

7

Hodor

Hodor non è molto aggressivo. Gli piace stare nel suo scudo a meno che non ci sia una buona opportunità di colpire.

compilare con: javac Hodor.javaed eseguire con:java Hodor

codice:

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

Modifica: aggiornamento del codice minore


Questa presentazione ha gettato qualche tipo di errore o eccezione ad un certo punto; potresti voler esaminare come risolverlo prima del prossimo round di prove.
Maniglia della porta

1
Prova con SB,BB. Quando altri uomini delle caverne si comportano male al primo turno, anche Hodor si comporta male.
Sylwester,

7

Sylwester speculativo - Perl5

Sylwester speculativo vuole eliminare i cercatori di spade osservando gli schemi e colpendo quando c'è una possibilità che l'avversario si affili e affili quando l'avversario ha maggiori probabilità di bloccare. Tuttavia, non lo farà se ci sarà la possibilità che avrebbe indovinato se stesso nella fase successiva e lui sarà ancora più cauto quando decidiamo di affilare.

Per quanto riguarda quando l'avversario è schietto, cerca di essere aggressivo, ma alla fine inizierà a salvare una spada quando sembra infruttuoso.

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

Per eseguire su Linux basta aggiungere questo in playerlist.txt:

perl players/SpeculativeSylwester/SpeculativeSylwester.pl

Facile Fibonacci - Schema R6RS

Oltre alla prima mossa, Facile Fibonacci si blocca quando il turno è a numero di Fibonacci (a partire da 0) e riempie il resto con PPSS..e cambia quando passa 8 in una sequenza infinita di PSSvincere con una spada.

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

Per eseguire basta installare ikarus con apt-get install ikaruse aggiungerlo in playerlist.txt:

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

Studious Sylwester - Perl5

Studious Sylwester usa la stessa tattica di Speculative Sylwester, ma esamina anche i giochi precedenti per determinare dove avrebbe potuto fare una scelta sbagliata.

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

Per eseguire su Linux basta aggiungere questo a playerlist.txt

perl players/StudiousSylwester/StudiousSylwester.pl

Modifica studiosa

Non riesco a riprodurre i problemi che hai avuto con il $0non essere il percorso completo dello script perl quando viene eseguito con perl. Ho anche apportato le tue modifiche e non vedo cambiamenti in CavemanDuels src ed è lo stesso che ho eseguito più di 20 volte senza il problema che stai segnalando. Sto iniziando a temere che tu possa aver acquistato lo script come script bash invece di eseguirlo mentre eseguibile o come argomento per perl. Ho bisogno di maggiori informazioni per sapere con certezza. Come test ho fatto questo e puoi fare lo stesso per vedere se ottieni lo stesso risultato:

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

Lo schema non sembra voler collaborare con me sulla mia macchina, quindi non sono stato in grado di testare quello di Fibonacci. Continuerò a cercare di farlo funzionare, ma sarebbe fantastico se tu potessi tradurlo in un'altra lingua.
Maniglia della porta

Anche quello studioso non sembra funzionare, perché $0viene bashchiamato da una riga di comando bash (cosa che fa il controller). players/StudiousSylwester/foo.txtTuttavia, potresti semplicemente hardcode .
Maniglia della porta

@Doorknob Ho aggiunto come installare ikaruse ho aggiunto i miei pensieri su $0Studious.
Sylwester,

6

spadaio

Hai bisogno di un bastone affilato. Se hai un bastoncino affilato, colpisci. Non sento dolore.

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

Salva con nome swordsmith.f90e compilare con gfortran -o swordsmith swordsmith.f90, eseguire come si farebbe con qualsiasi eseguibile normale: ./swordsmith.


Questo sembra stampare uno spazio (``) prima dell'output reale. Non ho idea di come risolverlo, quindi dovrò escludere questa presentazione dal primo round di test.
Maniglia della porta

Inoltre, ho corretto il percorso del tuo file; scopre che la directory di lavoro corrente quando viene eseguita non è quella del tuo programma. Oh, e se per "nuova istanza" intendi "ogni gioco", non posso farlo perché ciò richiederebbe un involucro speciale per il programma controller; potresti volerlo fare nel tuo codice.
Maniglia della porta

@Doorknob: ho aggiornato il mio codice: l'output è un singolo carattere, elimina un file già esistente alla prima esecuzione e il file si trova nella directory del lettore.
Kyle Kanos,

Va bene grazie! Questo invio è ora incluso nella classifica.
Maniglia della porta

@Doorknob: Cool! Fa schifo che non sono il primo. Inoltre: sono abbastanza sicuro che gli utenti di Fortran siano come i vampiri, quindi sono abbastanza sicuro che inizierai presto a scrivere codice in Fortran! Muahahahaha!
Kyle Kanos,

5

PatientBlacksmith

Questo bot è scritto in R, usa Rscript PatientBlacksmith.Rper attivarlo.

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)

Misura la nitidezza dello stick dell'avversario: si blocca quando è acuto, altrimenti impiega tempo per affinare. Quando la propria nitidezza raggiunge 5, colpire fino a quando la nitidezza non è scomparsa.


Questo si interrompe quando non viene dato alcun input (cioè al primo turno); Non so come risolverlo, quindi dovrò escluderlo dal primo round di test.
Maniglia della porta

@Doorknob corretto.
plannapus,

5

Regole della prigione, Haskell

La cavernicola pensa che l'uomo delle caverne e altri uomini delle caverne dovrebbero parlare, condividere il bastone. Ma, hey ho, se deve combattere, combattere le regole della prigione. Trova il boss e attacca.

Il vice capo Alpha Caveman ora; che chi cavernicolo deve combattere. Altri uomini delle caverne combattono più tardi. Se il mio uomo delle caverne perde, non preoccuparti; anche lui troppo peloso.

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

Scritto in Haskell (vai alla programmazione funzionale!), Quindi salva come prisonrules.hs , quindi compila con:

ghc prisonrules.hs

Ed esegui come:

prisonrules [history]

4

Lo chiamo JavaMan

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

nota: non intendo giocare a code golf .. ma se sei un golfista e gli spazi / le linee extra ti fanno sanguinare gli occhi .. sentiti libero di 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;
    }
}

4
Le proposte per le sfide di King of the Hill non sono pensate per essere giocate a golf, quindi non preoccuparti. ;)
Martin Ender,

Ho cambiato il suo nome in JavaMan, perché "Caveman" è un po 'troppo generico per essere in classifica. Spero che vada bene per te; in caso contrario, basta cambiarlo in qualcos'altro.
Maniglia della porta

1
Questo si interrompe quando non viene dato alcun input (cioè al primo turno); Non so come vuoi gestirlo, quindi dovrò escluderlo dal primo round di test.
Maniglia della porta

Risolto, e il cambio di nome va bene con me
user2813274

1
Penso che tu abbia un errore nell'analizzare lo stato, sia 'io' che 'nemico' ottengono le stesse mosse: afferma [0]
Roy van Rijn

4

Pensieri profondi, C

Codice Caveman. Il cavernicolo pensa. Caveman do.

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

Io faccio dei test. Più pensieri migliori.


1
+1 per i nomi e i commenti del cavernicolo var: P Inoltre, bel programma c:
cat

3

Nigel

Nigel è un vecchio cavernicolo paziente e difensivo che preferirebbe essere tattico piuttosto che andare in attacco.

È uno script PHP, chiama 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");  
}

?>

3

Aichmophobic - Lua

Occasionalmente ti colpirà, ma solo fino a quando il bastoncino non diventerà troppo affilato. Quando ciò accade, si farà prendere dal panico e si piegherà in posizione fetale.

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)

Eseguilo con:

lua aichmophobic.lua


2
L'output deve essere in maiuscolo; L'ho risolto per te. (Inoltre, ho sbagliato a scrivere il nome di questo contributo circa mille volte.: P)
Maniglia della porta

3

Bob Caves

Bob Caves è uno dei ragazzi più intelligenti nella sua caverna. Ha imparato a contare con una mano (l'altra è occupata a tenere il suo bastone). Conosceva le Olimpiadi dell'età della pietra e voleva partecipare.

La sua strategia principale è bloccare e affinare il suo bastone fino a quando non ha un bel bastone affilato o l'altro uomo delle caverne ne ha anche uno affilato. In questo caso Bob Caves cerca di colpirlo!

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

}

Compila javac BobCaves.javae corri conjava BobCaves

Modifica: Bob ora conta quando c'è un blocco! (grazie a Mikey Mouse ). Inoltre taglierà il suo bastone quando l'altro bastone da cavernicolo è spuntato.

Modifica 2: metodo di conteggio migliorato (grazie ancora a Mikey).

Modifica 3: Rendere Bob leggermente più aggressivo.


2
Bob dimentica l'effetto di conteggio di Poke: Block sulla propria nitidezza. Tre "S" in s non significano stick 3 volte taglienti. Ogni "P" in s significa stick non affilato. Eh eh eh ... "Pee" scherzo dell'uomo delle caverne ...
Mikey Mouse

@MikeyMouse concorda Bob. Bob visiterà lo stregone per migliorare la sua tecnica. Bob grato!
Averroè,

1
Il dottore strega insegna a Bob bene. Ma dimentica di menzionare Poke: scenario Poke. Anche il bastone diventa smussato. Bob non ha bisogno di considerare la mossa dell'avversario. Se Bob Poke, il bastone diventa ottuso. O smussato: colpo dell'avversario, sul blocco avversario o sulla testa dell'avversario. Se sulla testa dell'avversario, Bob vince e può ballare intorno alla caverna con il bastone smussato.
Mikey Mouse,

1
@MikeyMouse Bob sa come contare. Bob deve imparare a leggere. Grazie ancora!
Averroè,

3

Gruntt

Gruntt è difensivo. Gruntt analizza altre mosse di uomini delle caverne per sapere come colpirle. Poi li colpisce proprio negli occhi. Gruntt non è un simpatico uomo delle caverne.

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

}

Compila javac Gruntt.javae corri conjava Gruntt


Questo lancia un ArrayOutOfBoundsExceptional primo turno e talvolta genera più azioni in altri turni.
Maniglia della porta

@Doorknob Ops! Risolto, grazie!
Averroè,

3

È un uccello? È un aereo? È RegExMan!

Cerca di analizzare le tue sequenze super noiose con la sua speciale potenza RegEx primordiale!

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

Scritto in Python 2.7, eseguito con python RegExMan.py [history]


3

Sicillian

Ma è così semplice! Tutto ciò che devo fare è divino da ciò che conosco di un altro uomo delle caverne: è lui il tipo di uomo delle caverne che bloccherebbe, affilerebbe o colpire? Ora, un abile uomo delle caverne avrebbe colpito o bloccato, perché avrebbe saputo che solo un grande sciocco si sarebbe acuito e si sarebbe esposto agli attacchi. Non sono un grande sciocco, quindi chiaramente non riesco ad affinare. Ma gli altri uomini delle caverne devono sapere che non sono un gran scemo e ci avrei contato, quindi chiaramente non posso colpire o bloccare!

Corri con:

javac Sicillian.java
java Sicillian

Codice:

public class Sicillian {

    public static void main(String[] args) {

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

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

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

            else {          // Inconceivable!

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

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

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

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

3

bash-Magnon

I magneti Bash erano robusti e potenti. Il corpo era generalmente pesante e solido con una muscolatura forte. La fronte era piuttosto diritta piuttosto che inclinata come nei Neanderthal e con solo lievi sopracciglia. La faccia era corta e larga. Il mento era prominente. La capacità del cervello era di circa 1.600 centimetri cubici (98 cu in), maggiore della media per gli umani moderni. Tuttavia, ricerche recenti suggeriscono che le dimensioni fisiche del cosiddetto "Bash-Magnon" non sono sufficientemente diverse dagli umani moderni per giustificare una designazione separata.

Ho un cervello, ricordo.

Questo è un auto-eseguibile ./bash-magnon.sh

#!/bin/bash

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

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

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

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

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

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

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

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

1+ Ovviamente hai lo strumento giusto per il lavoro e i nomi dei tuoi uomini delle caverne sono abbastanza divertenti :) (Personalmente mi piace il pesce meglio però)
Sylwester

@Sylwester Grazie, è il mio primo +1. Ho provato prima a realizzare automi omeostatici ispirati a quello che ha fatto il primo cibernetico qualcosa che sente il suo equilibrio, poi ho rinunciato e ho realizzato una sceneggiatura bash.
Emmanuel,

2

PokeBackBot

Semplicemente adattato da PokeBot:

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

Corri con ruby pokebackbot.rb.

Questo utilizza la prossima strategia più semplice e blocca "pazientemente" per un round prima di attaccare.


3
@PeterTaylor Ho letto che non mi è stato permesso di cambiare la mia strategia sulla base dell'impronta digitale dell'avversario. Se il mio invio può battere solo un altro invio, ciò non influirà sul punteggio degli altri invii e probabilmente il mio invio avrà un prezzo molto basso. Inoltre, se esiste una sola richiesta e ne viene scritta una seconda, è probabile che la seconda battuta della prima (perché altrimenti, perché preoccuparsi) - si qualifica da sola come "specifica per un altro programma"? Il mio bot batterà qualsiasi bot che inizia con SPS(il che sembra ragionevole), ma finora PokeBot era l'unico in circolazione.
Martin Ender,

2

Maestro di spada

Scritto in Python 3.4 (funziona con Python 3.x)

Cerca di ottenere una spada il più velocemente possibile, ma attacca se ha la possibilità di colpirlo (nitidezza> 0) e anche il nemico potrebbe ferirla (nitidezza nemica> 0).
Blocca solo se non ha nitidezza e il nemico può attaccare.

Iniziare con:

python3 swordmaster.py MOVES

(supponendo che lo salvi come swordmaster.py)

Codice rapido e brutto:

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

(Impostare dgsu Trueper abilitare i messaggi di debug)


1
Suggerimento: Non lasciare che battaglia stessa - che sarà risultato con S, P, S, P...
chill0r

Ho scoperto che questo succede anche con il mio. A meno che non esamini la storia o usi un certo grado di casualità, sei obbligato a rimanere bloccato in un ciclo.
Pharap,

2

FoolMeOnce.py

Salvare le mosse di ogni giocatore per il primo duello, quindi ripetere con le stesse mosse esatte. Se l'algoritmo del nemico non è casuale, possiamo prevedere lo stesso risultato e colpire solo quando sappiamo che vinceremo.

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)

Scritto in python 3, quindi molto probabilmente dovrai usare python3 FoolMeOnce.py Al primo turno, non sono sicuro se otteniamo una stringa vuota o solo una virgola, quindi potrebbero esserci delle modifiche necessarie.


Ho corretto il percorso del tuo file - risulta che l'attuale directory di lavoro non è quella del tuo programma.
Maniglia della porta

Mentre giocavo con il tester CavemanDuel, ho notato che FoolMeOnce ottiene punti migliori se uso più thread (ho testato 16 thread contro 4). Con 4 thread ottiene ~ 25 punti, con 16 ottiene ~ 34.
wendelbsilva,

Strano, non ho idea del perché.
tzazy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.