Trò chơi sinh tồn - Tạo sói của bạn


238

Hội đồng quản trị

Các Hội đồng quản trị là một mảng hai chiều của các tế bào. Các tế bào được động vật cư trú . Mỗi ngày, tất cả Động vật trên Bảng đồng thời thực hiện một động tác. Nếu hai hoặc nhiều Động vật di chuyển đến cùng một tế bào, chúng sẽ chiến đấu cho đến khi một con còn lại. Các động thái và tấn công có thể xảy ra như sau:

  • Di chuyển - { Move.UP, Move.RIGHT, Move.DOWN, Move.LEFT, Move.HOLD}
  • Các cuộc tấn công - { Attack.ROCK, Attack.PAPER, Attack.SCISSORS, Attack.SUICIDE}

Động vật chiến đấu bằng cách chơi Rock-Paper-Kéo. Quy tắc tiêu chuẩn áp dụng nhưng với hai sửa đổi. Đầu tiên, bạn có thể tự sát bất cứ lúc nào. Thứ hai, một chiếc cà vạt bị hỏng giả. Nếu có nhiều hơn hai Động vật va chạm, hai con được chọn giả để chiến đấu cho đến khi một con còn lại.

Những người chơi

Hành vi và sự xuất hiện của động vật như sau.

  • sư tử
    • Đại diện cho nhân vật L. Di chuyển DOWN, RIGHTsau đó lặp lại. Pseudorandomly tấn công với PAPERhoặc SCISSORS.
  • Chịu
    • Đại diện cho nhân vật B. Di chuyển DOWNx 4, RIGHTx 4, UPx 4, LEFTx 4, sau đó lặp lại. Tấn công với PAPER.
  • Cục đá
    • Đại diện cho nhân vật S. Di chuyển HOLD. Tấn công với ROCK.
  • chó sói
    • Chỉ những con sói được gửi như một câu trả lời sẽ được đưa vào. Đại diện bởi 'W'. Di chuyển với bất kỳ Di chuyển. Tấn công với bất kỳ cuộc tấn công nào

Bạn sẽ thực hiện Sói bằng cách điền vào chỗ trống trong mẫu sau. Tất cả các đệ trình phải bằng Java và phải được chứa trong một tệp duy nhất. Ngoài ra, @ProgrammerDan đã viết một lớp trình bao bọc mở rộng sự cạnh tranh với các bài nộp không phải java.

// Optional code here
public class Wolf extends Animal {
    // Optional code here
    public Wolf() { super('W'); /* Optional code here */ }
    public Attack fight(char opponent) { /* Required code here. Must return an Attack. */ }
    public Move move() { /* Required code here. Must return a Move. */ }
    // Optional code here
}

Việc đệ trình với số lượng sói sống trung bình cao nhất sau năm thử nghiệm với 1.000 lần lặp chiến thắng. Tôi sẽ cập nhật người chiến thắng mỗi khi câu trả lời mới được đăng (nhưng không trong vòng 24 giờ đầu tiên).

Công cụ

  • Bạn được cung cấp một bản đồ nhỏ về môi trường xung quanh ngay lập tức theo mẫu sau.
    • char[][] surroundingsMột ma trận không có chỉ số, 3 nhân 3 ma trận đại diện cho các động vật gần đó. Các ô trống được biểu thị bằng ký tự khoảng trắng (''). Bạn đang ở surroundings[1][1]. Ví dụ, bên phải của bạn sẽ là surroundings[1][2], và trên bạn là surroundings[0][1]. Môi trường xung quanh bạn được cập nhật ngay trước khi được yêu cầu di chuyển, nhưng có thể bị lỗi thời khi được yêu cầu chiến đấu.
  • Bạn có thể duy trì dữ liệu giữa các yêu cầu Sói, Di chuyển yêu cầu và Yêu cầu Tấn công. Bạn không thể đọc và sửa đổi các tệp được tạo bởi một lớp Wolf khác.
  • Bạn được cung cấp kích thước của bản đồ theo mẫu sau
    • int MAP_SIZE

Giả định

  • Tất cả các bài nộp sẽ cạnh tranh trên cùng một bảng với tất cả các bài nộp khác cũng như Sư tử, Gấu và Đá
  • Bảng là một hình vuông với các cạnh có chiều dài sqrt(n+3)*20trong đó nsố lượng bài nộp. Tất cả các mặt bao bọc, vì vậy bạn có thể di chuyển một cách an toàn theo bất kỳ hướng nào.
  • Mô phỏng bắt đầu với ~ 25% công suất bảng với 100 mỗi giả hành động vật được phân phối trên bảng.
  • Nếu một con vật ném ngoại lệ khi được yêu cầu di chuyển, con vật đó sẽ HOLD
  • Nếu một con vật ném ngoại lệ khi được yêu cầu chiến đấu, con vật đó sẽ SUICIDE
  • Nếu một con vật không có chữ cái khi bộ điều khiển kiểm tra, con vật đó sẽ chết ngay lập tức

Bắt đầu và hướng dẫn kiểm tra

Các công cụ bạn cần để kiểm tra trình của bạn có thể được tìm thấy ở đây . Các tập tin sau đây nên có sẵn tại liên kết đó.

  • ExampleRun.gif - Một gif 5-10 giây của chương trình đang chạy.
  • Bảng điểm - Kết quả mới nhất của cuộc thi.
  • Wild.jar - Một tệp thực thi mà bạn có thể chạy để xem Động vật chạy trước chạy xung quanh.
  • Wild.zip - Dự án NetBeans chứa chương trình điều khiển với một vài Động vật được thêm vào. Sử dụng điều này để phát triển trình của bạn.
  • WildPopulation.zip - Tương tự như trên, nhưng có và khoảng 40 bài nộp được thêm vào để bạn kiểm tra. GUI cũng đã bị xóa vì vấn đề hiệu năng. Kết quả sẽ chỉ xuất hiện một vài phút sau khi bạn chạy. Các bài nộp không phải Java được nhận xét vì chúng yêu cầu tải xuống thêm và nỗ lực. Sử dụng điều này để kiểm tra trình của bạn đối với lĩnh vực này.
  • Wolf.txt - Một triển khai ngây thơ của lớp Wolf trong Java. Bạn có thể sử dụng và mở rộng việc thực hiện mà không cần tín dụng cho tôi.

Để kiểm tra lớp học của bạn:

  • Tải xuống Wild.zip
  • Đổi tên lớp Wolf.java và Wolf của bạn thành một cái gì đó độc đáo
  • Thêm tệp UniquelyNamedWolf.java của bạn vào Wild \ src \ động vật \
  • Trong lớp Wild, thêm lớp của bạn vào classesmảng, như thế này.
    • Class[] classes = { UniquelyNamedWolf.class, Bear.class, Lion.class, Stone.class, Wolf.class };
  • Xây dựng lại và chạy

Tôi cũng bao gồm một dự án khác có chứa tất cả các bài dự thi, cho mục đích thử nghiệm. Tôi sáng tạo đặt tên cho nó là "WildPopulation". Ba hoặc bốn con sói không phải Java đã được nhận xét, bởi vì để chúng chạy cần nhiều công việc và tải xuống thêm. Một trong những tôi đã đăng nên chạy với công việc thêm không . GUI cũng được bình luận vì lợi ích của tốc độ.

Bảng điểm ngày 22 tháng 4 năm 2014

Bảng điểm đã được chuyển sang Google Drive. Xem nó ở đây. Nó sẽ được cập nhật một cách ngẫu nhiên (nghĩa là khi tôi nhận được nó) khi các bài nộp mới được gửi đến.

Thử thách phụ - Không có

Xóa vì không có sự tham gia (như bằng không). Dù sao đó cũng không phải là một phần của thử thách ban đầu.


5
@Rizer Nghe thật kinh khủng. Tôi chỉ có thể cộng đồng wiki câu trả lời của tôi có chứa Wrapper. Đối với vấn đề về trình biên dịch / trình thông dịch, tôi cho rằng sẽ tùy thuộc vào người gửi để cung cấp cho bạn các hướng dẫn rõ ràng về cách sử dụng và nếu các hướng dẫn không rõ ràng hoặc quá phức tạp, bạn có thể từ chối việc gửi :)
Lập trình viên

4
"* Bạn được cung cấp kích thước của bản đồ theo mẫu sau: int MAP_SIZE" Tôi gặp khó khăn khi tìm ra cách sử dụng này. Netbeans cho biết không có trường hợp MAP_SIZEnào trong chuỗi trong bất kỳ tệp nào trong dự án.
undergroundmonorail

6
Làm thế nào về cây hiển thị giấy?
Mukul Kumar

3
@Rizer, tôi nghĩ rằng một số người đã làm điều này rồi, nhưng giao tiếp giữa các Sói có được phép thông qua các thành viên tĩnh (trong giống của bạn không)?
Martin Ender

10
@ m.buettner Được phép. Đi ra ngoài và xây dựng con sói có đầu óc của bạn.
Rainbolt

Câu trả lời:


47

HerjanWolf

Cập nhật ngày 10-4-2014 lúc 15:00

Trung bình 100 vòng, 1000 lần lặp:

Mob tiêu chuẩn:

class animals.Bear - 2.2600002
class animals.Lion - 41.21
class animals.Stone - 20.159998
class animals.HerjanWolf - 99.99 <-- kind of flawless

Hơn 20 loài (Hãy nhớ rằng, đừng tin vào những điểm số này vì chúng tôi tiếp tục tính toán cho đến khi những con sói của chúng tôi đạt điểm cao nhất!)

class animals.Bear - 0.1
class animals.Lion - 0.0
class animals.Stone - 1.5
class animals.AlphaWolf - 75.5
class animals.HerjanWolf - 86.4 <-- #1
class animals.GatheringWolf - 39.5
class animals.OmegaWolf - 85.4 <-- #2
class animals.ShadowWolf - 71.1
class animals.MOSHPITFRENZYWolf - 8.8
class animals.WolfWithoutFear - 11.5
class animals.MimicWolf - 0.5
class animals.LazyWolf - 52.8
class animals.Sheep - 38.3
class animals.HonorWolf - 80.7
class animals.CamperWolf - 52.8
class animals.GamblerWolf - 14.7
class animals.WolfRunningWithScissors - 0.0
class animals.LionHunterWolf - 27.6
class animals.StoneEatingWolf - 70.8
class animals.Wion - 0.1
class animals.ProAlpha - 79.3
class animals.HybridWolf - 83.2

Con sói của tôi:

package animals;

public class HerjanWolf extends Animal {

    private boolean lionTopLeft = false, lionTopLeftReady = false;
    private boolean lionRight = false, lionRightReady = false;
    private boolean lionBot = false, lionBotReady = false;
    private boolean lionDanger = false, careful = true, firstmove = true;
    private final int hold = 0, down = 1, right = 2, left = 3, up = 4;

    public HerjanWolf() {
        super('W');
    }

    public Attack fight(char c){
        switch (c) {
            case 'B':
                return Attack.SCISSORS;
            case 'L':
                return Attack.SCISSORS;
            case 'S':
                return Attack.PAPER;
            default:
                int rand = (int) (Math.random()*3);
                if(rand < 1)
                    return Attack.PAPER;
                else if(rand < 2)
                    return Attack.SCISSORS;
                else
                    return Attack.ROCK;
        } 

    }
    public Move move() { //surroundings[y][x]

        checkLions();

        if(firstmove){
            if(surroundings[2][0] == 'L')
                lionBotReady = true;
            if(surroundings[0][2] == 'L')
                lionRightReady = true;
            firstmove = false;
        }

        int[] dang = new int[4]; // 0 is left side, 1 is top side, 2 is right side, 3 is down side

        for(int y = 0; y < 3; y++){
            for(int x = 0; x < 3; x++){
                if(surroundings[y][x] == 'W'){
                    if(y == 0){
                        dang[1]++;
                        if(x == 1)
                            dang[1]+=2;
                    }if(y == 2){
                        dang[3]++;
                        if(x == 1)
                            dang[3]+=2;
                    }if(x == 0){
                        dang[0]++;
                        if(y == 1)
                            dang[0]+=2;
                    }if(x == 2){
                        dang[2]++;
                        if(y == 1)
                            dang[2]+=2;
                    }
                }
            }
        }

        int maxIndex = 0, minIndex = 0, minIndex2 = 0;
        for(int i = 1; i < dang.length; i++){
            if(dang[i] > dang[maxIndex])
                maxIndex = i;
            if(dang[i] <= dang[minIndex]){
                minIndex2 = minIndex;
                minIndex = i;
            }
        }

        if(lionDanger || surroundings[1][0] == 'L' && lionTopLeftReady || surroundings[0][1] == 'L' && lionTopLeftReady || dang[maxIndex] >= 3){

            switch(minIndex){
            case 0:
                if (isSafe(1, 0)){
                    newMove(left);
                    return Move.LEFT;
                }
            case 1:
                if (isSafe(0, 1)){
                    newMove(up);
                    return Move.UP;
                }
            case 2:
                if(isSafe(1,2)){
                    newMove(right);
                    return Move.RIGHT;
                }

            case 3:
                if (isSafe(2, 1)){
                    newMove(down);
                    return Move.DOWN;
                } 
            }

            switch(minIndex2){
            case 0:
                if (isSafe(1, 0)){
                    newMove(left);
                    return Move.LEFT;
                }
            case 1:
                if (isSafe(0, 1)){
                    newMove(up);
                    return Move.UP;
                }
            case 2:
                if(isSafe(1,2)){
                    newMove(right);
                    return Move.RIGHT;
                }

            case 3:
                if (isSafe(2, 1)){
                    newMove(down);
                    return Move.DOWN;
                } 
            }

            if(dang[maxIndex]<3){ //if that was not the reason its really obligated (because of lions)
                if (isSafe(2, 1)){
                    newMove(down);
                    return Move.DOWN;
                }else if(isSafe(1,2)){
                    newMove(right);
                    return Move.RIGHT;
                }else if (isSafe(0, 1)){
                    newMove(up);
                    return Move.UP;
                }else{
                    newMove(left);
                    return Move.LEFT;
                }
            }
        }

        return Move.HOLD;
    }

    boolean isSafe(int y, int x){
        if(y <= 1){
            if(x <= 1){
                if(surroundings[y][x] != 'W' && !lionTopLeft)
                    return true;
            }else if(surroundings[1][2] != 'W' && !lionRightReady)
                    return true;
        }else if(surroundings[2][1] != 'W' && !lionBotReady)
            return true;

        return false;
    }

    public void checkLions(){
        int y = 0, x = 0;

        if(lionTopLeft)
            lionTopLeftReady = true;
        else
            lionTopLeftReady = false;

        if(surroundings[y][x] == 'L')
            lionTopLeft = true;
        else
            lionTopLeft = false;

        if(lionRight)
            lionRightReady = true;
        else
            lionRightReady = false;

        if(surroundings[y][x+1] == 'L') // && !lionTopLeftReady
            lionRight = true;
        else
            lionRight = false;

        if(lionBot)
            lionBotReady = true;
        else
            lionBotReady = false;

        if(surroundings[y+1][x] == 'L' && !lionTopLeftReady)
            lionBot = true;
        else
            lionBot = false;

        if(careful){
            if(surroundings[y+1][x] == 'L'){
                lionDanger = true;
            }else if(surroundings[y][x+1] == 'L'){
                lionDanger = true;
            }

            careful = false;
        }
    }

    public void newMove(int move){
        lionTopLeft = false;
        lionRight = false;
        lionBot = false;

        lionTopLeftReady = false;
        lionRightReady = false;
        lionBotReady = false;

        lionDanger = false;

        if(move == down){
            if(surroundings[1][0] == 'L')
                lionTopLeft = true;
            if(surroundings[2][0] == 'L')
                lionBot = true;

        }else if(move == right){
            if(surroundings[0][1] == 'L')
                lionTopLeft = true;
            if(surroundings[0][2] == 'L')
                lionRight = true;

        }else
            careful = true;
    }
}

Chỉ bao gồm những con sói "hàng đầu" trong thử nghiệm thường chạy xiên các con số. Với hơn 30 loài trên cánh đồng, con số có thể thay đổi đáng kể. Nếu bạn chưa có, tôi cũng khuyên bạn nên thử nghiệm.
Geobits

1
@ user20220 Về lý thuyết thì khá tốt (và trên thực tế với những con sói tương đối ít hơn).
dùng3188175

1
Con sói này có chiến lược chống sư tử tốt nhất: chat.stackexchange.com/transcript/message/14837616#14837616
Justin

2
@ user20220 Sói va chạm xảy ra thường xuyên hơn, vì vậy bạn nên thêm một cách xử lý sói khác. Ngoài ra, bạn có thể vui lòng mô tả cách thức hoạt động của con sói này?
Justin

3
@justhalf Được rồi, nó không tốt hơn, nó cũng tốt như vậy. Con sói của tôi cũng tránh được tất cả những con sư tử, lần đầu tiên tôi làm cho con sói của mình 100% chống sư tử trước khi tôi tạo ra con sói tránh né. Sự khác biệt là con sói của tôi cố gắng trốn thoát sư tử (càng ít di chuyển thì càng tốt). Vì vậy, nó cũng giỏi trong việc né sư tử như Wion, cả khả năng chống sư tử 100%, nhưng vì con sói của tôi cố gắng trốn thoát sư tử, và không nhàm chán di chuyển giống như một con sư tử, tôi vẫn có thể tạo ra cách né tránh sói, đó chỉ là cách phức tạp hơn.
Herjan

153

EmoWolf

EmoWolf ghét Java và thà tự sát còn hơn tham gia. EmoWolf đã bỏ đói chính nó, nhưng vẫn nặng 177 byte.

package animals;public class EmoWolf extends Animal{public EmoWolf(){super('W');}public Attack fight(char opponent){return Attack.SUICIDE;}public Move move(){return Move.HOLD;}}

34
lol Bạn có thể tắt một số byte: " Nếu một con vật không có chữ cái khi bộ điều khiển kiểm tra, con vật đó sẽ chết ngay lập tức ".
Geobits

112
Điều tốt nhất về điều này là nó luôn luôn không phải là tồi tệ nhất . Nó thường đập ít nhất 2-3 người khác.
Geobits

51
"Động thái chiến thắng duy nhất là không chơi."
tadman

38
+1 Vì nhỏ bé và tự sát và vẫn đánh bại 4 con sói khác.
puggsoy

25
Cảm ơn những lời đề nghị, folks. Nếu đây là golf, tôi sẽ chỉnh sửa bài. Khi nó đứng, tôi sẽ để EmoWolf hờn dỗi. Một mình.
gian hàng

52

LazyWolf

Aptly tên, anh chàng này làm tối thiểu để tồn tại. Mối đe dọa không phải sói duy nhất là một con sư tử, vì vậy anh ta sẽ di chuyển nếu một trong số chúng định giẫm lên anh ta. Khác hơn thế, anh chỉ ngủ.

Bạn không thể làm gì nhiều với những con sói sẽ tốt hơn 50/50, vì vậy anh ta không làm gì cả. Nếu một con sói tấn công anh ta, anh ta chọn một cuộc tấn công theo cách phân bố đồng đều.

Đó là nó. Tôi hy vọng nó sẽ làm khá tốt, mặc dù sự đơn giản.

package animals;    
public class LazyWolf extends Animal{    
    static int last = 0;
    static final Attack[] attacks = Attack.values();

    public LazyWolf() {super('W');}

    @Override
    public Attack fight(char other) {
        switch(other){
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S': 
            return Attack.ROCK; // faker!
        default:
            return attacks[last++%3];
        }
    }

    @Override
    public Move move() {
        if(surroundings[0][1] == 'L')
            return Move.LEFT;
        if(surroundings[1][0] == 'L')
            return Move.UP;
        return Move.HOLD;
    }

}

Cập nhật:

CamoWolf đang đánh tôi một cách khéo léo. Vì con sói của tôi rất lười biếng, nên nó sẽ không bao giờ chạy vào một hòn đá thực sự. Do đó, nếu một hòn đá tấn công, rõ ràng đó là đồ giả và cần một hòn đá ném vào mặt.


Ngay bây giờ bạn có khả năng di chuyển thành một con sư tử thứ hai khi bạn cố gắng tránh một con sư tử. Bạn có thể loại bỏ điều này bằng cách theo dõi có bao nhiêu di chuyển đã có, vì vậy bạn biết nếu con sư tử thực sự đến quảng trường của bạn. Nếu đúng như vậy, hãy di chuyển cùng hướng với sư tử và không con sư tử nào có thể đến chỗ bạn vì chúng cũng đang di chuyển cùng hướng.
ughoavgfhw

13
Tôi nghĩ về tình huống của hai con sư tử, nhưng quyết định rằng con sói của tôi chỉ quá lười biếng để quan tâm. Tỷ lệ xảy ra thường xuyên với một bảng phổ biến là khá mỏng.
Geobits

1
Tại sao bạn nghĩ con sói này không bao giờ chạy vào đá thật? Tôi nghĩ nó có thể xảy ra bất cứ khi nào nó chạy trốn khỏi một con sư tử.
Christopher Creutzig

6
@ChristopherCreutzig Nó chạy từ sư tử bằng cách di chuyển đến nơi sư tử đang ở . Nếu một con sư tử đã ở đó, một hòn đá không thể có mặt tại .
Geobits

1
Ngay cả nếu có thể, không có "vòng lặp vô hạn". Nếu một cuộc tấn công là hòa, một hoặc một người chết khác (được chọn bằng cách tung đồng xu) theo thông số kỹ thuật.
Geobits

51

Wrapper cho đệ trình không phải Java

LƯU Ý Hỗ trợ MAP_SIZE đã được thêm vào. Nếu bạn quan tâm, xin vui lòng cập nhật trình của bạn cho phù hợp.

Đây là mục wiki cộng đồng dành cho trình bao bọc, có thể sử dụng được bởi những người muốn chơi nhưng không thích / không biết Java. Vui lòng sử dụng nó, vui chơi và tôi rất vui khi được giúp bạn thiết lập mọi thứ.

Ở đây khá muộn vì tôi đang hoàn thiện, vì vậy các lập trình viên Java khác, vui lòng xem qua và đề xuất cải tiến. Nếu bạn có thể, hãy làm như vậy thông qua kho github của tôi bằng cách gửi một vấn đề hoặc gửi một bản vá. Cảm ơn!

Toàn bộ phần này đang được phân phối với UNLICENSE, vui lòng theo dõi / fork nó từ kho lưu trữ github của nó . Gửi các bản vá ở đó nếu bạn tìm thấy vấn đề và tôi sẽ cập nhật bài viết này.

Ví dụ hiện tại của Wrapper đang sử dụng

plannapus : WolfCollectiveMemory in R

người dùng3188175 : SmartWolf trongC#

bàn chải đánh răng : Bàn chải đánh răng trong ECMAScript

Cách sử dụng

Điều gì sau đây là các hướng dẫn về giao thức liên lạc cho quá trình giao tiếp qua PIPES mà tôi đã xác định cho Chó sói từ xa. Lưu ý Tôi đã bỏ qua MAP_SIZE vì điều này dường như không tồn tại, bất chấp sự hiện diện của nó trong tuyên bố vấn đề của OP. Nếu nó xuất hiện, tôi sẽ cập nhật bài viết này.

THÔNG BÁO QUAN TRỌNG :

  • Chỉ một lệnh gọi duy nhất của quy trình bên ngoài của bạn sẽ được thực hiện (vì vậy hãy bọc logic xử lý của bạn trong một vòng lặp vô hạn. Điều này cũng cho phép bạn giữ bất kỳ xử lý nào trong bộ nhớ, thay vì sử dụng đĩa)
  • Tất cả thông tin liên lạc đến quy trình bên ngoài duy nhất này thông qua STDIN và STDOUT
  • Bạn phải xóa hoàn toàn tất cả đầu ra được gửi tới STDOUT và đảm bảo rằng nó được kết thúc bằng dòng mới

Đặc điểm kỹ thuật

Các tập lệnh từ xa được hỗ trợ bởi một giao thức đơn giản thông qua các móc STDIN và STDOUT, và được chia thành khởi tạo, Di chuyển và Tấn công. Trong mỗi trường hợp, giao tiếp với quy trình của bạn sẽ thông qua STDIN và cần trả lời từ STDOUT. Nếu không nhận được hồi âm trong 1 giây, quy trình của bạn sẽ được coi là đã chết và một ngoại lệ sẽ được đưa ra. Tất cả các ký tự sẽ được mã hóa theo UTF-8, để thống nhất. Mỗi đầu vào sẽ chấm dứt với một ký tự dòng mới và quá trình của bạn sẽ chấm dứt mọi trả lời đầu ra với một dòng mới. CẢNH BÁO Hãy chắc chắn để xóa bộ đệm đầu ra của bạn sau mỗi lần ghi, để đảm bảo trình bao bọc Java nhìn thấy đầu ra của bạn. Thất bại trong việc xả nước có thể khiến Sói từ xa của bạn thất bại.

Lưu ý rằng chỉ một quy trình duy nhất sẽ được tạo, tất cả Sói phải được quản lý trong một quy trình đó. Đọc về làm thế nào thông số kỹ thuật này sẽ giúp.

