เกมเอาชีวิตรอด - สร้างหมาป่าของคุณ


238

คณะกรรมการ

คณะกรรมการเป็นอาร์เรย์สองมิติของเซลล์ เซลล์ประชากรสัตว์ ทุกวันสัตว์ทุกตัวในคณะกรรมการจะเคลื่อนที่ไปพร้อม ๆ กัน หากสัตว์สองตัวหรือมากกว่าย้ายไปที่เซลล์เดียวกันพวกมันจะต่อสู้จนกว่าจะมีสัตว์อีก การเคลื่อนไหวและการโจมตีที่เป็นไปได้มีดังนี้:

  • ย้าย - { Move.UP, Move.RIGHT, Move.DOWN, Move.LEFT, Move.HOLD}
  • การโจมตี - { Attack.ROCK, Attack.PAPER, Attack.SCISSORS, Attack.SUICIDE}

สัตว์ต่อสู้โดยการเล่น Rock-Paper-Scissors ใช้กฎมาตรฐาน แต่มีสองการแก้ไข ขั้นแรกคุณสามารถฆ่าตัวตายได้ตลอดเวลา ประการที่สองเน็คไทเสีย pseudorandomly หากมีสัตว์มากกว่าสองตัวชนกันสองคนจะได้รับการสุ่มหลอกเพื่อต่อสู้จนกว่าจะมีใครเหลืออยู่

ผู้เล่น

พฤติกรรมและรูปลักษณ์ของสัตว์มีดังนี้

  • สิงโต
    • Lแทนด้วยตัวอักษร ย้ายDOWN, RIGHTแล้วซ้ำ การโจมตี Pseudorandomly ด้วยหรือPAPERSCISSORS
  • หมี
    • Bแทนด้วยตัวอักษร ย้ายDOWNx 4, RIGHTx 4, UPx 4, LEFTx 4 แล้วทำซ้ำ PAPERการโจมตีด้วย
  • หิน
    • Sแทนด้วยตัวอักษร HOLDการเคลื่อนไหว ROCKการโจมตีด้วย
  • หมาป่า
    • จะมีเฉพาะหมาป่าที่ส่งเป็นคำตอบเท่านั้น ตัวแทนโดย 'W' ย้ายด้วยการย้ายใด ๆ โจมตีด้วยการโจมตีใด ๆ

คุณจะนำ Wolf ไปใช้โดยกรอกข้อมูลลงในช่องว่างในแม่แบบต่อไปนี้ การส่งทั้งหมดจะต้องอยู่ใน Java และจะต้องอยู่ในไฟล์เดียว หรืออีกทางหนึ่ง @ProgrammerDan ได้เขียนคลาส wrapperที่ขยายการแข่งขันไปยังการส่งแบบ non-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
}

การส่งที่มีจำนวนหมาป่าโดยเฉลี่ยสูงที่สุดหลังจากการทดลองห้าครั้งโดยมีการวนซ้ำ 1,000 ครั้งชนะ ฉันจะอัปเดตผู้ชนะทุกครั้งที่มีการโพสต์คำตอบใหม่ (แต่ไม่ภายใน 24 ชั่วโมงแรก)

เครื่องมือ

  • คุณจะได้รับแผนที่ขนาดเล็กของสภาพแวดล้อมใกล้เคียงของคุณในรูปแบบต่อไปนี้
    • char[][] surroundingsศูนย์การจัดทำดัชนี 3 โดย 3 เมทริกซ์ของตัวละครที่เป็นตัวแทนของสัตว์ใกล้เคียง ช่องว่างจะแสดงด้วยอักขระเว้นวรรค ('') surroundings[1][1]คุณอยู่ที่ ยกตัวอย่างเช่นไปทางขวาของคุณจะเป็นและเหนือคุณsurroundings[1][2] surroundings[0][1]สภาพแวดล้อมของคุณได้รับการอัพเดตก่อนที่จะถูกขอให้ย้าย แต่อาจล้าสมัยเมื่อถูกขอให้สู้
  • คุณสามารถคงข้อมูลไว้ระหว่างการร้องขอ Wolf, การร้องขอย้ายและคำขอโจมตี คุณไม่สามารถอ่านหรือแก้ไขไฟล์ที่สร้างโดยคลาส Wolf อื่น
  • คุณมีขนาดของแผนที่ในแบบฟอร์มต่อไปนี้
    • int MAP_SIZE

สมมติฐาน

  • การส่งทั้งหมดจะแข่งขันในบอร์ดเดียวกันกับการส่งอื่น ๆ ทั้งหมดรวมถึง Lions, Bears และ Stones
  • กระดานเป็นสี่เหลี่ยมจัตุรัสที่มีด้านยาวsqrt(n+3)*20ซึ่งnเป็นจำนวนการส่ง ห่อทุกด้านเพื่อให้คุณสามารถเคลื่อนที่ได้ทุกทิศทางอย่างปลอดภัย
  • การจำลองเริ่มต้นที่ความจุของกระดานประมาณ 25% โดยแต่ละ 100 ของสัตว์หลอกเทียมกระจายทั่วกระดาน
  • หากสัตว์มีข้อผิดพลาดเมื่อถูกขอให้ย้ายสัตว์นั้นจะ HOLD
  • หากสัตว์มีข้อยกเว้นเมื่อถูกขอให้ต่อสู้สัตว์นั้นจะ SUICIDE
  • หากสัตว์ไม่มีตัวอักษรเมื่อผู้ควบคุมตรวจสอบสัตว์นั้นจะตายทันที

คำแนะนำในการเริ่มต้นและการทดสอบ

เครื่องมือที่คุณต้องการที่จะทดสอบการส่งของคุณสามารถพบได้ที่นี่ ไฟล์ต่อไปนี้ควรมีอยู่ที่ลิงค์นั้น

  • ExampleRun.gif - โปรแกรมรัน gif 5-10 วินาที
  • Scoreboard - ผลการแข่งขันล่าสุด
  • Wild.jar - ปฏิบัติการที่คุณสามารถเรียกใช้เพื่อดูสัตว์ที่ทำไว้ล่วงหน้าวิ่งไปมา
  • Wild.zip - โครงการ NetBeans ที่เป็นที่ตั้งของโปรแกรมควบคุมโดยเพิ่มสัตว์ที่สร้างไว้ล่วงหน้าไม่กี่ตัว ใช้สิ่งนี้เพื่อพัฒนาข้อเสนอของคุณ
  • WildPopulated.zip - เหมือนข้างต้น แต่มีและส่งมากกว่า 40 รายการเพื่อให้คุณทดสอบ GUI ได้ถูกลบเนื่องจากปัญหาด้านประสิทธิภาพ ผลลัพธ์จะปรากฏเพียงไม่กี่นาทีหลังจากที่คุณเรียกใช้ การส่งที่ไม่ใช่จาวาถูกคอมเม้นต์เนื่องจากต้องการการดาวน์โหลดและความพยายามเป็นพิเศษ ใช้สิ่งนี้เพื่อทดสอบการส่งของคุณกับเขตข้อมูล
  • Wolf.txt - การติดตั้งคลาส Wolf ใน Java อย่างไร้เดียงสา คุณสามารถใช้และขยายการใช้งานนั้นโดยไม่ให้เครดิตกับฉัน

เพื่อทดสอบชั้นเรียนของคุณ:

  • ดาวน์โหลด Wild.zip
  • เปลี่ยนชื่อชั้น Wolf.java และ Wolf เป็นสิ่งที่ไม่เหมือนใคร
  • เพิ่มไฟล์ UniquelyNamedWolf.java ของคุณไปยัง Wild \ src \ animals \
  • ในคลาส Wild ให้เพิ่มคลาสของคุณลงในclassesอาร์เรย์เช่นนี้
    • Class[] classes = { UniquelyNamedWolf.class, Bear.class, Lion.class, Stone.class, Wolf.class };
  • สร้างและเรียกใช้ใหม่

ฉันยังรวมโครงการอื่นที่มีการส่งทั้งหมดเพื่อวัตถุประสงค์ในการทดสอบ ฉันตั้งชื่อมันอย่างสร้างสรรค์ว่า "WildPopulated" หมาป่าสามหรือสี่ตัวที่ไม่ใช่จาวาถูกคอมเม้นท์เพราะการทำให้มันทำงานได้นั้นต้องใช้งานและการดาวน์โหลดเป็นพิเศษ หนึ่งที่ฉันโพสต์ควรทำงานโดยไม่มีงานพิเศษ GUI นั้นถูกคอมเม้นต์ด้วยความเร็ว

กระดานบอกคะแนน 22 เมษายน 2014

กระดานคะแนนถูกย้ายไปที่ Google Drive ดูที่นี่ มันจะได้รับการอัปเดตบนพื้นฐานที่ไม่เป็นทางการ (เช่นเมื่อฉันไปถึง) เมื่อมีการส่งเนื้อหาใหม่

Side Challenge - NoHOLD

นำออกเนื่องจากไม่มีส่วนร่วม (ในศูนย์) มันไม่ได้เป็นส่วนหนึ่งของความท้าทายเริ่มแรก


5
@Rusher นั่นฟังดูแย่มาก ฉันสามารถชุมชน wiki คำตอบของฉันที่ประกอบด้วย Wrapper สำหรับปัญหาคอมไพเลอร์ / ล่ามฉันคิดว่ามันขึ้นอยู่กับคณะอนุกรรมการที่จะให้คำแนะนำที่ชัดเจนเกี่ยวกับการใช้งานและหากคำแนะนำที่ไม่ชัดเจนหรือซับซ้อนเกินไปคุณสามารถปฏิเสธการส่ง :)
ProgrammerDan

4
"* คุณได้รับขนาดแผนที่ในรูปแบบต่อไปนี้: int MAP_SIZE" ฉันมีปัญหาในการหาวิธีใช้สิ่งนี้ Netbeans กล่าวว่าไม่มีอินสแตนซ์ของสตริงMAP_SIZEในไฟล์ใด ๆ ในโครงการ
undergroundmonorail

6
ต้นไม้แสดงกระดาษอย่างไร
Mukul Kumar

3
@Rusher ฉันคิดว่าบางคนกำลังทำสิ่งนี้อยู่แล้ว แต่การสื่อสารระหว่าง Wolf ได้รับอนุญาตผ่านสมาชิกแบบสแตติก (ภายในสายพันธุ์ของคุณ) หรือไม่
Martin Ender

10
@ m.buettner อนุญาต ออกไปและสร้างหมาป่ารังของคุณ
Rainbolt

คำตอบ:


47

HerjanWolf

อัปเดต 10-4-2014 เวลา 15:00 น

ค่าเฉลี่ย 100 รอบ 1,000 รอบซ้ำ:

mobs มาตรฐาน:

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

