Caveman Duels (hoặc: Tôi chọc bạn bằng cây gậy sắc nhọn)


151

Caveman điên. Người thượng cổ khác cầm gậy nhưng dính là cho tôi. Caveman chiến đấu !


Sự miêu tả

Caveman cần gậy sắc để đâm người thượng cổ khác. Những người thượng cổ khác cũng cố gắng đâm bằng cây gậy sắc nhọn. Caveman có thể mài gậy, chọc bằng gậy hoặc chặn gậy poky.

Nếu thượng cổ chọc người thượng cổ khác bằng cây gậy sắc nhọn, người thượng cổ khác bỏ chạy và tôi chiến thắng. Nhưng nếu người thượng cổ khác thông minh chặn khi tôi chọc, không có gì xảy ra ngoại trừ cây gậy của tôi trở nên cùn và tôi cần phải mài lại.

Caveman lười biếng. Ngoài ra, thượng cổ câm. Caveman không biết phải làm gì, vì vậy caveman cần chương trình máy tính kỹ thuật ưa thích để nói với caveman phải làm gì.

Đầu vào

Đầu vào của chương trình của bạn sẽ là một lịch sử của các sự kiện đã xảy ra, trong đó Stượng trưng cho sự sắc nét (tức là người thượng cổ đã mài cây gậy của mình), Pviết tắt của poke và Blà viết tắt của khối. Đầu vào sẽ là lịch sử của cả hai bên (bạn và đối thủ), do đó, di chuyển của bạn và đối thủ sẽ được phân tách bằng dấu phẩy ( ,).

Ví dụ đầu vào:

SPB,SBB

Điều này có nghĩa là người chơi mài cây gậy của mình, sau đó chọc, rồi chặn và đối thủ mài, rồi chặn, rồi lại bị chặn.

Bạn sẽ không nhận được đầu vào trong lượt 1.

Đầu ra

Đầu ra rất giống với đầu vào (vì caveman không thông minh lắm). Chương trình của bạn sẽ xuất ra Sđể làm sắc nét, Pcho chọc và Bcho khối. Chỉ có ký tự đầu tiên của đầu ra sẽ được tính đến và bất kỳ đầu vào nào khác sẽ được coi là Blệnh (chặn).

  • S: làm sắc nét

    Khi mài, độ sắc nét của gậy của người thượng cổ tăng thêm 1 và cây gậy được thêm 1 lần chọc. Mỗi lần chọc làm giảm độ sắc nét của que đi 1 và nếu độ sắc nét của gậy là 0, thì quá buồn để chọc. Độ sắc nét bắt đầu từ 0. Nếu độ sắc nét đạt đến 5, cây gậy là một thanh kiếm! (Xem bên dưới.)

    Nếu đối thủ chọc vào trong khi bạn đang mài (và họ có độ sắc nét> 0), đối thủ sẽ thắng!

  • P: chọc

    Khi chọc, độ sắc nét của gậy thượng cổ giảm đi 1 và bạn chọc đối thủ! Nếu đối thủ của bạn đang sắc bén, bạn thắng! Nếu đối thủ chọc, gậy của bạn chạm vào gậy của đối thủ và cả hai sẽ mờ hơn (bằng 1 "đơn vị sắc nét"). Nếu đối thủ đang chặn, không có gì xảy ra ngoại trừ việc cây gậy của bạn trở nên buồn tẻ hơn.

    Nếu bạn chọc khi độ sắc nét của cây gậy của bạn là 5 hoặc lớn hơn, cây gậy của bạn sẽ trở thành một thanh kiếm và bạn luôn chiến thắng! (Trừ khi đối thủ của bạn cũng có một thanh kiếm và cũng đã chọn P; trong trường hợp đó, cả hai đều trở nên đờ đẫn hơn và có thể trở lại gậy nếu độ sắc nét của chúng giảm xuống dưới 5.)

    Bạn không thể chọc với độ sắc nét bằng 0. Nếu bạn làm thế, sẽ không có gì xảy ra.

  • B: khối

    Khi bạn chặn, không có gì xảy ra khi đối thủ của bạn chọc. Nếu đối thủ của bạn không chọc, chặn không làm gì cả.

    Chặn không bảo vệ chống lại một thanh kiếm, ngay cả khi bạn cũng có một!

Các quy tắc và ràng buộc

Các quy tắc bổ sung là:

  • Chương trình của bạn có thể đọc và ghi các tệp trong thư mục riêng của mình (không bị đánh cắp!) Nếu bạn muốn lưu dữ liệu, nhưng bạn không thể truy cập bất cứ thứ gì bên ngoài nó (và cavemen không có kết nối internet ở nơi hoang dã).
    • Lưu ý quan trọng về tệp : Nếu bạn lưu tệp, hãy nhớ lưu chúng trong thư mục players/YourBotsName/somefile.foo! Thư mục làm việc hiện tại cho chương trình của bạn sẽ không phải là chương trình của bạn!
  • Cavemen là công bằng: Một chương trình không thể có mã cụ thể cho chương trình khác và các chương trình không thể giúp đỡ lẫn nhau. (Bạn có thể có nhiều chương trình, nhưng chúng không thể tương tác với nhau theo bất kỳ cách nào.)
  • Thẩm phán thượng cổ không kiên nhẫn. Nếu các cavemen mất hơn 100 lượt mỗi người để quyết định một người chiến thắng, thẩm phán sẽ chán và cả hai cavemen đều thua.

