穴居人デュエル(または:私は鋭い棒であなたを突く)


151

穴居人は怒っています。他の穴居人はスティックを取るが、スティックは私のためだった。穴居人の戦い


説明

穴居人は他の穴居人を刺すために鋭い棒を必要とします。他の穴居人も鋭い棒で刺そうとします。穴居人は、棒を研いだり、棒で突いたり、つまらない棒をブロックしたりできます。

穴居人が鋭い棒で他の穴居人を突くと、他の穴居人が逃げ出し、私が勝利します。しかし、他の穴居人が私が突っ込んでいるときに賢くブロックした場合、私のスティックが鈍くなるので何も起こらず、私は再び研ぐ必要があります。

穴居人怠け者。また、穴居人のダム。穴居人は何をすべきか分からないので、穴居人は何をすべきかを穴居人に伝えるために派手なテクノコンピュータープログラムが必要です。

入力

プログラムの入力は、発生したイベントの履歴になります。ここでSは、シャープ(つまり、穴居人がスティックを研いだ)をP表し、ポークをB表し、ブロックを表します。入力は両側(あなたと相手)の履歴であるため、あなたと相手の動きはコンマ(,)で区切られます。

入力例:

SPB,SBB

これは、プレイヤーがスティックをシャープにした後、突いてブロックした後、対戦相手がシャープになってからブロックし、再びブロックしたことを意味します。

1ターン目には何も入力されません。

出力

出力は入力に非常に似ています(穴居人はあまり賢くないため)。プログラムはS、シャープ、Pポケ、およびBブロックのために出力する必要があります。出力の最初の文字のみが考慮され、その他の入力はB(ブロック)コマンドとして扱われます。

  • S:シャープ

    削ると、穴居人のスティックの切れ味が1つ上がり、スティックが1本余分に突く。突くたびにスティックの切れ味が1減り、スティックの切れ味が0の場合は、くすみすぎて突き抜けません。シャープネスは0から始まります。シャープネスが5に達すると、スティックは剣になります。(下記参照。)

    シャープニング中に相手が突く(そしてシャープネスが0より大きい)場合、相手が勝ちます!

  • P: ポーク

    突くと、穴居人のスティックの切れ味が1下がり、相手を突く!相手が研ぎ澄ましている場合、あなたは勝ちます!相手が突っ込んでいる場合、スティックは相手のスティックにぶつかり、両方が鈍くなります(「シャープネスユニット」1つ分)。相手がブロックしている場合、スティックが鈍くなる以外は何も起こりません。

    スティックの切れ味が5以上のときに突くと、スティックが剣になり、常に勝ちます!(対戦相手も剣を持っていて、選択Pした場合を除き、その場合、両者は鈍くなり、鋭さが5を下回るとスティックに戻る可能性があります。)

    0のシャープネスで突くことはできません。その場合、何も起こりません。

  • B:ブロック

    ブロックすると、相手が突くときは何も起こりません。相手が突っ込んでいない場合、ブロックは何もしません。

    ブロッキングは、剣を持っていても保護しません!

ルールと制約

追加のルールは次のとおりです。

  • データを保存したい場合、プログラムは独自のフォルダーでファイルを読み書きできます(盗むことはできません!)が、その外部にアクセスすることはできません(そして穴居人は荒野でインターネットに接続できません)。
    • ファイルに関する重要な注意ファイルを保存する場合は、必ずディレクトリに保存してくださいplayers/YourBotsName/somefile.foo!プログラムの現在の作業ディレクトリは、プログラムのものではありません!
  • 穴居人は公平です。あるプログラムは別のプログラムに固有のコードを持つことはできず、プログラムは互いに助け合うことはできません。(複数のプログラムが存在する場合がありますが、それらは互いに相互作用することはできません。)
  • 穴居人の裁判官は患者ではありません。穴居人が勝者を決定するためにそれぞれ100ターン以上かかると、裁判官は退屈し、両方の穴居人が負けます。

プログラムがルールに違反するか、仕様に準拠していない場合、プログラムは失格となり、から削除されplayerlist.txt、すべての決闘は最初から再開されます。あなたのプログラムが失格の場合、穴居人のリーダー(私!)があなたのプログラムの投稿にコメントし、その理由を説明します。ルールに違反していない場合、プログラムはリーダーボードに追加されます。(あなたのプログラムがリーダーボードにない場合、あなたの投稿に説明的なコメントはなく、あなたは以下の「最終更新」時間の前にあなたのプログラムを投稿しました、穴居人のリーダーに伝えてください!たぶん彼はそれを忘れました。)