20+ สปีชีส์ (โปรดอย่าไว้วางใจคะแนนเหล่านี้เนื่องจากเราทำการคำนวณ avgs จนกระทั่งคะแนนหมาป่าของเราดีที่สุด!)

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

หมาป่าของฉัน:

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

การรวมเฉพาะหมาป่าที่ "ติดอันดับ" ในการทดสอบนั้นวิ่งไปตามปกติ ด้วยสปีชีส์มากกว่า 30 ชนิดบนสนามตัวเลขสามารถเปลี่ยนแปลงได้อย่างมาก หากคุณยังไม่ได้แนะนำการทดสอบ
Geobits

1
@ user20220 มันค่อนข้างดีในทางทฤษฎี (และในทางปฏิบัติกับหมาป่าค่อนข้างน้อย) แม้ว่า
user3188175

1
หมาป่าตัวนี้มีกลยุทธ์ต่อต้านสิงโตที่ดีที่สุด: chat.stackexchange.com/transcript/message/14837616#14837616
Justin

2
@ user20220 การปะทะกันของหมาป่าเกิดขึ้นบ่อยครั้งดังนั้นคุณควรเพิ่มการจัดการกับหมาป่าอีก คุณช่วยอธิบายว่าหมาป่าตัวนี้ทำงานอย่างไร
Justin

3
@ justhalf โอเคมันไม่ดีกว่ามันก็ดีแล้ว หมาป่าของฉันหลบสิงโตทั้งหมดเช่นกันฉันสร้างหมาป่าของฉันให้ปลอดภัย 100% ก่อนที่ฉันจะสร้างหมาป่าหลบ ความแตกต่างคือหมาป่าของฉันพยายามที่จะหลบหนีสิงโต (การเคลื่อนไหวน้อยกว่าดีกว่า) ดังนั้นมันก็ดีกับ Lion-dodging เช่นเดียวกับ Wion ทั้ง 100% lionproof แต่เนื่องจากหมาป่าของฉันพยายามที่จะหลบหนีไลออนส์และไม่น่าเบื่อแบบเดียวกับสิงโตฉันยังคงสามารถสร้างหมาป่า -dodging ได้เช่นกัน ซับซ้อนยิ่งขึ้น.
Herjan

153

EmoWolf

EmoWolf เกลียดชัง Java และอยากจะฆ่าตัวเองมากกว่าเข้าร่วม EmoWolf ได้อดอาหาร แต่ก็ยังมีน้ำหนัก 177 ไบต์

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 คุณสามารถโกนไบต์ได้: " ถ้าสัตว์ไม่มีตัวอักษรเมื่อตัวควบคุมตรวจสอบสัตว์นั้นจะตายทันที "
Geobits

112
สิ่งที่ดีที่สุดเกี่ยวกับเรื่องนี้คือมันไม่ได้เลวร้ายที่สุดเสมอ ปกติแล้วมันจะเต้นอย่างน้อย 2-3 ตัว
Geobits

51
"สิ่งเดียวที่ทำให้ชนะคือไม่เล่น"
tadman

38
+1 สำหรับตัวเล็กและฆ่าตัวตายและยังคงตีหมาป่าอีก 4 ตัว
puggsoy

25
ขอบคุณสำหรับคำแนะนำคน ถ้านี่คือกอล์ฟฉันจะรำคาญที่จะแก้ไขโพสต์ ฉันจะปล่อยให้ EmoWolf ซึมเศร้า คนเดียว
บูธโดย

52

LazyWolf

ตั้งชื่ออย่างถูกต้องผู้ชายคนนี้ทำขั้นต่ำเปลือยเพื่อความอยู่รอด ภัยคุกคามที่ไม่ใช่หมาป่าเพียงอย่างเดียวคือสิงโตดังนั้นเขาจะเคลื่อนไหวหากหนึ่งในนั้นกำลังจะก้าวเข้าสู่เขา นอกจากนั้นเขาแค่นอนหลับ

มีไม่มากที่คุณสามารถทำอะไรกับหมาป่าที่จะดีกว่า 50/50 ดังนั้นเขาแค่ไม่ทำอะไรเลย หากหมาป่าโจมตีเขาเขาเลือกการโจมตีด้วยวิธีกระจายที่เท่าเทียมกัน

แค่นั้นแหละ. ฉันคาดว่ามันจะทำได้ค่อนข้างดีแม้จะมีความเรียบง่าย

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

}

ปรับปรุง:

CamoWolfเต้นฉันอย่างคล่องแคล่ว เนื่องจากหมาป่าของฉันขี้เกียจเขาจึงไม่เคยวิ่งเข้าไปในหินจริง ดังนั้นหากมีการโจมตีด้วยหินจะเห็นได้ชัดว่าเป็นของปลอมและต้องการหินที่ถูกส่งไปที่หน้า


ตอนนี้คุณมีความเป็นไปได้ที่จะย้ายไปเป็นสิงโตตัวที่สองเมื่อคุณพยายามหลีกเลี่ยง คุณสามารถลบมันได้โดยติดตามว่ามีการเคลื่อนไหวกี่ครั้งดังนั้นคุณจะรู้ว่าสิงโตกำลังมาที่จัตุรัสของคุณหรือไม่ ถ้าเป็นเช่นนั้นให้ย้ายไปในทิศทางเดียวกันกับสิงโตและไม่มีสิงโตมาหาคุณเพราะพวกมันกำลังเคลื่อนที่ไปในทิศทางเดียวกัน
ughoavgfhw

13
ฉันคิดเกี่ยวกับสถานการณ์ของสิงโตสองตัว แต่ตัดสินใจว่าหมาป่าของฉันขี้เกียจเกินกว่าจะดูแล อัตราต่อรองของมันเกิดขึ้นบ่อยครั้งพอกับบอร์ดที่มีประชากรค่อนข้างบางอยู่แล้ว
Geobits

1
ทำไมคุณถึงคิดว่าหมาป่าตัวนี้ไม่เคยวิ่งเข้าไปในหินจริง? ฉันคิดว่ามันสามารถเกิดขึ้นได้ทุกครั้งที่มันวิ่งหนีสิงโต
Christopher Creutzig

6
@ChristopherCreutzig มันไหลออกมาจากสิงโตโดยการเคลื่อนย้ายไปยังที่ที่สิงโตเป็น ถ้าสิงโตก็มีหินไม่สามารถจะมีในขณะนี้
Geobits

1
แม้ว่าจะทำได้ แต่ก็ไม่มี "วนซ้ำไม่สิ้นสุด" หากการโจมตีเป็นเน็คไทหนึ่งหรืออีกตาย (เลือกโดยโยนเหรียญ) ต่อสเป็ค
Geobits

51

Wrapper สำหรับการส่งที่ไม่ใช่ Java

หมายเหตุมีการเพิ่มการสนับสนุน MAP_SIZE หากคุณสนใจโปรดอัปเดตการส่งของคุณตามนั้น

นี่คือรายการ wiki ชุมชนสำหรับ wrapper ใช้งานได้โดยผู้ที่ต้องการเล่น แต่ไม่ชอบ / ไม่รู้จัก Java โปรดใช้มันสนุกและฉันมีความสุขที่จะช่วยให้คุณตั้งค่าต่างๆ

มันค่อนข้างช้าที่นี่เมื่อฉันเสร็จแล้วดังนั้นตัวแปลงสัญญาณ Java อื่น ๆ โปรดดูที่นี่และแนะนำการปรับปรุง หากทำได้ให้ทำผ่านที่เก็บ github ของฉันโดยยื่นปัญหาหรือส่งแพทช์ ขอบคุณ!

ทั้งหมดนี้จะถูกกระจายกับ UNLICENSE โปรดปฏิบัติตาม / แยกได้จากพื้นที่เก็บข้อมูล ส่งแพตช์ที่นั่นหากคุณพบปัญหาและฉันจะอัปเดตโพสต์นี้

ตัวอย่างการใช้ Wrapper ปัจจุบัน

plannapus : WolfCollectiveMemory ใน R

user3188175 : SmartWolf ในC#

แปรงสีฟัน : แปรงสีฟันใน ECMAScript

วิธีใช้

สิ่งต่อไปนี้เป็นคำแนะนำเกี่ยวกับโปรโตคอลสำหรับการสื่อสารระหว่างกระบวนการผ่านทางท่อที่ฉันได้กำหนดไว้สำหรับหมาป่าระยะไกล หมายเหตุฉันข้าม MAP_SIZE เนื่องจากไม่ปรากฏแม้ว่าจะมีอยู่ในคำสั่งปัญหาของ OP หากปรากฏขึ้นฉันจะอัปเดตโพสต์นี้

หมายเหตุสำคัญ :

  • จะมีการเรียกใช้กระบวนการภายนอกของคุณเพียงครั้งเดียวเท่านั้น (เพื่อรวมตรรกะการประมวลผลของคุณไว้ในวงวนไม่สิ้นสุดซึ่งจะช่วยให้คุณสามารถประมวลผลใด ๆ ในหน่วยความจำแทนการใช้ดิสก์)
  • การสื่อสารทั้งหมดเป็นกระบวนการภายนอกเดียวผ่าน STDIN และ STDOUT
  • คุณต้องล้างข้อมูลทั้งหมดที่ส่งไปยัง STDOUT อย่างชัดเจนและตรวจสอบให้แน่ใจว่ามันถูกยกเลิกการขึ้นบรรทัดใหม่

สเปค

สคริปต์ระยะไกลได้รับการสนับสนุนโดยโปรโตคอลอย่างง่ายผ่านทาง STDIN และ STDOUT hooks และแบ่งออกเป็นการเตรียมใช้งานการย้ายและการโจมตี ในแต่ละกรณีการสื่อสารกับกระบวนการของคุณจะผ่าน STDIN และจำเป็นต้องมีการตอบกลับจาก STDOUT หากไม่ได้รับคำตอบภายใน 1 วินาทีกระบวนการของคุณจะถูกพิจารณาว่าตายและจะมีข้อยกเว้นเกิดขึ้น อักขระทั้งหมดจะถูกเข้ารหัสใน UTF-8 เพื่อความสอดคล้อง อินพุตทุกรายการจะจบลงด้วยอักขระขึ้นบรรทัดใหม่และกระบวนการของคุณควรยุติการตอบกลับเอาต์พุตทุกครั้งด้วยการขึ้นบรรทัดใหม่เช่นกัน คำเตือนตรวจสอบให้แน่ใจว่าได้ล้างบัฟเฟอร์เอาต์พุตของคุณทุกครั้งหลังการเขียนเพื่อให้แน่ใจว่า Java wrapper เห็นผลลัพธ์ของคุณ การไม่ล้างข้อมูลอาจทำให้ Wolf ระยะไกลล้มเหลว