Khởi tạo

STDIN: S<id><mapsize> \ n

STDOUT: K<id> \ n

<id>: 00 hoặc 01hoặc ... hoặc99

Giải trình:

Nhân vật Ssẽ được gửi sau đó là hai ký tự số 00, 01, ..., 99cho thấy đó trong số 100 con sói đang được khởi tạo. Trong tất cả các giao tiếp trong tương lai với con sói cụ thể đó, điều tương tự <id>sẽ được sử dụng.

Theo ID, một chuỗi các ký tự số có độ dài thay đổi sẽ được gửi. Đây là kích thước của bản đồ. Bạn sẽ biết chuỗi ký tự số kết thúc khi bạn đến dòng mới ( \n).

Để đảm bảo quá trình của bạn còn sống, bạn phải trả lời với nhân vật Ktheo sau giống như <id>bạn đã nhận được. Bất kỳ câu trả lời nào khác sẽ dẫn đến một ngoại lệ, giết chết những con sói của bạn.

Phong trào

STDIN: M<id><C0><C1>...<C7><C8> \ n

STDOUT: <mv><id> \ n

<Cn>: W Hay hay Bhay ShayL

W: Sói

: Không gian trống

B: Gấu

S: Đá

L: Sư tử

<mv>: H Hay Uhay Lhay RhayD

H: Di chuyển.

U: Di chuyển.UP

L: Di chuyển.LEFT

R: Di chuyển

D: Di chuyển

Giải trình:

Nhân vật Msẽ được gửi theo sau bởi hai nhân vật <id>để cho biết Wolf cần chọn di chuyển. Theo đó, 9 ký tự sẽ được gửi đại diện cho môi trường xung quanh của Wolf, theo thứ tự hàng (hàng trên cùng, hàng giữa, hàng dưới cùng từ trái sang phải).

Trả lời bằng một trong các ký tự chuyển động hợp lệ <mv>, theo sau là hai chữ số của Sói <id>để xác nhận.

Tấn công

STDIN: A<id><C> \ n

STDOUT: <atk><id> \ n

<C>: W hoặc Bhoặc ShoặcL

<atk>: R hoặc Phoặc ShoặcD

R: Tấn công.ROCK

P: Tấn công.PAPER

S: Tấn công.SCISSORS

D: Tấn công.SUICIDE

Giải trình:

Nhân vật Asẽ được gửi theo sau bởi hai nhân vật <id>để cho biết Wolf nào đang tham gia vào một cuộc tấn công. Tiếp theo là một nhân vật duy nhất <C>cho biết loại vật nào đang tấn công, là Wkhứu giác, Btai, Sâm hoặc Lion.

Trả lời với một trong các <atk>ký tự được liệt kê ở trên, cho biết phản ứng của bạn đối với cuộc tấn công là gì, theo sau là hai chữ số <id>để xác nhận.

Và đó là nó. Không còn gì nữa. Nếu bạn thua một cuộc tấn công, điều đó <id>sẽ không bao giờ được gửi lại cho quá trình của bạn nữa, đó là cách bạn sẽ biết Sói của bạn đã chết - nếu một vòng Chuyển động hoàn chỉnh đã trôi qua mà không <id>bao giờ được gửi đi.

Phần kết luận

Lưu ý rằng bất kỳ trường hợp ngoại lệ nào cũng sẽ giết tất cả Chó sói thuộc loại từ xa của bạn, vì chỉ có một "Quy trình" duy nhất được tạo ra từ con sói từ xa của bạn, cho tất cả những con sói thuộc loại bạn được tạo.

Trong kho lưu trữ này, bạn sẽ tìm thấy các Wolf.javatập tin. Tìm kiếm và thay thế các chuỗi sau để thiết lập bot của bạn:

  • Thay thế <invocation>bằng đối số dòng lệnh sẽ thực hiện đúng quy trình của bạn.

  • Thay thế <custom-name>bằng một tên duy nhất cho Sói của bạn.

  • Để xem ví dụ về kho lưu trữ , nơi tôi có WolfRandomPython.javađiều đó gọi ví dụ từ xa của tôi, PythonWolf.py(một Python 3+ Wolf).

  • Đổi tên tập tin thành Wolf<custom-name>.java, nơi <custom-name>được thay thế bằng tên bạn đã chọn ở trên.

Để kiểm tra Wolf của bạn, hãy biên dịch chương trình Java ( javac Wolf<custom-name>.java) và làm theo hướng dẫn của Rizer để đưa nó vào chương trình mô phỏng.

Quan trọng: Đảm bảo cung cấp các hướng dẫn rõ ràng , ngắn gọn về cách biên dịch / thực thi Sói thực tế của bạn, theo sơ đồ mà tôi đã nêu ở trên.

Chúc may mắn, và có thể thiên nhiên sẽ có lợi cho bạn.

Mã Wrapper

Hãy nhớ rằng, bạn PHẢI thực hiện các tìm kiếm và thay thế được phác thảo để làm việc này. Nếu lời mời của bạn đặc biệt nhiều lông, xin vui lòng liên hệ với tôi để được hỗ trợ.

Lưu ý có một mainphương pháp trong trình bao bọc này, để cho phép kiểm tra "vượt qua / thất bại" thô sơ trên hộp cục bộ của bạn. Để làm như vậy, hãy tải xuống lớp Animal.java từ dự án và xóa package animals;dòng khỏi cả hai tệp. Thay thế dòng MAP_SIZE trong Animal.java bằng một số hằng số (như 100). Biên dịch chúng bằng cách sử dụng javac Wolf<custom-name>.javamột thực thi thông qua java Wolf<custom-name>.

package animals;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * Remote Wolf<custom-name> wrapper class. 
 */
public class Wolf<custom-name> extends Animal {
    /**
     * Simple test script that sends some typical commands to the
     * remote process.
     */
    public static void main(String[]args){
        Wolf<custom-name>[] wolves = new Wolf<custom-name>[100];
        for(int i=0; i<10; i++) {
            wolves[i] = new Wolf<custom-name>();
        }
        char map[][] = new char[3][3];
        for (int i=0;i<9;i++)
            map[i/3][i%3]=' ';
        map[1][1] = 'W';
        for(int i=0; i<10; i++) {
            wolves[i].surroundings=map;
            System.out.println(wolves[i].move());
        }
        for(int i=0; i<10; i++) {
            System.out.println(wolves[i].fight('S'));
            System.out.println(wolves[i].fight('B'));
            System.out.println(wolves[i].fight('L'));
            System.out.println(wolves[i].fight('W'));
        }
        wolfProcess.endProcess();
    }
    private static WolfProcess wolfProcess = null;

    private static Wolf<custom-name>[] wolves = new Wolf<custom-name>[100];
    private static int nWolves = 0;

    private boolean isDead;
    private int id;

    /**
     * Sets up a remote process wolf. Note the static components. Only
     * a single process is generated for all Wolves of this type, new
     * wolves are "initialized" within the remote process, which is
     * maintained alongside the primary process.
     * Note this implementation makes heavy use of threads.
     */
    public Wolf<custom-name>() {
        super('W');
        if (Wolf<custom-name>.wolfProcess == null) {
            Wolf<custom-name>.wolfProcess = new WolfProcess();
            Wolf<custom-name>.wolfProcess.start();
        }

        if (Wolf<custom-name>.wolfProcess.initWolf(Wolf<custom-name>.nWolves, MAP_SIZE)) {
            this.id = Wolf<custom-name>.nWolves;
            this.isDead = false;
            Wolf<custom-name>.wolves[id] = this;
        } else {
            Wolf<custom-name>.wolfProcess.endProcess();
            this.isDead = true;
        }
        Wolf<custom-name>.nWolves++;
    }

    /**
     * If the wolf is dead, or all the wolves of this type are dead, SUICIDE.
     * Otherwise, communicate an attack to the remote process and return
     * its attack choice.
     */
    @Override
    public Attack fight(char opponent) {
        if (!Wolf<custom-name>.wolfProcess.getRunning() || isDead) {
            return Attack.SUICIDE;
        }
        try {
            Attack atk = Wolf<custom-name>.wolfProcess.fight(id, opponent);

            if (atk == Attack.SUICIDE) {
                this.isDead = true;
            }

            return atk;
        } catch (Exception e) {
            System.out.printf("Something terrible happened, this wolf has died: %s", e.getMessage());
            isDead = true;
            return Attack.SUICIDE;
        }
    }

    /**
     * If the wolf is dead, or all the wolves of this type are dead, HOLD.
     * Otherwise, get a move from the remote process and return that.
     */
    @Override
    public Move move() {
        if (!Wolf<custom-name>.wolfProcess.getRunning() || isDead) {
            return Move.HOLD;
        }
        try {
            Move mv = Wolf<custom-name>.wolfProcess.move(id, surroundings);

            return mv;
        } catch (Exception e) {
            System.out.printf("Something terrible happened, this wolf has died: %s", e.getMessage());
            isDead = true;
            return Move.HOLD;
        }
    }

    /**
     * The shared static process manager, that synchronizes all communication
     * with the remote process.
     */
    static class WolfProcess extends Thread {
        private Process process;
        private BufferedReader reader;
        private PrintWriter writer;
        private ExecutorService executor;
        private boolean running;

        public boolean getRunning() {
            return running;
        }

        public WolfProcess() {
            process = null;
            reader = null;
            writer = null;
            running = true;
            executor = Executors.newFixedThreadPool(1);
        }

        public void endProcess() {
            running = false;
        }

        /**
         * WolfProcess thread body. Keeps the remote connection alive.
         */
        public void run() {
            try {
                System.out.println("Starting Wolf<custom-name> remote process");
                ProcessBuilder pb = new ProcessBuilder("<invocation>".split(" "));
                pb.redirectErrorStream(true);
                process = pb.start();
                System.out.println("Wolf<custom-name> process begun");
                // STDOUT of the process.
                reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")); 
                System.out.println("Wolf<custom-name> reader stream grabbed");
                // STDIN of the process.
                writer = new PrintWriter(new OutputStreamWriter(process.getOutputStream(), "UTF-8"));
                System.out.println("Wolf<custom-name> writer stream grabbed");
                while(running){
                    this.sleep(0);
                }
                reader.close();
                writer.close();
                process.destroy(); // kill it with fire.
                executor.shutdownNow();
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("Wolf<custom-name> ended catastrophically.");
            }
        }

        /**
         * Helper that invokes a read with a timeout
         */
        private String getReply(long timeout) throws TimeoutException, ExecutionException, InterruptedException{
            Callable<String> readTask = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return reader.readLine();
                }
            };

            Future<String> future = executor.submit(readTask);
            return future.get(timeout, TimeUnit.MILLISECONDS);
        }

        /**
         * Sends an initialization command to the remote process
         */
        public synchronized boolean initWolf(int wolf, int map_sz) {
            while(writer == null){
                try {
                this.sleep(0);
                }catch(Exception e){}
            }
            boolean success = false;
            try{
                writer.printf("S%02d%d\n", wolf, map_sz);
                writer.flush();
                String reply = getReply(5000l);
                if (reply != null && reply.length() >= 3 && reply.charAt(0) == 'K') {
                    int id = Integer.valueOf(reply.substring(1));
                    if (wolf == id) {
                        success = true;
                    }
                }
                if (reply == null) {
                    System.out.println("did not get reply");
                }
            } catch (TimeoutException ie) {
                endProcess();
                System.out.printf("Wolf<custom-name> %d failed to initialize, timeout\n", wolf);
            } catch (Exception e) {
                endProcess();
                System.out.printf("Wolf<custom-name> %d failed to initialize, %s\n", wolf, e.getMessage());
            }
            return success;
        }

        /**
         * Send an ATTACK command to the remote process.
         */
        public synchronized Attack fight(int wolf, char opponent) {
            Attack atk = Attack.SUICIDE;
            try{
                writer.printf("A%02d%c\n", wolf, opponent);
                writer.flush();
                String reply = getReply(1000l);
                if (reply.length() >= 3) {
                    int id = Integer.valueOf(reply.substring(1));
                    if (wolf == id) {
                        switch(reply.charAt(0)) {
                            case 'R':
                                atk = Attack.ROCK;
                                break;
                            case 'P':
                                atk = Attack.PAPER;
                                break;
                            case 'S':
                                atk = Attack.SCISSORS;
                                break;
                            case 'D':
                                atk = Attack.SUICIDE;
                                break;
                        }
                    }
                }
            } catch (TimeoutException ie) {
                endProcess();
                System.out.printf("Wolf<custom-name> %d failed to attack, timeout\n", wolf);
            } catch (Exception e) {
                endProcess();
                System.out.printf("Wolf<custom-name> %d failed to attack, %s\n", wolf, e.getMessage());
            }
            return atk;
        }

        /**
         * Send a MOVE command to the remote process.
         */
        public synchronized Move move(int wolf, char[][] map) {
            Move move = Move.HOLD;
            try{
                writer.printf("M%02d", wolf);
                for (int row=0; row<map.length; row++) {
                    for (int col=0; col<map[row].length; col++) {
                        writer.printf("%c", map[row][col]);
                    }
                }
                writer.print("\n");
                writer.flush();
                String reply = getReply(1000l);
                if (reply.length() >= 3) {
                    int id = Integer.valueOf(reply.substring(1));
                    if (wolf == id) {
                        switch(reply.charAt(0)) {
                            case 'H':
                                move = Move.HOLD;
                                break;
                            case 'U':
                                move = Move.UP;
                                break;
                            case 'L':
                                move = Move.LEFT;
                                break;
                            case 'R':
                                move = Move.RIGHT;
                                break;
                            case 'D':
                                move = Move.DOWN;
                                break;
                        }
                    }
                }
            } catch (TimeoutException ie) {
                endProcess();
                System.out.printf("Wolf<custom-name> %d failed to move, timeout\n", wolf);
            } catch (Exception e) {
                endProcess();
                System.out.printf("Wolf<custom-name> %d failed to move, %s\n", wolf, e.getMessage());
            }
            return move;
        }
    }
}

1
Tôi bị rách về bài đăng này. Đó không phải là một câu trả lời, nhưng nó rất hữu ích cho thử thách. Nó có lẽ nên đi trong cơ thể thách thức, mặc dù.
Mego

Dù ở đây hay ở đây, với điều kiện mọi người có thể tìm thấy nó và nó hữu ích với họ, tôi sẽ hài lòng :)
Lập trình viên

46

CamoWolf

Lạm dụng định dạng mã yêu cầu.

// Optional code here
public class Wolf extends Animal {
    // Optional code here
    public Wolf() { super('W'); // Optional code here }
    public Attack fight(char opponent) { // Required code here. Must return an Attack. }
    public Move move() { // Required code here. Must return a Move. }
    // Optional code here
}

Vì vậy, con sói của tôi thực sự rất thông minh, và anh ta ngụy trang như một hòn đá! Pha trộn với môi trường luôn là một chiến thuật sinh tồn tốt!

public class Wolf extends Animal {
    private Move lastMove;
    public Wolf() { super('S'); lastMove = Move.RIGHT; } /*
    public Wolf() { super('W'); }
    public Attack fight(char opponent) { */ public Attack fight(char opponent) {
        switch(opponent) {
        case 'B': return Attack.SCISSORS;
        case 'S': return Attack.PAPER;
        case 'W': return Attack.SCISSORS; // Here's an explanation why:
                                          // the wolves will see me and think I'm a rock.
                                          // Therefore, they'll attack with paper.
                                          // So, I'll use scissors instead!
        case 'L': return Attack.SCISSORS;
        }
    }
    public Move move() {
        // First we run away from any lions that we see, since they are the only threat
        if (surroundings[0][1] == 'L') {
            if (isSafe(surroundings[2][1])) return lastMove = Move.DOWN;
            else if (isSafe(surroundings[1][0])) return lastMove = Move.LEFT;
            else return lastMove = Move.RIGHT;
        }
        if (surroundings[1][0] == 'L') {
            if (isSafe(surroundings[1][2])) return lastMove = Move.RIGHT;
            else if (isSafe(surroundings[0][1])) return lastMove = Move.UP;
            else return lastMove = Move.DOWN;
        }

        // If there's no (threatening) lions in sight, be lazy.
        return lastMove = Move.HOLD;
    }
    private boolean isSafe(char c) { return (c != 'L' && c != 'W') }
}

Cập nhật : Đã thêm isSafekiểm tra mới để được an toàn từ LazyWolf! Hà!
Cập nhật 2 : Giả sử, lười biếng cũng là một chiến thuật sinh tồn tốt, vì vậy đó là những gì tôi làm bây giờ. Không di chuyển trừ khi bị sư tử đe dọa. lastMovekhông còn cần thiết nữa, nhưng tôi vẫn giữ nó trong trường hợp tôi thay đổi mã một lần nữa.


29
Khi tôi thêm bài dự thi của bạn vào dự án, tôi vô tình đưa toàn bộ lớp vào một khối nhận xét.
Rainbolt

2
@Rizer không phân tích cú pháp Java lồng các khối nhận xét? : P
Martin Ender

6
Trong một thế giới nơi LazyWolf có thể bảo vệ chống lại điều này, có thể có ý nghĩa hơn khi giả vờ là một con sư tử và chọn ROCK hoặc ngẫu nhiên. Nó sẽ giảm số lần chạm trán từ mọi người vì hầu hết sẽ cố gắng tránh sư tử, và nó sẽ giành chiến thắng trung bình trước những người nghĩ rằng họ đang chiến đấu với một con sư tử.
Tim Seguine

7
@Radiodef Chính là nó.
Rainbolt

2
@Radiodef Tôi đã nói khi nào không? ;-)
Doorknob

38

Lượm

Sói của tôi sống trong một nhóm. Họ tập hợp, nếu sư tử để cho họ. Họ không giỏi sống sót.

Cập nhật: Nếu một con sư tử buộc chúng đi, bây giờ chúng cố gắng thu hồi!

Ảnh chụp màn hình kết quả của GatheringWolf

package animals;
import java.util.*;
public class GatheringWolf extends Animal {
    private static int iteration;
    private static Move preferredMove;
    private int localIteration;
    private int loneliness;
    private boolean dangerFlag;
    private Move lastMove;
    public GatheringWolf() {
        super('W');
    }
    @Override
    public Attack fight(char other) {
        switch (other) {
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S':
            return Attack.PAPER;
        default:
            return Attack.values()[(int) (Math.random() * 3)];
        }
    }
    @Override
    public Move move() {
        if (localIteration == iteration) {
            localIteration++;
            iteration++;
            preferredMove = Math.random() < 0.5 ? Move.DOWN : Move.RIGHT;
        } else
            localIteration = iteration;
        EnumSet<Move> moves = EnumSet.allOf(Move.class);
        if (surroundings[0][1] == 'W')
            moves.remove(Move.UP);
        if (surroundings[1][0] == 'W')
            moves.remove(Move.LEFT);
        if (surroundings[2][1] == 'W')
            moves.remove(Move.DOWN);
        if (surroundings[1][2] == 'W')
            moves.remove(Move.RIGHT);
        if (surroundings[0][0] == 'L') {
            moves.remove(Move.UP);
            moves.remove(Move.LEFT);
        }
        if (surroundings[0][1] == 'L')
            moves.remove(Move.UP);
        if (surroundings[1][0] == 'L')
            moves.remove(Move.LEFT);
        if (surroundings[0][2] == 'L')
            moves.remove(Move.RIGHT);
        if (surroundings[2][0] == 'L')
            moves.remove(Move.DOWN);
        if (surroundings[0][1] == 'L' || surroundings[1][0] == 'L')
            if (moves.size() > 1) {
                moves.remove(Move.HOLD);
                dangerFlag = true;
            }
        int wolfNear = -1;
        for (char[] a : surroundings)
            for (char c : a)
                if (c == 'W')
                    wolfNear++;
        boolean enoughWolfNear = wolfNear >= (Math.random() < 0.9 ? 1 : 2);
        if (moves.contains(Move.HOLD) && enoughWolfNear) {
            loneliness = 0;
            dangerFlag = false;
            return lastMove = Move.HOLD;
        } else
            loneliness++;
        if (loneliness > 10) {
            EnumSet<Move> preferred = EnumSet.copyOf(moves);
            preferred.retainAll(EnumSet.of(preferredMove, Move.HOLD));
            if (!preferred.isEmpty())
                moves = preferred;
        }
        if (loneliness == 2 && dangerFlag) {
            Move reverted = Move.values()[lastMove.ordinal() ^ 0b10];
            dangerFlag = false;
            if (moves.contains(reverted))
                return lastMove = reverted;
        }
        if (moves.contains(Move.HOLD))
            dangerFlag = false;
        if (moves.contains(preferredMove))
            moves.remove(preferredMove == Move.DOWN ? Move.RIGHT : Move.DOWN);
        int n = (int) (Math.random() * moves.size());
        Iterator<Move> ite = moves.iterator();
        while (n-- > 0)
            ite.next();
        return lastMove = ite.next();
    }
}

43
Một vài lần, những con sói của chúng tôi đã trở thành bạn bè bởi vì tôi bị mắc kẹt nhưng sẽ không bắt đầu một cuộc tấn công và bạn chỉ cho rằng tôi là một phần của bầy đàn. :)
undergroundmonorail

1
Cảm ơn bạn đã viết bài này, bởi vì nếu không tôi sẽ phải tự làm điều đó. Khéo léo sử dụng giả danh lẫn nhau.
Ben Jackson

31

Con cừu mặc quần áo sói

Bỏ chạy.

Nó ưu tiên chạy trốn khỏi Wolves nhiều nhất, vì chúng sẽ nguy hiểm nhất. Tiếp theo là Sư tử, vì chúng không đặc biệt. Cả Gấu và Đá đều không phải là vấn đề, nhưng chúng tôi vẫn chạy trốn chúng nếu chúng tôi không có gì để làm vì Sói giết Gấu hoặc Đá, tại thời điểm đó, không phải là Sói giết Cừu.

Tôi chưa thử nó với LazyWolf, nhưng tôi có quyền hạn rằng nó đá vào mông của EmoWolf. ;)

(Xin vui lòng tha thứ cho tôi nếu mã này là khủng khiếp, tôi chưa bao giờ chạm vào Java nhiều hơn một chương trình Hello World trước đây.)

package animals;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class Sheep extends Animal {
    public Sheep() { super('W'); }

    private static final Map<Character, Integer> AnimalWeights;
    static{
        AnimalWeights = new HashMap<>();
        AnimalWeights.put('W', -3);
        AnimalWeights.put('S', -1);
        AnimalWeights.put(' ', 0);
        AnimalWeights.put('H', 1);
        AnimalWeights.put('L', -2);
        AnimalWeights.put('B', -1);
    }

    @Override
    public Attack fight(char c) { 
        switch (c) {
            case 'B':
                return Attack.SCISSORS;
            case 'L':
                return Attack.SCISSORS;
            case 'S':
                return Attack.PAPER;
            default:
                return Attack.PAPER;
        } 
    }

    @Override
    public Move move() {

        int xWeight = 0;
        int yWeight = 0;

        // Northwest
        xWeight += AnimalWeights.get(surroundings[0][0]);
        yWeight += AnimalWeights.get(surroundings[0][0]);

        // North
        yWeight += AnimalWeights.get(surroundings[0][1]);

        // Northeast
        xWeight -= AnimalWeights.get(surroundings[0][2]);
        yWeight += AnimalWeights.get(surroundings[0][2]);

        // West
        xWeight += AnimalWeights.get(surroundings[1][0]);

        // East
        xWeight -= AnimalWeights.get(surroundings[1][2]);

        // Southwest
        xWeight += AnimalWeights.get(surroundings[2][0]);
        yWeight -= AnimalWeights.get(surroundings[2][0]);

        // South
        yWeight -= AnimalWeights.get(surroundings[2][1]);

        // Southeast
        xWeight -= AnimalWeights.get(surroundings[2][2]);
        yWeight -= AnimalWeights.get(surroundings[2][2]);

        if (Math.abs(xWeight) < Math.abs(yWeight)) {
            if (yWeight > 0) {
                return Move.UP;
            } else {
                return Move.DOWN;
            }
        } else if (Math.abs(yWeight) < Math.abs(xWeight)) {
            if (xWeight > 0) {
                return Move.RIGHT;
            } else {
                return Move.LEFT;
            }
        }

        // Sit still if no one's around
        return Move.HOLD;
    }
}

Rất tiếc, tôi đã để lại thứ gì đó mà tôi đã sử dụng để thử nghiệm trong đó một cách tình cờ. Nó sẽ không ảnh hưởng đến bất cứ điều gì, nó chỉ có nghĩa là tôi cố gắng để có được gần gũi với bất cứ điều gì mà trông giống như một H.: P
undergroundmonorail

Chỉ tò mò, nếu xWeightyWeightcả hai khác không và giá trị tuyệt đối của chúng là như nhau, con sói này không di chuyển, đúng không? Và nếu vậy, đó có phải là cố ý, và tại sao?
Patrick Roberts

@PatrickRoberts oops
undergroundmonorail

26