投稿に以下を含めてください:

  • 名前。
  • あなたのプログラム(例:実行するシェルコマンドjava MyBot.javaruby MyBot.rbpython3 MyBot.py、など)。
    • 注:入力はコマンドライン引数としてこれに追加されます。
    • 穴居人はUbuntu 14.04を使用しているため、コードが(自由に)動作することを確認してください。
  • 選択した言語のバージョンによってコードの動作が異なる場合は、バージョン番号。
  • あなたのコード(明らかに)。
  • 必要に応じて、コードをコンパイルする方法。

コントローラーコード/テスト、サンプルボット

穴居人のリーダーは、制御コードをC ++ で作成し、Githubリポジトリに投稿しました。そこでプログラムを実行およびテストできます。

非常単純なプログラム(1行!)も以下の回答に掲載されています

スコアリングとリーダーボード

スコアリングは簡単です。穴居人が勝つとポイントが得られます。他のすべての穴居人との3つの決闘の後、最もポイントを持つ穴居人が新しい穴居人のリーダーになります!

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

(このリーダーボードは自動的に生成されました)

*ある時点で何らかのエラーまたは例外がスローされたプレーヤー。これらのプレーヤーは自分の投稿にもコメントを持っています。

何らかの理由でテストに含めることができませんでしプレーヤー(これらのプレーヤーは、問題を説明する自分の投稿にコメントがあります): 、MonkeyElephant、。FacileFibonacciStudiousSylwester

最終更新:8月3日00:15(UTC)。


誰もミニマックス戦略を見つけようとしていないようです。当然のように思えます。
user2357112 14

@ user2357112ここでミニマックスが改善されるとは思わない。つまり、ミニマックス実装を設計することはできますが、ロジックは非常に単純なので、同じ状態を有限状態マシンで表現できます。(つまり、ボットは、相手が鈍くなるまで鋭くなりません。もしそうなら、相手の最小化の動きは突くため、あなたは負け、ボットの最大化の動きは常にあるため、ボットは常に剣を持つまでブロックしますブロックするなど)
HuddleWolf 14

3
エントリの多くは、計算でマイナスのシャープネスを考慮しているようです。書かれているルールでは、シャープネスをゼロにして突くと何も起こらないと書かれています。「何もない」ということは、デクリメントされる代わりに、シャープネスがゼロのままであることを意味しますか?
スパー

6
これここにある必要があります:dresdencodak.com/comics/2009-09-22-caveman_science_fiction.jpg たぶんそれは想像力を働かせます。:)
Evi1M4chine 14

2
これはまだ開いていますか?新しい投稿を追加する人がいますが、リーダーボードが更新されていません。
ASCIIThenANSI

回答:


35

ダーウィン-C

とにかく、誰が戦略を必要としますか?穴居人のグループにお互いに行き、自然選択に任せましょう!


穴居人の原始的な頭脳には非常に単純なモデルを使用します。記憶はなく、相手と相手のスティックの鋭さだけを考慮します。これらは、有限次数のバイナリ多項式の変数として使用されます。各アクション(ブロック、シャープ、ポーク)には関連付けられた多項式があり、その結果により、このアクションを選択する相対的な確率が決まります。これでほとんどすべてです。ランダム係数から始めて、繰り返し最適化します。

ボット:

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

でコンパイルしますgcc darwin.c -odarwin -w -O3。で実行します./darwin <history>

ボットprogramは、players/Darwinディレクトリで指定されたファイルから係数を読み取ります(別のファイルを2番目のコマンドライン引数として指定できます)。このプログラムはうまくいくようです:

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 

として保存しplayers/Darwin/programます。

以下は、programボットが使用できるファイルを生成するプログラムです(program上記のファイルを使用する場合、コンパイルする必要はありません)。

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

でコンパイルしますgcc genprog.c -ogenprog -w -O3。で実行します./genprog [output-filename]


ワトソン

勝利の穴居人のDNAとは何ですか?おそらく、このフェラには答えがあります:

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

で実行: python Watson.py

ワトソンは遺伝的アルゴリズムの産物です。ダーウィンとは異なり、今回の遺伝データは実際のプログラムであり、小さなドメイン固有の言語(ここではPythonに翻訳されています)で記述されています。


単純なシーケンスが大きなプレーヤーを打ち負かす

この小さなファラは、特にリーダーに対して、驚くほど(あるいは、それほど驚くほどではないかもしれません)うまくいきます。

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