โปรดทราบว่ากระบวนการเดียวเท่านั้นที่จะถูกสร้างขึ้น Wolves ทั้งหมดต้องได้รับการจัดการภายในกระบวนการเดียว อ่านต่อไปว่าสเป็คนี้จะช่วยได้อย่างไร

การเริ่มต้น

STDIN: S<id><mapsize> \ n

STDOUT: K<id> \ n

<id>: 00หรือ01หรือ ... หรือ99

คำอธิบาย:

ตัวละครตัวนี้Sจะถูกส่งไปตามตัวละครทั้งสองตัวเลข00, 01, ... , 99ระบุว่าใน 100 หมาป่าจะถูกเริ่มต้น ในการสื่อสารทั้งหมดในอนาคตกับหมาป่านั้น<id>จะใช้เหมือนเดิม

หลังจาก ID แล้วจะมีการส่งลำดับความยาวผันแปรของอักขระตัวเลข นี่คือขนาดของแผนที่ คุณจะรู้ว่าลำดับของอักขระตัวเลขสิ้นสุดลงเมื่อคุณไปถึงบรรทัดใหม่ ( \n)

เพื่อให้แน่ใจว่ากระบวนการของคุณยังมีชีวิตอยู่คุณต้องตอบกลับด้วยตัวละครที่Kตามมาด้วยสิ่งที่<id>คุณได้รับ การตอบกลับอื่น ๆ จะส่งผลให้มีข้อยกเว้นฆ่าหมาป่าของคุณ

การเคลื่อนไหว

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

STDOUT: <mv><id> \ n

<Cn>: WหรือหรือBหรือSหรือL

W:หมาป่า

:พื้นที่ว่างเปล่า

B:หมี

S:หิน

L:สิงโต

<mv>: HหรือUหรือLหรือRหรือD

H:ย้าย. โฮลด์

U:ย้าย

L: Move.LEFT

R:ย้าย. ขวา

D:ย้ายลง

คำอธิบาย:

ตัวละครMจะถูกส่งไปตามด้วยตัวละครสองตัว<id>เพื่อระบุว่า Wolf ต้องการเลือกการเคลื่อนไหวใด หลังจากนั้นจะมีการส่งอักขระ 9 ตัวเพื่อแสดงถึงสภาพแวดล้อมของ Wolf ตามลำดับแถว (แถวบน, แถวกลาง, แถวล่างจากซ้ายไปขวาสุด)

ตอบกลับด้วยหนึ่งในตัวละครเคลื่อนไหวที่ถูกต้อง<mv>ตามด้วยตัวเลขสองหลักของ Wolf <id>เพื่อยืนยัน

โจมตี

STDIN: A<id><C> \ n

STDOUT: <atk><id> \ n

<C>: WหรือBหรือSหรือL

<atk>: RหรือPหรือSหรือD

R: Attack.ROCK

P: Attack.PAPER

S: Attack.SCISSORS

D: Attack.SUICIDE

คำอธิบาย:

ตัวละครAจะถูกส่งไปตามด้วยตัวละครสองตัว<id>เพื่อระบุว่าหมาป่าตัวใดมีส่วนร่วมในการโจมตี ตามด้วยอักขระเดี่ยว<C>ระบุประเภทของสิ่งที่กำลังโจมตีทั้งWolf BหูSน้ำเสียงหรือLไอออน

ตอบกลับด้วยหนึ่งใน<atk>ตัวละครที่ระบุไว้ด้านบนเพื่อระบุว่าคุณตอบโต้การโจมตีอย่างไรตามด้วยตัวเลขสองหลัก<id>เพื่อยืนยัน

และนั่นคือมัน ไม่มีอะไรเพิ่มเติมอีกแล้ว หากคุณสูญเสียการโจมตีนั่น<id>จะไม่ถูกส่งไปยังกระบวนการของคุณอีกนั่นคือวิธีที่คุณจะรู้ว่าหมาป่าของคุณเสียชีวิต - หากรอบการเคลื่อนไหวที่สมบูรณ์ผ่านไปโดยที่ไม่มี<id>การส่ง

ข้อสรุป

โปรดทราบว่าข้อยกเว้นใด ๆ จะฆ่าหมาป่าทุกตัวในรีโมตของคุณเนื่องจากมีเพียง "กระบวนการ" เดียวที่สร้างขึ้นจากรีโมตหมาป่าของคุณสำหรับหมาป่าทุกประเภทที่สร้างขึ้น

ในพื้นที่เก็บข้อมูลนี้คุณจะพบWolf.javaไฟล์ ค้นหาและแทนที่สตริงต่อไปนี้เพื่อตั้งค่า bot ของคุณ:

  • แทนที่<invocation>ด้วยอาร์กิวเมนต์บรรทัดคำสั่งที่จะดำเนินการตามกระบวนการของคุณ

  • แทนที่<custom-name>ด้วยชื่อที่ไม่ซ้ำสำหรับ Wolf ของคุณ

  • สำหรับตัวอย่างดูที่เก็บซึ่งฉันมีWolfRandomPython.javaสิ่งนั้นเรียกใช้ตัวอย่างระยะไกลของฉันPythonWolf.py(Python 3+ Wolf)

  • เปลี่ยนชื่อไฟล์Wolf<custom-name>.javaที่<custom-name>จะถูกแทนที่ด้วยชื่อที่คุณเลือกด้านบน

ในการทดสอบ Wolf ของคุณให้รวบรวมโปรแกรม Java ( javac Wolf<custom-name>.java) และทำตามคำแนะนำของ Rusher เพื่อรวมไว้ในโปรแกรมจำลองสถานการณ์

สำคัญ:ตรวจสอบให้แน่ใจว่าได้เตรียมคำแนะนำที่ชัดเจนและรัดกุมเกี่ยวกับวิธีการรวบรวม / ดำเนินการ Wolf จริงของคุณซึ่งเป็นไปตามรูปแบบที่ฉันได้อธิบายไว้ข้างต้น

ขอให้โชคดีและอาจเป็นไปได้ว่าคุณจะชอบธรรมชาติ

รหัส Wrapper

จำไว้ว่าคุณต้องทำการค้นหาและแทนที่โครงร่างเกี่ยวกับสิ่งนี้เพื่อให้สามารถใช้งานได้ หากการร้องขอของคุณมีขนดกกรุณาติดต่อเราเพื่อขอความช่วยเหลือ

โปรดทราบว่ามีmainวิธีการใน wrapper นี้เพื่อให้การทดสอบ "ผ่าน / ไม่ผ่าน" ขั้นพื้นฐานในกล่องท้องถิ่นของคุณ ในการทำเช่นนั้นให้ดาวน์โหลดคลาส Animal.java จากโครงการและลบpackage animals;บรรทัดออกจากไฟล์ทั้งสอง แทนที่บรรทัด MAP_SIZE ใน Animal.java ด้วยค่าคงที่ (เช่น 100) รวบรวมพวกเขาโดยใช้ดำเนินการผ่านjavac Wolf<custom-name>.javajava 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
ฉันขาดโพสต์นี้ มันไม่ใช่คำตอบ แต่มันมีประโยชน์มากสำหรับความท้าทาย มันน่าจะเป็นไปได้ในร่างกายที่ท้าทาย
Mego

ไม่ว่าจะอยู่ที่นี่หรือที่นี่คนที่สามารถหามันได้และมีประโยชน์ต่อพวกเขาฉันจะพอใจ :)
โปรแกรมเมอร์

46

CamoWolf

รูปแบบรหัสที่ต้องการในทางที่ผิด

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

ดังนั้นหมาป่าของฉันฉลาดจริงๆและเขาพรางตัวเป็นก้อนหินแทน! การผสมผสานกับสภาพแวดล้อมเป็นกลยุทธ์การเอาชีวิตรอดที่ดีอยู่เสมอ!

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

อัปเดต : เพิ่มการisSafeตรวจสอบใหม่เพื่อความปลอดภัยจาก LazyWolf! ฮา!
Update 2 : สมมุติว่าการขี้เกียจก็เป็นกลยุทธ์การเอาชีวิตรอดที่ดีเช่นกัน ไม่เคลื่อนไหวยกเว้นสิงโตจะถูกคุกคาม lastMoveไม่จำเป็นอีกต่อไป แต่ฉันเก็บไว้ในกรณีที่ฉันเปลี่ยนรหัสอีกครั้ง


29
เมื่อฉันเพิ่มการส่งของคุณในโครงการฉันตั้งใจใส่ทั้งชั้นในบล็อกความคิดเห็น
Rainbolt

2
@Rusher Java ไม่แยกวิเคราะห์ความคิดเห็นซ้อน? : P
Martin Ender

6
ในโลกที่ LazyWolf สามารถป้องกันได้สิ่งนี้อาจสมเหตุสมผลกว่าที่จะแกล้งทำเป็นสิงโตและเลือก ROCK หรือสุ่ม มันจะลดจำนวนการเผชิญหน้าจากผู้คนเนื่องจากส่วนใหญ่จะพยายามหลีกเลี่ยงสิงโตและควรชนะโดยเฉลี่ยกับคนที่คิดว่าพวกเขากำลังต่อสู้กับสิงโต
Tim Seguine

7
@Radiodef มันเป็น
Rainbolt

2
@Radiodef ฉันไม่ได้บอกเมื่อมันไม่ได้? ;-)
Doorknob

38

GatheringWolf

หมาป่าของฉันอาศัยอยู่เป็นกลุ่ม พวกเขารวบรวมถ้าสิงโตปล่อยให้พวกเขา แม้ว่าพวกเขาจะไม่รอดชีวิตได้ดีนัก

อัปเดต:หากสิงโตบังคับพวกเขาให้ไปตอนนี้พวกเขาพยายามรวบรวมใหม่!

สกรีนช็อตของผลลัพธ์ของ 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
สองสามครั้งหมาป่าของเรากลายเป็นเพื่อนกันเพราะของฉันติดกับดัก แต่จะไม่เริ่มการโจมตีและคุณแค่คิดว่าของฉันเป็นส่วนหนึ่งของฝูง :)
undergroundmonorail

1
ขอบคุณที่เขียนสิ่งนี้เพราะมิฉะนั้นฉันจะต้องทำเอง การใช้ความฉลาดทางหลอกร่วมกันอย่างชาญฉลาด
เบ็คแจ็คสัน

31

เสื้อผ้าของ The Sheep in Wolf

วิ่งหนี.

มันจัดลำดับความสำคัญการวิ่งหนีจาก Wolves มากที่สุดเนื่องจากพวกเขากำลังจะเป็นอันตรายที่สุด ถัดไปคือ Lions เนื่องจากมันเป็น nondeterministic Bears and Stones ไม่ใช่ปัญหา แต่เรายังคงวิ่งหนีไปจากพวกเขาหากเราไม่มีอะไรดีไปกว่านี้เพราะหมาป่าฆ่า Bear หรือ Stone ในเวลานั้นไม่ใช่หมาป่าฆ่าแกะ