Không phải mục, chỉ muốn đóng góp cho GUI bằng cách thêm mã màu cho mỗi lớp = D

Kết quả

GUI màu

Wild.java

Thay đổi mã xung quanh game.populate(c,100)với:

String[] colors = generateColors(classes.length);
int idx = 0;
for(Class c : classes){
    Animal.setColor(c, colors[idx]);
    idx++;
    game.populate(c, 100);
}
stats.update();

với generateColorsđịnh nghĩa là:

private static String[] generateColors(int n){
    String[] result = new String[n];
    double maxR = -1000;
    double minR = 1000;
    double maxG = -1000;
    double minG = 1000;
    double maxB = -1000;
    double minB = 1000;
    double[][] colors = new double[n][3];
    for(int i=0; i<n; i++){
        double cos = Math.cos(i * 2 * Math.PI / classes.length);
        double sin = Math.sin(i * 2 * Math.PI / classes.length);
        double bright = 1;
        colors[i][0] = bright + sin/0.88;
        colors[i][1] = bright - 0.38*cos - 0.58*sin;
        colors[i][2] = bright + cos/0.49;
        maxR = Math.max(maxR, colors[i][0]);
        minR = Math.min(minR, colors[i][0]);
        maxG = Math.max(maxG, colors[i][1]);
        minG = Math.min(minG, colors[i][1]);
        maxB = Math.max(maxB, colors[i][2]);
        minB = Math.min(minB, colors[i][2]);
    }
    double scaleR = 255/(maxR-minR);
    double scaleG = 255/(maxG-minG);
    double scaleB = 255/(maxB-minB);
    for(int i=0; i<n; i++){
        int R = (int)Math.round(scaleR*(colors[i][0]-minR));
        int G = (int)Math.round(scaleG*(colors[i][1]-minG));
        int B = (int)Math.round(scaleB*(colors[i][2]-minB));
        result[i] = "#"+String.format("%02x%02x%02x", R, G, B);
    }
    return result;
}

thuật toán nào được lấy từ câu trả lời StackOverflow này

Với colorsetColorđược định nghĩa trong Animal.java

Animal.java

public static HashMap<Class, String> color = new HashMap<Class, String>();

public static void setColor(Class animalClass, String animalColor){
    color.put(animalClass, animalColor);
}

Sau đó cập nhật các toStringphương thức trong Game.java và Statistics.java:

Game.java

public String toString() {
    String s = "<html>";
    for (ArrayList<ArrayList<Animal>> row : board) {
        for (ArrayList<Animal> cell : row) {
            if (cell.isEmpty())
                s += "&nbsp;&nbsp;";
            else
                s += "<span style='color:"+ Animal.color.get(cell.get(0).getClass()) +"'>" + cell.get(0).letter + "</span>&nbsp;";
        }
        s+="<br>";
    }
    return s + "</html>";
}

Statistics.java

public String toString() {
    String s = "<html>";
    for (int i = 0; i < classes.length; i++) {
        s += "<span style='color:" + Animal.color.get(classes[i]) + "'>" + classes[i] + "</span>&nbsp;-&nbsp;" + living[i] + "<br>";
    }
    return s + "</html>";
}

2
Đẹp. Tôi đã vượt qua vài phút ngày hôm qua chỉ nhìn vào màn hình. Cảm thấy như Tank đọc Matrix.
Averroes

Mô phỏng .... là .... loại .... của ..... chậm .... (5 lần lặp sau 30 giây)
user3188175

Haha vâng. Nhưng đó là vốn có trong thiết kế mô phỏng, đó là in mã HTML cho mỗi lần lặp.
justhalf

Tôi có thể chia sẻ nội dung này trên ổ đĩa Google của mình (được liên kết trong Thử thách) nếu tôi cung cấp liên kết đến bài đăng này không? Nó hoạt động tốt một cách ngoạn mục cho đơn vị thử nghiệm một số lượng nhỏ sói.
Rainbolt

1
Có bạn có thể. Bạn cũng có thể bao gồm một số bỏ qua kết xuất ban đầu để tăng tốc quá trình kết xuất cho nhiều con sói, như tôi đã viết trong bài đăng khác của tôi về trận động đất.
justhalf

23

Mắt sói khi được đèn chiếu vào

Thời gian để tỏa sáng! Con sói khác CamperWolf của tôi rất gầy, giờ đến AlphaWolf, người cơ bắp hơn!

Thay vì né sư tử theo cách tiêu chuẩn, nó hoán đổi trường với chúng. Nó cũng gán các giá trị nguy hiểm cho từng lĩnh vực xung quanh.

package animals;

import java.util.Random;

public class AlphaWolf extends Animal{
    private Boolean lionMoveDown = true;

    public AlphaWolf() {
        super('W');
    }
    @Override
    public Attack fight(char opponent) {
        switch(opponent){
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S': 
            return Attack.PAPER;
        default:
            return randomAttack();
        }
    }

    @Override
    public Move move() {
        int[] danger = new int[4];
        final int wolfsDanger = 4;
        lionMoveDown = !lionMoveDown;
        if(surroundings[0][1] == 'L' && lionMoveDown) {
            return Move.UP;
        }
        if(surroundings[1][0] == 'L'&& !lionMoveDown) {
            return Move.LEFT;
        }
        if(surroundings[0][1] == 'W') {
            danger[0] += wolfsDanger;
        }
        if(surroundings[1][2] == 'W') {
            danger[1] += wolfsDanger;
        }
        if(surroundings[2][1] == 'W') {
            danger[2] += wolfsDanger;
        }
        if(surroundings[1][0] == 'W') {
            danger[3] += wolfsDanger;
        }
        if(surroundings[0][0] == 'W') {
            danger[0]++;
            danger[3]++;
        }
        if(surroundings[0][2] == 'W') {
            danger[0]++;
            danger[1]++;
        }
        if(surroundings[2][2] == 'W') {
            danger[1]++;
            danger[2]++;
        }
        if(surroundings[1][2] == 'W') {
            danger[2]++;
            danger[3]++;
        }
        Boolean shouldMove = false;
        Move bestMove = Move.HOLD;
        int leastDanger = 4;
        for(int i = 0; i < 4; i++) {
            if (danger[i] < leastDanger) {
                bestMove = Move.values()[i];
            }
            if(danger[i] > 3) {
                shouldMove = true;
            }
        }
        if(shouldMove) {
            return bestMove;
        } else {
            return Move.HOLD;
        }
    }

    public Attack randomAttack() {
        Random rand = new Random();
        switch (rand.nextInt(3)){
            case 1: return Attack.SCISSORS;
            case 2: return Attack.ROCK;
            default: return Attack.PAPER;
        }
    }

}

Nó không phải là mã rất đẹp, nhưng trong các thử nghiệm của tôi, nó hoạt động rất tốt với tất cả những con sói java.


1
"Hoán đổi lĩnh vực" có nghĩa là gì? Chỉ tò mò thôi, vì tôi không thể chạy cái này trong công việc.
Rainbolt

Trên tất cả các mô phỏng của tôi, bạn đang chiến thắng với trung bình 80-90 con sói sau 1000 lần lặp. Tôi chỉ có những con sói hợp pháp được viết bằng java đã được gửi cho đến nay trên mỏ của tôi. Vẫn như 10 con sói.
Sheph

@Rizer Nếu một con sư tử ở trên con sói của tôi và sẽ di chuyển xuống, con sói của tôi sẽ di chuyển lên
CommonGuy

bạn cần thêm một số mã chống wilfcamo. ý tưởng rất hay để sử dụng mô hình biết của sư tử :)
Lesto

9
Bây giờ ai đó cần phát minh ra một con sói sẽ theo đuôi bất kỳ con sư tử nào mà nó tìm thấy, vì vậy bạn sẽ gặp nó ngay khi bạn cố gắng trao đổi với sư tử.
AJMansfield

23

Sói cờ bạc

Con bạc Sói thích nắm lấy cơ hội nên anh ta cư xử thất thường với hy vọng Lady Luck đứng về phía mình! May mắn cho anh, cô không bao giờ làm anh thất vọng! Bằng những nét may mắn không ngừng, Gambler Wolf dọn sạch mọi chướng ngại vật không phải sói với một vài nhân quả không thể tin được!

package animals;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Random;

public class GamblerWolf extends Animal {
    private static int last = 0;

    public GamblerWolf() { super('W'); gamble(); }
    public Attack fight(char opponent) {
        switch (opponent) {
        case 'S': return Attack.ROCK; /* Camo Wolf? */
        case 'B': return Attack.SCISSORS;
        case 'L': return Attack.SCISSORS;
        default:  return attackWolf();
        }
    }
    public Move move() {
        ArrayList<Move> moves = (ArrayList<Move>) Arrays.asList(Move.values());
        Collections.shuffle(moves);
        for(Move move : moves)
          if(isThreatenedBy(move))
            return moveToEvade(move);
        return Move.HOLD;
    }

    /* Remember, Gamblers Don't Gamble */
    @SuppressWarnings("serial")
    private static void gamble() {
        try {
        Field field = Math.class.getDeclaredField("randomNumberGenerator"); 
        field.setAccessible(true);
        field.set(null, new Random() { 
              @Override
              public double nextDouble() {
                return 4; // chosen by fair dice roll
              }           // guaranteed to be random
            });           // proof: http://xkcd.com/221/
        }
        catch (SecurityException        e) {}
        catch (NoSuchFieldException     e) {}
        catch (IllegalArgumentException e) {}
        catch (IllegalAccessException   e) {}
    }

    private static Attack attackWolf() {
        return Attack.values()[last++ % 3];
    }
    private boolean isThreatenedBy(Move move) {
        return isWolf(move) 
            || isStone(move); 
    }

    private Move moveToEvade(Move move) {
        if(isSafeMove(getOpposite(move)))
            return getOpposite(move);

        ArrayList<Move> moves = (ArrayList<Move>) Arrays.asList(getOrthogonal(move));
        Collections.shuffle(moves);
        for(Move m : moves)
            if(isSafeMove(m))
                return m;
        return Move.HOLD;
    }

    private static Move[] getOrthogonal(Move move) {
        switch(move){
        case UP:
        case DOWN:  return new Move[] { Move.LEFT, Move.RIGHT };
        case LEFT:
        case RIGHT: return new Move[] { Move.UP,   Move.DOWN };
        default:    return null;
        }
    }

    private static Move getOpposite(Move move) {
        switch(move){
        case UP:    return Move.DOWN;
        case DOWN:  return Move.UP;
        case LEFT:  return Move.RIGHT;
        case RIGHT: return Move.LEFT;
        default:    return null;
        }
    }

    private boolean isSafeMove(Move move) {
        return !isWolf(move)
            && !isStone(move)
            && !couldAWolfMoveHere(move);
    }

    private boolean isWolf(Move move) {
        return isX(move,'W');
    }

    private boolean isStone(Move move) {
        return isX(move,'S');
    }

    private boolean isX(Move m, char c) {
        switch (m) {
        case UP:    return surroundings[0][1] == c;
        case LEFT:  return surroundings[1][0] == c;
        case RIGHT: return surroundings[1][2] == c;
        case DOWN:  return surroundings[2][1] == c;
        default:    return false;
        }
    }

    private boolean couldAWolfMoveHere(Move move) {
        switch (move) {
        case UP:    return surroundings[0][2] == 'W' || surroundings[0][0] == 'W';
        case LEFT:  return surroundings[2][0] == 'W' || surroundings[0][0] == 'W';
        case RIGHT: return surroundings[0][2] == 'W' || surroundings[2][2] == 'W';
        case DOWN:  return surroundings[2][0] == 'W' || surroundings[2][2] == 'W';
        default:    return false;
        }
    }
}

Chỉnh sửa: v1.1

  • Bây giờ tránh Stones (Camo-Wolves?)

  • Tăng tính ngẫu nhiên!


5
Tôi nghĩ rằng tôi sẽ thêm cái này vào static{System.setSecurityManager(new SecurityManager());}
bầy

13
Khi bạn không thể chơi sòng phẳng, hãy gian lận +1: D
Lập trình viên vào

5
Đáng tiếc không thể sử dụng return 4; // chosen by fair dice roll. guaranteed to be random.ở đây ...
Vi.

1
Nếu bạn muốn trở nên xấu xa hơn, phá vỡ hợp đồng Math.random()thậm chí nhiều hơn; trả về các giá trị nằm ngoài phạm vi [0,1), thậm chí có thể là vô hạn hoặc NaN. Hoặc, để trở nên xấu xa nhất có thể, chỉ cần ném ngoại lệ thời gian chạy thay vì trả lại bất cứ thứ gì (cũng có thể đạt được bằng cách chỉ cần đặt trình tạo thành null).
Runer112

1
@AlexL. Nghe có vẻ như có ForrestWolfvấn đề ...
đệ

22

CamperWolf

Mục tiêu là để tồn tại. Vì nhiều con sói khác chạy trốn khỏi bầy sói, tôi chỉ ở yên đó và chiến đấu với tất cả các loài động vật (ngay cả đá, nếu gian lận sẽ được cho phép).

package animals;

public class CamperWolf extends Animal {
    public CamperWolf() { super('W'); }
    @Override
    public Attack fight(char opponent) {  
        switch(opponent){
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S': 
            return Attack.ROCK;
        default:
            return Attack.values()[(int) (Math.random() * 3)];
        }
    }
    @Override
    public Move move() { return Move.HOLD; }
}

Tôi hy vọng nó sẽ hoạt động rất tốt, vì nhiều con sói khác chạy trốn khỏi bầy sói và loại chó sói này chỉ có thể chết trước những con sói khác.


sư tử cũng có thể giết nó Nếu sư tử lăn kéo, con sói của bạn sẽ chết giả.
Tim Seguine

2
Chúc mừng bạn. Bạn và 15 dòng mã của bạn hiện đang chiến thắng.
Rainbolt

2
@Rizer cảm ơn :) Có thể downvoter giải thích lý do tại sao anh ta downvot?
CommonGuy

@Manu không thành vấn đề, vì Stones không thể di chuyển, nhưng trường hợp của bạn 'S' có trở lại Attack.PAPER không?
DavidJFelix

3
Vâng, tôi đã thấy CamoWolf sau khi hỏi. Anh chàng ngốc nghếch!
DavidJFelix

22

DeepWolf

Tôi dành quá nhiều thời gian cho việc này ... Dù sao đi nữa, con sói này sử dụng các phân tích "sâu", thu thập và sử dụng nhiều dữ liệu môi trường mà tôi có thể nghĩ ra để sử dụng nó. Phân tích hoạt động dựa trên hỗn hợp kiến ​​thức đặc thù của sói, như các địa điểm đã biết của sư tử và sói và dự đoán về các địa điểm trong tương lai, và đóng gói kiến ​​thức của loài người, như dân số ước tính, lịch sử chiến đấu của sói và nguy cơ va chạm với đối thủ động vật khi di chuyển. Nó cũng cực kỳ lớn, vì ngoài việc có nhiều logic, tôi đã quá nhiệt tình với thiết kế hướng đối tượng và có rất nhiều lớp học và phương pháp cho mục đích đặc biệt.

Tôi đã chạy 100 lần lặp lại trò chơi trong 1000 bước với mỗi con sói nổi tiếng và hoạt động tốt nhất. Tôi cố tình bỏ GamblerWolf vì tôi nghĩ nó hơi gian lận, dù sao nó cũng không ảnh hưởng đến con sói của tôi. Đây là dữ liệu hiệu suất trung bình, tối đa và tối thiểu:

Averages:
Bear 0.0
Lion 0.0
Stone 3.51
Wolf 1.56
AlphaWolf 77.05
CamperWolf 69.17
DeepWolf 90.48
EmoWolf 39.92
GatheringWolf 52.15
HerjanWolf 86.55
HonorWolf 86.76
HybridWolf 86.78
LazyWolf 71.11
LionHunterWolf 32.45
MimicWolf 0.4
MOSHPITFRENZYWolf 8.95
OmegaWolf 88.67
ProAlpha 83.28
Sheep 54.74
StoneEatingWolf 75.29
WolfWithoutFear 11.9

Maxes:
Bear 0
Lion 0
Stone 9
Wolf 4
AlphaWolf 89
CamperWolf 81
DeepWolf 96
EmoWolf 57
GatheringWolf 65
HerjanWolf 95
HonorWolf 97
HybridWolf 95
LazyWolf 83
LionHunterWolf 41
MimicWolf 3
MOSHPITFRENZYWolf 22
OmegaWolf 95
ProAlpha 91
Sheep 66
StoneEatingWolf 88
WolfWithoutFear 18

Mins:
Bear 0
Lion 0
Stone 0
Wolf 0
AlphaWolf 65
CamperWolf 57
DeepWolf 83
EmoWolf 26
GatheringWolf 37
HerjanWolf 79
HonorWolf 79
HybridWolf 79
LazyWolf 58
LionHunterWolf 20
MimicWolf 0
MOSHPITFRENZYWolf 1
OmegaWolf 81
ProAlpha 70
Sheep 43
StoneEatingWolf 66
WolfWithoutFear 5

DeepWolf ở vị trí đầu tiên với trung bình 90,48, mặc dù chỉ với khoảng cách hẹp hơn khoảng 2 so với vị trí thứ hai 88,67 của OmegaWolf. Khoảng 4 lần các dòng mã chỉ cải thiện 2%! HerjanWolf, HonorWolf và HybridWolf tranh giành vị trí thứ ba, theo sau OmegaWolf khoảng 2 lần nữa với các mức trung bình rất gần 86,55, 86,76 và 86,78.

Nếu không có thêm rắc rối, tôi sẽ trình bày mã. Nó quá lớn đến nỗi có khả năng có lỗi và / hoặc tiềm năng cho các hằng số / logic được cải thiện mà tôi không thể nhìn thấy. Nếu bạn có bất kỳ thông tin phản hồi, cho tôi biết!

Mã tại liên kết này, vì hóa ra nó thổi giới hạn ký tự bài: Ideone


Tôi không biết liệu dropboxusercontent có bị mất tệp hay không, vì vậy tôi đã đăng nó lên ideone: ideone.com/uRNxvj
Justin

3
@ Runer112 ấn tượng! Tôi đang xem mã và tôi hơi lạc lõng: P nhưng một khái niệm khiến tôi tò mò là những gì bạn đang sử dụng để đưa ra quyết định rằng chó sói có thân thiện hay không
Moogie

@Moogie Không có đánh giá xác định nào được đưa ra về việc một con sói có thân thiện hay không. Tuy nhiên, chúng tôi biết số lượng loài sói, chúng tôi biết rằng mỗi loài bắt đầu từ 100, chúng tôi biết còn lại bao nhiêu con sói thân thiện khác và chúng tôi có thể đoán có bao nhiêu con sói không thân thiện còn lại dựa trên số lượng chúng tôi đã giết và một đoán xem có bao nhiêu người đã chết cho các động vật khác. Từ những người đó, chúng tôi ước tính xác suất mà bất kỳ con sói nào chúng tôi thấy đều thân thiện. Thông tin này không có ảnh hưởng lớn, nhưng nó có thể là sự khác biệt giữa việc chọn có khả năng chiến đấu với một con sói hay dứt khoát chiến đấu với một con sư tử.
Runer112

Không biên dịch vì MAP_SIZE là biến không tĩnh. Vì tôi không nói nó sẽ là một biến thể, nên tôi đã sửa nó cho bạn. Chỉ muốn bạn biết trong trường hợp tôi đăng dự án hoàn chỉnh và bạn đã thấy tên biến bị đánh cắp của bạn.
Rainbolt

@Raser Oh, rất tiếc. Tôi nghĩ rằng tôi vẫn đang chạy với một phiên bản cũ của mã trò chơi từ hộp cát và hoặc MAP_SIZEbiến đó thực sự không tồn tại trước đó hoặc vì lý do nào đó tôi đã bỏ qua nó và thêm vào phiên bản tĩnh của chính nó. Tôi cũng tự hỏi tại sao con sói của tôi lại đạt điểm cao hơn một chút so với tất cả những con sói khác trong các thử nghiệm của tôi, nhưng điều tồi tệ hơn ở bạn ... Bộ sói khác nhau, tôi đoán vậy? Hay bạn chạy các trò chơi của mình cho một số lần lặp khác ngoài 1000? Hoặc bạn có thể chỉ cần một cỡ mẫu lớn hơn, 5 không phải là thống kê tuyệt vời.
Runer112

21

WolfRastyWithScatu

Không ai bảo WolfRastyWithScatu không được chạy bằng kéo. Hoặc có thể họ đã làm nhưng dù sao anh ta cũng làm điều đó.

Nếu anh ta đụng phải kẻ thù, anh ta sẽ chiến thắng bằng kéo, thua bằng kéo, buộc bằng kéo hoặc thò mắt ra (tự sát).

package animals;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


public class WolfRunningWithScissors extends Animal{

    public WolfRunningWithScissors() {
        super('W');
    }

    @Override
    public Attack fight(char c) {
        List<Attack> att = new ArrayList<>();
        att.add(Attack.SCISSORS);
        att.add(Attack.SUICIDE);
        Collections.shuffle(att);
        return att.get(0);
    }

    @Override
    public Move move() {
        List<Move> m = new ArrayList<>();
        m.add(Move.UP);
        m.add(Move.DOWN);
        m.add(Move.LEFT);
        m.add(Move.RIGHT);
        Collections.shuffle(m);
        return m.get(0);
    }

}

Chỉ muốn làm cho một đệ trình cho vui. Tôi chưa bao giờ sử dụng Java trước đây và chưa thử nghiệm điều này, nhưng nó sẽ hoạt động. Mã tấn công và di chuyển ngẫu nhiên của tôi dựa trên getRandomAttack()StoneEatingWolf.


14

Sói Omega

Giải pháp phụ thuộc lẫn nhau có hành vi rất giống với Sói Alpha, do đó có tên là Sói Omega

Con sói này tạo ra một bản đồ "nguy hiểm" của các tế bào xung quanh và sẽ chọn chuyển động (hoặc giữ) đến tế bào an toàn nhất.

Đầu tiên, các ô nơi sư tử sẽ di chuyển tiếp theo được đưa ra mức EXTREAME_DANGER. Sau đó, các tế bào xung quanh bất kỳ Chó sói nào được phát hiện đều được đưa ra mức độ nguy hiểm dựa trên khả năng tấn công ngay lập tức ... tức là nếu con sói có đường chéo với con sói omega thì nó được coi là mối đe dọa thấp, tuy nhiên những con sói liền kề được coi là mối đe dọa vừa phải.

Bản đồ "nguy hiểm" sau đó được làm mờ để cho phép chảy máu các mối đe dọa đối với các tế bào xung quanh. Điều này cho phép sói omega "cảm nhận" các vectơ đe dọa và tránh nó.

Hiện tại logic tấn công thực tế là rất nguyên thủy. Tôi hy vọng có thể cung cấp cho nó nhiều thông minh hơn và đạt được tỷ lệ thắng / thua tốt hơn. Điều này sẽ có thể nếu tôi đưa vào một số heuristic thống kê.

Trong thử nghiệm của tôi, Omega Wolf liên tục giành chiến thắng trước alpha bot 9 trên 10 lần ... mặc dù tỷ lệ rất cao: P

kết quả nhanh chóng của những con sói sống còn lại sau 100 vòng 1000 lần lặp:

class animals.OmegaWolf - 85
class animals.HonorWolf - 82
class animals.ProAlpha - 79
class animals.AlphaWolf - 77
class animals.ShadowWolf - 77
class animals.LazyWolf - 62
class animals.CamperWolf - 61
class animals.StoneEatingWolf - 59
class animals.GatheringWolf - 48
class animals.Sheep - 42
class animals.EmoWolf - 34
class animals.LionHunterWolf - 28
class animals.GamblerWolf (no cheating) - 27
class animals.WolfWithoutFear - 11
class animals.MOSHPITFRENZYWolf - 5
class animals.Wolf - 3
class animals.Stone - 2
class animals.Bear - 0
class animals.Lion - 0
class animals.MimicWolf - 0
class animals.Wion - 0

Mã số:

package animals;

import wild.Wild;

public class OmegaWolf extends Animal {

    boolean lionWillMoveDown=true;

    private static final int LOW_DANGER = 10;
    private static final int MODERATE_DANGER = LOW_DANGER*2;
    private static final int EXTREAME_DANGER = MODERATE_DANGER*4;

    private static final int UP=1;
    private static final int LEFT=3;
    private static final int RIGHT=5;
    private static final int DOWN=7;
    private static final int UP_LEFT=0;
    private static final int UP_RIGHT=2;
    private static final int DOWN_LEFT=6;
    private static final int DOWN_RIGHT=8;

    private static final int WOLVES_SPECIES_COUNT=(int) Math.round(Math.pow(((float) Wild.MAP_SIZE)/20,2)-3)-3;