Nếu chương trình của bạn vi phạm quy tắc hoặc không tuân theo thông số kỹ thuật, chương trình sẽ bị loại, bị xóa khỏi playerlist.txtvà tất cả các cuộc đấu lại bắt đầu lại từ đầu. Nếu chương trình của bạn bị loại, nhà lãnh đạo thượng cổ (tôi!) Sẽ bình luận về bài đăng của chương trình của bạn và giải thích lý do. Nếu bạn không vi phạm bất kỳ quy tắc nào, chương trình của bạn sẽ được thêm vào bảng xếp hạng. (Nếu chương trình của bạn không có trên bảng xếp hạng, không có bình luận giải thích về bài đăng của bạn và bạn đã đăng chương trình của mình trước thời gian "Cập nhật lần cuối" bên dưới, hãy nói với người lãnh đạo thượng cổ! Có lẽ anh ấy đã quên nó.)

Trong bài viết của bạn, vui lòng bao gồm:

  • Một cái tên.
  • Một lệnh shell để chạy chương trình của bạn (ví dụ. java MyBot.java, ruby MyBot.rb, python3 MyBot.py, Vv).
    • Lưu ý: đầu vào sẽ được thêm vào đây như là một đối số dòng lệnh.
    • Các cavemen sử dụng Ubuntu 14.04, vì vậy hãy đảm bảo mã của bạn hoạt động (tự do) trên nó.
  • Số phiên bản, nếu mã của bạn hoạt động khác nhau trên các phiên bản khác nhau của ngôn ngữ bạn đã chọn.
  • Mã của bạn (rõ ràng).
  • Làm thế nào để biên dịch mã, nếu cần thiết.

Mã điều khiển / kiểm tra, ví dụ bot

Người lãnh đạo thượng cổ đã viết mã điều khiển trong C ++ và đăng nó lên repo Github . Bạn có thể chạy và kiểm tra chương trình của bạn ở đó.

Một chương trình rất, rất đơn giản (1 dòng!) Cũng được đăng trong các câu trả lời dưới đây .

Chấm điểm và bảng xếp hạng

Ghi điểm rất dễ. Bất cứ ai thượng cổ đều thắng được một điểm. Người thượng cổ có nhiều điểm nhất sau 3 trận đấu với mọi người thượng cổ khác trở thành thủ lĩnh thượng cổ mới!

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

(bảng xếp hạng này đã được tạo tự động một cách kỳ diệu)

Người chơi được đánh dấu bằng một *số lỗi hoặc ngoại lệ tại một số điểm; Những người chơi này cũng có một nhận xét về bài viết của họ.

Những người chơi không thể được bao gồm trong các bài kiểm tra vì lý do bất kỳ (những người chơi sẽ có một bình luận trên bài viết của họ giải thích vấn đề): Monkey, Elephant, FacileFibonacci, StudiousSylwester.

Cập nhật lần cuối: ngày 3 tháng 8 00:15 (UTC).


Tôi ngạc nhiên dường như không ai đã cố gắng tìm chiến lược minimax. Có vẻ như điều rõ ràng để làm.
dùng2357112

@ user2357112 Tôi không nghĩ minimax là một cải tiến ở đây. Ý tôi là, bạn có thể thiết kế một triển khai minimax, nhưng vì logic rất đơn giản, nên hành vi chính xác tương tự có thể được thể hiện bằng một máy trạng thái hữu hạn. (vd bị chặn, v.v.)
HuddleWolf

3
Nhiều mục có vẻ cho phép độ sắc nét tiêu cực trong tính toán của họ. Các quy tắc như bằng văn bản nói rằng không có gì xảy ra khi bạn chọc với độ sắc nét bằng không. Có phải "không có gì" cũng có nghĩa là độ sắc nét của bạn bằng không, thay vì bị giảm?
Sparr

6
Điều này cần phải có ở đây: dresdencodak.com/comics/2009-09-22-caveman_science_fiction.jpg Có lẽ nó sẽ khiến trí tưởng tượng diễn ra. :)
Evi1M4chine

2
Điều này vẫn còn mở? Tôi thấy mọi người thêm các bài nộp mới, nhưng tôi không thấy bảng xếp hạng được cập nhật.
ASCIIThenANSI

Câu trả lời:


35

Darwin - C

Ai cần chiến lược, dù sao? Có một nhóm các cavemen đi với nhau và để cho lựa chọn tự nhiên làm phần còn lại!


Chúng tôi sử dụng một mô hình rất đơn giản cho bộ não nguyên thủy của người thượng cổ: nó không có bộ nhớ và chỉ tính đến độ sắc nét của cây gậy của anh ta và đối thủ. Chúng được sử dụng làm biến cho đa thức nhị phân của một số thứ tự hữu hạn. Mỗi hành động (chặn, làm sắc nét và chọc) có một đa thức liên quan có kết quả xác định xác suất tương đối của việc chọn hành động này. Đó là khá nhiều tất cả để có nó --- bắt đầu với một số hệ số ngẫu nhiên và tối ưu hóa lặp đi lặp lại.

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

Biên dịch với : gcc darwin.c -odarwin -w -O3. Chạy với : ./darwin <history>.

Bot đọc các hệ số từ một tệp có tên programtrong players/Darwinthư mục (một tệp khác có thể được chỉ định làm đối số dòng lệnh thứ hai). Chương trình này dường như làm tốt:

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 

Lưu như players/Darwin/program.

Sau đây là chương trình tạo programtệp có thể được sử dụng bởi bot (không phải biên dịch nếu bạn sử dụng programtệp ở trên):

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

Biên dịch với : gcc genprog.c -ogenprog -w -O3. Chạy với : ./genprog [output-filename].


Watson

DNA của một thượng cổ chiến thắng là gì? Có lẽ fella này có câu trả lời:

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

Chạy với: python Watson.py

Watson là sản phẩm của một thuật toán di truyền. Không giống như Darwin, dữ liệu di truyền lần này là một chương trình thực tế, được viết bằng một ngôn ngữ cụ thể theo miền nhỏ (ở đây được dịch sang Python).