ฉันยังไม่ได้ทดสอบกับ LazyWolf แต่ฉันมีสิทธิ์ที่ดีที่จะเตะตูดของ EmoWolf ;)

(โปรดยกโทษให้ฉันหากรหัสนี้แย่มากฉันไม่เคยแตะต้อง Java มานานกว่าโปรแกรม Hello World มาก่อน)

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

อ๊ะฉันออกจากสิ่งที่ฉันใช้ในการทดสอบที่นั่นโดยไม่ได้ตั้งใจ มันจะไม่ส่งผลกระทบอะไรเลยมันแค่หมายความว่าฉันพยายามเข้าใกล้ทุกสิ่งที่มีลักษณะคล้าย H. : P
undergroundmonorail

แค่อยากรู้อยากเห็นถ้าxWeightและyWeightเป็นทั้งไม่ใช่ศูนย์และค่าสัมบูรณ์ของพวกเขาเหมือนกันหมาป่าตัวนี้ไม่ขยับใช่ไหม? และถ้าเป็นเช่นนั้นโดยเจตนาแล้วทำไม?
Patrick Roberts

@PatrickRoberts oops
undergroundmonorail

26

ไม่ใช่รายการเพียงต้องการมีส่วนร่วมกับ GUI โดยการเพิ่มรหัสสีสำหรับแต่ละคลาส = D

ผลลัพธ์

GUI สี

Wild.java

เปลี่ยนรหัสgame.populate(c,100)โดยใช้:

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

ด้วยการgenerateColorsกำหนดเป็น:

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

ขั้นตอนวิธีใดที่นำมาจากคำตอบ StackOverflow นี้

ด้วยcolorและsetColorถูกกำหนดใน 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);
}

จากนั้นอัปเดตtoStringวิธีการใน Game.java และ 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
สวย. ฉันผ่านไปหลายนาทีเมื่อวานนี้แค่มองหน้าจอ รู้สึกเหมือนอ่านเมทริกซ์รถถัง
เฉลี่ย

การจำลอง .... คือ .... ชนิด .... จาก ..... ช้า .... (5 การวนซ้ำหลังจาก 30 วินาที)
user3188175

ฮ่าฮ่าใช่ แต่มันมีอยู่ในการออกแบบการจำลองซึ่งกำลังพิมพ์รหัส HTML สำหรับการวนซ้ำแต่ละครั้ง
justhalf

ฉันสามารถแบ่งปันสิ่งนี้กับไดรฟ์ Google ของฉัน (เชื่อมโยงในการท้าทาย) ได้หรือไม่ถ้าฉันให้ลิงค์ไปยังโพสต์นี้ มันใช้งานได้ดีมากสำหรับการทดสอบหมาป่าจำนวนหนึ่ง
Rainbolt

1
ใช่คุณสามารถ. คุณสามารถรวมการข้ามการเรนเดอร์เบื้องต้นเพื่อเพิ่มความเร็วในการเรนเดอร์สำหรับหมาป่าหลายตัวดังที่ฉันเขียนไว้ในบทความอื่นเกี่ยวกับแผ่นดินไหว
justhalf

23

AlphaWolf

ได้เวลาส่องแสง! หมาป่าตัวอื่น ๆ ของฉัน CamperWolf ผอมมากมาถึงตอนนี้ AlphaWolf ผู้มีกล้ามเนื้อมากขึ้น!

แทนที่จะหลบสิงโตไปตามทางมาตรฐานมันสลับฟิลด์กับพวกมัน นอกจากนี้ยังกำหนดค่าอันตรายให้กับแต่ละเขตข้อมูลโดยรอบ

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

}

มันไม่ได้เป็นรหัสที่สวยงามมาก แต่ในการทดสอบของฉันมันทำงานได้ดีมากกับหมาป่าจาวาทุกตัว


1
"สลับฟิลด์" หมายความว่าอย่างไร แค่อยากรู้อยากเห็นเนื่องจากฉันไม่สามารถทำงานในที่ทำงาน
Rainbolt

จากการจำลองทั้งหมดของฉันคุณชนะโดยเฉลี่ย 80-90 ตัวหลังจากทำซ้ำ 1,000 ครั้ง ฉันมีเพียงหมาป่าทางกฎหมายที่เขียนด้วยภาษาจาวาที่ถูกส่งมาถึงฉัน ยังคงเหมือนหมาป่า 10 ตัวหรือมากกว่านั้น
Sheph

@Rusher ถ้าสิงโตอยู่เหนือหมาป่าของฉันและจะเลื่อนลงหมาป่าของฉันจะเลื่อนขึ้น
CommonGuy

คุณต้องเพิ่มรหัส anti-wilfcamo ความคิดที่ดีมากที่จะใช้รูปแบบของสิงโตรู้ :)
Lesto

9
ตอนนี้มีคนต้องการประดิษฐ์หมาป่าที่จะหาสิงโตพบดังนั้นคุณจะพบมันทันทีที่คุณพยายามที่จะแลกเปลี่ยนกับสิงโต
AJMansfield

23

นักพนันหมาป่า

Gambler Wolf ชอบที่จะใช้โอกาสเพื่อให้เขาทำงานอย่างผิดปกติโดยหวังว่า Lady Luck จะอยู่ข้างเขา! โชคดีสำหรับเขาเธอไม่เคยทำให้เขาผิดหวัง! Gambler Wolf ล้างสนามรบของอุปสรรคที่ไม่ใช่หมาป่าทั้งหมดด้วยจังหวะที่ไม่หยุดยั้ง

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

แก้ไข: v1.1

  • ตอนนี้หลีกเลี่ยง Stones (Camo-Wolves?)

  • เพิ่มความสุ่ม!


5
ฉันคิดว่าฉันจะเพิ่มนี้เพื่อหมาป่าฉัน:static{System.setSecurityManager(new SecurityManager());}
johnchen902

13
เมื่อคุณเล่นไม่ยุติธรรมให้โกง +1: D
ProgrammerDan

5
โชคไม่ดีไม่สามารถใช้return 4; // chosen by fair dice roll. guaranteed to be random.ที่นี่ ...
Vi

1
หากคุณต้องการที่จะชั่วร้ายมากขึ้นทำลายสัญญาของMath.random()มากยิ่งขึ้น; ส่งคืนค่าที่อยู่นอกช่วง [0,1) หรืออาจเป็นอนันต์หรือ NaN หรือจะเป็นความชั่วร้ายที่สุดเท่าที่จะเป็นไปได้เพียงแค่โยนข้อยกเว้นรันไทม์แทนการคืนสิ่งใดnull
Runer112

1
@AlexL ดูเหมือนForrestWolfปัญหา ...
recursion.ninja

22

CamperWolf

เป้าหมายคือเพื่อความอยู่รอด ในขณะที่หมาป่าตัวอื่น ๆ วิ่งหนีไปจากหมาป่าหมาป่าของฉันก็อยู่ที่ตรงนั้นและต่อสู้กับสัตว์ทุกตัว (แม้แต่ก้อนหิน

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

ฉันคาดหวังว่ามันจะทำงานได้ดีมากเนื่องจากมีหมาป่าตัวอื่น ๆ วิ่งหนีออกจากหมาป่าและความคิดแบบนี้สามารถตายกับหมาป่าตัวอื่นได้เท่านั้น


สิงโตก็สามารถฆ่ามันได้เช่นกัน หากสิงโตกลิ้งกรรไกรหมาป่าของคุณจะตายแบบสุ่ม
Tim Seguine

2
ยินดีด้วย คุณและรหัส 15 บรรทัดของคุณกำลังได้รับรางวัล
Rainbolt

2
@Rusher ขอบคุณ :) สามารถ downvoter โปรดอธิบายว่าทำไมเขา downvote?
CommonGuy

@Manu มันไม่สำคัญหรอกเพราะ Stones ไม่สามารถขยับได้ แต่ควรจะกลับมาโจมตีของคุณเหรอ?
DavidJFelix

3
ใช่ฉันเห็น CamoWolf หลังจากถาม เจ้าเล่ห์!
DavidJFelix

22

DeepWolf

ฉันใช้เวลากับสิ่งนี้มากเกินไป ... เอาล่ะหมาป่าตัวนี้ใช้การวิเคราะห์แบบ "ลึก" รวบรวมและใช้ข้อมูลด้านสิ่งแวดล้อมให้มากที่สุดเท่าที่ฉันจะคิดได้ การวิเคราะห์ดำเนินการโดยใช้ความรู้เฉพาะของหมาป่าเช่นตำแหน่งที่เป็นที่รู้จักของสิงโตและหมาป่าและการทำนายตำแหน่งในอนาคตและรวบรวมความรู้ hivemind เช่นประชากรประมาณประวัติศาสตร์การต่อสู้หมาป่าและอันตรายจากการปะทะกับฝ่ายตรงข้ามสัตว์เมื่อเคลื่อนไหว มันมีขนาดใหญ่เป็นพิเศษด้วยนอกเหนือจากการมีเหตุผลมากมายฉันก็ลงน้ำในการออกแบบเชิงวัตถุและมีคลาสและวิธีการพิเศษมากมาย

ฉันวิ่งวน 100 เกมในแต่ละ 1,000 ขั้นตอนด้วยหมาป่าที่เป็นที่นิยมและมีประสิทธิภาพที่สุด ฉันจงใจออกไปจาก GamblerWolf เพราะฉันคิดว่ามันเป็นเรื่องขี้โกงแม้ว่ามันจะไม่ส่งผลกระทบต่อหมาป่าของฉัน แต่อย่างใด นี่คือข้อมูลประสิทธิภาพโดยเฉลี่ยสูงสุดและต่ำสุด:

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 อยู่ในสถานที่แรกที่มีค่าเฉลี่ย 90.48 แม้ว่าจะมีเพียงนำแคบ ๆ ประมาณ 2 มากกว่าสถานที่ที่สองของ OmegaWolf 88.67 บรรทัดรหัสประมาณ 4 เท่าเพื่อการปรับปรุง 2% เท่านั้น! HerjanWolf, HonorWolf และ HybridWolf vie เป็นอันดับสามตามมาด้วย OmegaWolf อีก 2 ตัวโดยเฉลี่ยอยู่ที่ 86.55, 86.76 และ 86.78 ตามลำดับ

หากไม่มีความกังวลใจเพิ่มเติมฉันจะแสดงรหัส มันใหญ่มากจนมีข้อผิดพลาดและ / หรือมีแนวโน้มที่จะปรับปรุงค่าคงที่ / ตรรกะที่ฉันไม่สามารถมองเห็นได้ หากคุณมีข้อเสนอแนะใด ๆ แจ้งให้เราทราบ!