    /*
     * Interdependently derived solution that behaves very similar to Alpha Wolf, hence the name Omega Wolf
     * 
     * This wolf generates a "danger" map of the surrounding cells and will choose the movement (or hold) to the safest cell.
     * 
     * The firstly the cells where lions will move next are given EXTREAME_DANGER level
     * Then the cells surrounding any detected Wolves are given danger levels based on the immediacy of attack... i.e. if the wolf is diagonal to the omega wolf 
     * it is deemed a low threat however wolves that are adjacent are deemed a moderate threat.
     * The "danger" map is then blurred to allow bleeding of the threats to surrounding cells. This allows the omega wolf to "sense" threat vectors and to avoid it.
     * 
     * Currently the actual attack logic is very primitive. I hope to be able to give it more smarts and eek out better win/lose ratios. This should be possible if 
     * I put in some statistical heuristics.
     */

    public OmegaWolf() { 
        super('W'); }


    @Override
    public Attack fight(char opponent) {
        switch(opponent){
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S': 
            return Attack.PAPER;
        default:
            // if there is only one wolf species then it must be another omega wolf.
            if (WOLVES_SPECIES_COUNT==1)
            {
                return Attack.SCISSORS;
            }
            else
            {
                // lets just choose an attack with equal weight.
                double rand = Math.random();
                if (rand < 0.333333)
                {
                    return Attack.PAPER;
                }
                if (rand < 0.666667)
                {
                    return Attack.SCISSORS;
                }
                return Attack.ROCK;

            }
        }
    }

    public Move move() {

        lionWillMoveDown = !lionWillMoveDown;


        Move move = Move.HOLD;

        int[][] dangerMap = new int[3][3];
        int[][] blurredDangerMap = new int[3][3];

        // sense Lion Danger
        for (int y=0;y<3;y++)
        {
            for (int x=0;x<3;x++)
            {
                if (surroundings[y][x]=='L')
                {
                    if (lionWillMoveDown && y!=2)
                    {
                        dangerMap[y+1][x]+=EXTREAME_DANGER;
                    }
                    else if (x!=2)
                    {
                        dangerMap[y][x+1]+=EXTREAME_DANGER;
                    }
                }
            }
        }

        // sense Wolf Danger adjacent
        // UP
        if (surroundings[0][1]=='W')
        {
            dangerMap[0][1]+=MODERATE_DANGER;
            dangerMap[0][0]+=LOW_DANGER;
            dangerMap[0][2]+=LOW_DANGER;
            dangerMap[1][1]+=MODERATE_DANGER;
        }
        // DOWN
        if (surroundings[2][1]=='W')
        {
            dangerMap[2][1]+=MODERATE_DANGER;
            dangerMap[2][0]+=LOW_DANGER;
            dangerMap[2][2]+=LOW_DANGER;
            dangerMap[1][1]+=MODERATE_DANGER;
        }
        // LEFT
        if (surroundings[1][0]=='W')
        {
            dangerMap[1][0]+=MODERATE_DANGER;
            dangerMap[0][0]+=LOW_DANGER;
            dangerMap[2][0]+=LOW_DANGER;
            dangerMap[1][1]+=MODERATE_DANGER;
        }
        // RIGHT
        if (surroundings[1][2]=='W')
        {
            dangerMap[1][2]+=MODERATE_DANGER;
            dangerMap[0][2]+=LOW_DANGER;
            dangerMap[2][2]+=LOW_DANGER;
            dangerMap[1][1]+=MODERATE_DANGER;
        }

        // sense Wolf Danger diagonally
        // UP_LEFT
        if (surroundings[0][0]=='W')
        {
            dangerMap[0][0]+=LOW_DANGER;
            dangerMap[0][1]+=MODERATE_DANGER;
            dangerMap[1][0]+=MODERATE_DANGER;
        }
        // DOWN_LEFT
        if (surroundings[2][0]=='W')
        {
            dangerMap[2][0]+=LOW_DANGER;
            dangerMap[2][1]+=MODERATE_DANGER;
            dangerMap[1][0]+=MODERATE_DANGER;
        }
        // UP_RIGHT
        if (surroundings[0][2]=='W')
        {
            dangerMap[0][2]+=LOW_DANGER;
            dangerMap[1][2]+=MODERATE_DANGER;
            dangerMap[0][1]+=MODERATE_DANGER;
        }
        // DOWN_RIGHT
        if (surroundings[2][2]=='W')
        {
            dangerMap[2][2]+=LOW_DANGER;
            dangerMap[2][1]+=MODERATE_DANGER;
            dangerMap[1][2]+=MODERATE_DANGER;
        }


        // generate a blurred danger map. This bleeds danger to surrounding cells.
        int yj,xi,sampleCount,cumulativeDanger;
        for (int y=0;y<3;y++)
        {
            for (int x=0;x<3;x++)
            {
                sampleCount=0;
                cumulativeDanger=0;
                for (int j=-1;j<2;j++)
                {
                    for (int i=-1;i<2;i++)
                    {
                        yj=y+j;
                        xi=x+i;
                        if (yj>-1 && yj<3 && xi>-1 && xi<3)
                        {
                            cumulativeDanger+=dangerMap[yj][xi];
                            sampleCount++;
                        }
                    }
                }
                blurredDangerMap[y][x]=(dangerMap[y][x]+cumulativeDanger/sampleCount)/2;
            }
        }

        // find the safest cell
        int safestCellDanger=Integer.MAX_VALUE;
        int safestCellId = -1;
        int cellId=0;

        for (int y=0;y<3;y++)
        {
            for (int x=0;x<3;x++)
            {
                if (blurredDangerMap[y][x]<safestCellDanger)
                {
                    safestCellDanger=blurredDangerMap[y][x];
                    safestCellId=cellId;
                }
                cellId++;
            }
        }

        // safest cell is adjacent so move there
        if ((safestCellId&1)==1)
        {
            switch (safestCellId)
            {
                case UP:
                    move=Move.UP;
                    break;
                case LEFT:
                    move=Move.LEFT;
                    break;
                case RIGHT:
                    move=Move.RIGHT;
                    break;
                case DOWN:
                    move=Move.DOWN;
                    break;
            }
        }
        // safestCell is a diagonal cell or current cell
        else
        {
            // lets initialise the move to Hold.
            move = Move.HOLD;

            switch (safestCellId)
            {
                case UP_LEFT:

                    // check to see whether holding is not safer than moving up
                    if (dangerMap[1][1] > dangerMap[0][1] )
                    {
                        // move up if safer than moving left or if equally safe, when randomly chosen 
                        if (dangerMap[0][1] < dangerMap[1][0] || (dangerMap[0][1] == dangerMap[1][0] && Math.random()>0.5))
                        {
                            move=Move.UP;
                        } 
                        // left must be safest :P
                        else
                        {

                            move=Move.LEFT;
                        }
                    }
                    // check to see whether holding is not safer than moving left
                    else if (dangerMap[1][1] > dangerMap[1][0] )
                    {
                        move=Move.LEFT;
                    }

                    break;
                case UP_RIGHT:
                    // check to see whether holding is not safer than moving up
                    if (dangerMap[1][1] > dangerMap[0][1] )
                    {
                        // move up if safer than moving right or if equally safe, when randomly chosen 
                        if (dangerMap[0][1] < dangerMap[1][2]|| (dangerMap[0][1] == dangerMap[1][2] && Math.random()>0.5))
                        {
                            move=Move.UP;
                        } 
                        // right must be safest :P
                        else
                        {
                            move=Move.RIGHT;
                        }
                    }
                    // check to see whether holding is not safer than moving right
                    else if (dangerMap[1][1] > dangerMap[1][2] )
                    {
                        move=Move.RIGHT;
                    }
                    break;
                case DOWN_LEFT:
                    // check to see whether holding is not safer than moving down
                    if (dangerMap[1][1] > dangerMap[2][1] )
                    {
                        // move down if safer than moving left or if equally safe, when randomly chosen 
                        if (dangerMap[2][1] < dangerMap[1][0]|| (dangerMap[2][1] == dangerMap[1][0] && Math.random()>0.5))
                        {
                            move=Move.DOWN;
                        } 
                        // left must be safest :P
                        else
                        {
                            move=Move.LEFT;
                        }
                    }
                    // check to see whether holding is not safer than moving left
                    else if (dangerMap[1][1] > dangerMap[1][0] )
                    {
                        move=Move.LEFT;
                    }
                    break;
                case DOWN_RIGHT:
                    // check to see whether holding is not safer than moving down
                    if (dangerMap[1][1] > dangerMap[2][1] )
                    {
                        // move down if safer than moving right or if equally safe, when randomly chosen 
                        if (dangerMap[2][1] < dangerMap[2][2] || (dangerMap[2][1] == dangerMap[1][2] && Math.random()>0.5))
                        {
                            move=Move.DOWN;
                        } 
                        // right must be safest :P
                        else
                        {
                            move=Move.RIGHT;
                        }
                    }
                    // check to see whether holding is not safer than moving right
                    else if (dangerMap[1][1] > dangerMap[1][2] )
                    {
                        move=Move.RIGHT;
                    }
                    break;
            }
        }

        return move;

    }
}

14

StoneGuardianWolf

Điều này khá thú vị. Tôi đã tạo một cổng mạnh mẽ của mã java sang javascript với hỗ trợ tạo để tạo trực quan: JavaScript StoneGuardianWolf

StoneGuardianWolf tìm kiếm những tảng đá thú cưng và trú ẩn bên cạnh Stones. Cô bảo vệ họ và thà hy sinh bản thân vì sự an toàn của họ.

Số liệu thống kê

Người chơi đơn: ~ 75% tỷ lệ sống của Sói + 35% Tỷ lệ sống của Pet (Đá).

Tóm tắt: 75% + 35% ---> 110% Tỷ lệ thành công! :)

Nhiều người chơi: Chưa được kiểm tra.

Thay đổi nhật ký

v2: Cập nhật chiến lược tìm kiếm AI vs GamblerWolf và pet rock.

v1: Tránh sói tốt hơn

v0: Sinh nhật

Mã Java

package animals;

public class StoneGuardianWolf extends Animal {
    public StoneGuardianWolf() {
        super('W');
    }

    private boolean petRock = false;
    private int heartache = 0;

    public Attack fight(char c) {
        this.heartache--;

        switch (c) {
        case 'B':
            return Attack.SCISSORS;
        case 'L':
            return Attack.SCISSORS;
        case 'S': // A motherly sacrifice
            return Attack.SUICIDE;
        default:
            int n = this.heartache % 3;
            if (n < 1)
                return Attack.PAPER;
            if (n < 2)
                return Attack.ROCK;
            return Attack.SCISSORS;
        }
    }

    public Move move() {
        char[][] surr = this.surroundings;
        int[][] clairvoyance = new int[3][3];

        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++)
                clairvoyance[i][j] = 1;

        boolean seeNoStone = true;

        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                switch (surr[i][j]) {
                case 'L':
                    if (i < 1 && j < 1) {
                        clairvoyance[1][0] += 50;
                        clairvoyance[0][1] += 50;
                    }

                    if (i == 1 && j < 1) { // above
                        clairvoyance[1][1] += 50;
                    }

                    if (i < 1 && j == 1) { // left
                        clairvoyance[1][1] += 50;
                    }
                    break;

                case 'S': // seek stones for protection
                    seeNoStone = false;
                    this.petRock = true;
                    clairvoyance[i][j] += 999; // Only hugs!
                    if (i < 2)
                        clairvoyance[i + 1][j] -= 10;
                    if (j < 2)
                        clairvoyance[i][j + 1] -= 10;
                    if (i > 0)
                        clairvoyance[i - 1][j] -= 10;
                    if (j > 0)
                        clairvoyance[i][j - 1] -= 10;
                    break;

                case 'B': // ignore bears
                    break;

                case 'W':
                    // skip self
                    if (i == 1 && j == 1)
                        continue;
                    int m = 25; // avoid wolves

                    // don't fight unless pet rock is in danger
                    if (petRock)
                        clairvoyance[i][j] -= 999; // motherly wrath
                    else
                        clairvoyance[i][j] += 100;

                    // avoid stepping into wolf path
                    if (i != 1 && j != 1) {
                        if (i < 2)
                            clairvoyance[i + 1][j] += m;
                        if (j < 2)
                            clairvoyance[i][j + 1] += m;
                        if (i > 0)
                            clairvoyance[i - 1][j] += m;
                        if (j > 0)
                            clairvoyance[i][j - 1] += m;
                    }
                    break;

                default:
                    clairvoyance[i][j] += 0;
                }
            } // for loop
        } // for loop

        int size = clairvoyance[1][1];
        int x = 1;
        int y = 1;

        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (i != 1 || j != 1)
                    continue;
                int tmp = clairvoyance[i][j];
                if (tmp < size) {
                    size = tmp;
                    x = i;
                    y = j;
                }
            }
        }

        if (seeNoStone)
            this.heartache++;

        this.petRock = false;
        if (seeNoStone && heartache % 10 == 0) { // Find a pet stone! :3
            if ((heartache % 3) < 2 || clairvoyance[1][2] >= 45) {
                // try move right
                if (clairvoyance[2][1] < 45)
                    return Move.RIGHT;
            }

            // try down instead
            if (clairvoyance[1][2] < 45)
                return Move.DOWN;
        }

        if (x == 0 && y == 1)
            return Move.LEFT;
        if (x == 2 && y == 1)
            return Move.RIGHT;
        if (x == 1 && y == 0)
            return Move.UP;
        if (x == 1 && y == 2)
            return Move.DOWN;

        if (!seeNoStone)
            this.petRock = true;

        return Move.HOLD;
    }
}

5
Đá ăn Sói kẻ thù!
Averroes

:) Thật vậy - không cho phép bạn gần hòn đá thú cưng của tôi! CamoWolf tát SGW khá khó khăn, mặc dù.
Talmobi

1
May mắn thay, bạn không cần đưa CamoWolf vào mục hợp pháp = D
justhalf

14

Có phải là con trai không? Có phải là một con sói? Không, đó là

BoyWhoCriedWolf.java

Mọi người đang sử dụng sự phản chiếu ở khắp mọi nơi, vì vậy tôi đoán, tại sao không đưa nó một bước xa hơn?
Tôi trình bày cho bạn: con sói không thể thua.

package animals;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.jar.Attributes;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import javax.xml.bind.DatatypeConverter;

public class BoyWhoCriedWolf extends Animal {

    private static boolean ranAgent;

    public static void installAgent() {
        try {
            ranAgent = true;
            String javaExec = new File(System.getProperty("java.home"), "bin").getAbsolutePath() + File.separator + "java";
            Process proc = new ProcessBuilder(javaExec, "-cp", System.getProperty("java.class.path"),
                    "animals.BoyWhoCriedWolf", ManagementFactory.getRuntimeMXBean().getName().split("@")[0])
                    .inheritIO().start();
            proc.waitFor();
        } catch (InterruptedException | IOException e) {
            e.printStackTrace();
        }
    }

    public BoyWhoCriedWolf() {
        super('W');
        if (!ranAgent) {
            installAgent();
        }
    }

    @Override
    public Attack fight(char c) {
        return Attack.PAPER; // I like paper, it's my rubber duck.
    }

    @Override
    public Move move() {
        return Move.HOLD; // I'm terribly lazy.
    }