で実行: python SSBBP.py


これをコンパイルして実行するにはどうすればよいですか?また、質問で述べたように、players/Darwinディレクトリ内のファイルの読み取り/書き込みのみが可能です。
ドアノブ

@Doorknob:修正されました。
DarwinBot 14

私は取得していますこれらのコンパイルエラーをこのコードをコンパイルするとき。(私はUbuntu 14.04を使用しています。)
ドアノブ

@Doorknob:修正されました。今すぐ動作するはずです。
DarwinBot 14

私は今得ていundefined reference to `fmax'ます。-編集-気にしないで、私は本当に必要-lmでした。
ドアノブ

50

予測不可能な穴居人

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!

この穴居人はラウンドごとにランダムに選択しますが、特定のアクションは時々意味をなさないことが非常に簡単に彼に説明しました。別のロジックを表現する場合は、このコードを自由にコピーしてください。

これはRubyで、「unpredictable.rb」として保存して実行します ruby unpredictable.rb


実際、no 'Block'相手が剣を持っている場合もそうすべきです。
njzk2

最初の「ブロック」は実際にはそれをカバーしていません。先のとがった棒は剣ではありません。
histocrat

2
なぜあなたは使用していないunlessためno 'Block'no 'Poke"文?(no 'Block' unless he.has_pointy_stick
wchargin 14

25

洞窟の医者-ルア

「私は新しい外国人に負け、彼らをノックアウトして勉強した」

あなたが洞窟の医者と同じくらい多くの患者を見たとき、あなたは洞窟の男の精神を本当に理解し始めます(または私はそう願っています)。洞窟の医者のゲームは純粋な戦略であり、彼は敵を武装させようとブロックするポークを待ちますが、彼はその敵が剣を作るのに近づけさせません。彼は、上手が緩まないように、いつ研ぐことが安全であるかを予測しようとします。

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

で実行: lua CaveDoctor.lua


3
これは、現在のリーダーボードで2回しか失われませんか?オブジェクト指向
justhalf

リビジョン5は多数のエラーをスローするため、リビジョン4は現在の試行に含まれています。
ドアノブ

@Doorknob私はそれらのすべてを修正したと思う、とにかく実際のロジックへの変更は1つだけだった。
ネクサス14

20

外国人穴居人

ForeignCavemanはあなたが今言ったことを知らない。彼はただ...何かをします。

javac ForeignCaveman.java それから 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
これはおそらく、それがどれほど悪いかについてあまりにも多くの賛成票を持っています
ケビンL 14

19

副リーダー

Doorknob♦はリーダーです。私はリーダーになりたい!スーパーインテリジェントプログラムをフォローしてリーダーになろう!

コンパイル:javac ViceLeader.java実行: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;
    }
}

なぜこれがないですif (enemySharpness <= 4 || mySharpness >= 5)==
durron597 14

@ durron597なぜなら、次のターンに敵が剣を作ることができる場合にのみ敵を突くからです(彼はおそらくそうするでしょう)。VizeLeaderは頻繁に突くのではなく、適切なタイミングで実行します。
CommonGuy 14

しかし、あなたは剣を持っているし、あなたの対戦相手は...ない
durron597

@ durron597いいえ、ORステートメントです。それは「私が剣を持っている場合、または彼がすぐに剣を持っている場合、相手を突く」ことを意味します。
CommonGuy 14

7
いいね コーヒーをもう一杯飲む時間:)または新しいコンタクトレンズ
durron597 14

15

たぶんマルコフ2.1

マルコフ連鎖を使用して他の穴居人が何をするかを予測すると思いますが、マルコフ連鎖に関するウィキペディアのページを簡単に見て、テキストが多すぎると判断しました。

30ラウンドの間生き続けることを試み、次に現在の状態の変化を含むテーブルを構築し、他の穴居人が行うと思われることに反応します。

コードには多くの不要なステートメントが含まれていますが、パフォーマンスは非常に良好です。

編集

ロジックの欠陥を検出しました。今では実際に剣を持っているときに何かをします。

$ 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

定期的なC穴居人

このかなり賢い洞窟の男は、特定のバグを研究し、素数のセミを活用するために誰もライフスタイルを調整できないことに気付きました。

それは人生のほとんどを隠し/ブロックしますが、時々突く。確かにそれはSwordsに対して脆弱であり、シャープでないスティックでサイクル全体を過ごしますが、完全に鈍いときにスティックをシャープにしますか?それはまさに他の人がそれから期待することです...このCではありません

コンパイルするには:mcs program.csmono 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"); 

  }

}

編集:シャープネスを変更しました-コード...突くか勝つか、スティックが鈍くなる場合

編集2:ボブスの提案に追加

編集:シャープネス2のときにのみ突くように変更しました。スティックがゼロになると、他の男が剣を作る可能性があります。


1
Ubuntuで実行しています。これはMonoでコンパイルされますか?もしそうなら、どのようにコンパイルし、どのように実行しますか?
ドアノブ

正直に言うと、私は知りません。私はちょうどベッドに向かいます。明日の朝、仕事でJavaに書き換えることができます。Javaコードはほぼ同じである必要があります。
マイキーマウス14

5
@Doorknob mcs program.csはそれをコンパイルし、mono program実行しますが、foo.Dump();s を置き換えるSystem.Console.WriteLine(foo);(または拡張メソッドを追加するpublic static void Dump(this string value) { System.Console.WriteLine(value); })必要があります。
ボブ14

@Bobありがとう、バディ、拡張メソッドに追加しました。
マイキーマウス14

申し訳ありませんが、実際のデフォルトのファイル名がmcs生成され<filename>.exe、例えばprogram.csになりますprogram.exe。したがって、実行コマンドはになりますmono program.exe。(以前のコメントの時点でモノにアクセスできませんでした。)
ボブ14

14

ファンシーテクノアルゴリズム

ファンシーテクノコンピュータープログラム用のファンシーテクノアルゴリズム。

穴居人は戦いに負け続けます。穴居人は怒っています。だから穴居人はコンピュータースクールに行くアルゴリズムを学びます。

import random, sys  # Need import some advanced techno code

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

    try:  # Me try use fancy techno algorithm!

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

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

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

Python 2プログラム。走る:python fancytechnoalgorithm.py


これは、入力がない場合(つまり、最初のターン)に中断します。どうやってそれを処理したいかわからないので、最初のテストから除外する必要があります。
ドアノブ

@Doorknob最初の入力では、「、」または「」ですか?それから後者だと思います。
ベクトル化

最初の入力については、引数はありません(として実行されますpython StickSharpener.py)。
ドアノブ

@Doorknob編集しました。動作するか確認してください。
2014

わかりました、ありがとう!これは次のトライアルに含めます。
ドアノブ

14

ウォッチャー

彼は相手の動きを監視し、攻撃する前に常に相手に手を見せます。彼は特に剣に向かって働くことを怠る人々のために準備されています。

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

ファイル名: watcher.py

走る: python watcher.py

バジリスク

彼をあまりにも近くで見ている人々を破壊しようとしています。常にウォッチャーを倒しますが、おそらく全体的に悪化します。

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

ファイル名: basilisk.py

走る: python basilisk.py

ナッシュ

リスクと報酬を考慮した確率で各移動を選択することにより、相手の選択を無関係にしようとする

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

これはナッシュ均衡ではありません(私の戦略ジェネレーターは不安定です)が、近いです。

好奇心のために、ゲームの各状態でこのボットが勝つ可能性の推定値を以下に示します。

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

ファイル名: nash.py

走る: python nash.py

フェイント

簡単な攻撃で開き、相手の防御をテストします。

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

ファイル名: feint.py

走る: python feint.py

LatePokeBot

PokeBotの弟。弱さを示すことはありませんが、兄のように戦おうとします。

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

ファイル名: latepokebot.py

走る: python latepokebot.py


:バシリスクで行方不明になりました。あなたのためにそれを修正しました
ドアノブ

この送信は、ある時点で何らかのエラーまたは例外をスローしました。次の試行の前に修正することを検討してください。(バジリスク1)
ドアノブ

@Doorknob The WatcherとCave Doctorが行った仮定を見て、それらの仮定がひどく間違ってしまうシーケンスを見つけることで、バシリスクの開始シーケンスを選択しました。それは「穴居人は公正」という規則に違反していますか?
ブリリアンド14

ナッシュに行こう!P = 0オプションを回避するのに十分なほどスマートにすべてのボットに対してマッチの半分を獲得してください!
アシェプラー14

12

PokeBot

Rubyで書かれています。

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

で実行しruby pokebot.rbます。

このボットはあまり賢くありません。とにかく、それは平均的な穴居人が自分で何をするかについてです。


9

PatientWolf v2.0

鈍い場合は鋭くし、次のターンに敵が剣を持つか突くか、敵が鈍い場合はブロックします。

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

で実行

perl patientwolf.pl

編集:バグを指摘してくれた@sylwesterに感謝


コンマで区切られた両方の履歴を持つ1つの引数のみを取得するため、間違って解析しています。例えば。それはそれは鋭いスティックを持っていると考えているので。PatientWolf.pl SB,SPP
シルウェスター

@Sylwesterそれは正しくありません。最初の行は、私と彼を$ 2番目の引数$する最初の引数を割り当て
killmous

CavemanDuelプログラムは2つの引数を使用せず、1つだけを使用します。例えば。perl patientwolf.pl "SB,SP"。あなたがする必要がmy($me,$him) = split/,/ $ARGV[0];ありif( @ARGV ) {print "S";exit}ます。
シルウェスター14

@Sylwesterわかりました、私はあなたが得ているものを見る。これは、OPからも、コントローラーコードを一目見ただけでも明らかではありませんでした。私はすぐにそれを修正します
殺人14

9

バイナリ穴居人

シャープ、刺し、繰り返し

ブロッキングはシシスのためであるという考えに基づいて、この穴居人は残りの2つのオプションを交互に使用します。

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

コンパイルする javac BinaryCaveman.java

で実行 java BinaryCaveman

編集:文字列配列の冒険..... args.length()はエラーをスローします。args.lengthは常に1を返します。args[0] .length()は、配列の最初の文字列の長さを返します。

編集2: Doorknob、Brilliand、Sylwesterの支援により更新されました。みんなありがとう。


@MartinBüttnerargsを1から2で除算するのを忘れて、1人のプレーヤーによる過去の提出数のみを取得しました。それを修正しました。私はドルクノブの提案を理解することはできません。ルビーは私にとって実質的に意味不明です。彼はいつも研ぎ始めますか?
Red_Shadow 14

はい、彼はちょうど彼の最後の動きがあったかどうかチェックしPたりS、反対を行います。そして、まだ歴史がない場合、彼は歴史がそうであるふりをしますP,(そして、それは彼をS最初にするように導きます)。
マーティンエンダー14

同じ出力をもたらす2つの異なるアプローチ。それはルールに反していますか?
Red_Shadow 14

おそらくそうではない、私はあなたに知らせたいと思います。
マーティンエンダー14

2
@Doorknob私はそれがあるべきだと思うargs[0].length()、ではないargs.length
ブリリアンド14

8

CavekidBlocks

泣いておびえた洞窟の子供は、簡単な獲物のように見えるかもしれません。彼がブロックする方法を知っているので、彼のかわいい顔にだまされてはいけません。

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

で実行 python3 cavekidblocks.py

ChargerMan

この穴居人は非常に保守的です。彼の武器を充電しようとし、必要なときにのみ攻撃します。

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)

で実行 python3 chargerman.py

トリックスター

トリックスターは戦う方法を知らないので、他の穴居人を混乱させようとします。

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

で実行 python3 trickster.py

残念ながら、コミットacc74の後、Tricksterは計画どおりに動作しなくなりました。


4
そのトリックスタープログラムは悪である
ネクサス

@Nexus私もそうです。残念ながら、Tricksterは決闘でうまくいっていません。
wendelbsilva 14

7

ホドル

Hodorはそれほど攻撃的ではありません。彼は攻撃する良い機会がない限り、彼の盾にとどまるのが好きです。

でコンパイル:javac Hodor.javaで実行:java Hodor

コード:

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

編集:マイナーコードの更新


この送信は、ある時点で何らかのエラーまたは例外をスローしました。次の試行の前に修正することを検討してください。
ドアノブ

1
でお試しくださいSB,BB。他の穴居人が最初のターンで誤動作するとき、ホドールも誤動作します。
シルウェスター14

7

投機的シルウェスター-Perl5

投機的シルウェスターは、パターンを見て剣を探している人を排除し、対戦相手がブロックする可能性が最も高いときに相手が研ぎ澄ませる可能性があるときに突くことを望んでいます。ただし、次の動きで自分がシャープになると推測する可能性がある場合、彼はそれを行いません。シャープにすることに決めた場合、さらに慎重になります。

相手が鈍いときは、彼は攻撃的になろうとしますが、最終的には無駄に思えたときに剣を貯め始めます。

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

Linuxで実行するには、playerlist.txtにこれを追加するだけです:

perl players/SpeculativeSylwester/SpeculativeSylwester.pl

簡単なフィボナッチ-R6RSスキーム

最初の動きに加えて、ターンがフィボナッチ数(0から始まる)である場合にFacile Fibonacciがブロックし、剣で勝つためにPPSS..8を無限のシーケンスに渡すときに残りを埋め、変更しPSSます。

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

実行するには、ikarusをインストールしてplayerlist.txtにapt-get install ikarus追加します:

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

Studious Sylwester-Perl5

Studious Sylwesterは投機的Sylwesterと同じ戦術を使用しますが、以前のゲームを見て、間違った選択をした可能性のある場所を判断します。

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

Linuxで実行するには、これをplayerlist.txtに追加するだけです

perl players/StudiousSylwester/StudiousSylwester.pl

熱心な編集

$0perlをperlで実行すると、perlスクリプトへの完全なパスではないという問題を再現できません。私もあなたの変更を引っ張りました、そして、私はCavemanDuels srcに何の変化も見ません、そして、それはあなたが報告している問題なしで20回以上実行したのと同じです。スクリプトを実行中に実行したり、perlの引数として実行するのではなく、bashスクリプトとしてソース化したのではないかと心配し始めています。実際に確実に知るためにはもっと情報が必要です。テストとしてこれを行いました。同じ結果が得られるかどうかを確認するために同じことを行うことができます。

echo '#!/usr/bin/perl
print "$0\n\n";' > testcmd.pl;
perl ./testcmd.pl;           # outputs ./testcmd.pl
bash -c "perl ./testcmd.pl"; # outputs ./testcmd.pl
bash -c ./testcmd.pl;        # outputs an error since it's not executable
chmod 755 ./testcmd.pl;
./testcmd.pl;                # outputs ./testcmd.pl
bash -c ./testcmd.pl;        # outputs ./testcmd.pl since it's executable

Schemeは私のマシン上で私と協力したくないようですので、私はフィボナッチのものをテストすることができませんでした。私はそれを機能させようとし続けますが、別の言語に翻訳できたら素晴らしいと思います。
ドアノブ

ため勤勉1はまた、動作するようには思えない$0bash(コントローラはありません)bashコマンドラインから呼び出された場合。players/StudiousSylwester/foo.txtただし、ハードコードすることもできます。
ドアノブ

@Doorknobインストール方法をikarus追加し$0、Studious についての考えを追加しました。
シルウェスター14

6

ソードスミス

鋭い棒が必要です。鋭い棒があれば、突く。私は痛みを感じません。

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

として保存しswordsmith.f90、でコンパイルしgfortran -o swordsmith swordsmith.f90ます./swordsmith。通常の実行可能ファイルと同じように実行します。


これは、実際の出力の前にスペース( ``)を印刷するように見えます。私はそれを修正する方法がわからないので、この提出物を最初のテストから除外する必要があります。
ドアノブ

また、ファイルパスを修正しました。実行時に現在の作業ディレクトリプログラムのものではないことがわかります。ああ、「新しいインスタンス」で「各ゲーム」を意味する場合、コントローラープログラムの特別なケーシングが必要になるため、私はそれを行うことができません。あなたはあなた自身のコードでそれをしたいかもしれません。
ドアノブ

@Doorknob:コードを更新しました。出力は単一の文字で、最初の実行時に既存のファイルを削除し、ファイルはプレーヤーディレクトリにあります。
カイルカノス14

わかりました、ありがとう!この投稿は、リーダーボードに含まれています。
ドアノブ

@Doorknob:クール!私は最初ではないことを吸います。また、FortranユーザーはVampiresに似ていると確信しているので、Fortranですぐにコーディングを開始することになると確信しています。ムアハハハハ!
カイルカノス14

5

患者の鍛冶屋

このボットはRで記述されており、使用Rscript PatientBlacksmith.Rしてトリガーします。

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)

相手のスティックの鋭さを測定します。鋭い場合はブロックし、そうでない場合は時間をかけてシャープにします。自分のシャープネスが5に達したら、シャープネスがなくなるまで突く。


これは、入力がない場合(つまり、最初のターン)に壊れます。修正方法がわからないので、テストの第1ラウンドから除外する必要があります。
ドアノブ

@Doorknobが修正されました。
plannapus 14

5

刑務所規則、ハスケル

穴居人は、穴居人と他の穴居人が話をするべきだと思います。しかし、ほらほら、もし戦わなければならないなら、刑務所のルールと戦ってください。ボスを見つけて攻撃してください。

ViceLeader Alpha Cavemanになりました。穴居人が戦わなければならないこと。他の穴居人は後で戦う。穴居人が負けても心配はありません。とにかく毛深い。

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

Haskellで書かれているので(関数型プログラミングを行ってください!)、prisonrules.hsとして保存し、次のようにコンパイルします:

ghc prisonrules.hs

そして次のように実行します:

prisonrules [history]

4

私は彼をJavaManと呼んでいます

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

注:私はコードゴルフをするつもりはありません。しかし、もしあなたがゴルファーであり、スペース/余分な線が目を出血させるなら..気軽に変えてください。

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
キングオブザヒルチャレンジへの応募はゴルフを目的としたものではないため、心配しないでください。;)
マーティン・エンダー14

「Caveman」は少し汎用的すぎてリーダーボードに入れることができないため、その名前をJavaManに変更しました。うまくいけばそれでいいです。そうでない場合は、それを別のものに変更します。
ドアノブ

1
これは、入力がない場合(つまり、最初のターン)に壊れます。どのようにそれを処理するのかわからないので、最初のテストから除外する必要があります。
ドアノブ

固定、および名前の変更は、私と罰金です
user2813274

1
[0]の状態:私は両方の「私」と「敵」は同じ動きを取得し、あなたが状態を解析して間違いを持っていると思う
ロイ・バン・レイン

4

深い思考、C

穴居人のコード。穴居人は思う。穴居人がやる。

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

私はテストを行います。より多くの考え。


1
穴居人のvar名とコメントの+1:Pまた、素敵なプログラムc:
cat

3

ナイジェル

ナイジェルは、攻撃に全力を尽くすよりも戦術的になる忍耐強く防御的な古い穴居人です。

PHPスクリプトです。 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

愛情恐怖症-ルア

彼は時々あなたを突くでしょうが、スティックが鋭くなりすぎるまでです。これが起こると、彼はパニックを起こし、胎児の位置にカールします。

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)

以下で実行します:

lua aichmophobic.lua


2
出力は大文字にする必要があります。私はあなたのためにそれを修正しました。(また、私はこの提出の名前のスペルを千回も間違えました。:P)
ドアノブ

3

ボブ洞窟

ボブ洞窟は、彼の洞窟で最も賢い男の一人です。彼は片手で数えることを学びました(もう片方はスティックを握るのに専念しています)彼はこの石器時代のオリンピックを知っており、参加したいと考えていました。

彼の主な戦略は、彼が素敵な鋭利なスティックを持っているか、他の穴居人が鋭いスティックを持っているまで、彼のスティックをブロックしてシャープにすることです。この場合、ボブ・ケイブスは彼を突くように試みます!

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

}

でコンパイルしjavac BobCaves.javaて実行java BobCaves

編集:ボブはブロックがあるときにカウントするようになりました!(Mikey Mouseに感謝)。また、他の穴居人の棒が鈍いとき、彼は彼の棒を鋭くします。

編集2:カウント方法の改善(マイキーのおかげ)。

編集3:ボブを少し攻撃的にします。


2
ボブは、自分のスティックの鋭さに対するPoke:Blockのカウント効果を忘れます。sの3つの「S」は、3倍の鋭さを意味しません。sのすべての「P」は、シャープでないスティックを意味します。ハァッハァッ…「おしっこ」の洞窟の男の冗談...
マイキーマウス14

@MikeyMouseボブは同意します。ボブは魔女の医者を訪ねてテクニックを向上させます。ボブは感謝します!
アベロス14

1
魔女の医者はボブに良い教えます。しかし、彼はPoke:Pokeシナリオに言及するのを忘れています。スティックも鈍くなります。ボブは、相手の動きを考慮する必要はありません。ボブ・ポケの場合、スティックは鈍くなる。鈍く:相手が突く、相手のブロック、または相手の頭に。相手の頭にいる場合、ボブが勝ち、鈍い棒で洞窟の周りを踊ることができます。
マイキーマウス14

1
@MikeyMouseボブは数える方法を知っています。ボブは読むことを学ぶ必要があります。再度、感謝します!
アベロス14

3

グラント

Grunttは防御的です。Grunttは他の穴居人の動きを分析して、それらを突く方法を知ります。それから彼は目でそれらを突きます。Grunttはいい穴居人ではありません。

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

}

でコンパイルしjavac Gruntt.javaて実行java Gruntt


これArrayOutOfBoundsExceptionは最初のターンでをスローし、時には他のターンで複数のアクションを出力します。
ドアノブ

@Doorknob Ops!修正済み、ありがとう!
アヴェローズ14

3

それは鳥ですか?飛行機ですか?RegExManです!

彼は彼の特別な原始RegEx-powerであなたの超退屈なシーケンスを分析しようとします!

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

Python 2.7で記述され、次で実行 python RegExMan.py [history]


3

シシリアン

しかし、それはとても簡単です!私がしなければならないことは、私が他の穴居人について知っていることから神聖なことです:彼は、ブロック、シャープ、または突く穴居人の一種ですか?さて、賢い穴居人は突っ込んだりブロックしたりします。なぜならば、偉大な愚か者だけが鋭くなり、攻撃にさらされることを知っているからです。私は大バカではないので、はっきりとは言えません。しかし、他の穴居人は、私が偉大な愚か者ではないことを知っている必要があり、それに頼っていたので、私は明らかに突くかブロックすることはできません!

で実行:

javac Sicillian.java
java Sicillian

コード:

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は堅牢に構築され、強力でした。体は一般的に重くて硬く、強い筋肉組織でした。額はネアンデルタール人のように傾斜しているのではなく、かなり真っ直ぐで、わずかな眉毛しかありませんでした。顔は短くて広い。あごが目立った。脳の容量は約1,600立方センチメートル(98立方インチ)で、現代の人間の平均よりも大きかった。しかし、最近の研究では、いわゆる「バッシュ・マニョン」の物理的寸法は、現代の人間とは十分に異なるものではなく、個別の指定が必要であることが示唆されています。

私は脳を持っている、私は覚えている。

これは自己実行可能です ./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+明らかに仕事に適したツールがあり、穴居人の名前は非常に面白いです:)(個人的には魚が好きです)
シルウェスター14

@Sylwesterありがとう、それが私の最初の+1です。最初に、最初のサイバネティシャンが自分自身のバランスを感じるものに触発された恒常性オートマトンを作ろうとした後、triedめてスクリプトを作成しました。
エマニュエル14

2

PokeBackBot

PokeBotから単純に適応:

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

で実行しruby pokebackbot.rbます。

これは、次の最も単純な戦略を使用し、攻撃の前に1ラウンドの間「患者」をブロックします。


3
@PeterTaylor相手のフィンガープリントに基づいて戦略を切り替えることは許可されていないと読みました。私の提出物が他の提出物を1つしか打ち負かすことができなければ、それは他の提出物のスコアに実際には影響せず、おそらく私自身の提出物は非常にひどくうまくいくでしょう。さらに、提出物が1つだけで、2つ目の提出物が書かれている場合、2つ目の提出物は最初の提出物よりも勝つ可能性が高くなります(そうでなければ、なぜわざわざ)私のボットはSPS(合理的と思われる)で始まるすべてのボットを倒しますが、これまでのところPokeBotが唯一のボットでした。
マーティンエンダー14

2

ソードマスター

Python 3.4で書かれています(Python 3.xで動作します)

できるだけ早く剣を手に入れようとしますが、攻撃する機会があり(鋭さ> 0)、敵も傷つける可能性がある場合(敵の鋭さ> 0)に攻撃します。
鋭さがなく、敵が攻撃できる場合にのみブロックします。

皮切りに:

python3 swordmaster.py MOVES

(として保存すると仮定しますswordmaster.py

すばやくandいコード:

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

(デバッグメッセージを有効dgTrueするように設定)


1
ヒント:それは自分自身と戦う聞かせてはいけない-それはでデッドロックよSPSP...
chill0r

私もこれが私のものだとわかりました。履歴を調べたり、ある程度のランダム性を使用しない限り、サイクルに巻き込まれます。
ファラプ14

2

FoolMeOnce.py

最初の決闘で各プレイヤーの動きを保存してから、まったく同じ動きでリプレイします。敵のアルゴリズムがランダムでない場合、同じ結果を予測し、勝つことがわかっている場合にのみ攻撃することができます。

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)

python 3で書かれているので、おそらくpython3 FoolMeOnce.pyを使用する必要があります。 最初のラウンドでは、空の文字列を取得するのかコンマだけを取得するのかがわからないため、微調整が必​​要になる場合があります。


ファイルパスを修正しました-現在の作業ディレクトリはプログラムのものではないことがわかりました。
ドアノブ

CavemanDuelテスターで遊んでいるときに、より多くのスレッドを使用するとFoolMeOnceがより良いポイントを獲得することに気付きました(4に対して16スレッドをテストしました)。4スレッドでは最大25ポイント、16スレッドでは最大34ポイントになります。
wendelbsilva 14

奇妙なことに、なぜそうなるのかわかりません。
tzazy 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.