โค้ดที่ลิงค์นี้เนื่องจากปรากฎว่ามีการ จำกัด จำนวนอักขระของโพสต์: Ideone


ฉันไม่ทราบว่า dropboxusercontent จะสูญเสียไฟล์หรือไม่ดังนั้นฉันโพสต์ไว้ใน ideone: ideone.com/uRNxvj
Justin

3
@ Runer112 ที่น่าประทับใจ! ฉันกำลังมองหาที่รหัสและฉันเป็นบิตหายไป: P แต่หนึ่งในแนวคิดที่ชั่วช้าฉันเป็นสิ่งที่คุณกำลังใช้ฐานการตัดสินใจที่หมาป่ามีความเป็นมิตรหรือไม่
Moogie

@Mogogie ไม่มีการประเมินที่แน่นอนว่าหมาป่านั้นเป็นมิตรหรือไม่ อย่างไรก็ตามเรารู้ว่ามีหมาป่าหลายสายพันธุ์เรารู้ว่าแต่ละเผ่าพันธุ์เริ่มต้นที่ 100 เรารู้ว่ามีหมาป่าที่เป็นมิตรอื่นเหลืออยู่อีกกี่ตัวและเราสามารถเดาได้ว่ามีหมาป่าที่ไม่เป็นมิตรเหลืออยู่เท่าไร เดาว่าสัตว์อื่น ๆ มีจำนวนเท่าไร จากนั้นเราประมาณความน่าจะเป็นที่หมาป่าใด ๆ ที่เราเห็นว่าเป็นมิตร ข้อมูลนี้ไม่มีผลกระทบมากนัก แต่อาจเป็นความแตกต่างระหว่างการเลือกว่าจะต่อสู้กับหมาป่าหรือต่อสู้กับสิงโตอย่างแน่นอน
Runer112

ไม่ได้รวบรวมเพราะ MAP_SIZE เป็นตัวแปรแบบไม่คงที่ เนื่องจากฉันไม่ได้บอกว่ามันจะเป็นตัวแปรอินสแตนซ์ที่ฉันแก้ไขให้คุณ แค่อยากให้คุณรู้ว่าในกรณีที่ฉันโพสต์โครงการที่สมบูรณ์และคุณเห็นชื่อตัวแปรที่ถูกฆ่า
Rainbolt

@ Rusher โอ้โห ฉันคิดว่าฉันยังคงทำงานกับโค้ดเกมรุ่นเก่าจากแซนด์บ็อกซ์และMAP_SIZEตัวแปรนั้นไม่ได้มีอยู่จริงในตอนนั้นหรือด้วยเหตุผลบางอย่างที่ฉันเพิกเฉยและเพิ่มบางอย่างลงในเวอร์ชันคงที่ของฉันเอง ฉันยังสงสัยว่าทำไมหมาป่าของฉันทำคะแนนได้ดีกว่าหมาป่าอื่น ๆ ในการทดลองของฉันอย่างต่อเนื่องเล็กน้อย แต่ในตัวคุณแย่กว่าเดิม ... หมาป่าชุดอื่นฉันเดา? หรือคุณเล่นเกมเป็นจำนวนซ้ำมากกว่า 1,000? หรือคุณอาจต้องการตัวอย่างขนาดที่ใหญ่กว่านั้น 5 ไม่ได้ยอดเยี่ยมมาก
Runer112

21

WolfRunningWithScissors

ไม่มีใครบอก WolfRunning ด้วยกรรไกรไม่ให้วิ่งด้วยกรรไกร หรือบางทีพวกเขาทำ แต่เขาทำมันต่อไป

หากเขาวิ่งเข้าหาศัตรูเขาจะชนะด้วยกรรไกรแพ้ด้วยกรรไกรผูกด้วยกรรไกรหรือสะบัดตา (ฆ่าตัวตาย)

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

}

แค่อยากจะส่งเรื่องสนุก ๆ ฉันไม่เคยใช้ Java มาก่อนและไม่ได้ทำการทดสอบ แต่ควรใช้งานได้ การโจมตีแบบสุ่มและโค้ดเคลื่อนที่ของgetRandomAttack()ฉันนั้นมาจาก StoneEatingWolf


14

Omega Wolf

วิธีการแก้ปัญหาที่ได้มาซึ่งพึ่งพาซึ่งกันและกันซึ่งมีลักษณะคล้ายกับอัลฟ่าหมาป่าจึงชื่อโอเมก้าหมาป่า

หมาป่าตัวนี้สร้างแผนที่ "อันตราย" ของเซลล์รอบข้างและจะเลือกการเคลื่อนไหว (หรือกดค้างไว้) ไปยังเซลล์ที่ปลอดภัยที่สุด

เซลล์แรกที่สิงโตจะเคลื่อนที่ต่อไปจะได้รับระดับ EXTREAME_DANGER จากนั้นเซลล์รอบ ๆ หมาป่าที่ถูกตรวจพบจะได้รับระดับอันตรายตามการโจมตีที่ฉับพลัน ... นั่นคือถ้าหากสุนัขนั้นมีแนวทแยงกับหมาป่าโอเมก้าก็ถือว่าเป็นภัยคุกคามที่ต่ำอย่างไรก็ตามหมาป่าที่อยู่ติดกันถือว่าเป็นภัยคุกคามปานกลาง

จากนั้นแผนที่ "อันตราย" จะเบลอเพื่อให้เลือดออกจากการคุกคามต่อเซลล์รอบข้าง วิธีนี้ทำให้โอเมก้าหมาป่าสามารถ "รับรู้" ภัยคุกคามเวกเตอร์และหลีกเลี่ยงได้

ปัจจุบันตรรกะการโจมตีที่แท้จริงนั้นดั้งเดิมมาก ฉันหวังว่าจะสามารถให้สมาร์ทมากขึ้นและ eek ออกอัตราส่วนการชนะ / แพ้ที่ดีขึ้น สิ่งนี้น่าจะเป็นไปได้หากฉันใส่ฮิวริสติกเชิงสถิติ

ในการทดสอบของฉัน Omega Wolf ชนะอย่างต่อเนื่องกับบอทอัลฟ่า 9 จาก 10 เท่า ...

ผลลัพธ์อย่างรวดเร็วของหมาป่าที่มีชีวิตโดยเฉลี่ยหลังจากรอบ 100 รอบของการวนซ้ำ 1,000 รอบ:

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

รหัส:

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

มันสนุกดี ฉันสร้างพอร์ต clunky ของรหัสจาวาเป็นจาวาสคริปต์ด้วยการสนับสนุนการสร้างภาพสำหรับการสร้างภาพ: JavaScript StoneGuardianWolf

StoneGuardianWolf ค้นหาหินสัตว์เลี้ยงและพักอาศัยข้างหิน เธอปกป้องพวกเขาและค่อนข้างจะเสียสละตัวเองเพื่อความปลอดภัยของพวกเขา

สถิติ

ผู้เล่นคนเดียว: ~ 75% อัตราการอยู่รอดของหมาป่า + 35% สัตว์เลี้ยง (หิน) อัตราการอยู่รอด

สรุป: 75% + 35% ---> อัตราความสำเร็จ 110%! :)

ผู้เล่นหลายคน:ยังไม่ทดลอง

เปลี่ยนบันทึก

v2:อัพเดท AI กับ Gambler หมาป่าและกลยุทธ์การหาหินสำหรับสัตว์เลี้ยง

v1:การเลี่ยงหมาป่าที่ดีกว่า

v0:วันเกิด

รหัส 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
Stone Eating Wolf ศัตรู - ศัตรู!
Averroes

:) แน่นอน - อย่าให้คุณอยู่ใกล้หินสัตว์เลี้ยงของฉัน! CamoWolf ตบ SGW ค่อนข้างยาก แต่
talmobi

1
โชคดีที่คุณไม่จำเป็นต้องใส่ CamoWolf เป็นรายการที่ถูกต้อง = D
justhalf

14

มันเป็นผู้ชายหรือไม่? มันเป็นหมาป่าหรือเปล่า? ไม่มันเป็น

BoyWhoCriedWolf.java

ผู้คนกำลังใช้การไตร่ตรองอยู่ทั่วสถานที่ดังนั้นฉันจึงคิดว่าทำไมไม่ก้าวไปอีกขั้น
ฉันนำเสนอคุณ: หมาป่าที่ไม่สามารถสูญเสีย

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

โอ้ใช่มันต้องใช้ JDK ในการทำงาน แต่ฉันไม่คิดว่ามันจะเป็นปัญหา


1
ประณามคุณเอาชนะฉันไป ฉันทำงานเกี่ยวกับ SabotageAgentWolf ด้วยชั้นเชิงที่แน่นอนนี้
mackthehobbit

1
คลาสนี้ทำอะไร
justhalf

3
@justhalf มันกำหนดคลาสเกมใหม่ด้วยไฟล์ที่เข้ารหัสใน base64 ใกล้กับด้านล่าง ไฟล์นั้นมีการตรวจสอบอินสแตนซ์ของ; ถ้ามันเป็นหมาป่าของฉันตัวอื่น ๆ ก็จะตาย
14mRh4X0r

1
ฉันมีความคิดที่จะใช้กลไกนี้เพื่อทำให้สัตว์อื่น ๆ ทั้งหมดฆ่าตัวตายและเรียกสิ่งนั้นว่า HypnoWolf ฉันไม่ได้จัดการเพื่อให้มันทำงานอย่างถูกต้อง แต่คุณทำ - เคารพ!
Francois Bourgeois

12

Wion

พยายามทำน้อยที่สุดเท่าที่จะทำได้เพื่อเอาชีวิตรอดให้นานที่สุดเท่าที่จะทำได้ในค่าที่คาดหวัง มันพยายามเคลื่อนที่ขนานกับสิงโต (ไม่ว่ามันจะเห็นก็ตาม)

มันไม่สนใจหมาป่าเพราะมันตัดสินใจว่ามันไม่แน่นอน ถ้ามันเจอหมาป่ามันควรจะชนะประมาณครึ่งต่อสู้ (นี่มันดีที่สุดเว้นแต่ฉันจะพยายามจับคู่รูปแบบ) หมาป่าของฉันไม่ควรต่อสู้ซึ่งกันและกัน ถ้ามันเจอสิงโต (ซึ่งมันไม่ควร) มันควรจะชนะประมาณ 3/4 ของการต่อสู้ หมีและหินควรสูญเสีย

สมมติว่ามีหมาป่าในการจำลองโดยใช้กลยุทธ์อื่นพวกเขาควรหลีกเลี่ยงหมาป่าของฉันเนื่องจากพวกเขามีโอกาส 50% ที่จะแพ้การเผชิญหน้าใด ๆ โดยเฉลี่ยแล้วควรดำเนินการอย่างน้อยเช่นเดียวกับกลยุทธ์อื่นใด