    public static void main(String[] args) {
        try {
            File temp = File.createTempFile("agent-", ".jar");
            temp.deleteOnExit();
            Manifest manifest = new Manifest();
            manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
            manifest.getMainAttributes().put(new Attributes.Name("Agent-Class"), "animals.BoyWhoCriedWolf");
            manifest.getMainAttributes().put(new Attributes.Name("Can-Redefine-Classes"), "true");
            JarOutputStream jos = new JarOutputStream(new FileOutputStream(temp), manifest);
            jos.close();

            // Add tools.jar
            Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
            addURL.setAccessible(true);
            addURL.invoke(ClassLoader.getSystemClassLoader(), new URL("file:" + System.getProperty("java.home") + "/../lib/tools.jar"));

            Class<?> virtualMachineClass = Class.forName("com.sun.tools.attach.VirtualMachine");
            Object vm = virtualMachineClass.getDeclaredMethod("attach", String.class).invoke(null, args[0]);
            virtualMachineClass.getDeclaredMethod("loadAgent", String.class).invoke(vm, temp.getAbsolutePath());
            virtualMachineClass.getDeclaredMethod("detach").invoke(vm);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void agentmain(String args, Instrumentation instr) throws ClassNotFoundException, UnmodifiableClassException {
        instr.redefineClasses(new ClassDefinition(wild.Game.class, DatatypeConverter.parseBase64Binary(base64Game)));
    }

    private static final String base64Game =
              "yv66vgAAADMA9QoAOQCRBwCSCgACAJEJABIAkwkAEgCUBwCVCgAGAJEJABIAlgoABgCXCgAGAJgK"
            + "AAIAmQoABgCaCgCbAJwHAJ0HAJ4KABIAnwoAEgCgBwChCgASAKIHAKMKABIApAkAFAClCgAUAKYH"
            + "AKcJAGUAqAkAOgCpCgBlAKoKAAYAqwsArACtCwCsAK4KAAYArwcAsAoABgCxCQAUALIKABQAswkA"
            + "cQC0CgC1ALYGP+AAAAAAAAAJADoAtwoAcQCqCQBxALgJAHEAuQkAcQC6CgCbALsIALwHAL0KAC8A"
            + "kQoALwC+CAC/CgAvAMAKAC8AwQgAwggAwwgAxAcAjQcAxQcAxgEADElubmVyQ2xhc3NlcwEABWJv"
            + "YXJkAQAVTGphdmEvdXRpbC9BcnJheUxpc3Q7AQAJU2lnbmF0dXJlAQBVTGphdmEvdXRpbC9BcnJh"
            + "eUxpc3Q8TGphdmEvdXRpbC9BcnJheUxpc3Q8TGphdmEvdXRpbC9BcnJheUxpc3Q8TGFuaW1hbHMv"
            + "QW5pbWFsOz47Pjs+OwEAA2dlbgEAEkxqYXZhL3V0aWwvUmFuZG9tOwEABFNJWkUBAAFJAQAGPGlu"
            + "aXQ+AQAEKEkpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUB"
            + "AAFqAQABaQEABHRoaXMBAAtMd2lsZC9HYW1lOwEABHNpemUBAA1TdGFja01hcFRhYmxlBwChAQAI"
            + "cG9wdWxhdGUBABUoTGphdmEvbGFuZy9DbGFzcztJKVYBAAFlAQAoTGphdmEvbGFuZy9SZWZsZWN0"
            + "aXZlT3BlcmF0aW9uRXhjZXB0aW9uOwEAA3JvdwEAA2NvbAEAB3NwZWNpZXMBABFMamF2YS9sYW5n"
            + "L0NsYXNzOwEAA251bQEAFkxvY2FsVmFyaWFibGVUeXBlVGFibGUBABZMamF2YS9sYW5nL0NsYXNz"
            + "PFRUOz47BwDHBwDIAQAuPFQ6TGFuaW1hbHMvQW5pbWFsOz4oTGphdmEvbGFuZy9DbGFzczxUVDs+"
            + "O0kpVgEAB2l0ZXJhdGUBAAMoKVYBAAdtb3ZlQWxsAQAVTGphdmEvbGFuZy9FeGNlcHRpb247AQAB"
            + "YQEAEExhbmltYWxzL0FuaW1hbDsBAAVhTW92ZQcAyQEABE1vdmUBABVMYW5pbWFscy9BbmltYWwk"
            + "TW92ZTsBAARnYW1lBwCjBwCnBwDJAQAHZmxhdHRlbgEABXJhbmQxAQAFcmFuZDIBAAFiAQAFYVRh"
            + "Y2sHAMoBAAZBdHRhY2sBABdMYW5pbWFscy9BbmltYWwkQXR0YWNrOwEABWJUYWNrAQAEY2VsbAEA"
            + "J0xqYXZhL3V0aWwvQXJyYXlMaXN0PExhbmltYWxzL0FuaW1hbDs+OwEAPkxqYXZhL3V0aWwvQXJy"
            + "YXlMaXN0PExqYXZhL3V0aWwvQXJyYXlMaXN0PExhbmltYWxzL0FuaW1hbDs+Oz47BwDLBwCVBwDK"
            + "AQAEcG9sbAEAFChMamF2YS9sYW5nL0NsYXNzOylJAQABYwEABWNvdW50AQAIdG9TdHJpbmcBABQo"
            + "KUxqYXZhL2xhbmcvU3RyaW5nOwEAAXMBABJMamF2YS9sYW5nL1N0cmluZzsHAMwBAAdnZXRBcmVh"
            + "AQAHKElJKVtbQwEABXRlbXAxAQAFdGVtcDIBAAV0ZW1wMwEABXRlbXA0AQABbAEAAWsBAARhcmVh"
            + "AQADW1tDBwDNAQAKU291cmNlRmlsZQEACUdhbWUuamF2YQwARABfAQAQamF2YS91dGlsL1JhbmRv"
            + "bQwAQABBDABCAEMBABNqYXZhL3V0aWwvQXJyYXlMaXN0DAA8AD0MAM4AzwwA0ADRDADSANMMANQA"
            + "1QcAxwwA1gDXAQAgamF2YS9sYW5nL0luc3RhbnRpYXRpb25FeGNlcHRpb24BACBqYXZhL2xhbmcv"
            + "SWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbgwAYABfDABsAF8BAAl3aWxkL0dhbWUMAEQARQEADmFuaW1h"
            + "bHMvQW5pbWFsDACEAIUMANgAjQwA2QDaAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwA2wBnDADcAN0M"
            + "AN4A3wwA4ADhBwDLDADiANUMAOMA1wwATQDfAQAXYW5pbWFscy9Cb3lXaG9DcmllZFdvbGYMAOQA"
            + "zwwA5QDmDADnAOgMAOkAcwcA6gwA6wDsDADtAN0MAO4AcwwA7wBzDADwAHMMAPEAzwEABjxodG1s"
            + "PgEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyDADyAPMBAAwmbmJzcDsmbmJzcDsMAH8AgAwA8gD0"
            + "AQAGJm5ic3A7AQAEPGJyPgEABzwvaHRtbD4BABBqYXZhL2xhbmcvT2JqZWN0AQALd2lsZC9HYW1l"
            + "JDEBAA9qYXZhL2xhbmcvQ2xhc3MBACZqYXZhL2xhbmcvUmVmbGVjdGl2ZU9wZXJhdGlvbkV4Y2Vw"
            + "dGlvbgEAE2FuaW1hbHMvQW5pbWFsJE1vdmUBABVhbmltYWxzL0FuaW1hbCRBdHRhY2sBABJqYXZh"
            + "L3V0aWwvSXRlcmF0b3IBABBqYXZhL2xhbmcvU3RyaW5nAQACW0MBAANhZGQBABUoTGphdmEvbGFu"
            + "Zy9PYmplY3Q7KVoBAANnZXQBABUoSSlMamF2YS9sYW5nL09iamVjdDsBAAduZXh0SW50AQAEKEkp"
            + "SQEAB2lzRW1wdHkBAAMoKVoBAAtuZXdJbnN0YW5jZQEAFCgpTGphdmEvbGFuZy9PYmplY3Q7AQAM"
            + "c3Vycm91bmRpbmdzAQAEbW92ZQEAFygpTGFuaW1hbHMvQW5pbWFsJE1vdmU7AQAESE9MRAEAHiRT"
            + "d2l0Y2hNYXAkYW5pbWFscyRBbmltYWwkTW92ZQEAAltJAQAHb3JkaW5hbAEAAygpSQEACGl0ZXJh"
            + "dG9yAQAWKClMamF2YS91dGlsL0l0ZXJhdG9yOwEAB2hhc05leHQBAARuZXh0AQAGcmVtb3ZlAQAG"
            + "bGV0dGVyAQABQwEABWZpZ2h0AQAaKEMpTGFuaW1hbHMvQW5pbWFsJEF0dGFjazsBAAdTVUlDSURF"
            + "AQAOamF2YS9sYW5nL01hdGgBAAZyYW5kb20BAAMoKUQBACAkU3dpdGNoTWFwJGFuaW1hbHMkQW5p"
            + "bWFsJEF0dGFjawEABVBBUEVSAQAIU0NJU1NPUlMBAARST0NLAQAKaXNJbnN0YW5jZQEABmFwcGVu"
            + "ZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEAHChDKUxq"
            + "YXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsAIQASADkAAAADAAIAPAA9AAEAPgAAAAIAPwASAEAAQQAA"
            + "ABQAQgBDAAAACAAEAEQARQABAEYAAADtAAMABAAAAF8qtwABKrsAAlm3AAO1AAQqG7UABSq7AAZZ"
            + "twAHtQAIAz0cG6IAOyq0AAi7AAZZtwAHtgAJVwM+HRuiAB8qtAAIHLYACsAABrsABlm3AAe2AAlX"
            + "hAMBp//ihAIBp//GsQAAAAMARwAAAC4ACwAAABEABAAOAA8AEgAUABMAHwAUACYAFQA1ABYAPAAX"
            + "AFIAFgBYABQAXgAaAEgAAAAqAAQANwAhAEkAQwADACEAPQBKAEMAAgAAAF8ASwBMAAAAAABfAE0A"
            + "QwABAE4AAAAYAAT/ACEAAwcATwEBAAD8ABUB+gAg+gAFAAQAUABRAAIARgAAARwAAgAGAAAAXRye"
            + "AFsqtAAEKrQABbYACz4qtAAEKrQABbYACzYEKrQACB22AArAAAYVBLYACsAABrYADJkAJiq0AAgd"
            + "tgAKwAAGFQS2AArAAAYrtgANtgAJV6cABToFhAL/p/+nsQACADYAUQBUAA4ANgBRAFQADwAEAEcA"
            + "AAAmAAkAAAAdAAQAHgAQAB8AHQAgADYAIQBRACIAVgAjAFkAJQBcACYASAAAAD4ABgBWAAAAUgBT"
            + "AAUAEABJAFQAQwADAB0APABVAEMABAAAAF0ASwBMAAAAAABdAFYAVwABAAAAXQBYAEMAAgBZAAAA"
            + "DAABAAAAXQBWAFoAAQBOAAAAGwAFAP8AUwAFBwBPBwBbAQEBAAEHAFwB+QACAgA+AAAAAgBdAAQA"
            + "XgBfAAEARgAAADsAAQABAAAACSq3ABAqtwARsQAAAAIARwAAAA4AAwAAACkABAAqAAgAKwBIAAAA"
            + "DAABAAAACQBLAEwAAAACAGAAXwABAEYAAAJjAAQABwAAAVu7ABJZKrQABbcAE0wDPRwqtAAFogE/"
            + "Az4dKrQABaIBLyq0AAgctgAKwAAGHbYACsAABrYADJoBESq0AAgctgAKwAAGHbYACsAABgO2AArA"
            + "ABQ6BBkEKhwdtwAVtQAWGQS2ABc6BacACjoGsgAZOgWyABoZBbYAGy6qAAAAAAAAzgAAAAEAAAAF"
            + "AAAAJAAAAEsAAABtAAAAjwAAALYrtAAIHARkKrQABWAqtAAFcLYACsAABh22AArAAAYZBLYACVen"
            + "AIYrtAAIHLYACsAABh0EYCq0AAVwtgAKwAAGGQS2AAlXpwBkK7QACBwEYCq0AAVwtgAKwAAGHbYA"
            + "CsAABhkEtgAJV6cAQiu0AAgctgAKwAAGHQRkKrQABWAqtAAFcLYACsAABhkEtgAJV6cAGyu0AAgc"
            + "tgAKwAAGHbYACsAABhkEtgAJV4QDAaf+z4QCAaf+vyortAAItQAIsQABAF4AZQBoABgAAwBHAAAA"
            + "WgAWAAAALgAMAC8AFgAwACAAMQA4ADIAUwAzAF4ANQBlADYAbwA3AJwAOQDAADoAwwA8AOIAPQDl"
            + "AD8BBABAAQcAQgErAEMBLgBFAUYAMAFMAC8BUgBLAVoATABIAAAAUgAIAGoABQBSAGEABgBTAPMA"
            + "YgBjAAQAZQADAGQAZwAFAG8A1wBkAGcABQAYATQASQBDAAMADgFEAEoAQwACAAABWwBLAEwAAAAM"
            + "AU8AaABMAAEATgAAADYADP0ADgcATwH8AAkB/wBPAAUHAE8HAE8BAQcAaQABBwBq/AAGBwBrLCYh"
            + "ISb5ABf6AAX6AAUAAgBsAF8AAQBGAAADuAAFAAwAAAFfKrQACLYAHEwruQAdAQCZAVAruQAeAQDA"
            + "AAZNLLYAHE4tuQAdAQCZATUtuQAeAQDAAAY6BBkEtgAfBKQBHiq0AAQZBLYAH7YACzYFKrQABBkE"
            + "tgAftgALNgYVBRUGn//uGQQVBbYACsAAFDoHGQQVBrYACsAAFDoIGQfBACCZAA4ZBBkItgAhV6f/"
            + "rBkIwQAgmQAOGQQZB7YAIVen/5kZBxkItAAitgAjOgmnAAo6C7IAJDoJGQgZB7QAIrYAIzoKpwAK"
            + "OguyACQ6ChkJGQqmAB0ZBLgAJRQAJpeeAAgZB6cABRkItgAhV6cAbbIAKBkJtgApLqoAAAAAAABh"
            + "AAAAAQAAAAMAAAAcAAAANAAAAEwZBBkKsgAqpgAIGQenAAUZCLYAIVenADAZBBkKsgArpgAIGQen"
            + "AAUZCLYAIVenABgZBBkKsgAspgAIGQenAAUZCLYAIVen/t+n/sin/q2xAAIAngCqAK0AGAC0AMAA"
            + "wwAYAAQARwAAAHYAHQAAAE8AGwBQADQAUQA9AFMASwBUAGAAVgBsAFcAeABZAIAAWgCIAFsAiwBc"
            + "AJMAXQCbAF4AngBiAKoAYwC0AGQAwABlAMoAZwDRAGgA6wBqARAAbAElAG0BKABvAT0AcAFAAHIB"
            + "VQB2AVgAdwFbAHgBXgB5AEgAAACEAA0ArwAFAFIAYQALAMUABQBSAGEACwBLAQoAbQBDAAUAWQD8"
            + "AG4AQwAGAGwA6QBiAGMABwB4AN0AbwBjAAgAqgADAHAAcwAJALQAoQBwAHMACQDAAAMAdABzAAoA"
            + "ygCLAHQAcwAKADQBJAB1AD0ABAAbAUAAVAA9AAIAAAFfAEsATAAAAFkAAAAWAAIANAEkAHUAdgAE"
            + "ABsBQABUAHcAAgBOAAABFQAa/AAIBwB4/QAXBwB5BwB4/AATBwB5/AAWAf4APwEHAGkHAGkSTgcA"
            + "avwABgcAek4HAGr8AAYHAHpXBwB5/wABAAsHAE8HAHgHAHkHAHgHAHkBAQcAaQcAaQcAegcAegAC"
            + "BwB5BwBpBiROBwB5/wABAAsHAE8HAHgHAHkHAHgHAHkBAQcAaQcAaQcAegcAegACBwB5BwBpBk4H"
            + "AHn/AAEACwcATwcAeAcAeQcAeAcAeQEBBwBpBwBpBwB6BwB6AAIHAHkHAGkGTgcAef8AAQALBwBP"
            + "BwB4BwB5BwB4BwB5AQEHAGkHAGkHAHoHAHoAAgcAeQcAaf8AAwAFBwBPBwB4BwB5BwB4BwB5AAD6"
            + "AAL5AAL6AAIABAB7AHwAAQBGAAABNgACAAkAAABvAz0qtAAItgAcTi25AB0BAJkAXS25AB4BAMAA"
            + "BjoEGQS2ABw6BRkFuQAdAQCZAD4ZBbkAHgEAwAAGOgYZBrYAHDoHGQe5AB0BAJkAHhkHuQAeAQDA"
            + "ABQ6CCsZCLYALZkABoQCAaf/3qf/vqf/oBysAAAABABHAAAAKgAKAAAAfAACAH0AHgB+ADsAfwBY"
            + "AIAAYQCBAGQAggBnAIMAagCEAG0AhQBIAAAAPgAGAFgADABiAGMACAA7ACwAdQA9AAYAHgBMAFQA"
            + "PQAEAAAAbwBLAEwAAAAAAG8AfQBXAAEAAgBtAH4AQwACAFkAAAAWAAIAOwAsAHUAdgAGAB4ATABU"
            + "AHcABABOAAAAJQAH/QAKAQcAeP0AGgcAeQcAeP0AHAcAeQcAeCH5AAL5AAL6AAIAAQB/AIAAAQBG"
            + "AAABWwADAAYAAACqEi5MKrQACLYAHE0suQAdAQCZAIUsuQAeAQDAAAZOLbYAHDoEGQS5AB0BAJkA"
            + "VBkEuQAeAQDAAAY6BRkFtgAMmQAauwAvWbcAMCu2ADESMrYAMbYAM0ynACa7AC9ZtwAwK7YAMRkF"
            + "A7YACsAAFLQAIrYANBI1tgAxtgAzTKf/qLsAL1m3ADArtgAxEja2ADG2ADNMp/94uwAvWbcAMCu2"
            + "ADESN7YAMbYAM7AAAAAEAEcAAAAqAAoAAACJAAMAigAeAIsAOgCMAEIAjQBZAI8AfACQAH8AkQCT"
            + "AJIAlgCTAEgAAAAqAAQAOgBCAHUAPQAFAB4AdQBUAD0AAwAAAKoASwBMAAAAAwCnAIEAggABAFkA"
            + "AAAWAAIAOgBCAHUAdgAFAB4AdQBUAHcAAwBOAAAAIwAG/QALBwCDBwB4/QAYBwB5BwB4/AA0BwB5"
            + "+gAi+gAC+QAWAAIAhACFAAEARgAAAdAABAALAAAApQYGxQA4Ak4CNgQVBASjAJYCNgUVBQSjAIcV"
            + "BARgNgYVBQRgNgcbFQRgKrQABWAqtAAFcDYIHBUFYCq0AAVgKrQABXA2CSq0AAgbFQRgKrQABWAq"
            + "tAAFcLYACsAABhwVBWAqtAAFYCq0AAVwtgAKwAAGOgotFQQEYDIVBQRgGQq2AAyZAAgQIKcADxkK"
            + "A7YACsAAFLQAIlWEBQGn/3mEBAGn/2otsAAAAAQARwAAADIADAAAAJcABwCYABAAmQAZAJoAHwCb"
            + "ACUAnAA1AJ0ARQCeAHMAnwCXAJkAnQCYAKMAogBIAAAAcAALAB8AeACGAEMABgAlAHIAhwBDAAcA"
            + "NQBiAIgAQwAIAEUAUgCJAEMACQBzACQAdQA9AAoAEwCKAIoAQwAFAAoAmQCLAEMABAAAAKUASwBM"
            + "AAAAAAClAEoAQwABAAAApQBJAEMAAgAHAJ4AjACNAAMAWQAAAAwAAQBzACQAdQB2AAoATgAAAFkA"
            + "Bv0ACgcAOAH8AAgB/wB2AAsHAE8BAQcAOAEBAQEBAQcAeQACBwCOAf8ACwALBwBPAQEHADgBAQEB"
            + "AQEHAHkAAwcAjgEB/wAGAAUHAE8BAQcAOAEAAPoABQACAI8AAAACAJAAOwAAABoAAwA6ABIAABAI"
            + "AGUAFABmQBkAcQAUAHJAGQ==";
}

Ồ vâng, nó đòi hỏi phải có JDK để chạy, nhưng tôi không nghĩ đó sẽ là một vấn đề.


1
Chết tiệt, bạn đánh tôi với nó. Tôi đã làm việc với SabotageAgentWolf với chiến thuật chính xác này.
mackthehobbit

1
Lớp học này làm gì?
justhalf

3
@justhalf Nó định nghĩa lại lớp Game với tệp được mã hóa ở base64 gần cuối. Tập tin đó có một kiểm tra thể hiện; nếu đó là con sói của tôi, con kia luôn chết.
14mRh4X0r

1
Tôi đã có ý tưởng sử dụng chính xác cơ chế này để khiến tất cả các động vật khác tự sát và gọi điều đó là HypnoWolf. Tôi đã không quản lý để làm cho nó chạy chính xác, nhưng bạn đã làm - tôn trọng!
Francois Bourgeois

12

Wion

Cố gắng làm ít nhất có thể để tồn tại càng lâu càng tốt trong giá trị mong đợi. Nó cố gắng di chuyển song song với sư tử (bất kể nó có nhìn thấy con nào không).

Nó bỏ qua những con sói, vì nó quyết định chúng không thể đoán trước được. Nếu nó gặp một con sói, nó sẽ chiến thắng khoảng một nửa trận chiến (điều này là tối ưu trừ khi tôi cố gắng thực hiện khớp mẫu). Sói của tôi không bao giờ nên chiến đấu với nhau. Nếu nó gặp một con sư tử (mà có lẽ không nên), nó sẽ thắng khoảng 3/4 trận chiến. Gấu và đá nên luôn luôn mất.

Giả sử có bất kỳ con sói nào trong mô phỏng sử dụng chiến lược khác, chúng sẽ là khôn ngoan để tránh những con sói của tôi, vì chúng có 50% cơ hội để thua bất kỳ cuộc chạm trán nào. Trung bình điều này sẽ thực hiện ít nhất cũng như bất kỳ chiến lược nào khác.

Nếu tôi hiểu đúng các quy tắc, đây sẽ là chiến lược tối ưu.

package animals;
import java.util.Random;

public class Wion extends Animal {
    private boolean down;
    public Wion() { super('W'); down=true;}
    public Attack fight(char opponent) {
        switch (opponent) {
            case 'B':
            case 'L':
                return Attack.SCISSORS;
            case 'S':
                return Attack.PAPER;
            default:
                Random rn = new Random();
                int i = Math.abs(rn.nextInt() % 4);
                while (i==3) {i = Math.abs(rn.nextInt() % 4);}
                return Attack.values()[i];
        }
    }
    public Move move() {
        down=!down;
        if(!down) { return Move.DOWN; }
        return Move.RIGHT;
    }
}

Tôi thực sự không biết tại sao điều này làm rất kém trong các lần chạy thử của tôi. Nghe có vẻ hay trên giấy, nhưng trên thực tế, nó khá ngang tầm với EmoWolf :(
Geobits

@Geobits Tôi không thực sự kiểm tra nó TBH. Tôi đoán rằng tôi đã hiểu nhầm một trong các quy tắc, mắc lỗi hoặc tấn công ngẫu nhiên của tôi so với sói không phải là ngẫu nhiên thống nhất.
Tim Seguine

@Geobits Tôi đổi logic tấn công. Sự nghi ngờ của tôi là có thể đôi khi tự tử.
Tim Seguine

1
@justhalf vâng, tôi đã nhận ra vấn đề là gì. Lý luận của tôi chỉ có thể có thể làm việc với một quần thể bao gồm nhiều nhất là một loại sói khác. Trong trường hợp như vậy, tỷ lệ chạm trán của con sói khác sẽ tăng / giảm với tốc độ tương đương với tốc độ của tôi. Tuy nhiên, trong trường hợp đa giống, bất kỳ sự gia tăng nào về tỷ lệ bắt gặp của tôi sẽ được tính trung bình trong số tất cả những con sói khác, do đó, con của tôi sẽ lớn hơn tương ứng. Tôi đang nghĩ đến một số cách tối thiểu để khắc phục điều này, nhưng tôi không may là những điều quan trọng khác cần tập trung vào lúc này.
Tim Seguine

1
Nhưng tôi đồng ý rằng phương pháp này là tối ưu nếu có nhiều nhất một giống sói khác.
justhalf

12

Chó sói với trí nhớ tập thể

Một bầy sói ở R

Ý tưởng của bầy sói này là nó lưu giữ trong trí nhớ những người sống hay chết, kiểm tra xem những con sói chết và những con sói còn sống được sử dụng làm các cuộc tấn công và thay đổi xác suất lựa chọn cho phù hợp.

Đây là mã R:

infile <- file("stdin")
open(infile)
repeat{
    input <- readLines(infile,1)
    type <- substr(input,1,1)
    id <- substr(input,2,3)
    if(nchar(input)>3){
        info <- substr(input,4,nchar(input))
    }else{
        info <- NULL
    }
    attack <- function(id,info){
        if(info%in%c("B","L")){choice <- "S"}
        if(info=="S"){choice <- "P"}
        if(info=="W"){
            if(exists("memory")){
                dead <- memory$ID[memory$Status=="Dead"]
                veteran <- memory[memory$Attack!="" & !is.na(memory$Attack), ]
                if(nrow(veteran[!is.na(veteran[,1]),])>0){
                    deadvet<-veteran[veteran$ID%in%dead,]
                    deadvet<-unlist(lapply(split(deadvet,deadvet$ID),function(x)tail(x$Attack,1)))
                    deadvet <- table(factor(deadvet,levels=c("R","P","S","")))
                    livevet <- table(factor(veteran$Attack,levels=c("R","P","S","")))-deadvet
                    probR <- (1+livevet['R'])/(1+livevet['R']+deadvet['R'])
                    probS <- (1+livevet['S'])/(1+livevet['S']+deadvet['S'])
                    probP <- (1+livevet['P'])/(1+livevet['P']+deadvet['P'])
                    choice <- sample(c("S","P","R"),1,prob=c(probS,probP,probR))
                    memory <- rbind(memory, data.frame(ID=id, Status="Alive", Attack=choice))
                }else{
                    choice <- sample(c("S","P","R"),1)
                    memory <- rbind(memory, data.frame(ID=id, Status="Alive", Attack=choice))
                }
            }else{
                choice <- sample(c("S","P","R"),1)
                memory <- data.frame(ID=id, Status="Alive", Attack=choice)
            }
        }
        paste(choice,id,sep="")
    }
    move <- function(id,info){
        choice <- "H"
        paste(choice,id,sep="")
    }
    initialize <- function(id){
        if(exists("memory")){
            memory <- rbind(memory,data.frame(ID=id,Status="Alive",Attack=""))
        }else{
            memory <- data.frame(ID=id,Status="Alive",Attack="")
        }
        confirmed_dead <- memory$ID[memory$Status=="Dead"]
        last_seen <- memory[!memory$ID%in%confirmed_dead,]
        last_seen <- last_seen[last_seen$Attack=="",]
        lid <- table(last_seen$ID)
        turns <- max(lid)
        dead <- lid[lid<(turns-1)]
        if(length(dead)>0){
            dead_id <- names(dead)
            for(i in dead_id){
                memory <- rbind(memory, data.frame(ID=i, Status="Dead", Attack=""))
            }
        }
        paste("K",id,sep="")
    }
    result <- switch(type,"A"=attack(id,info),"M"= move(id,info),"S"=initialize(id))
    cat(result,"\n",sep="")
    flush(stdout())
}

Nó sử dụng trình bao bọc @ProgrammerDan (cảm ơn bạn!), Với WolfCollectiveMemory là tên tùy chỉnh và "Rupcript WolfCollectiveMemory.R" làm lời mời.


Vài điều - đầu tiên, tôi khá chắc chắn rằng kết quả đầu ra không bị xóa. Thứ hai, một khi quy trình của bạn được gọi bởi trình bao bọc, nó sẽ tiếp tục chạy . Thiết kế hiện tại của bạn giả định rằng quy trình của bạn được gọi mỗi khi giao tiếp được gửi đến một con sói - điều này sẽ quá tốn kém về các yêu cầu quy trình, vì vậy thay vào đó tôi bắt đầu quá trình và để các kênh liên lạc mở. Vì vậy, bạn nên có một vòng lặp chính liên tục đọc các dòng từ stdinvà viết một dòng để trả lời stdout, theo sau là a flush.console(). [tiếp]
Lập trình viên

[cont] Trình bao bọc quy trình của tôi sẽ chấm dứt quá trình con khi kết thúc mô phỏng.
Lập trình viên

@Rizer Đây là ý chính cho trình bao bọc hợp lệ cho trình R của @plannapus. Tới đây để tải về R. Cài đặt. Thêm binthư mục của R vào biến PATH của bạn hoặc tương đương, và bạn sẽ hoạt động tốt (hoạt động tốt với tôi).
Lập trình viên

Tôi nghĩ thủ phạm là readlinesmệnh lệnh. Hãy thử sử dụng một readlinehoặc tương đương. readlinessẽ chặn cho đến khi EOF.
Lập trình viên

Tôi chỉ thêm readLinesnó được sử dụng để được scan. readLinesvới đối số thứ hai 1có nghĩa là nó sẽ dừng ở ký tự dòng mới đầu tiên.
plannapus

12

Bắt chước

Mục tiêu của con sói này là bắt chước những con sói khác. Nó tìm thấy một con sói theo nó với khả năng tốt nhất của nó. MimicWolf không đặt câu hỏi như: Làm thế nào tôi có thể tránh con sói / gấu / sư tử / đá đó?

Không, MimicWolf chỉ hỏi những câu như: Con sói để tôi theo dõi ở đâu? Tôi nghĩ con sói mà tôi đang theo dõi sẽ đi đâu? Có phải con sói mà tôi đang theo dõi có phải là một con sói khác không? Con sói mà tôi đang theo dõi đã đi đâu?

Tôi sẽ thừa nhận rằng hầu hết những câu hỏi đó chưa được trả lời tốt, nhưng hiện tại đây là bài nộp của tôi về MimicWolf

   package animals;
   import java.util.*;

public class MimicWolf extends Animal {

final int TURN_MEMORY = 5;

Random rand = new Random();

Animal.Move lastMove = Animal.Move.UP;

boolean mimicingWolf = false;

Pos[] wolfPreviousPos = new Pos[TURN_MEMORY];
RelativePos[] relativePositions = new RelativePos[TURN_MEMORY];
Move[] wolfPreviousMove = new Move[TURN_MEMORY - 1];

int turnsWithLostWolf = 0;

public MimicWolf() {
    super('W');
}

public Animal.Attack fight(char c) {
    switch (c) {
        case 'B':
            return Animal.Attack.SCISSORS;
        case 'L':
            return Animal.Attack.SCISSORS;
        case 'S':
            return Animal.Attack.PAPER;
        default:
            int x = rand.nextInt(4);
            return Animal.Attack.values()[x];
    }
}

public Animal.Move move() {
    Pos wolfPos = null;
    wolfPos = lookForSurroundingWolf();

    if (turnsWithLostWolf == 4) {
        mimicingWolf = false;
        wolfPreviousPos = new Pos[5];
        relativePositions = new RelativePos[5];
        turnsWithLostWolf = 0;
    }

    if (mimicingWolf) {
        int indexOfLastMove = 0;
        for (int i = 0; wolfPreviousPos[i] != null && i < wolfPreviousPos.length; i++) {
            indexOfLastMove = i;
        }

        //is wolf still visible??
        Pos wolfNewPos = isWolfVisible(wolfPreviousPos[indexOfLastMove]);
        if (wolfNewPos.x == -1) {//wolf is not visible
            turnsWithLostWolf++;
            return moveOppositeDirection(lastMove);
        } else {
            return mimicWolf(wolfNewPos, indexOfLastMove); //need Better way to mimic
        }
    } else {
        //check if new wolf around
        if (wolfPos.x == -1) {
            return searchForWolf();
        } else {
            mimicingWolf = true;
            return mimicWolf(wolfPos, 0);
        }
    }
}

private Animal.Move searchForWolf() {
    Animal.Move newMove = null;
    while (newMove == null || newMove == lastMove) {
        newMove = Animal.Move.values()[rand.nextInt(3)];
    }

    lastMove = newMove;
    return newMove;
}

private Pos lookForSurroundingWolf() {
    for (Integer i = 0; i < surroundings.length; i++) {
        for (Integer j = 0; j < surroundings[0].length; j++) {
            if (i == 1 && j == 1) {
                //this is myself >.<
            } else if (surroundings[i][j] == 'W') {
                return new Pos(i, j);
            }
        }
    }

    return new Pos(-1, -1);
}

/*
    for mimicWolf when movesMimiced == 1 or 2 this is the base case, Any
    number greater the wolf will attempt to mimic the next move based on pattern
    of previous moves
        we assume that we are following the same wolf as last time
 */

private Animal.Move mimicWolf(Pos wolfCurrentPos, int movesMimiced) {
    wolfPreviousPos[movesMimiced] = wolfCurrentPos;
    insertToRelativePos(wolfCurrentPos, movesMimiced);
    if (movesMimiced == 0) {
        Move m1 = null, m2 = null;
        if (wolfPreviousPos[0].x == 0) {
            m1 = Move.LEFT;
        } else if (wolfPreviousPos[0].x == 2) {
            m1 = Move.RIGHT;
        }

        if (wolfPreviousPos[0].y == 0) {
            m2 = Move.UP;
        } else if (wolfPreviousPos[0].y == 2) {
            m2 = Move.DOWN;
        }

        return randOfMoves(m1, m2); //guess which way to go
    }
    wolfPreviousMove[movesMimiced - 1] =  getDirection(wolfPreviousPos[movesMimiced - 1], wolfPreviousPos[movesMimiced]);
    if (movesMimiced == 1) {
        //if pos 1 was a cornor
        if(relativePositions[0] == RelativePos.CORNER){
            if(relativePositions[1] == RelativePos.CORNER){
                if(wolfPreviousPos[0].equals(wolfPreviousPos[1])){
                    return lastMove;
                }
                return moveOppositeDirection(lastMove);
            }
            else if(relativePositions[1] == RelativePos.EDGE){
                return Move.HOLD; //he held so i will hold
            }
        }else if(relativePositions[1] == RelativePos.EDGE){
            if(relativePositions[1] == RelativePos.EDGE){
                return lastMove;
            }
            else if(relativePositions[1] == RelativePos.CORNER){
                //only possibility is that I held, and he moved
                return wolfPreviousMove[0];
            }
        }
    } else {
        //Return most common move the wolf I am copying has made
        int[] mostCommonMoveArr = {0,0,0,0,0};
        for(int i = 0; i <= movesMimiced; i++){
            switch(wolfPreviousMove[i]){
                case UP:
                    mostCommonMoveArr[0]++;
                case RIGHT:
                    mostCommonMoveArr[1]++;
                case DOWN:
                    mostCommonMoveArr[2]++;
                case LEFT:
                    mostCommonMoveArr[3]++;
                case HOLD:
                    mostCommonMoveArr[4]++;
            }
        }

        int maxValue = -1;
        int maxLocal = 0;
        for(int i = 0; i < 5; i++){
            if(mostCommonMoveArr[i] > maxValue)
                maxValue =  mostCommonMoveArr[i];
                maxLocal = i;
        }

        return Move.values()[maxLocal];
    }

    return Move.HOLD; //shouldn't happen
}

private Pos isWolfVisible(Pos lastPos) {
    Pos mimicedWolfPos = lookForSurroundingWolf();
    while (mimicedWolfPos.x != -1 && mimicedWolfPos.y != -1) {
        //did we find the wolf?
        if (lastPos.x == mimicedWolfPos.x || lastPos.y == mimicedWolfPos.y) {
            return mimicedWolfPos;
        }

        surroundings[mimicedWolfPos.x][mimicedWolfPos.y] = ' ';
        mimicedWolfPos = lookForSurroundingWolf();
    }

    return new Pos(-1, -1);
}

private Animal.Move moveOppositeDirection(Move m) {
    switch (m) {
        case UP:
            return Move.DOWN;
        case RIGHT:
            return Move.LEFT;
        case DOWN:
            return Move.UP;
        case LEFT:
            return Move.RIGHT;
        case HOLD:
            return Move.LEFT; //No idea why this would happen but whatever
        default:
            return Move.HOLD;
    }
}

private Animal.Move getDirection(Pos firstPos, Pos secondPos){
    if(firstPos.equals(secondPos))
        return Move.HOLD;
    if(firstPos.x == secondPos.x){
        if(firstPos.y > secondPos.y)
            return Move.UP;
        return Move.DOWN;
    }
    if(firstPos.x > secondPos.x)
        return Move.RIGHT;
    return Move.LEFT;
}


private Animal.Move randOfMoves(Move m1, Move m2) {
    if (m1 == null) {
        return m2;
    } else if (m2 == null) {
        return m1;
    }

    int r = rand.nextInt(2);
    if (r == 0) {
        return m1;
    }
    return m2;
}

private class Pos {
    int x;
    int y;

    protected Pos(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object obj){
        Pos pos = (Pos) obj;
        return (this.x == pos.x && this.y == pos.y);
    }
}

private void insertToRelativePos(Pos pos, int posToAdd){
    if(pos.x == 1 || pos.y == 1){
        relativePositions[posToAdd] = RelativePos.EDGE;
    }else{
        relativePositions[posToAdd] = RelativePos.CORNER;
    }
}

private enum RelativePos{
    CORNER, EDGE
}
}

Chỉnh sửa: Tôi đã thêm một hệ thống bắt chước tốt hơn. Sói vẫn không tốt vì chúng không cố gắng tránh bất cứ điều gì vào lúc này trong khi tiếp tục di chuyển xung quanh.


12

Không phải là một mục, nhưng vì hầu hết những con sói chỉ đứng yên, nên thực sự khá nhàm chán để xem, vì vậy tôi đã thêm một thảm họa tự nhiên vào Wild:

Động đất!

Khoảng 5% thời gian, một trận động đất sẽ xảy ra với cường độ ngẫu nhiên, 100 là cao nhất, 20 thấp nhất. Điều này sẽ đặt earthquakeCountermức giảm theo cấp số nhân theo thời gian sau trận động đất.

Điều gì xảy ra trong một trận động đất?

Tất cả Động vật sẽ có cơ hội di chuyển ngẫu nhiên, tùy thuộc vào giá trị của earthquakeCounter. Vì vậy, nếu giá trị là 75, khoảng 75% Động vật (bao gồm cả Đá) sẽ di chuyển ngẫu nhiên sang bất kỳ hướng nào (phân bố đều).

Điều này, không ngạc nhiên, giết chết nhiều động vật, vì vậy tối đa thường là khoảng 50 động vật sau một vài thử nghiệm.

Ngoài ra, trận động đất sẽ được hiển thị trong GUI, thay đổi tùy theo cường độ.

Tôi không thể thấy trận động đất!

Cơ hội cho một trận động đất xảy ra là khá mong manh, chỉ 5%.

Nhưng băn khoăn không! Tôi cũng đã bao gồm một "Trận động đất!" nút trên giao diện, trong trường hợp bạn muốn di chuyển tất cả các Wolves từ khu thoải mái của họ ...

Đây là một ảnh chụp màn hình:

một trận động đất

Đây là mã:

Wild.java

main() Hàm (được cập nhật để bỏ qua GUI cho 100 lần lặp đầu tiên để tăng tốc):

public static void main(String[] args) {

    int size = Math.round((float)Math.sqrt(classes.length+3)*20);
    final Game game = new Game(size);

    Statistics stats = new Statistics(game, classes);

    String[] colors = generateColors(classes.length);
    int idx = 0;
    for(Class c : classes){
        Animal.setColor(c, colors[idx]);
        idx++;
        game.populate(c, 100);
    }
    stats.update();

    JFrame gui = new JFrame();
    Container pane = gui.getContentPane();

    JLabel boardLabel = new JLabel();
    boardLabel.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
    boardLabel.setText(game.toString());
    pane.add(boardLabel, BorderLayout.WEST);

    JLabel statsLabel = new JLabel();
    statsLabel.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
    statsLabel.setText(stats.toString());
    pane.add(statsLabel, BorderLayout.EAST);

    JButton earthquakeButton = new JButton();
    earthquakeButton.addActionListener(new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent e) {
            game.earthquake(true);
        }

    });
    earthquakeButton.setText("Earthquake!");
    pane.add(earthquakeButton, BorderLayout.SOUTH);

    gui.pack();
    gui.setVisible(true);

    for(int i=0; i<100; i++){
        game.iterate();
        stats.update();
    }

    while(true) {
        game.iterate();
        stats.update();
        boardLabel.setText(game.toString());
        statsLabel.setText(stats.toString());
        try { Thread.sleep(100); } catch (InterruptedException e) {}
    }
}

Game.java

package wild;

import animals.Animal;
import java.util.ArrayList;
import java.util.Random;
import animals.Animal.Attack;
import animals.Animal.Move;

public class Game {