Trình tự đơn giản đánh bại người chơi lớn

Fella nhỏ này làm đáng ngạc nhiên (hoặc, có thể, không quá ngạc nhiên) tốt, đặc biệt là chống lại các nhà lãnh đạo:

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

Chạy với: python SSBBP.py


Làm thế nào để tôi biên dịch và chạy này? Ngoài ra, như đã đề cập trong câu hỏi, bạn chỉ có thể đọc / ghi tệp trong players/Darwinthư mục.
Doorknob

@Doorknob: đã sửa.
DarwinBot

Tôi nhận được các lỗi biên dịch khi biên dịch mã này. (Tôi đang dùng Ubuntu 14.04.)
Doorknob

@Doorknob: Đã sửa. Nên làm việc bây giờ.
DarwinBot

Tôi đang nhận được undefined reference to `fmax'. - Chỉnh sửa-- Đừng bận tâm, tôi thực sự cần -lm.
Doorknob

50

Caveman không thể đoán trước

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!

Người thượng cổ này chọn ngẫu nhiên mỗi vòng, nhưng tôi đã giải thích với anh ta rất đơn giản rằng đôi khi một số hành động nhất định không có ý nghĩa. Vui lòng sao chép mã này nếu bạn muốn thể hiện logic khác nhau.

Đây là Ruby, lưu dưới dạng 'không thể đoán trước.rb' và chạy với ruby unpredictable.rb


Thật ra, tôi no 'Block'cũng nên làm thế nếu đối thủ của tôi có kiếm.
njzk2

Cái 'Block' đầu tiên thực sự bao hàm điều đó: một cây gậy nhọn không phải là thanh kiếm.
lịch sử

2
Tại sao bạn không sử dụng unlesscho các câu lệnh no 'Block'no 'Poke'? ( no 'Block' unless he.has_pointy_stick)
wchargein

25

Bác sĩ hang động - Lua

"Tôi thua người nước ngoài mới, đánh gục họ để nghiên cứu họ"

Khi bạn đã xem nhiều bệnh nhân như bác sĩ hang động, bạn bắt đầu thực sự hiểu tâm lý người hang động (hoặc vì vậy tôi hy vọng). Trò chơi của bác sĩ Cave là chiến lược thuần túy, anh ta chờ đợi những cú chọc mà anh ta ngăn chặn để giải giáp đối thủ, nhưng anh ta sẽ không để đối thủ đến gần để tạo ra một thanh kiếm. Anh ta cố gắng dự đoán khi nào an toàn để làm sắc nét để anh ta không mất thế thượng phong.

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

Chạy với: lua CaveDoctor.lua


3
Điều này chỉ mất hai lần trong bảng xếp hạng hiện tại? oO
justhalf

Bản sửa đổi 5 đưa ra một loạt các lỗi, vì vậy bản sửa đổi 4 là bản sửa lỗi được đưa vào vòng thử nghiệm hiện tại.
Doorknob

@Doorknob Tôi nghĩ rằng tôi đã sửa tất cả chúng, chỉ có một thay đổi đối với logic dù sao đi nữa.
Nexus

20

Ngoại trưởng

ForeignCaveman không biết bạn vừa nói gì. Anh ta chỉ ... làm mọi thứ.

javac ForeignCaveman.java sau đó 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
Điều này có lẽ có quá nhiều sự ủng hộ cho việc nó tệ như thế nào
Kevin L

19

Phó lãnh đạo

Doorknob ♦ là người lãnh đạo. Tôi muốn trở thành người lãnh đạo! Thực hiện theo chương trình siêu thông minh để trở thành nhà lãnh đạo!

Biên dịch: javac ViceLeader.javaChạy : 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;
    }
}

Tại sao không phải là if (enemySharpness <= 4 || mySharpness >= 5)vs ==?
durron597

@ durron597 Bởi vì tôi chỉ muốn chọc kẻ thù nếu anh ta có thể tạo ra một thanh kiếm ở lượt tiếp theo (điều mà anh ta rất có thể sẽ làm). VizeLeader không chọc thường xuyên, nó thực hiện đúng lúc .
CommonGuy

Nhưng bạn có một thanh kiếm và đối thủ của bạn không ...
durron597

@ durron597 Không, đó là câu lệnh OR. Nó có nghĩa là "chọc đối thủ nếu tôi có kiếm HOẶC nếu anh ta sẽ sớm có kiếm".
CommonGuy

7
Ôi trời ơi. Thời gian để có thêm một tách cà phê :) Hoặc kính áp tròng mới
durron597

15

Có lẽ Markov 2.1

Tôi nghĩ rằng nó sử dụng Chuỗi Markov để dự đoán những người thượng cổ khác sẽ làm gì, nhưng tôi chỉ nhìn thoáng qua trang wikipedia về Markov Chains và quyết định nó có quá nhiều văn bản.

Nó cố gắng sống sót trong 30 vòng và sau đó xây dựng một bảng với những thay đổi trạng thái tiếp theo hiện tại và phản ứng với những gì được cho là người thượng cổ khác sẽ làm.

Mã này chứa rất nhiều câu lệnh không cần thiết, nhưng nó thực hiện khá tốt.

BIÊN TẬP

Phát hiện một lỗ hổng trong logic. Bây giờ nó thực sự làm một cái gì đó khi nó có một thanh kiếm.

$ 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

Định kỳCicadaCaveman

Người đàn ông hang động khá thông minh này đã nghiên cứu một con bọ nhất định và nhận ra không ai có thể điều chỉnh lối sống của mình để tận dụng số nguyên tố Cicada.

Nó ẩn / chặn trong phần lớn cuộc đời, nhưng đôi khi chọc. Chắc chắn rằng nó dễ bị tấn công bởi Kiếm, và dành cả một chu kỳ với một cây gậy không bị bong tróc, nhưng làm sắc nét cây gậy của bạn khi nó hoàn toàn cùn? Đó chính xác là những gì người khác mong đợi từ nó ... không phải con ve sầu này

để biên dịch: mcs program.cs để chạy chương trình mono

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

  }

}

Chỉnh sửa: Thay đổi độ sắc nét-- mã ... nếu tôi chọc hoặc tôi thắng hoặc cây gậy của tôi bị mờ hơn

Edit2: Đã thêm trong đề xuất Bobs

Chỉnh sửa: Thay đổi thành chỉ chọc khi ở độ sắc nét 2, nếu cây gậy ở mức 0, anh chàng kia có thể tạo ra một thanh kiếm.


1
Tôi đang chạy trên Ubuntu; điều này sẽ được biên dịch dưới Mono? Nếu vậy, làm thế nào để tôi biên dịch nó và làm thế nào để tôi chạy nó?
tay nắm cửa

Thành thật mà nói, tôi không biết. Tôi chuẩn bị đi ngủ. Tôi có thể viết lại nó vào Java sáng mai tại nơi làm việc. Mã Java phải gần như giống hệt nhau.
Chuột Mikey

5
@Doorknob mcs program.cssẽ biên dịch nó, mono programsẽ chạy nó, nhưng bạn sẽ cần thay thế foo.Dump();s bằng System.Console.WriteLine(foo);(hoặc thêm một phương thức mở rộng public static void Dump(this string value) { System.Console.WriteLine(value); }).
Bob

@Bob Cảm ơn bạn, tôi đã thêm vào phương thức tiện ích mở rộng của bạn.
Chuột Mikey

Xin lỗi, tên tệp mặc định thực tế mcstạo ra <filename>.exe, ví dụ như program.cssẽ trở thành program.exe. Vì vậy, lệnh chạy sẽ là mono program.exe. (Tôi không có quyền truy cập vào đơn âm tại thời điểm nhận xét trước đó của mình.)
Bob

14

Thuật toán FancyTechno

Một thuật toán kỹ thuật ưa thích cho chương trình máy tính kỹ thuật ưa thích.

Caveman tiếp tục thua trận. Caveman tức giận. Vì vậy, thượng cổ đi học máy tính học thuật toán.

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"

Chương trình Python 2. Chạy:python fancytechnoalgorithm.py


Điều này phá vỡ khi không có đầu vào (tức là ở lượt đầu tiên). Tôi không biết bạn muốn xử lý vấn đề đó như thế nào, vì vậy tôi sẽ phải loại trừ nó khỏi vòng thử nghiệm đầu tiên.
Doorknob

@Doorknob Đối với đầu vào đầu tiên, đó là "," hay ""? Tôi đoán đó là cái sau từ đó.
Vectorized

Đối với đầu vào đầu tiên, sẽ không có đối số (nó sẽ được chạy dưới dạng python StickSharpener.py).
Doorknob

@Doorknob Tôi đã chỉnh sửa nó. Hãy xem nếu nó hoạt động bây giờ.
Vectorized

Được rồi, cám ơn! Tôi sẽ bao gồm điều này trong vòng thử nghiệm tiếp theo.
Doorknob

14

Người xem

Anh ta quan sát chuyển động của đối thủ, luôn để họ giơ tay trước khi anh ta tấn công. Anh ta đặc biệt chuẩn bị cho những người bỏ bê việc làm kiếm.

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

Tên tệp: watcher.py

Chạy: python watcher.py

Basilisk

Tìm cách tiêu diệt những người nhìn anh quá kỹ. Liên tục đánh bại Watcher, nhưng có thể sẽ khiến giá vé tệ hơn về tổng thể.

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

Tên tệp: basilisk.py

Chạy: python basilisk.py

Nash

Tìm cách làm cho lựa chọn của đối thủ không liên quan, bằng cách chọn từng nước đi với xác suất tính đến rủi ro và phần thưởng của nó

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

Đây không hoàn toàn là điểm cân bằng Nash (trình tạo chiến lược của tôi có một số bất ổn), nhưng nó đã đóng.

Vì sự tò mò, đây là ước tính về khả năng bot này sẽ giành chiến thắng trong mỗi trạng thái trò chơi:

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

Tên tệp: nash.py

Chạy: python nash.py

Feint

Mở ra với một cuộc tấn công nhanh chóng, để kiểm tra phòng thủ của đối thủ.

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

Tên tệp: feint.py

Chạy: python feint.py

Muộn

Em trai của PokeBot. Không bao giờ tỏ ra yếu đuối, nhưng cố gắng chiến đấu như người anh lớn của mình.

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

Tên tệp: latepokebot.py

Chạy: python latepokebot.py


Bạn đã bỏ lỡ một :trong Basilisk; Tôi đã sửa nó cho bạn
Doorknob

Trình này đã ném một số loại lỗi hoặc ngoại lệ tại một số điểm; bạn có thể muốn xem xét việc khắc phục điều đó trước vòng thử nghiệm tiếp theo. (Basilisk one)
Doorknob

@Doorknob Tôi đã chọn trình tự khởi đầu cho Basilisk bằng cách xem xét các giả định được đưa ra bởi The Watcher và Cave Doctor và tìm ra một chuỗi có thể khiến những giả định đó trở nên sai lầm. Điều đó có vi phạm quy tắc "thượng cổ là công bằng" không?
Brilliand

Đi Nash! Chiến thắng chính xác một nửa trận đấu của bạn trước tất cả các bot đủ thông minh để tránh các tùy chọn P = 0 của bạn!
aschepler

12

PokeBot

Viết bằng Ruby.

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

Chạy với ruby pokebot.rb.

Bot này không thông minh lắm; dù sao nó cũng là về những gì người thượng cổ bình thường sẽ tự làm.


9

Bệnh nhânWolf v2.0

Làm sắc nét nếu đờ đẫn, chọc vào nếu kẻ thù sẽ có một thanh kiếm tiếp theo hoặc nếu kẻ địch bị xỉn, hãy chặn lại.

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

Chạy với

perl patientwolf.pl

EDIT: cảm ơn @sylwester đã chỉ ra một lỗi


Vì bạn chỉ nhận được một đối số với cả hai lịch sử được phân tách bằng dấu phẩy nên bạn đang phân tích cú pháp sai. Ví dụ. PatientWolf.pl SB,SPlàm một Pvì nó nghĩ rằng nó có thanh sắc nét.
Sylwester

@Sylwester không đúng. Dòng đầu tiên gán đối số đầu tiên cho $ tôi và đối số thứ hai cho $ anh ta
killmous

Chương trình CavemanDuel không sử dụng hai đối số, chỉ một. ví dụ. perl patientwolf.pl "SB,SP". Bạn nên làm my($me,$him) = split/,/ $ARGV[0];if( @ARGV ) {print "S";exit}.
Sylwester

@Sylwester ok Tôi thấy những gì bạn đang nhận được. Điều đó không rõ ràng từ OP hoặc từ cái nhìn nhanh mà tôi đã ném vào mã điều khiển. Tôi sẽ khắc phục điều đó trong thời gian ngắn
giết người

9

Caveman nhị phân

Làm sắc nét, đâm, lặp lại

Dựa trên ý tưởng rằng chặn là dành cho những kẻ yếu đuối, người thượng cổ này xen kẽ giữa hai tùy chọn còn lại.

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

Biên dịch với javac BinaryCaveman.java

Chạy với java BinaryCaveman

EDIT: Adventures in String Arrays ..... args.length () ném lỗi. args.length luôn trả về 1. args [0] .length () trả về độ dài của chuỗi đầu tiên trong mảng.

EDIT 2: Được cập nhật nhờ sự giúp đỡ từ Doorknob, Brilliand và Sylwester. Cảm ơn các bạn.


@ MartinBüttner Tôi quên chia args - 1 cho 2 để chỉ nhận được số lần gửi trong quá khứ của một người chơi. Đã sửa lỗi đó. Tôi không thể hiểu sự phục tùng của Dorknob, ruby ​​thực sự vô nghĩa với tôi. Có phải anh ấy luôn bắt đầu với mài?
Red_Shadow

Vâng, anh ấy chỉ kiểm tra xem bước cuối cùng của anh ấy là Phay Svà ngược lại. Và nếu chưa có lịch sử, anh ta giả vờ lịch sử sẽ xảy ra P,(sau đó dẫn anh ta đi Strước).
Martin Ender

Hai cách tiếp cận khác nhau dẫn đến cùng một đầu ra. Điều đó có trái với quy định không?
Red_Shadow

Có lẽ là không, tôi chỉ muốn cho bạn biết.
Martin Ender

2
@Doorknob Tôi nghĩ là nó nên args[0].length(), không phải args.length.
Brilliand

8

CavekidBlocks

Một đứa trẻ hang động khóc và sợ hãi có thể trông giống như một con mồi dễ dàng. Đừng để khuôn mặt xinh đẹp của anh ấy đánh lừa bạn vì anh ấy biết cách chặn.

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

Chạy với python3 cavekidblocks.py

Bộ sạc

Người thượng cổ này rất bảo thủ. Sẽ cố gắng sạc vũ khí của mình và chỉ tấn công khi cần thiết.

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)

Chạy với python3 chargerman.py

Thủ thuật

Trickster không biết cách chiến đấu, vì vậy anh ta cố gắng gây nhầm lẫn cho người thượng cổ khác.

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

Chạy với python3 trickster.py

Thật không may, sau khi xác nhận acc74 , Trickster không hoạt động như kế hoạch nữa.


4
Chương trình lừa đảo đó là xấu xa
Nexus

@Nexus tôi cũng vậy. Thật không may, Trickster không làm tốt trong các cuộc đấu tay đôi.
wendelbsilva

7

Hodor

Hodor không phải là rất tích cực. Anh ấy thích ở trong khiên của mình trừ khi có cơ hội tốt để tấn công.

biên dịch với: javac Hodor.javavà chạy với:java Hodor

mã:

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

Chỉnh sửa: cập nhật mã nhỏ


Trình này đã ném một số loại lỗi hoặc ngoại lệ tại một số điểm; bạn có thể muốn xem xét việc khắc phục điều đó trước vòng thử nghiệm tiếp theo.
Doorknob

1
Hãy thử với SB,BB. Khi các cavemen khác hành vi sai trái trong lượt đầu tiên, Hodor misbehave cũng vậy.
Sylwester

7

Đầu cơ Sylwester - Perl5

Sylwester đầu cơ muốn loại bỏ những người tìm kiếm bằng cách nhìn vào các mẫu và chọc khi có cơ hội đối thủ sẽ sắc bén và sắc bén khi đối thủ có khả năng chặn. Tuy nhiên, anh ta sẽ không làm điều đó nếu có cơ hội rằng anh ta sẽ đoán rằng bản thân sẽ sắc bén trong bước tiếp theo và chúng tôi thậm chí còn thận trọng hơn khi chúng tôi quyết định làm sắc nét.

Khi đối thủ cùn, anh ta cố tỏ ra hung hăng nhưng cuối cùng sẽ bắt đầu tiết kiệm cho một thanh kiếm khi điều đó dường như không có kết quả.

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

Để chạy trên linux, chỉ cần thêm phần này vào playerlist.txt:

perl players/SpeculativeSylwester/SpeculativeSylwester.pl

Fibre Facile - Sơ đồ R6RS

Bên cạnh bước di chuyển đầu tiên, khối Fibile di chuyển đầu tiên khi lượt là số Fibonacci (bắt đầu từ 0) và lấp đầy phần còn lại PPSS..và thay đổi khi vượt qua 8 đến chuỗi vô tận PSSđể giành chiến thắng bằng kiếm.

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

Để chạy, chỉ cần cài đặt ikarus apt-get install ikarusvà thêm phần này vào playerlist.txt:

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

Nghiên cứu Sylwester - Perl5

Nghiên cứu Sylwester sử dụng chiến thuật tương tự như Đầu cơ Sylwester, nhưng anh ta cũng xem xét các trò chơi trước đó để xác định nơi mà anh ta có thể đã chọn sai.

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

Để chạy trên linux, chỉ cần thêm nó vào playerlist.txt

perl players/StudiousSylwester/StudiousSylwester.pl

Chỉnh sửa học tập

Tôi không thể tái tạo các vấn đề bạn gặp phải khi $0không phải là đường dẫn đầy đủ đến tập lệnh perl khi nó chạy với perl. Tôi cũng đã lấy các thay đổi của bạn và tôi thấy không có thay đổi nào trong CavemanDuels src và cũng giống như tôi đã chạy hơn 20 lần mà không gặp sự cố nào bạn đang báo cáo. Tôi bắt đầu sợ rằng bạn có thể đã lấy tập lệnh thành tập lệnh bash thay vì chạy tập lệnh trong khi thực thi hoặc làm đối số cho perl. Tôi cần thêm thông tin để thực sự biết chắc chắn. Như một bài kiểm tra tôi đã làm điều này và bạn có thể làm tương tự để xem bạn có nhận được kết quả tương tự không:

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

Lược đồ dường như không muốn hợp tác với tôi trên máy của tôi, vì vậy tôi đã không thể kiểm tra mức Fibonacci. Tôi sẽ tiếp tục cố gắng để nó hoạt động, nhưng sẽ thật tuyệt nếu bạn có thể dịch nó sang ngôn ngữ khác.
Doorknob

Người hiếu học cũng dường như không làm việc, bởi vì $0bashkhi gọi từ một dòng lệnh bash (mà bộ điều khiển thực hiện). Bạn chỉ có thể hardcode players/StudiousSylwester/foo.txt, mặc dù.
Doorknob

@Doorknob Tôi đã thêm cách cài đặt ikarusvà tôi đã thêm suy nghĩ của mình về Học $0tập.
Sylwester

6

Kiếm sĩ

Cần thanh sắc. Nếu có que nhọn, chọc. Tôi không cảm thấy đau.

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

Lưu dưới dạng swordsmith.f90và biên dịch với gfortran -o swordsmith swordsmith.f90, thực thi như bất kỳ thực thi bình thường nào : ./swordsmith.


Điều này xuất hiện để in một khoảng trắng (``) trước đầu ra thực. Tôi không biết làm thế nào để khắc phục điều đó, vì vậy tôi sẽ phải loại trừ bài nộp này khỏi vòng thử nghiệm đầu tiên.
Doorknob

Ngoài ra, tôi đã sửa đường dẫn tệp của bạn; Hóa ra thư mục làm việc hiện tại khi họ chạy không phải là chương trình của bạn. Ồ, và nếu theo "ví dụ mới", bạn có nghĩa là "mỗi trò chơi", tôi không thể làm điều đó bởi vì điều đó đòi hỏi phải có chương trình điều khiển đặc biệt; bạn có thể muốn làm điều đó trong mã của riêng bạn.
Doorknob

@Doorknob: Tôi đã cập nhật mã của mình: đầu ra là một ký tự, nó sẽ xóa một tệp đã tồn tại trong lần chạy đầu tiên và tệp nằm trong thư mục trình phát.
Kyle Kanos

Được rồi, cám ơn! Trình này hiện được bao gồm trong bảng thành tích.
Doorknob

@Doorknob: Tuyệt! Sucks mà tôi không phải là đầu tiên. Ngoài ra: Tôi khá chắc chắn rằng người dùng Fortran giống như Ma cà rồng, vì vậy tôi khá chắc chắn rằng bạn sẽ sớm bắt đầu viết mã trong Fortran! Muahahahaha!
Kyle Kanos

5

Bệnh nhân

Bot này được viết bằng R, sử dụng Rscript PatientBlacksmith.Rđể kích hoạt nó.

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)

Đo độ sắc nét của đối thủ: khối khi sắc, mất thời gian để mài khác. Khi độ sắc nét riêng đạt đến 5, chọc cho đến khi hết độ sắc nét.


Điều này phá vỡ khi không có đầu vào (tức là ở lượt đầu tiên); Tôi không biết cách khắc phục vì vậy tôi sẽ phải loại trừ nó khỏi vòng 1 của thử nghiệm.
tay nắm cửa

@Doorknob đã sửa.
plannapus

5

Nội quy nhà tù, Haskell

Cave Woman nghĩ thượng cổ và thượng cổ khác nên nói chuyện, chia sẻ. Nhưng, hey ho, nếu phải chiến đấu, chiến đấu với nội quy nhà tù. Tìm ông chủ và tấn công.

Phó giám đốc Alpha Caveman bây giờ; ai thượng cổ phải chiến đấu. Những người khác chiến đấu sau đó. Nếu thượng cổ của tôi mất, không phải lo lắng; Dù sao anh cũng lông.

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

Được viết bằng Haskell (đi lập trình chức năng!), Vì vậy hãy lưu dưới dạng prisonrules.hs , sau đó biên dịch với:

ghc prisonrules.hs

Và chạy như:

prisonrules [history]

4

Tôi gọi anh ấy là JavaMan

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

lưu ý: Tôi không có ý định chơi golf mã .. nhưng nếu bạn là người chơi gôn và khoảng trống / vạch thừa làm cho mắt bạn bị chảy máu .. hãy thoải mái thay đổi nó

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
Đệ trình cho các thử thách King of the Hill không có nghĩa là phải chơi gôn, vì vậy đừng lo lắng. ;)
Martin Ender

Tôi đã đổi tên thành JavaMan, vì "Caveman" hơi quá chung chung để có trong bảng xếp hạng. Hy vọng rằng điều đó ổn với bạn; nếu không, chỉ cần thay đổi nó thành một cái gì đó khác.
tay nắm cửa

1
Điều này phá vỡ khi không có đầu vào (tức là ở lượt đầu tiên); Tôi không biết bạn muốn xử lý vấn đề đó như thế nào nên tôi sẽ phải loại trừ nó khỏi vòng thử nghiệm đầu tiên.
Doorknob

Đã sửa lỗi và thay đổi tên là tốt với tôi
user2813274

1
Tôi nghĩ rằng bạn đã có một lỗi khi phân tích trạng thái, cả 'tôi' và 'kẻ thù' đều có cùng một động thái: bang [0]
Roy van Rijn

4

Suy nghĩ sâu sắc, C

Mã Caveman. Caveman nghĩ. Caveman làm.

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

Tôi làm thử nghiệm. Nhiều suy nghĩ tốt hơn.


1
+1 cho tên và bình luận var caveman: P Ngoài ra, chương trình hay c:
mèo

3

Nigel

Nigel là một người thượng cổ già dặn, kiên nhẫn, thích chiến thuật hơn là tấn công.

Đó là một đoạn mã PHP, gọi với 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

Thỉnh thoảng anh ta sẽ chọc bạn, nhưng chỉ đến khi cây gậy nào đó quá sắc. Khi điều này xảy ra, anh ta sẽ hoảng loạn và cuộn mình vào vị trí của thai nhi.

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)

Chạy nó với:

lua aichmophobic.lua


2
Đầu ra của bạn phải được viết bằng chữ in hoa; Tôi đã sửa nó cho bạn. (Ngoài ra, tôi đã viết sai tên của bài đăng này khoảng một nghìn lần .: P)
Doorknob

3

Hang động Bob

Hang động Bob là một trong những kẻ thông minh nhất trong hang động của mình. Anh ta đã học đếm bằng một tay (tay kia đang chiếm giữ cây gậy của anh ta). Anh ta đã biết đến Thế vận hội thời kỳ đồ đá này và muốn tham gia.

Chiến lược chính của anh ta là chặn và mài cây gậy của anh ta cho đến khi anh ta có một cây gậy sắc nét đẹp hoặc người thượng cổ khác cũng có một cây gậy sắc nét. Trong trường hợp này, Bob Cave cố gắng chọc anh ta!

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

}

Biên dịch với javac BobCaves.javavà chạy vớijava BobCaves

Chỉnh sửa: Bây giờ Bob tính khi có bất kỳ khối! (cảm ơn chuột Mikey ). Ngoài ra anh ta sẽ mài cây gậy của mình khi cây gậy thượng cổ khác bị cùn.

Chỉnh sửa 2: Cải thiện phương pháp đếm (một lần nữa cảm ơn Mikey).

Chỉnh sửa 3: Làm Bob mạnh hơn một chút.


2
Bob quên hiệu ứng đếm của Poke: Chặn độ sắc nét của cây gậy. Ba chữ "S" trong s không có nghĩa là dính 3 lần. Mỗi chữ "P" trong s có nghĩa là thanh không bị bong ra. Huh huh huh ... Trò đùa người đàn ông hang động "Pee" ...
Chuột Mikey

@MikeyMouse Bob đồng tình. Bob sẽ đến gặp bác sĩ phù thủy để cải thiện kỹ thuật của mình. Bob biết ơn!
Averroes

1
Bác sĩ phù thủy dạy Bob tốt. Nhưng anh quên đề cập đến kịch bản Poke: Poke. Dính thì cùn rồi. Bob không cần xem xét di chuyển đối thủ. Nếu Bob Poke, hãy nhận được cùn. Hoặc là cùn trên: đối thủ chọc, vào khối đối thủ hoặc trên đầu đối thủ. Nếu trên Head đối thủ, Bob thắng và có thể nhảy quanh hang bằng gậy cùn.
Chuột Mikey

1
@MikeyMouse Bob biết đếm. Bob cần học đọc. Cảm ơn một lần nữa!
Averroes

3

Grunt

Gruntt là phòng thủ. Gruntt phân tích các động tác khác để biết cách chọc chúng. Rồi anh chọc chúng ngay vào mắt. Gruntt không phải là một thượng cổ tốt đẹp.

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

}

Biên dịch với javac Gruntt.javavà chạy vớijava Gruntt


Điều này ném một ArrayOutOfBoundsExceptionlượt ở lượt đầu tiên và đôi khi nó tạo ra nhiều hành động ở lượt khác.
Doorknob

@Doorknob Ops! Đã sửa, cảm ơn!
Averroes

3

Có phải là một con chim? Có phải là một chiếc máy bay? Đó là RegExMan!

Anh ta cố gắng phân tích các chuỗi siêu nhàm chán của bạn với sức mạnh RegEx nguyên thủy đặc biệt của mình!

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

Viết bằng Python 2.7, chạy với python RegExMan.py [history]


3

Sicilia

Nhưng nó thật đơn giản! Tất cả những gì tôi phải làm là thần thánh từ những gì tôi biết về người thượng cổ khác: anh ta có phải là người thượng cổ sẽ chặn, làm sắc hay chọc? Bây giờ, một người thượng cổ thông minh sẽ chọc hoặc chặn, bởi vì anh ta sẽ biết rằng chỉ có một kẻ ngốc vĩ đại mới mài giũa và phơi bày bản thân để tấn công. Tôi không phải là một kẻ ngốc vĩ đại, vì vậy tôi rõ ràng không thể làm sắc nét. Nhưng những người thượng cổ khác phải biết tôi không phải là một kẻ ngốc vĩ đại, và sẽ tính vào nó, vì vậy tôi rõ ràng không thể chọc hay chặn!

Chạy với:

javac Sicillian.java
java Sicillian

Mã số:

public class Sicillian {

    public static void main(String[] args) {

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

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

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

            else {          // Inconceivable!

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

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

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

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

3

bash-Magnon

Bash-Magnons được xây dựng mạnh mẽ và mạnh mẽ. Cơ thể nói chung là nặng và rắn chắc với một cơ bắp mạnh mẽ. Trán khá thẳng chứ không phải dốc như ở người Neanderthal, và chỉ có một chút lông mày. Khuôn mặt ngắn và rộng. Cằm đã nổi bật. Dung lượng não khoảng 1.600 cm khối (98 cu in), lớn hơn mức trung bình của người hiện đại. Tuy nhiên, nghiên cứu gần đây cho thấy rằng kích thước vật lý của cái gọi là "Bash-Magnon" không đủ khác biệt so với người hiện đại để đảm bảo một chỉ định riêng.

Tôi có một bộ não, tôi nhớ.

Đây là một tự thực thi ./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+ Bạn rõ ràng có công cụ phù hợp cho công việc và tên của bạn khá thú vị :) (Cá nhân tôi thích cá hơn mặc dù vậy)
Sylwester

@Sylwester Cảm ơn bạn đó là +1 đầu tiên của tôi. Trước tiên, tôi đã cố gắng tạo ra một máy tự động cân bằng nội môi lấy cảm hứng từ những gì mà nhà điều khiển học đầu tiên đã cảm nhận được sự cân bằng của chính nó, sau đó tôi đã từ bỏ và tạo ra một kịch bản bash.
Emmanuel

2

PokeBackBot

Chỉ đơn giản là chuyển thể từ PokeBot:

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

Chạy với ruby pokebackbot.rb.

Điều này sử dụng chiến lược đơn giản nhất tiếp theo và chặn "kiên nhẫn" một vòng trước khi tấn công.


3
@PeterTaylor Tôi đọc được rằng không được phép chuyển đổi chiến lược của mình dựa trên việc in ngón tay của đối thủ. Nếu bài nộp của tôi chỉ có thể đánh bại một bài nộp khác, điều đó sẽ không thực sự ảnh hưởng đến điểm số bài nộp khác đó và bài dự thi của tôi có thể sẽ rất tệ. Hơn nữa, nếu chỉ có một bài nộp và bài thứ hai được viết, bài thứ hai có khả năng đánh bại bài đầu tiên (vì nếu không, tại sao phải bận tâm) - liệu điều đó có đủ điều kiện là "cụ thể cho chương trình khác" không? Bot của tôi sẽ đánh bại bất kỳ bot nào bắt đầu bằng SPS(có vẻ hợp lý), nhưng cho đến nay PokeBot là người duy nhất xung quanh.
Martin Ender

2

Kiếm sĩ

Được viết bằng Python 3.4 (hoạt động với Python 3.x)

Cố gắng để có được một thanh kiếm càng nhanh càng tốt nhưng tấn công nếu nó có cơ hội đánh anh ta (độ sắc nét> 0) và kẻ thù cũng có thể làm tổn thương nó (độ sắc bén của kẻ thù> 0).
Khối chỉ khi không có độ sắc nét và kẻ thù có thể tấn công.

Bắt đầu với:

python3 swordmaster.py MOVES

(giả sử bạn lưu nó dưới dạng swordmaster.py)

Mã nhanh và xấu:

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

(Đặt dgđể Truebật thông báo gỡ lỗi)


1
Gợi ý: Đừng để nó chiến đấu riêng của mình - nó sẽ bế tắc với S, P, S, P...
chill0r

Tôi thấy điều này xảy ra với tôi quá. Trừ khi bạn kiểm tra lịch sử hoặc sử dụng một mức độ ngẫu nhiên, bạn sẽ bị mắc kẹt trong một chu kỳ.
Pharap

2

FoolMeOnce.py

Lưu di chuyển của mỗi người chơi cho trận đấu đầu tiên, sau đó phát lại với các bước di chuyển chính xác. Nếu thuật toán của kẻ thù là không hợp lý, chúng ta có thể dự đoán kết quả tương tự và chỉ tấn công khi chúng ta biết mình sẽ thắng.

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)

Được viết bằng python 3, do đó rất có thể bạn sẽ phải sử dụng python3 FoolMeOnce.py Ở vòng đầu tiên, tôi không chắc chúng ta có nhận được chuỗi trống hay chỉ là dấu phẩy, vì vậy có thể cần một số điều chỉnh.


Tôi đã sửa đường dẫn tệp của bạn - hóa ra thư mục làm việc hiện tại không phải là chương trình của bạn.
Doorknob

Trong khi chơi với trình kiểm tra CavemanDuel, tôi nhận thấy rằng FoolMeOnce có được điểm tốt hơn nếu tôi sử dụng nhiều luồng hơn (tôi đã kiểm tra 16 luồng so với 4). Với 4 luồng, nó được ~ 25 điểm, với 16 điểm là ~ 34.
wendelbsilva

Thật kỳ lạ, tôi không biết tại sao điều đó sẽ xảy ra.
tzazy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.