หากฉันเข้าใจกฎอย่างถูกต้องน่าจะเป็นกลยุทธ์ที่ดีที่สุด

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

ฉันไม่รู้ว่าทำไมสิ่งนี้ถึงแย่มากในการทดสอบ มันฟังดูดีบนกระดาษ แต่ในทางปฏิบัติมันค่อนข้างจะเทียบเท่ากับ EmoWolf :(
Geobits

@Geobits ฉันไม่ได้ทดสอบ TBH จริงๆ ฉันเดาว่าฉันเข้าใจผิดกฎข้อใดข้อหนึ่งทำผิดพลาดหรือการโจมตีแบบสุ่มกับหมาป่าไม่สุ่มเหมือนกัน
Tim Seguine

@Geobits ฉันสลับตรรกะการโจมตีออก ความสงสัยของฉันคือบางครั้งมันอาจเป็นการฆ่าตัวตาย
Tim Seguine

1
@ เพียงครึ่งหนึ่งใช่ฉันได้ตระหนักแล้วว่าปัญหาคืออะไร เหตุผลของฉันอาจทำงานกับประชากรที่มีหมาป่าอย่างน้อยหนึ่งชนิดเท่านั้น ในกรณีเช่นนี้อัตราการเผชิญหน้าของหมาป่าตัวอื่นจะเพิ่มขึ้น / ลดลงในอัตราเดียวกับของฉัน อย่างไรก็ตามในกรณีที่มีหลายสายพันธุ์อัตราการเผชิญหน้าของฉันที่เพิ่มขึ้นจะถูกเฉลี่ยในหมาป่าอื่น ๆ ทั้งหมดดังนั้นฉันจะใหญ่ขึ้นตามสัดส่วน ฉันกำลังคิดหาวิธีที่จะแก้ไขปัญหานี้ได้เล็กน้อย แต่น่าเสียดายที่ฉันมีสิ่งสำคัญอื่น ๆ ที่ต้องให้ความสนใจในขณะนี้
Tim Seguine

1
แต่ฉันยอมรับว่าวิธีนี้เหมาะสมที่สุดถ้ามีหมาป่าสายพันธุ์อื่นอยู่มากที่สุด
justhalf

12

หมาป่ากับหน่วยความจำรวม

ฝูงหมาป่าในอาร์

แนวคิดของฝูงหมาป่านี้คือมันเก็บไว้ในความทรงจำที่ยังมีชีวิตอยู่หรือตายตรวจสอบสิ่งที่หมาป่าที่ตายแล้วและหมาป่าที่มีชีวิตใช้เพื่อการโจมตีและเปลี่ยนความน่าจะเป็นทางเลือก

นี่คือรหัส 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())
}

มันใช้ wrapper @ProgrammerDan (ขอขอบคุณ!) โดยมี WolfCollectiveMemory เป็นชื่อที่กำหนดเองและ "Rscript WolfCollectiveMemory.R" เป็นคำร้องขอ


สองสิ่ง - อันดับแรกฉันค่อนข้างมั่นใจว่าผลลัพธ์จะไม่ถูกลบออก ประการที่สองเมื่อกระบวนการของคุณถูกเรียกใช้โดย wrapper กระบวนการจะยังคงทำงานต่อไป การออกแบบในปัจจุบันของคุณจะถือว่ากระบวนการของคุณถูกเรียกใช้ทุกครั้งที่การสื่อสารถูกส่งไปยังหมาป่า - ซึ่งมันแพงเกินไปในแง่ของการร้องขอกระบวนการดังนั้นฉันจึงเริ่มกระบวนการและเปิดช่องทางการสื่อสารแทน ดังนั้นคุณควรจะมีวงหลักอย่างต่อเนื่องอ่านบรรทัดจากstdinและเขียนเส้นในการตอบกลับไปตามstdout flush.console()[ต่อ]
ProgrammerDan

[ต่อ] wrapper กระบวนการของฉันควรยุติกระบวนการเด็กเมื่อการจำลองสิ้นสุดลง
ProgrammerDan

@Rusher นี่คือส่วนสำคัญสำหรับ wrapper ที่ถูกต้องสำหรับการส่ง @plannapus 'R ไปที่นี่เพื่อดาวน์โหลดติดตั้งอาร์ เพิ่มbinโฟลเดอร์ของ R ไปยังตัวแปร PATH หรือเทียบเท่าและคุณควรจะดี (ใช้ได้ดีสำหรับฉัน)
ProgrammerDan

ฉันคิดว่าผู้กระทำผิดเป็นreadlinesคำสั่ง ลองใช้ a readlineหรือ equiv readlinesจะบล็อกจนกว่า EOF
ProgrammerDan

ฉันเพิ่งเพิ่มที่มันเคยเป็นreadLines ด้วยการโต้แย้งที่สองหมายความว่ามันควรจะหยุดที่ตัวละครขึ้นบรรทัดแรก scanreadLines1
plannapus

12

MimicWolf

เป้าหมายของหมาป่าตัวนี้คือการเลียนแบบหมาป่าตัวอื่น มันพบว่าหมาป่าตามมันไปจนสุดความสามารถ MimicWolf ไม่ถามคำถามเช่น: ฉันจะหลีกเลี่ยงหมาป่า / หมี / สิงโต / หินได้อย่างไร?

ไม่ MimicWolf เพิ่งถามคำถามเช่น: หมาป่าอยู่ที่ไหนเพื่อให้ฉันติดตาม ฉันคิดว่าหมาป่าที่ฉันกำลังติดตามกำลังจะไปไหน? นั่นคือหมาป่าที่ฉันติดตามมันเป็นหมาป่าตัวอื่นหรือไม่? หมาป่าตัวไหนที่ฉันติดตามไป?

ฉันจะยอมรับว่าคำถามเหล่านั้นส่วนใหญ่ยังไม่ได้รับคำตอบที่ดี แต่ในขณะนี้คือการส่ง 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
}
}

แก้ไข: ฉันเพิ่มระบบเลียนแบบที่ดีขึ้น หมาป่ายังคงไม่ดีนักเนื่องจากพวกเขาไม่ได้พยายามหลีกเลี่ยงสิ่งใดในขณะที่เดินไปมาอย่างต่อเนื่อง


12

ไม่ใช่รายการ แต่เนื่องจากหมาป่าส่วนใหญ่เป็นเพียงเครื่องเขียนมันน่าเบื่อจริงๆที่จะดูดังนั้นฉันจึงเพิ่มภัยพิบัติทางธรรมชาติใน Wild:

แผ่นดินไหว!

ประมาณ 5% ของเวลาแผ่นดินไหวจะเกิดขึ้นเมื่อขนาดสุ่ม 100 เป็นสูงสุดและต่ำสุด 20 อันดับ นี่จะเป็นการตั้งค่าearthquakeCounterที่จะลดลงแบบเอกซ์โปเนนเชียลหลังจากเกิดแผ่นดินไหว

เกิดอะไรขึ้นเมื่อเกิดแผ่นดินไหว

earthquakeCounterสัตว์ทั้งหมดจะมีโอกาสที่จะย้ายสุ่มขึ้นอยู่กับมูลค่าของ ดังนั้นหากค่าคือ 75 ประมาณ 75% ของสัตว์ (รวมถึงหิน) จะเคลื่อนที่แบบสุ่มไปทุกทิศทาง (กระจายอย่างสม่ำเสมอ)

นี่ไม่ใช่เรื่องที่น่าประหลาดใจที่ฆ่าสัตว์จำนวนมากดังนั้นจำนวนสูงสุดคือสัตว์ประมาณ 50 ตัวหลังจากการทดลองไม่กี่ครั้ง

นอกจากนี้แผ่นดินไหวจะถูกสร้างภาพใน GUI ซึ่งแตกต่างกันไปตามขนาด

ฉันไม่เห็นแผ่นดินไหว!

โอกาสที่จะเกิดแผ่นดินไหวค่อนข้างบางเพียง 5%

แต่ไม่ต้องกังวล! ฉันได้รวม"แผ่นดินไหว!" ไว้ด้วย ปุ่มบน GUI ในกรณีที่คุณต้องการที่จะสะบัดหมาป่าทั้งหมดจากโซนความสะดวกสบายของพวกเขา ...

นี่คือภาพหน้าจอ:

แผ่นดินไหว

นี่คือรหัส:

Wild.java

main() ฟังก์ชั่น (อัปเดตเพื่อข้าม GUI สำหรับการทำซ้ำ 100 ครั้งแรกเพื่อเพิ่มความเร็ว):

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
ผู้ชายบางคนแค่อยากจะดูโลก ... การเกิดแผ่นดินไหว
CommonGuy

5
GatheringWolves ของฉันกำลังร้องไห้
johnchen902

12

MultiWolf (Java)

หมาป่าตัวนี้รู้เกี่ยวกับหมาป่าตัวอื่นในการเขียนโปรแกรมนี้ มันช่วยให้พวกมัน (เป็น 'สัตว์เลี้ยง') สามารถใช้งานได้และใช้มันเพื่อกำหนดว่าจะทำอย่างไรโดยขอให้สัตว์เลี้ยงหมาป่าทุกตัวเป็นเจ้าของและเลือกคำตอบที่ได้รับความนิยมมากที่สุด

หมาป่าตัวนี้จะปลอดภัยไม่มีที่สิ้นสุด - เรียกซ้ำ - เช่นถ้ามีคนอื่นใช้แนวคิดที่คล้ายกัน - และจะคืนค่าการกระทำเริ่มต้นของAttack.ROCK/ Move.HOLDถ้ามันตรวจพบการถูกเรียกในขณะที่เรียกสัตว์อื่น

ในการทดสอบของฉันสิ่งนี้มีผลที่แตกต่างกัน ฉันไม่แน่ใจว่าจะอนุญาตหรือไม่ แต่ถ้ามันเป็นและสิ่งมหัศจรรย์ที่เป็นไปไม่ได้เกิดขึ้นทำให้ฉันชนะฉันคิดว่าชื่อเรื่องการชนะควรจะถูกส่งต่อไปยังหมาป่าที่มา "สอง" - มันยุติธรรมเท่านั้นฉันอาจขโมยตรรกะของมัน

มันหลีกเลี่ยงการฆ่าตัวตาย

แก้ไข - ฉันเชื่อว่า Wolf นี้จะต้องโหลดหลังจาก wolves ที่อ้างอิงถึงทำงานได้อย่างถูกต้อง

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

}

ถ้าฉันจำได้อย่างถูกต้องคุณสามารถรับคลาสผ่าน Wild.classes เนื่องจากเป็นฟิลด์แบบสแตติก ... ดังนั้นคุณไม่จำเป็นต้องอัปเดตหมาป่าทุกครั้งที่มีการโพสต์หมาป่าใหม่ที่นี่;)
GeneralGuy