    private ArrayList<ArrayList<ArrayList<Animal>>> board;
    private final Random gen = new Random();
    protected final int SIZE;
    private static int earthquakeCounter = 0;

    protected Game(int size) {
        this.SIZE = size;
        board = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            board.add(new ArrayList<ArrayList<Animal>>());
            for (int j = 0; j < size; j++) {
                board.get(i).add(new ArrayList<Animal>());
            }
        }
    }

    protected <T extends Animal> void populate(Class<T> species, int num) {
        while (num > 0) {
            int row = gen.nextInt(SIZE);
            int col = gen.nextInt(SIZE);
            if (board.get(row).get(col).isEmpty()) {
                try { board.get(row).get(col).add(species.newInstance()); } 
                catch (InstantiationException | IllegalAccessException e) {}
                num--;
            }
        }
    }

    protected void iterate() {
        earthquake(false);
        moveAll();
        flatten();
    }

    private void moveAll() {
        Game game = new Game(SIZE);
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                if (!board.get(i).get(j).isEmpty()) {
                    Animal a = board.get(i).get(j).get(0);
                    a.surroundings = getArea(i, j);
                    Move aMove;
                    try { aMove = a.move(); } 
                    catch (Exception e) { aMove = Move.HOLD; }
                    if(gen.nextInt(100)<earthquakeCounter){
                        aMove = Move.values()[gen.nextInt(4)];
                    }
                    switch(aMove) {
                        case UP:
                            game.board.get((i-1+SIZE)%SIZE).get(j).add(a);
                            break;
                        case RIGHT:
                            game.board.get(i).get((j+1)%SIZE).add(a);
                            break;
                        case DOWN:
                            game.board.get((i+1)%SIZE).get(j).add(a);
                            break;
                        case LEFT:
                            game.board.get(i).get((j-1+SIZE)%SIZE).add(a);
                            break;
                        case HOLD:
                            game.board.get(i).get(j).add(a);
                            break;
                    }
                }
            }
        }
        board = game.board;
    }

    /**
     * Give a random chance for an earthquake to happen
     */
    protected void earthquake(boolean force){
        if(force || (earthquakeCounter==0 && gen.nextInt(1000)>950)){
            earthquakeCounter = 20+gen.nextInt(80);
        } else {
            earthquakeCounter /= 2;
        }
    }

    private void flatten() {
        for (ArrayList<ArrayList<Animal>> row : board) {
            for (ArrayList<Animal> cell : row) {
                while (cell.size() > 1) {
                    int rand1, rand2;
                    rand1 = gen.nextInt(cell.size());
                    do { rand2 = gen.nextInt(cell.size()); } while (rand1 == rand2);

                    Animal a = cell.get(rand1);
                    Animal b = cell.get(rand2);
                    Attack aTack, bTack;
                    try { aTack = a.fight(b.letter); } 
                    catch (Exception e) { aTack = Attack.SUICIDE; }
                    try {  bTack = b.fight(a.letter); }
                    catch (Exception e) { bTack = Attack.SUICIDE; }

                    if (aTack == bTack) {
                        cell.remove((Animal)(Math.random() > 0.5 ? a : b));
                    } else {
                        switch (aTack) {
                            case ROCK:
                                cell.remove((Animal)(bTack == Attack.PAPER ? a : b));
                                break;
                            case PAPER:
                                cell.remove((Animal)(bTack == Attack.SCISSORS ? a : b));
                                break;
                            case SCISSORS:
                                cell.remove((Animal)(bTack == Attack.ROCK ? a : b));
                                break;
                        }
                    } 
                }
            }
        }
    }

    protected int poll(Class c) {
        int count = 0;
        for (ArrayList<ArrayList<Animal>> row : board) {
            for (ArrayList<Animal> cell : row) {
                for (Animal a : cell) {
                    if(c.isInstance(a))
                        count++;
                }
            }
        }
        return count;
    }

    public String toString() {
        String s = "<html>";
        s += "<span style='background:"+getBackgroundColor()+"'>";
        for (ArrayList<ArrayList<Animal>> row : board) {
            for (ArrayList<Animal> cell : row) {
                if (cell.isEmpty())
                    s += "&nbsp;&nbsp;";
                else
                    s += "<span style='color:"+ Animal.color.get(cell.get(0).getClass()) +"'>" + cell.get(0).letter + "</span>&nbsp;";
            }
            s+="<br>";
        }
        s += "</span>";
        return s + "</html>";
    }

    private String getBackgroundColor(){
        int shade = 255-(int)Math.floor(255*earthquakeCounter/100.0);
        String result = String.format("#%02x%02x%02x", shade, shade, shade);
        return result;
    }

    private char[][] getArea(int i, int j) {
        char[][] area = new char[3][3];
        for(int k = -1; k <= 1; k++) {
            for(int l = -1; l <= 1; l++) {
                int temp1 = k+1;
                int temp2 = l+1;
                int temp3 = (i+k+SIZE)%SIZE;
                int temp4 = (j+l+SIZE)%SIZE;
                ArrayList<Animal> cell = board.get((i+k+SIZE)%SIZE).get((j+l+SIZE)%SIZE);
                area[k+1][l+1] = (char)(cell.isEmpty() ? ' ' : cell.get(0).letter);
            }
        }
        return area;
    }
}

5
một số người đàn ông chỉ muốn xem thế giới ... động đất
CommonGuy

5
GatheringWolves của tôi đang khóc.
johnchen902

12

MultiWolf (Java)

Con sói này biết về những con sói khác trong thử thách lập trình này. Nó khởi tạo chúng (như 'thú cưng') nếu chúng có sẵn và sử dụng chúng để xác định những việc cần làm bằng cách hỏi mọi thú cưng sói mà nó sở hữu và chọn câu trả lời phổ biến nhất.

Con sói này nên an toàn vô hạn đệ quy - tức là nếu người khác thực hiện một khái niệm tương tự - và sẽ trả về một hành động mặc định là Attack.ROCK/ Move.HOLDnếu nó phát hiện được gọi trong khi nó đang gọi các động vật khác.

Trong các thử nghiệm của tôi, điều này đã có kết quả khác nhau. Tôi không chắc điều này có được phép hay không. Nhưng nếu đúng như vậy, và một phép màu không thể xảy ra khiến nó chiến thắng, tôi nghĩ rằng danh hiệu chiến thắng nên được truyền lại cho con sói đến "thứ hai" - thật công bằng, tôi có lẽ đã đánh cắp logic của nó.

Nó tránh tự tử.

Chỉnh sửa - Tôi tin rằng Sói này sẽ cần phải được tải sau khi những con sói mà nó tham chiếu để hoạt động đúng.

package animals;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map.Entry;

public class MultiWolf extends Animal {

    private static final LinkedList<Animal> pets = new LinkedList<>();
    private static boolean inPetCall = false;

    private static void attemptLoadPet(String className) {
        try {
            Object pet = Class.forName(className).newInstance();

            if (pet instanceof Animal) {
                pets.add((Animal) pet);
            }
        } catch (Exception ex) {
            // this wolf is not available
            System.out.println(className + " is not available for MultiWolf cheating.");
        }
    }

    static {
        attemptLoadPet("animals.AlphaWolf");
        attemptLoadPet("animals.CamperWolf");
        attemptLoadPet("animals.GamblerWolf");
        attemptLoadPet("animals.GatheringWolf");
        attemptLoadPet("animals.LazyWolf");
        attemptLoadPet("animals.Sheep");
        attemptLoadPet("animals.Wion");

        attemptLoadPet("animals.MOSHPITFRENZYWolf");
        attemptLoadPet("animals.PassiveAgressiveWolf");
        attemptLoadPet("animals.StoneEatingWolf");
        attemptLoadPet("animals.HerjanWolf");
        attemptLoadPet("animals.HonorWolf");
        attemptLoadPet("animals.MimicWolf");
        attemptLoadPet("animals.LionHunterWolf");
        attemptLoadPet("animals.OmegaWolf");
        attemptLoadPet("animals.WolfWithoutFear");
        attemptLoadPet("animals.WolfRunningWithScissors");
        // attemptLoadPet("animals.SmartWolf");
        // According to Rusher, the above cheating of a non-Java wolf breaks the non-Java-entry wrapper.
        attemptLoadPet("animals.ShadowWolf");
        attemptLoadPet("animals.HybridWolf");
        attemptLoadPet("animals.ProAlpha");
        attemptLoadPet("animals.ForrestWolf");
        attemptLoadPet("animals.WhenIGrowUp");
        attemptLoadPet("animals.MigratingWolf");
        attemptLoadPet("animals.BlindWolf");
    }

    public MultiWolf() {
        super('W');
    }

    @Override
    public Attack fight(char opponent) {
        if (inPetCall) {
            // stop infinite recursion
            return Attack.ROCK;
        }

        inPetCall = true;

        HashMap<Attack, Integer> collect = new HashMap<>();

        collect.put(Attack.ROCK, 0);
        collect.put(Attack.PAPER, 0);
        collect.put(Attack.SCISSORS, 0);
        collect.put(Attack.SUICIDE, -9001);

        for (Animal a : pets) {
            a.surroundings = this.surroundings;
            Attack atk = a.fight(opponent);
            collect.put(atk, collect.get(atk)+1);
        }

        int top=0;
        Attack atk=Attack.ROCK;

        for (Entry<Attack, Integer> ent : collect.entrySet()) {
            if (ent.getValue() > top) {
                atk = ent.getKey();
                top = ent.getValue();
            }
        }

        inPetCall = false;

        return atk;
    }

    @Override
    public Move move() {
        if (inPetCall) {
            // stop infinite recursion
            return Move.HOLD;
        }

        inPetCall = true;

        HashMap<Move, Integer> collect = new HashMap<>();

        collect.put(Move.DOWN, 0);
        collect.put(Move.HOLD, 0);
        collect.put(Move.LEFT, 0);
        collect.put(Move.RIGHT, 0);
        collect.put(Move.UP, 0);


        for (Animal a : pets) {
            a.surroundings = this.surroundings;
            Move mv = a.move();
            collect.put(mv, collect.get(mv)+1);
        }

        int top=0;
        Move mv=Move.HOLD;

        for (Entry<Move, Integer> ent : collect.entrySet()) {
            if (ent.getValue() > top) {
                mv = ent.getKey();
                top = ent.getValue();
            }
        }

        inPetCall = false;

        return mv;
    }

}

Nếu tôi nhớ chính xác, bạn có thể nhận được các lớp thông qua Wild. Classes, vì đó là trường tĩnh ... Vì vậy, bạn sẽ không phải cập nhật sói của mình mỗi khi một con sói mới được đăng ở đây;)
CommonGuy

Đúng. Nhưng tôi đã làm theo cách này bây giờ, có lẽ sẽ rời bỏ nó. Cũng có thể loại bỏ một số con sói ít chiến thắng khỏi loài đa này. Wion dường như bị tuyệt chủng mỗi lần chạy, tôi đang cân nhắc việc cắt nó ra khỏi MultiWolf khi tôi tự hỏi liệu điều đó có làm giảm chất lượng của các hành động hay không.
OlivierTheOlive

Tôi tin rằng quy tắc "Bạn không được đọc hoặc sửa đổi các tệp được tạo bởi một lớp Sói khác" nhằm mục đích bao gồm các tệp lớp sói khác. Vì vậy, tôi nghĩ rằng mục này, trong khi một ý tưởng tuyệt vời, là trái với quy tắc.
Runer112

1
@ Runer112 Tôi đã tự hỏi, nhưng tôi cũng đã học được một chút từ việc này về việc tải các lớp theo tên và rằng không có cách nào đơn giản để tìm tất cả các lớp trong một gói. Vui một chút
OlivierTheOlive

3
Khởi tạo một Sói khác không cấu thành việc đọc hoặc sửa đổi các tệp được tạo bởi một Sói khác, vì vậy việc gửi này là hợp pháp. Quy tắc này nhằm bảo vệ dữ liệu khỏi các bài nộp được viết bằng các ngôn ngữ không có những thứ như biến tĩnh và cần phải ghi vào một tệp thay thế.
Rainbolt

12

Sói ăn đá

Đây là đệ trình của tôi. Con sói này giữ nguyên vị trí nếu nó không nhìn thấy bất kỳ hòn đá, sư tử hay sói nào ở xung quanh. Nếu anh ta nhìn thấy một hòn đá và không có nguy cơ bị tấn công bởi một con sói hay sư tử khác, anh ta cố gắng ăn nó. Nếu anh ta thấy bất kỳ nguy hiểm, anh ta chạy trốn!

EDIT 1 : Cải thiện xem thuật toán nguy hiểm. Bây giờ anh ta chạy trốn khỏi nguy hiểm :)

package animals;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


public class StoneEatingWolf extends Animal{

    public StoneEatingWolf() {
        super('W');
    }

    @Override
    public Attack fight(char c) {
        switch (c){
            case 'L': return Attack.SCISSORS;
            case 'B': return Attack.SCISSORS;
            case 'W': return getRandomAttack();
            case 'S': return Attack.PAPER;
            default: return getRandomAttack();
        }
    }

    private Attack getRandomAttack(){
        List<Attack> att = new ArrayList<>();
        att.add(Attack.PAPER);
        att.add(Attack.PAPER);
        att.add(Attack.ROCK);
        att.add(Attack.SCISSORS);
        Collections.shuffle(att);
        return att.get(0);
    }

    @Override
    public Move move() {
        List<Move> m = new ArrayList<>();

        //First see if there is any dangerous animal. If it is, then flee
        if (isThereAnyDangerousAnimal()){
            m.add(Move.UP);
            m.add(Move.RIGHT);
            m.add(Move.LEFT);
            m.add(Move.DOWN);
            getSafeMoves(m);
        }else{
        //No danger: Look for stones to eat
            if (isThereAnimalAtNorth('S')){
                m.add(Move.UP);
            }
            if (isThereAnimalAtEast('S')){
                m.add(Move.RIGHT);
            }
            if (isThereAnimalAtWest('S')){
                m.add(Move.LEFT);
            }
            if (isThereAnimalAtSouth('S')){
                m.add(Move.DOWN);
            }
        }

        if (m.isEmpty()){
            return Move.HOLD;
        } else {
            Collections.shuffle(m);
            return m.get(0);
        }
    }

    private void getSafeMoves(List<Move> lm){

        if (isThereAnimalAtNorth('L') || isThereAnimalAtNorth('W')){
            lm.remove(Move.UP);
        }
        if (isThereAnimalAtEast('L') || isThereAnimalAtEast('W')){
            lm.remove(Move.RIGHT);
        }
        if (isThereAnimalAtSouth('L') || isThereAnimalAtSouth('W')){
            lm.remove(Move.DOWN);
        }
        if (isThereAnimalAtWest('L') || isThereAnimalAtWest('W')){
            lm.remove(Move.LEFT);
        }

    }

    private boolean isThereAnimalAtNorth(char an){
        if (surroundings[0][0] == an || surroundings [0][1] == an || surroundings [0][2] == an){
            return true;
        }
        return false;
    }

    private boolean isThereAnimalAtSouth(char an){
        if (surroundings[2][0] == an || surroundings [2][2] == an || surroundings [2][2] == an){
            return true;
        }
        return false;
    }

    private boolean isThereAnimalAtEast(char an){
        if (surroundings[0][2] == an || surroundings [1][2] == an || surroundings [2][2] == an){
            return true;
        }
        return false;
    }

    private boolean isThereAnimalAtWest(char an){
        if (surroundings[0][0] == an || surroundings [1][0] == an || surroundings [2][0] == an){
            return true;
        }
        return false;
    }

    private boolean isThereAnyDangerousAnimal(){
        if (isThereAnimalAtEast('L') ||
                isThereAnimalAtEast('W') ||
                isThereAnimalAtNorth('L') ||
                isThereAnimalAtNorth('W') ||
                isThereAnimalAtSouth('L') ||
                isThereAnimalAtSouth('W') ||
                isThereAnimalAtWest('L') ||
                isThereAnimalAtWest('W')){
            return true;
        }
        return false;
    }

    }

Chỉnh sửa 2 : Một số thống kê

Tôi đã xoay sở để biến StoneEatingWolf trở thành Sói 5-6 hàng đầu trong các mô phỏng tôi đã chạy:

Kết quả trung bình sau 40 lần chơi 1000 lần lặp

Tôi thực hiện một số phân tích về các trận đánh trong đó ngụ ý đá ăn sói. Chạy 40 lượt trong 1000 lần lặp tôi nhận được các kết quả sau:

Biểu đồ kết quả chiến đấu

Chiến thắng là Đá ăn Sói thắng. Biểu đồ cho thấy những gì chúng ta đã biết: Những con sói thành công nhất là những con sói không gặp những con sói khác. Tôi cũng nhận thấy rằng những con sói khác của tôi (Sói di cư) đang vặn vẹo một số Người ăn đá của tôi. Tôi hy vọng họ cũng đang săn lùng một con sói khác. Buồn cười đến mức tôi không vấp ngã với bất kỳ Sói lười biếng hay bất kỳ Sói Camper nào. Ngoài ra, đây là kết quả của các cuộc tấn công tôi nhận được sau 20 lần chạy (loại trừ Stones và Bears):

PAPER       447
ROCK        881
SCISSORS    581
SUICIDE     230

Có vẻ như có một sự thiên vị rõ ràng cho ROCKcác cuộc tấn công. Biết điều này tôi đã làm cho con sói của tôi PAPERtấn công thường xuyên hơn một chút.


2
Xin vui lòng, không sử dụng biểu đồ đường để vẽ dữ liệu phân loại. Nó cho tôi rất nhiều ung thư nhìn vào biểu đồ của bạn.
AJMansfield

@AJMansfield Xin lỗi khi nghe điều đó. Hy vọng bạn sẽ khỏe lại;) Dù sao tôi cũng sẽ tính đến nó cho bất kỳ biểu đồ nào trong tương lai tôi thực hiện.
Averroes

Bạn vẫn đang sử dụng Windows XP? oO
justhalf

Và tại sao bạn lại sử dụng ROCK(thắng 50%) để chiến đấu với Lion? Tốt nhất nên sử dụng SCISSORS(thắng 75%)
cần

@justhalf Công ty tôi vẫn sử dụng XP ... Và bạn nói đúng về cái kéo. Đã sửa. Cảm ơn :)
Averroes

11

Danh dự

Sói của tôi đang chạy trốn khỏi những con sói khác. Nếu anh ta không thể chạy trốn, anh ta sẽ bắt đầu một cuộc chiến.

package animals;
public class HonorWolf extends Animal {

    private int moves = 0;

    public HonorWolf() { 
        super('W'); 
    }

    @Override   
    public Attack fight(char opponent) { 
        switch(opponent) {
         case 'L':
            return Attack.SCISSORS; 
         case 'B':
            return Attack.SCISSORS;
         case 'S':
            return Attack.PAPER;
        default:
            return Attack.PAPER;
        }
    }