นั่นเป็นเรื่องจริง แต่ฉันได้ทำแบบนี้แล้วอาจจะจากไป อาจลบหมาป่าที่ได้รับรางวัลน้อยกว่าจาก multiwolf นี้ ดูเหมือนว่า Wion จะสูญพันธุ์ทุกครั้งในการวิ่งของฉันฉันกำลังพิจารณาตัดออกจาก MultiWolf เพราะฉันสงสัยว่านั่นเป็นการลดคุณภาพของการกระทำ
OlivierTheOlive

ฉันเชื่อว่ากฎ "คุณไม่สามารถอ่านหรือแก้ไขไฟล์ที่สร้างโดยคลาส Wolf อื่น" มีวัตถุประสงค์เพื่อรวมไฟล์คลาส Wolf อื่น ๆ ด้วยตนเอง ดังนั้นฉันคิดว่ารายการนี้ในขณะที่ความคิดที่ยอดเยี่ยมขัดต่อกฎ
Runer112

1
@ Runer112 ฉันสงสัย แต่ฉันได้เรียนรู้เล็กน้อยเกี่ยวกับการโหลดคลาสจากชื่อและไม่มีวิธีง่ายๆในการค้นหาคลาสทั้งหมดในแพ็คเกจ สนุก
นิดหน่อย

3
การสร้างอินสแตนซ์ใหม่ของ Wolf ไม่ได้เป็นการอ่านหรือแก้ไขไฟล์ที่สร้างโดย Wolf อื่นดังนั้นการส่งนี้จึงถูกต้องตามกฎหมาย กฎมีวัตถุประสงค์เพื่อปกป้องข้อมูลจากการส่งที่เขียนด้วยภาษาที่ไม่มีสิ่งใดเช่นตัวแปรคงที่และจำเป็นต้องเขียนลงในไฟล์แทน
Rainbolt

12

หมาป่ากินหิน

นี่คือการส่งของฉัน หมาป่าตัวนี้ยังคงอยู่ในสถานที่หากเขาไม่เห็นหินสิงโตหรือหมาป่าอยู่ในบริเวณใกล้เคียง หากเขาเห็นก้อนหินและไม่มีอันตรายจากการถูกโจมตีโดยหมาป่าหรือสิงโตอีกตัวเขาพยายามจะกินมัน หากเขาเห็นอันตรายใด ๆ เขาก็จะหนี!

แก้ไข 1 : ปรับปรุงการดูอัลกอริธึมอันตราย เขาหนีจากอันตรายได้ดีกว่าตอนนี้ :)

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

    }

แก้ไข 2 : สถิติบางอย่าง

ฉันได้จัดการให้ StoneEatingWolf เป็นหมาป่า 5-6 อันดับต้น ๆ ในการจำลองที่ฉันวิ่ง:

ผลลัพธ์เฉลี่ยหลังจากเล่น 40 ครั้งจาก 1,000 ครั้ง

ฉันวิเคราะห์การต่อสู้ที่ Stone Eating Wolves พูดถึง ใช้การเล่น 40 ครั้งจาก 1,000 ครั้งฉันได้รับผลลัพธ์เหล่านี้:

ต่อสู้กับแผนภูมิผลลัพธ์

ชัยชนะคือการกินหมาป่าที่กินหิน แผนภูมิแสดงสิ่งที่เรารู้แล้ว: หมาป่าที่ประสบความสำเร็จมากที่สุดคือหมาป่าที่ไม่ตรงกับหมาป่าตัวอื่น ฉันยังสังเกตเห็นว่าหมาป่าตัวอื่นของฉัน (Migrating Wolves) กำลังเขมือบผู้เสพติดหินของฉัน ฉันหวังว่าพวกเขาจะตามล่าหมาป่าอีกตัวเช่นกัน ตลกพอฉันไม่ได้สะดุดกับ Lazy Wolf หรือ Camper Wolf ใด ๆ นอกจากนี้ยังเป็นผลลัพธ์ของการโจมตีที่ฉันได้รับในการวิ่ง 20 ครั้ง (ยกเว้น Stones and Bears):

PAPER       447
ROCK        881
SCISSORS    581
SUICIDE     230

ดูเหมือนว่ามีอคติที่ชัดเจนต่อROCKการโจมตี เมื่อรู้สิ่งนี้ฉันทำให้หมาป่าของฉันPAPERโจมตีบ่อยขึ้นอีกเล็กน้อย


2
โปรดอย่าใช้กราฟเส้นเพื่อพล็อตข้อมูลที่เป็นหมวดหมู่ มันทำให้ฉันเป็นมะเร็งมากเมื่อดูกราฟของคุณ
AJMansfield

@AJMansfield ขออภัยที่ได้ยินเช่นนั้น หวังว่าคุณจะดี;) ยังไงก็ตามฉันจะคำนึงถึงแผนภูมิในอนาคตที่ฉันทำ
Averroes

คุณยังใช้ Windows XP อยู่หรือ oO
justhalf

และทำไมคุณถึงใช้ROCK(ชนะ 50%) เพื่อต่อสู้กับไลอ้อน? เป็นการดีที่สุดที่จะใช้SCISSORS(ชนะ 75%)
justhalf

@ justhalf บริษัท ของฉันยังคงใช้ XP ... และคุณพูดถูกกรรไกร แก้ไขแล้ว. ขอบคุณ :)
เฉลี่ย

11

HonorWolf

หมาป่าของฉันหนีไปจากหมาป่าตัวอื่น หากเขาไม่สามารถหนีไปได้เขาจะเริ่มต่อสู้อย่างมีเกียรติ

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

ฉันจำเป็นต้องเปลี่ยนกลยุทธ์โจมตีอัลฟาหมาป่าของฉันเอง ถ้าฉันถูกจับและถูกโจมตีโดยหมาป่า: ต่อสู้กับ
Scissors

11

หมาป่าตาบอด

หมาป่าตาบอดกลัวที่จะเคลื่อนไหวและไม่รู้ว่ามันคืออะไรต่อสู้ โดยการเล่นกรรไกรทุกครั้งที่มีอัตราต่อรองที่ดีที่สุดเพราะมันจะไม่วิ่งเข้าไปในหินจริง

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

เมื่อผมเติบโตขึ้น

เมื่อหมาป่าตัวนี้โตขึ้นมันต้องการที่จะเป็นสิงโต ดังนั้นมันจึงสุ่มเดินไปรอบ ๆ เพื่อมองหาสิงโตเพื่อตามรอยเท้าของพวกเขาและเรียนรู้วิธีการเป็นสิงโต

หมาป่าตัวนี้ได้รับการออกแบบให้เป็นเคาน์เตอร์ของหมาป่าที่สลับกับสิงโต

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

SpyWolf

SpyWolf สอดแนมเป็นศัตรูและบันทึกกิจกรรมของพวกเขาเพื่อให้สามารถติดตามดูทุกคนในขณะที่รักษาระยะห่าง ไม่อยากเจอ!

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

มันค่อนข้างดี แต่ค่าโดยสาร HybridWolf ที่โกงเกินไป! SpyWolf อาจกลับไปโรงเรียนสายลับและฝึกฝนเทคนิคการต่อต้านหมาป่าขั้นสูงเราจะเห็น


1
คุณเรียกมันว่าง่อยฉันเรียกมันว่าฉลาด;)
สามัญซื้อ

5
ahhhhh! มากมายgoto! และในภาษาที่ไม่มีแม้แต่พวกเขา!
AJMansfield

9

HybridWolf

ฉันอดไม่ได้ที่จะสร้างหมาป่าอีกตัว อันนี้แตกต่างกันมาก (ในรหัสไม่ใช่ในพฤติกรรม) เพราะมันเลือกโจมตี / ย้ายซึ่งหมาป่าดีอื่น ๆ จะทำ
แน่นอนว่าหมาป่าทุกตัวนั้นดี แต่ฉันหมายถึงตัวที่มีคะแนนมากที่สุด :)

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

}

คะแนนทดสอบของฉันดีกว่า AlphaWolf ก่อนหน้าของฉัน แต่บางครั้ง Omega / Honor / ProAlpha ก็เอาชนะฉัน ... ยิ่งมีการส่งที่ดีกว่าหมาป่าตัวนี้ก็จะดีขึ้น: D


นี่เป็นหน้าด้านเล็กน้อย! ความคิดที่ฉลาดว่า ไม่แน่ใจว่าสิ่งนี้จะยุติธรรมในฐานะรายการที่ถูกต้องตามกฎหมายหรือไม่เนื่องจากฉันไม่มีความคิดเกี่ยวกับการทดสอบที่ Rusher จะนำไปใช้เพื่อกำหนดรายการที่ถูกต้อง เช่นถ้าเขาทำการทดสอบแยกกับหมาป่าอื่น ๆ ที่มีอยู่แล้วหมาป่าตัวนี้จะล้มเหลวอย่างน่าสังเวช: P
Moogie

@Mogogie 90% ของผลงานทั้งหมดถูกต้อง จนถึงตอนนี้ฉันได้ยกเว้นเฉพาะรายการที่เปลี่ยนจดหมายเป็นสิ่งอื่นที่ไม่ใช่ 'W' หรือรายการที่ฉันไม่สามารถหาวิธีรวบรวมในภาษาอื่น (และฉันแจ้งให้พวกเขาทราบว่าเป็นกรณีนี้ แต่คุณอาจ ไม่เห็นที่นี่เพราะฉันคุยกับพวกเขาในการแชท)
Rainbolt

@Rusher มีบางรายการที่ลองเปลี่ยนอัตราต่อรองในความโปรดปรานของพวกเขา เช่น Gambler wolf เปลี่ยนแปลงตัวสร้างตัวเลขสุ่มของ Math.random () ของ java เพื่อกลับ 1 เสมอ! สนุกมากพอที่มันจะมีผลกระทบต่อผลลัพธ์เล็กน้อยเนื่องจากหมาป่าชนะคือหมาป่าที่หลีกเลี่ยงการต่อสู้!
Moogie

@Moogie GamblerWolf เป็นผู้ส่งที่ถูกต้อง (และก็ฉลาดเช่นกัน) คุณพูดถูกมันไม่ได้เปลี่ยนแปลงผลลัพธ์มากนัก หากสิ่งต่าง ๆ ออกไปจากมือฉันจะพูดว่า "โอเคเขาชนะ แต่นี่คือผลลัพธ์ถ้าเขาไม่ได้รวมอยู่ด้วย" ด้วยวิธีนี้คนอื่น ๆ ยังสามารถเพลิดเพลินกับการไม่ถูกกำจัด
Rainbolt

2
@Mogogie หากบางสิ่งไม่ได้ถูกห้ามโดยเฉพาะในข้อกำหนดของความท้าทายมันเป็นความจริงโดยชอบธรรมและประเพณีในเว็บไซต์นี้คือการไม่เปลี่ยนกฎเมื่อผู้คนโพสต์คำตอบแล้ว
plannapus

9

EvoWolf

ทั้งหมดที่คุณโง่ออกแบบหมาป่าอย่างชาญฉลาด! EvoWolf อาศัยอยู่ในป่าพร้อมกับหมาป่าที่แข็งแกร่งอื่น ๆ เช่น DeepWolf และ HerjanWolf ดังนั้นมันจึงต้องมีวิวัฒนาการเพื่อความอยู่รอด

รหัสใช้อัลกอริทึมทางพันธุกรรมในการพัฒนาหมาป่าที่ดีที่สุด (ฉันไม่ได้สังเกต LionHunterWolf จนกว่าฉันจะคว้าหมาป่าเพื่อฝึกซ้อม) ยีนต่างกันสำหรับสัตว์แต่ละตัว / โจมตีคอมโบทิศทางการเคลื่อนไหวเมื่อปลอดภัยและทิศทางการเคลื่อนไหวของสัตว์แต่ละตัวในบริเวณโดยรอบ หลังจากการปัดเศษ 1,000 รอบหมาป่าที่มีจำนวนเทิร์นมากที่สุดจะมีความน่าจะเป็นสูงสุดในการผลิตลูกหลาน นอกจากนี้เรายังมีการเปลี่ยนแปลงแบบสุ่มในเด็กประมาณ 10% ที่หวังว่าจะช่วยได้

นี่คือรหัส EvoWolf คุณจะต้องมีevowolf.txt ในไดเรกทอรีการทำงานของคุณด้วยมันประกอบไปด้วยGENOOLOปัจจุบัน หากคุณต้องการวิวัฒนาการหมาป่าของคุณเองจากการสุ่มแบบดั้งเดิมไม่รวม evowolf.txt แต่สิ่งที่ให้ไว้ในปัจจุบันคือวิวัฒนาการที่ดีที่สุด มันดูเรียบร้อยมากเมื่อดูการวิวัฒนาการในตอนแรกมีเพียง 2-3 คนที่รอดชีวิต แต่จากนั้นจะเพิ่มขึ้นเป็น 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);       
    }
}

ฉันได้ทำการเปลี่ยนแปลงบางอย่างกับ Statistics.java และ Wild.java เพื่อแสดงให้ฉันเห็นว่ามีกี่รอบและรุ่นที่ผ่านไปแล้ว หลังจากที่คุณวิ่งครบ 1,000 รอบแล้วให้โทรEvoWolf.nextGen();เพื่อคำนวณลูกหลาน สิ่งนี้ไม่จำเป็นสำหรับการแข่งขันเฉพาะในกรณีที่คุณต้องการพัฒนาชุดของคุณเอง

ไฟล์ทั้งหมดที่นี่ แก้ไข: แก้ไขลิงก์

เท่าที่การพัฒนาดีที่สุดมันก็ไม่ได้ดีไปกว่าอันดับ 10 ส่วนหนึ่งของข้อ จำกัด คือมันมีความทรงจำน้อยมากจากการเคลื่อนไหวก่อนหน้านี้ แม้ว่ามันจะทำหน้าที่เหมือน WolvesWithCollectiveMemory ซึ่งประสบการณ์ของคนรุ่นก่อนจะส่งผลต่อการทำงานของรุ่นต่อไปที่ทำหน้าที่เป็นหน่วยความจำระดับโลกในระยะยาว มันแน่ใจว่าสนุก ในลิงค์ก่อนหน้ามีแผ่นงาน Excel ที่สามารถช่วยคุณวิเคราะห์กลุ่มยีนได้ แทนที่ 1 และ 0 ทั้งหมดใน. txt ด้วย 1 และ 0 ด้วยเครื่องหมายจุลภาคแล้ววางลงในสเปรดชีต

หมายเหตุที่น่าสนใจซึ่งส่วนใหญ่ยืนยันกลยุทธ์ของทุกคน:

  • การโจมตีจริงนั้นสำคัญน้อยกว่าการหลีกเลี่ยงการต่อสู้ หรือบางทีหมาป่าที่ไม่ใช่หมาป่าทั้งหมดจะถูกกำจัดอย่างรวดเร็วดังนั้นมันจึงไม่ใช่ภัยคุกคาม การสร้างการแข่งขันมีโอกาสสม่ำเสมอระหว่าง RPS กับหมีแม้ว่าคุณควรโยน S
  • ฉันต้องปิดการใช้งานการฆ่าตัวตายด้วยตนเองเนื่องจากไม่ได้พัฒนาแม้ว่าคุณจะคิด
  • การถือครองเป็นวิธีที่ดีที่สุดเมื่อไม่มีใครอยู่
  • การวิ่งหนีดูเหมือนจะดีเช่นกันเมื่อมีคนอยู่ใกล้ ๆ
  • คุณควรพักไว้แทนที่จะขยับทิศทางแบบสุ่ม (ตัวเลือกนี้เป็นยีนพิเศษที่วิวัฒนาการออกมา)
  • เมื่อมีสัตว์มากกว่า 1 ตัวอยู่รอบ ๆ การย้ายแบบสุ่มออกจากจุดตัดของการเคลื่อนไหวสำหรับแต่ละรอบ / สัตว์นั้นดีกว่าการรวมตัวกัน (ยีนพิเศษอื่น ๆ )

8

SmartWolf

ผลลัพธ์อยู่ใน (1,000 การวนซ้ำ) (ฉันจะอัปเดตต่อไป แต่ดูว่าเป็นการทดสอบอิสระโดยไม่มีค่าเฉลี่ยเนื่องจากมีหมาป่าหลายตัวที่ค่อนข้างช้า)

ป้อนคำอธิบายรูปภาพที่นี่

รวบรวม:

* ระวัง (จำเป็นต้องใช้โมโน):

gmcs SmartWolf.cs

ของ windows:

csc SmartWolf.cs

คัดลอกไปยังไดเรกทอรีการทำงาน

หมายเหตุ:เมื่อใช้ Windows คุณจะต้องแทนที่"mono SmartWolf.exe"ด้วยเพียงแค่"SmartWolf.exe"ใน wrapper code

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

แรปเปอร์ (ให้เครดิตกับ @ProgrammerDan ฉันแค่ใส่ไว้ที่นี่ดังนั้นจึงง่ายกว่าการคัดลอกวาง):

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

ไม่ค่อยดีเท่าไหร่อัตราการเอาชีวิตรอดเฉลี่ยอยู่ที่ 75 ~ สำหรับการวนซ้ำ 1,000 ครั้งโดยมีหมาป่าอยู่สองสามตัว

ใช้แนวทาง ML ในการแก้ปัญหา


ฉันคิดว่าฉันเข้าใจสิ่งที่หมาป่าของคุณทำ แต่คุณสามารถอธิบายรายละเอียดเพิ่มเติมได้ไหม? นอกจากนี้คุณควรจะพูดถึงภาษาว่าอะไร (ฉันแน่ใจว่ามันชัดเจนสำหรับคนส่วนใหญ่ แต่มันก็ไม่ชัดเจนสำหรับฉัน)
plannapus

มันเขียนใน C # และมีรายการความรู้ซึ่งแสดงการเคลื่อนไหวแต่ละครั้งที่ทำกับสัตว์ชนิดหนึ่งและอัตราความสำเร็จ เมื่อหมาป่าโจมตีและตายอัตราความสำเร็จของท่านั้นจะลดลง ถ้ามันมีชีวิตอัตราความสำเร็จก็จะเพิ่มขึ้น ระบบเริ่มเลือกการเคลื่อนไหวจากฐานความรู้แทนที่จะเลือกแบบสุ่มหลังจากผ่านไปสองสาม (20-30) ครั้ง
user3188175

1
ดีใจที่เห็นคุณใช้เสื้อคลุม! คุณควรจะมีคำแนะนำในการคอมไพล์โค้ดของคุณและอะไรmonoคือสิ่งที่จะใช้ @Rusher
ProgrammerDan

1
Markdown ล้มเหลว หากคุณดูที่แหล่งข้อมูล '#' จะอยู่ที่นั่น แต่เนื่องจากอยู่ในบล็อกส่วนหัว Markdown จึงไม่สนใจมัน แก้ไขแล้ว. : D
ProgrammerDan

2
FYI - ฉันสามารถคอมไพล์และรันสำเร็จด้วย wrapper ของ @ ProgrammerDan (และโดยที่เขาไม่ได้ช่วยในครั้งนี้) คุณจะได้ผลลัพธ์ต่อไป ขออภัยในความล่าช้า!
Rainbolt

7

Passive-Aggressive Wolf (สคาลาหมาป่า)

หลีกเลี่ยงทุกสิ่งที่ทำได้ใน 500 รอบแรกโดยปล่อยให้สนามล้างตัวเอง จากนั้นไปในทิศทางที่กำหนดเพื่อโจมตีสิ่งต่าง ๆ ที่เข้ามาในระยะ

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

ในฐานะภาษาที่ใช้ภาษา JVM Scala สามารถรวมเข้าด้วยกันได้อย่างง่ายดาย

หากคุณกำลังรวบรวมโปรแกรมด้วยตัวเองให้ใส่ไฟล์ scala ด้วย.classไฟล์java (ไม่ใช่.javaไฟล์) และใช้งาน

scalac PassiveAggressiveWolf.scala

เพื่อรวบรวมมัน จากนั้นคุณสามารถใช้PassiveAggressiveWolf.classในWild.javaคลาสหลักได้เช่นเดียวกับคลาส Java คุณจะต้องเพิ่มการscala-library.jarclasspath ของคุณด้วย (ฉันได้ใช้ตัวเลือกบรรทัดคำสั่ง-cp /path/to/scala-library.jar)

อีกวิธีหนึ่งฉันได้อัปโหลด jar ที่มีคลาสไฟล์ที่สร้างขึ้นและscala-library.jarสำหรับ Scala 2.10.3 เพื่อให้คุณสามารถดาวน์โหลดได้

PassiveAggressiveWolf.jar
scala-library.jar


บางทีคุณสามารถแพ็คไฟล์ 10 ไฟล์ลงในไฟล์ zip ไฟล์เดียวเพื่อให้ง่ายต่อการดาวน์โหลด
johnchen902

@ johnchen902 มีคนแนะนำให้ฉันในการแชทที่ฉันสร้างขวดที่มีชั้นเรียนของฉัน ฉันจะดูการทำที่เย็นนี้หลังเลิกงาน มันจะลดการดาวน์โหลดลงเหลือ 2 ครั้งและหวังว่าจะแก้ปัญหาที่ Rusher มีอยู่ด้วย
Gareth
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.