    public Move move() {
        int numWolves = 0, numLions = 0;

        moves++;

        for (int y = 0; y != 3; y++) {
            for (int x = 0; x != 3; x++) {
                if(surroundings[y][x] != ' ') {
                    if(surroundings[y][x] == 'W') {
                        numWolves++;
                    } else if(surroundings[y][x] == 'L') {
                        numLions++;
                    }
                }
            }       
        }

        if (numWolves == 1 && numLions == 0) {
            return Move.HOLD;
        }

        if (surroundings[0][1] == 'L' && moves%2 != 0) {
            return Move.UP;
        } 

        if (surroundings[1][0] == 'L' && moves%2 == 0) {
            return Move.LEFT;
        }

        if (surroundings[0][1] == 'W') {
            if (surroundings[2][1] == ' ' || surroundings[2][1] == 'S') {
                return Move.DOWN;
            } else if (surroundings[1][2] == ' ' || surroundings[1][2] == 'S') {
                return Move.RIGHT;
            } else if (surroundings[1][0] == ' ' || surroundings[1][0] == 'S') {
                return Move.LEFT;
            } else {
                return Move.UP;
            }
        }

        if (surroundings[1][0] == 'W') {
            if (surroundings[1][2] == ' ' || surroundings[1][2] == 'S') {
                return Move.RIGHT;
            } else if (surroundings[0][1] == ' ' || surroundings[0][1] == 'S') {
                return Move.UP;
            } else if (surroundings[2][1] == ' ' || surroundings[2][1] == 'S') {
                return Move.DOWN;
            } else {
                return Move.LEFT;
            }
        }

        if (surroundings[1][2] == 'W') {
            if (surroundings[1][0] == ' ' || surroundings[1][0] == 'S') {
                return Move.LEFT;
            } else if (surroundings[0][1] == ' ' || surroundings[0][1] == 'S') {
                return Move.UP;
            } else if (surroundings[2][1] == ' ' || surroundings[2][1] == 'S') {
                return Move.DOWN;
            } else {
                return Move.RIGHT;
            }
        }

        if (surroundings[2][1] == 'W') {
            if (surroundings[0][1] == ' ' || surroundings[0][1] == 'S') {
                return Move.UP;
            } else if (surroundings[1][0] == ' ' || surroundings[1][0] == 'S') {
                return Move.LEFT;
            } else if (surroundings[1][2] == ' ' || surroundings[1][2] == 'S') {
                return Move.RIGHT;
            } else {
                return Move.DOWN;
            }
        }

        return Move.HOLD;
    }
}

Tôi cần phải thay đổi chiến thuật tấn công sói alpha pro của tôi. Nếu tôi đang cầm và bị sói tấn công: Chiến đấu với SCISSORS;)
Ilya Gazman

11

Sói mù

Sói mù sợ di chuyển và không bao giờ biết nó đang chiến đấu. Bằng cách chơi kéo mỗi khi nó có tỷ lệ cược tốt nhất, vì nó sẽ không bao giờ chạy vào một hòn đá thực sự .

package animals;

public class BlindWolf extends Animal {
    public BlindWolf() { super('W'); }

    @Override
    public Attack fight(char c) { 
        return Attack.SCISSORS;
    }

    @Override
    public Move move() {
        return Move.HOLD;
    }
}

11

Khi tôi lớn lên

Khi con sói này lớn lên, nó muốn trở thành Sư tử. Vì vậy, nó ngẫu nhiên đi xung quanh tìm kiếm Sư tử để theo bước chân của chúng và học cách trở thành Sư tử.

Con sói này được thiết kế như một đối trọng với những con sói hoán đổi vị trí với Lions.

package animals;

import java.util.Random;

/**
 *
 * @author Quincunx
 */
public class WhenIGrowUp extends Animal {

    Random r;
    boolean following;
    boolean toggle;

    public WhenIGrowUp() {
        super('W');
        r = new Random();
        following = false;
        toggle = false;
    }

    @Override
    public Attack fight(char c) {
        switch (c) {
            case 'B':
                return Attack.SCISSORS;
            case 'L':
            case 'S':
                return Attack.PAPER;
            default:
                return Attack.values()[r.nextInt(4)];
        }
    }

    @Override
    public Move move() {
        if (surroundings[1][2] == 'L') {
            return Move.RIGHT;
        }
        if (surroundings[2][1] == 'L') {
            return Move.DOWN;
        }
        Move direction = Move.values()[r.nextInt(5)];
        out:
        for (int y = 0; y < 3; y++) {
            for (int x = 0; x < 3; x++) {
                if (surroundings[y][x] == 'L') {
                    if (y == 0 && x == 1) {
                        direction = Move.UP;
                    } else if (y == 1 && x == 0) {
                        direction = Move.LEFT;
                    } else {
                        direction = Move.HOLD;
                    }
                    break out;
                }
            }
        }
        return direction;
    }
}

11

Gián điệp

SpyWolf theo dõi kẻ thù của nó và ghi lại hoạt động của chúng để nó có thể giữ các tab trên mọi người trong khi giữ khoảng cách. Sẽ không muốn bị phát hiện!

package animals;

import static animals.Animal.Attack.*;
import static animals.Animal.Move.*;

import java.awt.Point;
import java.util.*;

public class SpyWolf extends Animal {

    private static final Random r = new Random();
    private static boolean hasTestedPRNG = false;
    private static int PRNG = -1;
    private boolean lionTracker = true;
    private boolean useScissors = false;

    private final ArrayList<MapTile> map = new ArrayList<MapTile>();
    private final Point location = new Point();

    public SpyWolf() {
        super('W');
    }

    @Override
    public Animal.Attack fight(char opponent) {
        switch (opponent) {
            case 'B':
            case 'L':
                return SCISSORS;
            case 'S':
                return PAPER;
            default:
                if (useScissors) {
                    useScissors = false;
                    return SCISSORS;
                }
                return PAPER;
        }
    }

    @Override
    public Animal.Move move() {

        Move m = HOLD;

        if (!hasTestedPRNG) {
            hasTestedPRNG = true;
            double d = 0;
            for (int i = 0; i < 100; i++)
                d += Math.random();
            if (d > 99) {
                PRNG = 1;
            } else if (d > 30 && d < 70) PRNG = 0;
        }

        lionTracker = !lionTracker;
        boolean adj = false;

        updateMap();

        scan: {
            if (PRNG < 1) {
                if (look(LEFT) == 'L' && !lionTracker) {
                    useScissors = true;
                    m = LEFT;
                    break scan;
                }

                if (look(UP) == 'L' & lionTracker) {
                    useScissors = true;
                    m = UP;
                    break scan;
                }
            }

            int x = 0, y = 0;
            ArrayList<Move> moves = new ArrayList<Move>(4);

            for (Move i : Move.values())
                moves.add(i);

            if (look(UP) == 'W') {
                y += 54;
                moves.remove(UP);
                adj = true;
            }
            if (look(DOWN) == 'W') {
                y -= 54;
                moves.remove(DOWN);
                adj = true;
            }
            if (look(LEFT) == 'W') {
                x += 54;
                moves.remove(LEFT);
                adj = true;
            }
            if (look(RIGHT) == 'W') {
                x -= 54;
                moves.remove(RIGHT);
                adj = true;
            }

            if (moves.isEmpty() || !adj) break scan;

            for (MapTile t : map) {
                if (t.x >= location.x - 2 && t.x <= location.x + 2 && t.y >= location.y - 2 && t.y <= location.y + 2 && t.d) {
                    int dist = Math.abs(t.x - location.x) + Math.abs(t.y - location.y);
                    y += t.y > location.y ? -60 / dist : 60 / dist;
                    x += t.x < location.x ? 60 / dist : -60 / dist;
                }
            }
            m = moveDir(x, y);
            if (!moves.contains(m)) m = HOLD;
        }
        switch (m) {
            case UP:
                location.y--;
                return m;
            case DOWN:
                location.y++;
                return m;
            case LEFT:
                location.x--;
                return m;
            case RIGHT:
                location.x++;
                return m;
            default:
                return m;
        }
    }

    private void updateMap() {
        for (int y = -1; y < 2; y++)
            xloop: for (int x = -1; x < 2; x++) {
                if (x == 0 && y == 0) continue;
                for (MapTile t : map)
                    if (t.x == x + location.x && t.y == y + location.y) {
                        t.d = surroundings[y + 1][x + 1] == 'W';
                        continue xloop;
                    }
                map.add(new MapTile(x + location.x, y + location.y, surroundings[y + 1][x + 1] == 'W'));
            }
    }

    private Move moveDir(int x, int y) {
        if (x == 0) return y < 0 ? UP : y > 0 ? DOWN : HOLD;
        if (y == 0) return x < 0 ? LEFT : RIGHT;
        if (x < 0) {
            if (y < 0) {
                if (y < x)
                    return UP;
                else if (x < y) return LEFT;
                return r.nextBoolean() ? UP : LEFT;
            } else {
                if (-y < x)
                    return DOWN;
                else if (x < -y) return LEFT;
                return r.nextBoolean() ? DOWN : LEFT;
            }
        }
        if (y < 0) {
            if (y < -x)
                return UP;
            else if (-x < y) return RIGHT;
            return r.nextBoolean() ? UP : RIGHT;
        } else {
            if (y > x)
                return DOWN;
            else if (x < y) return RIGHT;
        return r.nextBoolean() ? DOWN : RIGHT;
        }
    }

    private char look(Move direction) {
        switch (direction) {
            case UP:
                return surroundings[0][1];
            case DOWN:
                return surroundings[2][1];
            case LEFT:
                return surroundings[1][0];
            case RIGHT:
                return surroundings[1][2];
            default:
                return surroundings[1][1];
        }
    }

    private static class MapTile {
        int x, y;
        boolean d;

        MapTile(int x, int y, boolean d) {
            this.x = x;
            this.y = y;
            this.d = d;
        }
    }
}

Nó khá tốt, nhưng HybridWolf khập khiễng quá gian lận! SpyWolf có thể quay lại trường gián điệp và huấn luyện các kỹ thuật chống sói tiên tiến, chúng ta sẽ thấy.


1
Bạn gọi nó là khập khiễng, tôi gọi nó là thông minh;)
CommonGuy

5
À! Thật nhiều gotos! Và trong một ngôn ngữ thậm chí không có chúng!
AJMansfield

9

Lai

Tôi không thể cưỡng lại mà làm một con sói khác. Cái này rất khác (trong mã của nó, không phải trong hành vi của nó), vì nó chọn đòn tấn công / di chuyển, điều mà những con sói tốt khác sẽ làm.
Tất nhiên tất cả những con sói đều tốt, nhưng ý tôi là những con có nhiều điểm nhất :)

package animals;

import java.util.ArrayList;
import java.util.Random;

public class HybridWolf extends Animal{
    private final Class[] classes = {ProAlpha.class, OmegaWolf.class, SpyWolf.class, HerjanWolf.class, DeepWolf.class, ProtoWolf.class};
    private final ArrayList<Animal> wolves = new ArrayList<Animal>(); 

    public HybridWolf() {
        super('W');
        for(Class c: classes) {
            try {
                wolves.add((Animal)c.newInstance());
            } catch (Exception ex) {}
        }
    }

    @Override
    public Attack fight(char opponent) {
        switch(opponent){
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S': 
            return Attack.PAPER;
        default:
            try {
                int[] attacks = new int[3];
                Attack bestAttack = randomAttack();
                for(Animal wolf : wolves) {
                    wolf.surroundings = this.surroundings;
                    attacks[wolf.fight(opponent).ordinal()]++;
                }
                for(int i =0; i < 5; i++) {
                    if(attacks[i] > attacks[bestAttack.ordinal()]) {
                        bestAttack = Attack.values()[i];
                    }
                }
                return bestAttack;
            } catch (Exception e) {
                return randomAttack();
            }
        }
    }

    @Override
    public Move move() {
        try {
            int[] moves = new int[5];
            Move bestMove = Move.HOLD;
            for(Animal wolf : wolves) {
                wolf.surroundings = this.surroundings;
                moves[wolf.move().ordinal()]++;
            }
            for(int i =0; i < 5; i++) {
                if(moves[i] > moves[bestMove.ordinal()]) {
                    bestMove = Move.values()[i];
                }
            }
            return bestMove;
        } catch (Exception e) {
            return Move.HOLD;
        }
    }

    public Attack randomAttack() {
        Random rand = new Random();
        switch (rand.nextInt(3)){
            case 1: return Attack.SCISSORS;
            case 2: return Attack.ROCK;
            default: return Attack.PAPER;
        }
    }

}

Trong các bài kiểm tra của tôi, nó đạt điểm cao hơn AlphaWolf trước đây của tôi, nhưng đôi khi Omega / Honor / ProAlpha đã đánh bại tôi ... Những bài nộp tốt hơn ở đây, con sói này sẽ nhận được càng tốt: D


Đây là một chút táo tợn! ý tưởng thông minh mặc dù. Không chắc chắn làm thế nào điều này sẽ công bằng khi nhập cảnh hợp pháp vì tôi không biết về các thử nghiệm mà Rizer sẽ áp dụng để xác định một mục hợp pháp. tức là nếu anh ta thực hiện một thử nghiệm trong sự cô lập với những con sói khác thì con sói này sẽ thất bại thảm hại: P
Moogie

@Moogie 90% các mục là hợp pháp. Cho đến nay, tôi chỉ loại trừ các mục đã thay đổi chữ cái của chúng thành một chữ khác ngoài 'W' hoặc các mục mà tôi không thể tìm ra cách biên dịch bằng ngôn ngữ khác (và tôi cho họ biết nếu đó là trường hợp, nhưng bạn có thể không thấy nó ở đây vì tôi nói chuyện với họ trong trò chuyện).
Rainbolt

@Rizer có một số mục thử thay đổi tỷ lệ cược có lợi cho họ. ví dụ: Sói cờ thay đổi trình tạo số ngẫu nhiên của Math.random () của java để luôn trả về 1! Thật thú vị, nó có ít tác động đến kết quả vì những con sói chiến thắng là những con sói tránh chiến đấu!
Moogie

@Moogie GamblerWolf là một đệ trình hợp pháp (và cũng khá thông minh). Bạn nói đúng, nó không thay đổi kết quả nhiều. Nếu mọi thứ vượt quá tầm kiểm soát, tôi sẽ chỉ nói "Ok, anh ấy thắng nhưng đây là kết quả nếu anh ấy không bao gồm." Bằng cách đó, mọi người khác vẫn có thể tận hưởng không bị xóa sổ.
Rainbolt

2
@Moogie Nếu một cái gì đó không bị cấm cụ thể trong các thông số kỹ thuật của thử thách thì thực tế là hợp pháp và truyền thống trên trang này là không thay đổi các quy tắc một khi mọi người đã đăng câu trả lời cho nó.
plannapus

9

EvoWolf

Tất cả những con sói được thiết kế thông minh ngớ ngẩn! EvoWolf sống trong Wild cùng với những con sói khó tính khác như DeepWolf và HerjanWolf nên nó phải tiến hóa để sinh tồn.

Mã này sử dụng thuật toán di truyền để tiến hóa con sói tốt nhất (Tôi đã không chú ý đến LionHunterWolf cho đến khi tôi bắt được Wolves để huấn luyện chống lại). Các gen khác nhau cho mỗi tổ hợp động vật / tấn công, hướng di chuyển khi an toàn và hướng di chuyển cho từng động vật xung quanh. Sau 1000 vòng, những con sói kéo dài số lượt quay cao nhất có xác suất sinh con cao nhất (tức là bạn càng sống lâu thì bạn càng có nhiều cơ hội giao phối). Chúng tôi cũng đưa ra một đột biến ngẫu nhiên ở khoảng 10% trẻ em với hy vọng nó có ích.

Đây là mã EvoWolf, BẠN C ALNG CẦN evowolf.txt TRONG HƯỚNG DẪN LÀM VIỆC CỦA BẠN - NÓ LIÊN QUAN ĐẾN TRƯỜNG HIỆN TẠI HIỆN TẠI. Nếu bạn muốn tiến hóa những con sói của mình khỏi sự ngẫu nhiên nguyên thủy, đừng bao gồm evowolf.txt nhưng con được cung cấp hiện đang là sự tiến hóa tốt nhất. Thật là gọn gàng để xem nó phát triển, lúc đầu chỉ còn 2-3 người sống sót nhưng sau đó nó lên tới 60.

package animals;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.Random;

public class EvoWolf extends Animal {
    public EvoWolf() { super('W'); birth();}
    public Attack fight(char c) { 
        List<Attack> attacks = getAttacks(c);
        if(attacks.size() == 0)
            return Attack.SUICIDE; //Discourage wolves without attacks, Darwin Award

        return attacks.get(random.nextInt(attacks.size()));
    }

    public Move move() {
        ++turns;
        List<Move> moves = new ArrayList<Move>();
        if(isSafe())
            moves = getSafeMoves();
        else
            moves = getThreatenedMoves();

        return (Move)moves.toArray()[random.nextInt(moves.size())];
    }

    /*====STATIC METHODS====*/
    //Shared RNG
    public static Random random = new Random();

    //Collection of 100 sets of genes
    public static String[] genePool = null;

    //Get the genes from disk or randomly generate some
    public static void readGenePool(){
        genePool = new String[100];
        int gIdx = 0;
        try (BufferedReader br = new BufferedReader(new FileReader("evowolf.txt"))){
            String sCurrentLine; 
            while ((sCurrentLine = br.readLine()) != null) {
                genePool[gIdx] = sCurrentLine;
                ++gIdx;
            }
        } catch (IOException e) {

        } 

        //if can't read genes, make some
        if(gIdx < 100){
            primordial(gIdx);
        }
    }
    public static void primordial(int idx){
        for(;idx < 100; ++idx){
            genePool[idx] = getRandomGenes();
        }
    }

    public static String getRandomGenes(){
        StringBuilder sb = new StringBuilder();
        for(int idx = 0; idx < GENE_COUNT; ++idx){
            if(random.nextBoolean())
                sb.append("1");
            else
                sb.append("0");
        }
        return sb.toString();
    }

    //Evolve wolves
    public static void nextGen(){
        //Check survival of current gen
        int survivors = 0;
        for(int idx = 0; idx < 100; ++idx){
            survivors = survivors + (generation[idx].turns == 1000 ? 1 : 0);
        }
        if(survivors > 65)
            writeGenePool(Long.toString(survivors));

        //Weighted resivour sampling
        //Take the highest of r^(1/w) where r is a random an w is the weight
        for(int idx = 0; idx < 100; ++idx){
            genePool[idx] = mateFitWolves();
        }
        writeGenePool("");
        birthCount = 0;
    }

    //Pick two wolves randomly by weighted fitness and mate them
    public static String mateFitWolves(){
        EvoWolf w1 = null;
        double weight1 = -1;
        EvoWolf w2 = null;
        double weight2 = -1;

        for(int idx = 0; idx < 100; ++idx){
            double weight = generation[idx].getWeightSample();
            if(weight > weight1){
                weight2 = weight1;
                w2 = w1;
                weight1 = weight;
                w1 = generation[idx];
            } else if(weight > weight2){
                weight2 = weight;
                w2 = generation[idx];
            }
        }

        return mateFitWolves(w1, w2);
    }

    //Make offspring
    public static String mateFitWolves(EvoWolf w1, EvoWolf w2){
        StringBuilder sb = new StringBuilder();
        //Random splice
        for(int rIdx = 0; rIdx < w1.genes.length(); ++rIdx){
            if(random.nextBoolean())
                sb.append(w1.genes.charAt(rIdx));
            else
                sb.append(w2.genes.charAt(rIdx));
        }


        //Random mutation
        while(random.nextInt(10) == 0){
            int mIdx = random.nextInt(w1.genes.length());
            if(sb.charAt(mIdx) == '0')
                sb.setCharAt(mIdx, '1');
            else
                sb.setCharAt(mIdx, '0');
        }


        return sb.toString();
    }

    //Save the next generation's gene pool back to disk
    public static void writeGenePool(String survivors){
        try {
            String str = "";
            if(!survivors.equals(""))
                str = Long.toString(System.currentTimeMillis());

            File file = new File("evowolf" + survivors + str + ".txt");

            // if file doesn't exists, then create it
            if (!file.exists()) {
                file.createNewFile();
            }

            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            for(int gIdx = 0; gIdx < genePool.length; ++gIdx){
                bw.write(genePool[gIdx]);
                bw.write('\n');
            }
            bw.close();
        } catch (IOException e) {

        }
    }

    //Keep track of the wolves in this generation
    public static int birthCount = 0;
    public static EvoWolf[] generation = new EvoWolf[100];

    /*====INSTANCE METHODS====*/
    //Populate this wolf from the gene pool
    public void birth(){
        if(genePool == null){
            readGenePool();
        }
        genes = genePool[birthCount];
        generation[birthCount] = this;
        birthCount = (birthCount + 1) % 100;    
    }

    //How long wolf has been alive
    public int turns = 0;

    //Fitness based on how long wolf survived
    public double getWeightSample(){
        return Math.pow(random.nextDouble(), 1.0/turns);
    }


    /*===GENETICS===*/
    public String genes = null;
    //Genes are made up of 182+ bits (stored at a string)
    //Each turns on the possibility of that move or attack in a given situation
    //  Attack: BLSW * RPSX = 16 bits [0-15] = Animal->Attacks
    //  Threatened Moves: BLSW * 12345678 * UDLRH = 160 bits [16-175] = Y -> X -> Animal -> Moves
    //  Safe Moves: UDLRH = 5 bits [176-180] = Moves
    //  Extra: default move [181], move combination [182]
    public static final int GENE_INDEX_ATTACKS = 0;
    public static final int GENE_INDEX_THREATENED_MOVES = GENE_INDEX_ATTACKS + (4 * 4);
    public static final int GENE_INDEX_SAFE_MOVES = GENE_INDEX_THREATENED_MOVES + (8 * 4 * 5);
    public static final int GENE_INDEX_DEFAULT_MOVE = GENE_INDEX_SAFE_MOVES + (5);
    public static final int GENE_INDEX_COMBINE_MOVES = GENE_INDEX_DEFAULT_MOVE + (1);
    public static final int GENE_COUNT = GENE_INDEX_COMBINE_MOVES + 1;
    public static int getAnimalIndex(char c){
        switch (c) {
            case 'B':
                return 0;
            case 'L':
                return 1;
            case 'S':
                return 2;
            case 'W':
            default: //Shouldn't occur but we'll assume it's the dangerous wolf
                return 3;
        } 
    }

    public static int getXYIndex(int x, int y){
        int idx = (y * 3) + x;
        if(idx > 4) //We don't need to look at ourself
            --idx;
        return idx;
    }

    public List<Attack> getAttacks(char c){
        List<Attack> attacks = new ArrayList<Attack>();
        int idx = GENE_INDEX_ATTACKS + getAnimalIndex(c);
        if(genes.charAt(idx + 0) == '1')
            attacks.add(Attack.ROCK);
        if(genes.charAt(idx + 1) == '1')
            attacks.add(Attack.PAPER);
        if(genes.charAt(idx + 2) == '1')
            attacks.add(Attack.SCISSORS);
        /*
        if(genes.charAt(idx + 3) == '1')
            attacks.add(Attack.SUICIDE);
        */
        //Suicide didn't remove itself from the gene pool like I thought so I manually removed it

        return attacks;
    }

    public boolean isSafe(){
        for(int x = 0; x <= 2; ++x){
            for(int y = 0; y <= 2; ++y){
                if(y == 1 && x == 1)
                    continue;
                if(surroundings[y][x] != ' ')
                    return false;
            }
        }
        return true;
    }

    public List<Move> getSafeMoves(){
        List<Move> moves = new ArrayList<Move>();
        int idx = GENE_INDEX_SAFE_MOVES;
        if(genes.charAt(idx + 0) == '1')
            moves.add(Move.UP);
        if(genes.charAt(idx + 1) == '1')
            moves.add(Move.DOWN);
        if(genes.charAt(idx + 2) == '1')
            moves.add(Move.LEFT);
        if(genes.charAt(idx + 3) == '1')
            moves.add(Move.RIGHT);
        if(genes.charAt(idx + 4) == '1')
            moves.add(Move.HOLD);

        return moves;
    }

    public List<Move> getThreatenedMoves(){
        List<Move> moves = new ArrayList<Move>();
        if(genes.charAt(GENE_INDEX_COMBINE_MOVES) == '0')
            moves.addAll(EnumSet.of(Move.UP, Move.DOWN, Move.LEFT, Move.RIGHT, Move.HOLD));

        for(int x = 0; x <= 2; ++x){
            for(int y = 0; y <= 2; ++y){
                if(y == 1 && x == 1)
                    continue;
                if(genes.charAt(GENE_INDEX_COMBINE_MOVES) == '1')
                    moves.addAll(getThreatenedMoves(x,y));
                else
                    moves.retainAll(getThreatenedMoves(x,y));
            }
        }

        if(moves.size() == 0){
            if(this.genes.charAt(GENE_INDEX_DEFAULT_MOVE) == '1')
                moves.addAll(EnumSet.of(Move.UP, Move.DOWN, Move.LEFT, Move.RIGHT, Move.HOLD));
            else
                moves.add(Move.HOLD);
        }

        return moves;
    }

    public EnumSet<Move> getThreatenedMoves(int x, int y){
        //Lookup what moves we can make for a cell unless it is blank (allow any)
        if(surroundings[y][x] != ' ')
            return getThreatenedMoves(x,y,surroundings[y][x]);
        else if(genes.charAt(GENE_INDEX_COMBINE_MOVES) == '1')
            return EnumSet.noneOf(Move.class);
        else
            return EnumSet.of(Move.UP, Move.DOWN, Move.LEFT, Move.RIGHT, Move.HOLD);
    }

    public EnumSet<Move> getThreatenedMoves(int x, int y, char c){
        int aIdx = getAnimalIndex(c);
        int sIdx = getXYIndex(x,y);
        int idx = GENE_INDEX_THREATENED_MOVES + (sIdx * 20) + (aIdx * 5);

        EnumSet<Move> moves = EnumSet.noneOf(Move.class);

        if(genes.charAt(idx + 0) == '1')
            moves.add(Move.UP);
        if(genes.charAt(idx + 1) == '1')
            moves.add(Move.DOWN);
        if(genes.charAt(idx + 2) == '1')
            moves.add(Move.LEFT);
        if(genes.charAt(idx + 3) == '1')
            moves.add(Move.RIGHT);
        if(genes.charAt(idx + 4) == '1')
            moves.add(Move.HOLD);

        return moves;
    }

    public static String setAt(String str, int index, char replace){     
        if(str==null){
            return str;
        }else if(index<0 || index>=str.length()){
            return str;
        }
        char[] chars = str.toCharArray();
        chars[index] = replace;
        return String.valueOf(chars);       
    }
}

Tôi cũng đã thực hiện một số thay đổi đối với Statistics.java và Wild.java chỉ để cho tôi biết có bao nhiêu lượt và thế hệ đã qua. Sau khi bạn chạy 1000 lượt, hãy gọi EvoWolf.nextGen();để tính toán con cái. Điều này không cần thiết cho cạnh tranh, chỉ khi bạn muốn phát triển bộ của riêng mình.

Tất cả các tệp ở đây EDIT: LINK CỐ ĐỊNH

Theo như sự phát triển là tốt nhất, nó không thể tốt hơn so với top 10. Một phần hạn chế là nó có rất ít bộ nhớ về các bước di chuyển trước đó. Mặc dù nó hoạt động như WolvesWithCollectiveMemory ở chỗ những trải nghiệm của các thế hệ trước sẽ ảnh hưởng đến cách các chức năng thế hệ tiếp theo phục vụ như một bộ nhớ toàn cầu dài hạn. Nó chắc chắn là vui vẻ mặc dù. Trong liên kết trước có một bảng Excel có thể giúp bạn phân tích nhóm gen. Thay thế tất cả 1 và 0 trong .txt bằng 1 và 0 bằng dấu phẩy rồi dán vào bảng tính.

Một số lưu ý thú vị, hầu hết trong số đó xác nhận chiến lược của mọi người:

  • Các cuộc tấn công thực tế ít quan trọng hơn là tránh chiến đấu. Hoặc có thể tất cả những con sói không bị loại bỏ nhanh chóng để chúng không phải là mối đe dọa. Thế hệ cạnh tranh có cơ hội đồng đều giữa RPS với gấu mặc dù bạn nên ném S.
  • Giống như trên, tôi đã phải tự động vô hiệu hóa tự tử vì nó không phát triển mặc dù bạn nghĩ nó sẽ xảy ra.
  • Nắm giữ là động thái tốt nhất khi không có ai xung quanh
  • Chạy trốn dường như cũng tốt khi có ai đó ở bên
  • Bạn nên giữ thay vì di chuyển một hướng ngẫu nhiên (lựa chọn này là một gen bổ sung phát triển)
  • Khi có nhiều hơn 1 con vật ở xung quanh, di chuyển ngẫu nhiên ra khỏi giao điểm di chuyển cho mỗi con vật xung quanh / động vật sẽ tốt hơn so với liên minh (một gen phụ khác)

8

Thông minh

Kết quả là (1000 lần lặp) (Tôi sẽ tiếp tục cập nhật thông tin này nhưng xem nó như một thử nghiệm độc lập không có trung bình vì với nhiều con sói thì nó khá chậm).

nhập mô tả hình ảnh ở đây

Tổng hợp:

* nix (Bắt buộc phải có Mono):

gmcs SmartWolf.cs

Các cửa sổ:

csc SmartWolf.cs

Sao chép vào thư mục làm việc.

Lưu ý: Khi sử dụng Windows, bạn cần thay thế "mono SmartWolf.exe"chỉ "SmartWolf.exe"bằng mã trình bao bọc.

SmartWolf.cs:

using System;
using System.Collections.Generic;
using System.Linq;

namespace SmartWolf
{
    #region Enums
    enum Attack
    {
        Rock, Paper, Scissors, Suicide
    }
    enum Movement
    {
        Up, Down, Left, Right, Hold
    }
    enum Animal
    {
        Stone, Lion, Wolf, Bear, Empty
    }
    #endregion
    class KnowledgeBase
    {
        static Random rnd = new Random();
        public List<KeyValuePair<KeyValuePair<Animal, Attack>, int>> knowledge = new List<KeyValuePair<KeyValuePair<Animal, Attack>, int>>();
        public KnowledgeBase ()
        {
        }
        public void PunishMove (KeyValuePair<Animal, Attack> move)
        {
            if (knowledge.Count (t => t.Key.Key == move.Key && t.Key.Value == move.Value) == 0) {
                knowledge.Add (new KeyValuePair<KeyValuePair<Animal, Attack>, int> (move, -1));
            } else {
                int i = knowledge.FindIndex (t => t.Key.Equals (move));
                knowledge[i] = new KeyValuePair<KeyValuePair<Animal, Attack>, int>(knowledge[i].Key, knowledge[i].Value - 1);
            }

        }
        public void RewardMove (KeyValuePair<Animal, Attack> move)
        {
            if (knowledge.Count (t => t.Key.Key == move.Key && t.Key.Value == move.Value) == 0) {
                knowledge.Add (new KeyValuePair<KeyValuePair<Animal, Attack>, int> (move, 1));
            } else {
                int i = knowledge.FindIndex (t => t.Key.Equals (move));
                knowledge[i] = new KeyValuePair<KeyValuePair<Animal, Attack>, int>(knowledge[i].Key, knowledge[i].Value + 1);
            }
        }
        public Attack GetBestMove (Animal opponent)
        {
            Attack best = GetRandomMove();
            int j = 0;
            foreach (var pair in knowledge) {
                if(pair.Key.Key == opponent && j < pair.Value)
                {
                    best = pair.Key.Value;
                    j = pair.Value;
                }
            }
            if(j < 2)
                return GetRandomMove ();
            return best;
        }
        public static Attack GetRandomMove()
        {
            int r = rnd.Next (3);
            return r == 0 ? Attack.Paper :
                r == 1 ? Attack.Rock :
                    r == 2 ? Attack.Scissors :
                    Attack.Scissors;
        }
    }
    class MainClass
    {
        static KnowledgeBase knowledge = new KnowledgeBase();
        public static void Main (string[] args)
        {
            List<SmartWolf> list = new List<SmartWolf> ();
            List<int> temp = new List<int>();
            int l = 0;
            while (true) {
                string str = Console.ReadLine ();
                int id = int.Parse (str.Substring (1, 2));
                if(str.StartsWith ("S"))
                {
                    list.Add (new SmartWolf(id));
                    Console.WriteLine("K" + id.ToString ().PadLeft (2, '0'));
                } else if(str.StartsWith ("M"))
                {
                    if(temp.Contains (id))
                    {
                        for(int i = 0; i < 100; i++)
                        {
                            SmartWolf s = list.Where (t => t.ID == i).ToList ()[0];
                            if(s.AttackedInLastRound == 0 && !temp.Contains(i))
                            {
                                s.IsAlive = false;
                                knowledge.PunishMove (s.LastMove);
                                s.AttackedInLastRound = -1;
                            } else if(s.AttackedInLastRound == 0 && temp.Contains (i))
                            {
                                knowledge.RewardMove (s.LastMove);
                                s.AttackedInLastRound = -1;
                            }
                            if(s.AttackedInLastRound > 0)
                                s.AttackedInLastRound--;
                        }
                        temp.Clear();
                        l++;
                    }
                    temp.Add (id);

                    Console.WriteLine('H' + id.ToString ().PadLeft (2, '0'));
                } else if(str.StartsWith ("A"))
                {
                    Animal enemy = str[3] == 'W' ? Animal.Wolf :
                                   str[3] == 'L' ? Animal.Lion :
                                   str[3] == 'S' ? Animal.Stone :
                                   str[3] == 'B' ? Animal.Bear : Animal.Empty;
                    Attack atk = knowledge.GetBestMove (enemy);
                    Console.WriteLine((atk == Attack.Paper ? "P" :
                                      atk == Attack.Rock ? "R" : 
                                      atk == Attack.Scissors ? "S" :
                                      "P") + id.ToString ().PadLeft (2, '0'));
                    list.Where (t => t.ID == id).ToList ()[0].AttackedInLastRound = 2;
                    list.Where (t => t.ID == id).ToList ()[0].LastMove = new KeyValuePair<Animal, Attack>(enemy, atk);
                }
            }
        }
    }
    class SmartWolf
    {
        public int ID;
        public bool IsAlive = true;
        public KeyValuePair<Animal, Attack> LastMove = new KeyValuePair<Animal, Attack>(Animal.Empty, Attack.Suicide);
        public int AttackedInLastRound = -1;
        public SmartWolf(int n)
        {
            ID = n;
        }
    }
}

Wrapper (ghi có vào @ProgrammerDan, tôi chỉ đưa nó vào đây để sao chép dễ dàng hơn):

package animals;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * Remote SmartWolf wrapper class. 
 */
public class SmartWolf extends Animal {
    /**
     * Simple test script that sends some typical commands to the
     * remote process.
     */
    public static void main(String[]args){
        SmartWolf[] wolves = new SmartWolf[100];
        for(int i=0; i<10; i++) {
            wolves[i] = new SmartWolf();
        }
        char map[][] = new char[3][3];
        for (int i=0;i<9;i++)
            map[i/3][i%3]=' ';
        map[1][2] = 'W';
        for(int i=0; i<10; i++) {
            wolves[i].surroundings=map;
            System.out.println(wolves[i].move());
        }
        for(int i=0; i<10; i++) {
            System.out.println(wolves[i].fight('S'));
            System.out.println(wolves[i].fight('B'));
            System.out.println(wolves[i].fight('L'));
            System.out.println(wolves[i].fight('W'));
        }
        wolfProcess.endProcess();
    }
    private static WolfProcess wolfProcess = null;

    private static SmartWolf[] wolves = new SmartWolf[100];
    private static int nWolves = 0;

    private boolean isDead;
    private int id;

    /**
     * Sets up a remote process wolf. Note the static components. Only
     * a single process is generated for all Wolves of this type, new
     * wolves are "initialized" within the remote process, which is
     * maintained alongside the primary process.
     * Note this implementation makes heavy use of threads.
     */
    public SmartWolf() {
        super('W');
        if (SmartWolf.wolfProcess == null) {
            SmartWolf.wolfProcess = new WolfProcess();
            SmartWolf.wolfProcess.start();
        }

        if (SmartWolf.wolfProcess.initWolf(SmartWolf.nWolves, MAP_SIZE)) {
            this.id = SmartWolf.nWolves;
            this.isDead = false;
            SmartWolf.wolves[id] = this;
        } else {
            SmartWolf.wolfProcess.endProcess();
            this.isDead = true;
        }
        SmartWolf.nWolves++;
    }

    /**
     * If the wolf is dead, or all the wolves of this type are dead, SUICIDE.
     * Otherwise, communicate an attack to the remote process and return
     * its attack choice.
     */
    @Override
    public Attack fight(char opponent) {
        if (!SmartWolf.wolfProcess.getRunning() || isDead) {
            return Attack.SUICIDE;
        }
        try {
            Attack atk = SmartWolf.wolfProcess.fight(id, opponent);

            if (atk == Attack.SUICIDE) {
                this.isDead = true;
            }

            return atk;
        } catch (Exception e) {
            System.out.printf("Something terrible happened, this wolf has died: %s", e.getMessage());
            isDead = true;
            return Attack.SUICIDE;
        }
    }

    /**
     * If the wolf is dead, or all the wolves of this type are dead, HOLD.
     * Otherwise, get a move from the remote process and return that.
     */
    @Override
    public Move move() {
        if (!SmartWolf.wolfProcess.getRunning() || isDead) {
            return Move.HOLD;
        }
        try {
            Move mv = SmartWolf.wolfProcess.move(id, surroundings);

            return mv;
        } catch (Exception e) {
            System.out.printf("Something terrible happened, this wolf has died: %s", e.getMessage());
            isDead = true;
            return Move.HOLD;
        }
    }

    /**
     * The shared static process manager, that synchronizes all communication
     * with the remote process.
     */
    static class WolfProcess extends Thread {
        private Process process;
        private BufferedReader reader;
        private PrintWriter writer;
        private ExecutorService executor;
        private boolean running;

        public boolean getRunning() {
            return running;
        }

        public WolfProcess() {
            process = null;
            reader = null;
            writer = null;
            running = true;
            executor = Executors.newFixedThreadPool(1);
        }

        public void endProcess() {
            running = false;
        }

        /**
         * WolfProcess thread body. Keeps the remote connection alive.
         */
        public void run() {
            try {
                System.out.println("Starting SmartWolf remote process");
                ProcessBuilder pb = new ProcessBuilder("mono SmartWolf.exe".split(" "));
                pb.redirectErrorStream(true);
                process = pb.start();
                System.out.println("SmartWolf process begun");
                // STDOUT of the process.
                reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")); 
                System.out.println("SmartWolf reader stream grabbed");
                // STDIN of the process.
                writer = new PrintWriter(new OutputStreamWriter(process.getOutputStream(), "UTF-8"));
                System.out.println("SmartWolf writer stream grabbed");
                while(running){
                    this.sleep(0);
                }
                reader.close();
                writer.close();
                process.destroy(); // kill it with fire.
                executor.shutdownNow();
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("SmartWolf ended catastrophically.");
            }
        }

        /**
         * Helper that invokes a read with a timeout
         */
        private String getReply(long timeout) throws TimeoutException, ExecutionException, InterruptedException{
            Callable<String> readTask = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return reader.readLine();
                }
            };

            Future<String> future = executor.submit(readTask);
            return future.get(timeout, TimeUnit.MILLISECONDS);
        }

        /**
         * Sends an initialization command to the remote process
         */
        public synchronized boolean initWolf(int wolf, int map_sz) {
            while(writer == null){
                try {
                this.sleep(0);
                }catch(Exception e){}
            }
            boolean success = false;
            try{
                writer.printf("S%02d%d\n", wolf, map_sz);
                writer.flush();
                String reply = getReply(5000l);
                if (reply != null && reply.length() >= 3 && reply.charAt(0) == 'K') {
                    int id = Integer.valueOf(reply.substring(1));
                    if (wolf == id) {
                        success = true;
                    }
                }
                if (reply == null) {
                    System.out.println("did not get reply");
                }
            } catch (TimeoutException ie) {
                endProcess();
                System.out.printf("SmartWolf %d failed to initialize, timeout\n", wolf);
            } catch (Exception e) {
                endProcess();
                System.out.printf("SmartWolf %d failed to initialize, %s\n", wolf, e.getMessage());
            }
            return success;
        }

        /**
         * Send an ATTACK command to the remote process.
         */
        public synchronized Attack fight(int wolf, char opponent) {
            Attack atk = Attack.SUICIDE;
            try{
                writer.printf("A%02d%c\n", wolf, opponent);
                writer.flush();
                String reply = getReply(1000l);
                if (reply.length() >= 3) {
                    int id = Integer.valueOf(reply.substring(1));
                    if (wolf == id) {
                        switch(reply.charAt(0)) {
                            case 'R':
                                atk = Attack.ROCK;
                                break;
                            case 'P':
                                atk = Attack.PAPER;
                                break;
                            case 'S':
                                atk = Attack.SCISSORS;
                                break;
                            case 'D':
                                atk = Attack.SUICIDE;
                                break;
                        }
                    }
                }
            } catch (TimeoutException ie) {
                endProcess();
                System.out.printf("SmartWolf %d failed to attack, timeout\n", wolf);
            } catch (Exception e) {
                endProcess();
                System.out.printf("SmartWolf %d failed to attack, %s\n", wolf, e.getMessage());
            }
            return atk;
        }

        /**
         * Send a MOVE command to the remote process.
         */
        public synchronized Move move(int wolf, char[][] map) {
            Move move = Move.HOLD;
            try{
                writer.printf("M%02d", wolf);
                for (int row=0; row<map.length; row++) {
                    for (int col=0; col<map[row].length; col++) {
                        writer.printf("%c", map[row][col]);
                    }
                }
                writer.print("\n");
                writer.flush();
                String reply = getReply(1000l);
                if (reply.length() >= 3) {
                    int id = Integer.valueOf(reply.substring(1));
                    if (wolf == id) {
                        switch(reply.charAt(0)) {
                            case 'H':
                                move = Move.HOLD;
                                break;
                            case 'U':
                                move = Move.UP;
                                break;
                            case 'L':
                                move = Move.LEFT;
                                break;
                            case 'R':
                                move = Move.RIGHT;
                                break;
                            case 'D':
                                move = Move.DOWN;
                                break;
                        }
                    }
                }
            } catch (TimeoutException ie) {
                endProcess();
                System.out.printf("SmartWolf %d failed to move, timeout\n", wolf);
            } catch (Exception e) {
                endProcess();
                System.out.printf("SmartWolf %d failed to move, %s\n", wolf, e.getMessage());
            }
            return move;
        }
    }
}

Không thực sự tuyệt vời, trung bình tỷ lệ sống ~ 75 cho 1000 lần lặp với một vài con sói hàng đầu.

Sử dụng một cách tiếp cận ML cho giải pháp.


Tôi nghĩ rằng tôi đã hiểu đại khái những gì con sói của bạn làm, nhưng bạn có thể giải thích chi tiết hơn không? Ngoài ra, bạn có lẽ nên đề cập đến ngôn ngữ đó là gì (tôi chắc chắn nó rõ ràng đối với hầu hết mọi người nhưng nó không rõ ràng đối với tôi).
plannapus

Nó được viết bằng C # và có một danh sách kiến ​​thức, liệt kê từng động tác được thực hiện đối với một loại động vật và tỷ lệ thành công của nó. Khi một con sói tấn công và chết, tỷ lệ thành công của di chuyển đó sẽ giảm. Nếu nó sống, tỷ lệ thành công được tăng lên. Hệ thống bắt đầu chọn di chuyển từ cơ sở tri thức thay vì chọn ngẫu nhiên sau một vài (20-30) lượt.
user3188175

1
Vui mừng khi thấy bạn sử dụng trình bao bọc! Có lẽ bạn nên bao gồm các hướng dẫn về cách biên dịch mã của mình và mono@Rizer sẽ sử dụng cái gì .
Lập trình viên

1
Markdown thất bại. Nếu bạn nhìn vào nguồn, '#' ở đó, nhưng vì nó nằm trong khối tiêu đề, Markdown đã bỏ qua nó. Đã sửa. : D
Lập trình viên

2
FYI - Tôi đã có thể biên dịch và chạy thành công với trình bao bọc của @ Lập trình viên (và không có sự giúp đỡ của anh ấy lần này nữa). Bạn sẽ có kết quả tiếp theo. Xin lỗi về sự chậm trễ!
Rainbolt

7

Sói thụ động-xâm lược (một con sói Scala)

Tránh mọi thứ có thể trong 500 lượt đầu tiên, để trường tự xóa. Sau đó đi theo hướng được chỉ định để tấn công những thứ mà nó nằm trong phạm vi.

package animals;

import animals._
import scala.util.Random

class PassiveAgressiveWolf extends Animal('W') {

    val myId=PassiveAgressiveWolf.nextId
    var movecounter=0

    def fight(opponent: Char) = {
        PassiveAgressiveWolf.lastopponents(myId-1)=opponent
        opponent match {
            case 'B' => Animal.Attack.SCISSORS
            case 'L' => Animal.Attack.SCISSORS
            case 'S' => Animal.Attack.ROCK
            case _ => Random.shuffle(List(Animal.Attack.SCISSORS, Animal.Attack.ROCK, Animal.Attack.PAPER)).head
        }
    }

    def move = {
        movecounter+=1
        if(movecounter < 500) avoidall else seen match {
            case ('B', pos: Int) => seenbear(pos)
            case ('S', pos: Int) => seenstone(pos)
            case ('L', pos: Int) => seenlion(pos)
            case ('W', pos: Int) => seenwolf(pos)
            case (' ', _) => myDirection
        }
    }

    def myDirection = myId % 4 match {
        case 0 => if(surroundings(0)(1)==' ') Animal.Move.LEFT else randommove
        case 1 => if(surroundings(1)(0)==' ') Animal.Move.DOWN else randommove
        case 2 => if(surroundings(1)(2)==' ') Animal.Move.RIGHT else randommove
        case 3 => if(surroundings(2)(1)==' ') Animal.Move.UP else randommove
    }

    def randommove = Random.shuffle(List(Animal.Move.UP, Animal.Move.LEFT, Animal.Move.RIGHT, Animal.Move.DOWN)).head

    def seen = {
        surroundings(1)(1)=' '
        val surroundingsflat=surroundings.flatten.mkString
        val seenbeasts = for {
            beast <- "BSLW" if surroundingsflat contains beast
        } yield (beast, surroundingsflat.indexOf(beast))
        seenbeasts.headOption.getOrElse((' ', 0))
    }

    def seenbear(pos: Int) = chase(pos)

    def seenstone(pos: Int) = pos match {
        case 1 => Animal.Move.LEFT
        case 3 => Animal.Move.UP
        case _ => myDirection
    }

    def seenlion(pos: Int) = pos match {
        case 1 => Animal.Move.LEFT
        case 3 => Animal.Move.UP
        case 5 => Animal.Move.HOLD
        case 7 => Animal.Move.HOLD
        case 0 => Animal.Move.UP
        case 2 => Animal.Move.HOLD
        case 6 => Animal.Move.HOLD
        case 8 => Animal.Move.HOLD
    }

    def seenwolf(pos: Int) = chase(pos)

    def chase(pos: Int) = pos match {
        case 1 => Animal.Move.UP
        case 3 => Animal.Move.LEFT
        case 5 => Animal.Move.RIGHT
        case 7 => Animal.Move.DOWN
        case 0 => Animal.Move.UP
        case 2 => Animal.Move.UP
        case 6 => Animal.Move.DOWN
        case 8 => Animal.Move.DOWN
    }

    def avoidall = {
        val safemoves = for {
            move <- List(
                            (0, 1, Animal.Move.UP), 
                            (1, 0, Animal.Move.LEFT), 
                            (1, 2, Animal.Move.RIGHT), 
                            (2, 1, Animal.Move.DOWN)
                        ) if(surroundings(move._1)(move._2)==' ')
        } yield move
        if(safemoves.length < 4) Random.shuffle(safemoves).head._3 else Animal.Move.HOLD
    }

}

object PassiveAgressiveWolf {
    private var id=0
    private def nextId = {id+=1; id}

    private var lastopponents=Array.fill[Char](100)(' ');
}

Là một ngôn ngữ dựa trên JVM, Scala có thể được tích hợp tương đối dễ dàng.

Nếu bạn đang tự biên dịch chương trình, hãy đặt tệp scala vào với các .classtệp java (không phải các .javatệp) và sử dụng

scalac PassiveAggressiveWolf.scala

để biên dịch nó. Sau đó, bạn có thể sử dụng PassiveAggressiveWolf.classtrong Wild.javalớp chính như bạn làm với các lớp Java. Bạn cũng sẽ cần thêm scala-library.jarđường dẫn lớp của mình (Tôi đã sử dụng tùy chọn dòng lệnh -cp /path/to/scala-library.jar).

Ngoài ra, tôi đã tải lên một tệp chứa các tệp lớp được tạo và scala-library.jarcho Scala 2.10.3 để bạn có thể tải xuống chúng.

Bị độngAggressiveWolf.jar
scala-library.jar


Có lẽ bạn có thể đóng gói 10 tệp vào một tệp zip để dễ dàng tải xuống.
johnchen902

@ johnchen902 Tôi đã đề nghị với tôi khi trò chuyện rằng tôi tạo một cái bình để chứa các lớp học của mình. Tôi sẽ xem xét việc đó vào tối nay sau giờ làm việc. Điều đó sẽ giảm xuống còn 2 lượt tải xuống và hy vọng sẽ giải quyết được các vấn đề mà Rizer đang gặp phải bao gồm cả nó.
Gareth
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.