Hayatta kalma oyunu - kurt oluşturmak


238

Pano

Kurulu hücrelerinin iki boyutlu bir dizidir. Hücreler Hayvanlar tarafından doldurulur . Her gün, Gemideki tüm Hayvanlar aynı anda bir hamle yapar. İki veya daha fazla Hayvan aynı hücreye giderse, biri kalana kadar savaşırlar. Muhtemel hareketler ve saldırılar aşağıdaki gibidir:

  • Taşır - { Move.UP, Move.RIGHT, Move.DOWN, Move.LEFT, Move.HOLD}
  • Saldırılar - { Attack.ROCK, Attack.PAPER, Attack.SCISSORS, Attack.SUICIDE}

Hayvanlar Rock-Paper-Scissors oynayarak savaşıyorlar. Standart kurallar uygulanır, ancak iki değişiklik yapılır. İlk önce, herhangi bir zamanda intihar edebilirsin. İkincisi, bir kravat sözde kırılmış. İkiden fazla Hayvan çarpışırsa, iki tanesi sahte kalana kadar dövüşmek için sahte ve seçilmişlerdir.

Oyuncular

Hayvan davranışları ve görünüşleri aşağıdaki gibidir.

  • Aslan
    • Karakteri ile temsil edilir L. Hamle DOWN, RIGHTsonra tekrar eder. Sözderandomly PAPERveya ile saldırır SCISSORS.
  • Ayı
    • Karakteri ile temsil edilir B. DOWNX 4, RIGHTx 4, UPx 4, LEFTx 4 taşır , sonra tekrar eder. Saldırıları PAPER.
  • Taş
    • Karakteri ile temsil edilir S. Taşır HOLD. Saldırıları ROCK.
  • Kurt
    • Sadece cevap olarak gönderilen kurtlar dahil edilecektir. 'W' ile temsil edilir. Herhangi bir Taşı ile hareket eder. Herhangi bir Saldırı ile Saldırı

Wolf'u aşağıdaki şablondaki boşlukları doldurarak uygulayacaksınız. Tüm başvurular Java ile yazılmalı ve tek bir dosyada bulunmalıdır. Alternatif olarak, @ProgrammerDan, rekabeti java dışı gönderilere genişleten bir sarmalayıcı sınıfı yazmıştır .

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

1000 iterasyona sahip beş denemeden sonra, ortalama en yüksek canlı kurt sayısına sahip olanı kazanır. Her yeni cevap gönderildiğinde kazananı güncelleyeceğim (ancak ilk 24 saat içinde değil).

Araçlar

  • Aşağıdaki biçimde, yakın çevrenizin küçük bir haritası verilmektedir.
    • char[][] surroundingsSıfırdan indekslenmiş, yakındaki hayvanları temsil eden 3 ila 3 karakter matrisi. Boş fayans, boşluk karakteri ('') ile temsil edilir. Sen altındadır surroundings[1][1]. Mesela, sağında surroundings[1][2]ve senin üstünde olacaktı surroundings[0][1]. Çevrenizden taşınması istenmeden hemen önce güncellenir, ancak mücadele istendiğinde güncel olmayabilir.
  • Wolf'un çağrıları, Taşı istekleri ve Saldırı istekleri arasındaki verileri kaldırabilirsin. Başka bir Wolf sınıfı tarafından oluşturulan dosyaları okuyabilir veya değiştiremezsiniz.
  • Haritanın büyüklüğünü aşağıdaki formda bulabilirsiniz
    • int MAP_SIZE

Varsayımlar

  • Tüm gönderimler aynı kurulda, diğer tüm gönderilere ve Lions, Ayılar ve Taşlara karşı yarışacaktır.
  • Tahta uzunluğunun kenarlara sahip bir karedir gönderimler sayısıdır. Tüm taraflar sarılır, böylece sonsuz bir şekilde herhangi bir yönde güvenle hareket edebilirsiniz.sqrt(n+3)*20n
  • Simülasyon, tahtaya dağıtılan her Hayvanın 100'üyle 100% pano kapasitesinde başlar.
  • Bir Hayvan, taşınması istendiğinde bir istisna atarsa, o Hayvan HOLD
  • Bir Hayvan savaşmak istendiğinde bir istisna atarsa, bu Hayvan SUICIDE
  • Denetleyici kontrol ederken bir Hayvanın mektubu yoksa, bu Hayvan derhal ölür

Başlarken ve Test Talimatları

Gönderinizi test etmek için ihtiyacınız olan araçları burada bulabilirsiniz . Bu linkte aşağıdaki dosyalar bulunmalıdır.

  • ExampleRun.gif - Çalışan programın 5-10 saniyelik bir gif'i .
  • Scoreboard - Yarışmanın en son sonuçları.
  • Wild.jar - Hazır hayvanların koştuğunu izlemek için koşabileceğiniz bir çalıştırılabilir.
  • Wild.zip - Denetleyici programı barındıran NetBeans projesi birkaç hazır hayvan eklenmiştir. Gönderinizi geliştirmek için bunu kullanın.
  • WildPopulated.zip - Yukarıdakiyle aynı, ancak test etmek için yaklaşık 40 başvuru eklendi. GUI ayrıca performans sorunları nedeniyle kaldırılmıştır. Sonuçlar, siz koşduktan birkaç dakika sonra ortaya çıkacak. Java dışı gönderiler ek indirmeler ve çaba gerektirdikleri için yorumlanmıştır. Gönderinizi alana karşı test etmek için bunu kullanın.
  • Wolf.txt - Java'da Wolf sınıfının saf bir uygulaması. Bu uygulamayı bana kredi vermeden kullanabilir ve genişletebilirsiniz.

Sınıfınızı test etmek için:

  • Wild.zip indir
  • Wolf.java ve Wolf sınıfınızı benzersiz bir şeye yeniden adlandırın
  • UniquelyNamedWolf.java dosyanızı Wild \ src \ animals \ içine ekleyin
  • Wild sınıfında, sınıfınızı bu şekilde classesdiziye ekleyin .
    • Class[] classes = { UniquelyNamedWolf.class, Bear.class, Lion.class, Stone.class, Wolf.class };
  • Yeniden oluştur ve çalıştır

Test amaçlı olarak tüm başvuruları içeren başka bir proje de ekledim. Yaratıcı bir şekilde "WildPopulated" adını verdim. Java dışı üç kurt ya da dördü yorumladı, çünkü kaçmaları için fazladan çalışma ve indirme gerektiriyor. Ben yayınlanmıştır biri ile çalışmalıdır sıfır ekstra iş. GUI ayrıca hız uğruna yorumlandı.

Scoreboard 22 Nisan 2014

Scoreboard Google Drive'a taşındı. Buradan görüntüleyin. Yeni başvurular geldiğinde, geçici olarak (yani, ulaştığımda) güncellenecektir.

Yan Mücadelesi - NoHOLD

Hayır (sıfırda olduğu gibi) katılım nedeniyle kaldırıldı. Zaten orjinal mücadelenin bir parçası değildi.


5
@Rusher Bu kulağa korkunç geliyor. Wrapper'ı içeren cevabımı topluluktan wiki yapabilirdim. Derleyici / tercüman konusuna gelince, kullanımla ilgili net talimatlar
ProgramcıDan

4
“* Size haritanın büyüklüğü aşağıdaki biçimde verilmiştir: int MAP_SIZE“ Bunun nasıl kullanılacağını bulmakta güçlük çekiyorum. Netbeans MAP_SIZE, projedeki dosyaların hiçbirinde dizenin hiçbir örneği olmadığını söylüyor .
undergroundmonorail

6
kağıt gösteren ağaçlar nasıl?
Mukul Kumar

3
@Rusher, bence bazı insanlar bunu zaten yapıyorlar, ancak statik üyeler tarafından Kurtlar arası iletişime izin veriliyor mu (kendi cinsinizde)?
Martin Ender

10
@ m.buettner İzin Verildi. Dışarı çık ve kovana bakan kurtunu kur.
Rainbolt

Yanıtlar:


47

HerjanWolf

10-4-2014 15: 00'da güncellendi

100 tur ortalamalar, 1000 yineleme:

Standart çetelerin:

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

20+ Tür (Kurtlarımız en iyi skorlanana kadar avgs'i hesaplamaya devam ettiğimizden, bu puanlara güvenme!

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

Kurdum:

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

Test çalışmalarında sadece "üst" kurtların bulunması normalde sayıları çarpıtır. Sahadaki 30+ tür ile sayılar önemli ölçüde değişebilir. Henüz yapmadıysanız, test etmenizi de tavsiye ederim.
Geobits

1
@ user20220 Yine de teoride (ve göreceli olarak daha az kurt içeren pratikte) oldukça iyidir.
user3188175

1
Bu kurt en iyi anti-aslan stratejisine sahip: chat.stackexchange.com/transcript/message/14837616#14837616
Justin,

2
@ user20220 Kurt çarpışması çok daha sık gerçekleşir, bu nedenle başka bir kurt eklemelisiniz. Ayrıca, bu kurtların nasıl çalıştığını açıklayabilir misiniz?
Justin,

3
Sadece tamam, daha iyi değil, o zamanki kadar iyi. Kurtum da bütün aslanlardan kaçıyor, ilk önce kurt atlatmadan önce kurtumu% 100 aslan geçirmez yaptım. Fark şu ki kurtlarım aslanlardan kaçmaya çalışır (daha az hareket, daha iyi). Bu yüzden Wion kadar aslan kaçmak kadar iyidir, ikisi de% 100 su geçirmezdir, fakat kurtum aslanlardan kaçmaya çalıştığından ve sıkıcı bir şekilde aslan gibi aynı şekilde hareket etmediğinden, hala kurt kaçmak için inşa edebileceğim gibi daha karmaşık.
Herjan

153

EmoWolf

EmoWolf, Java'dan nefret eder ve katılmaktansa kendisini öldürmeyi tercih eder. EmoWolf kendisini aç bıraktı, ama yine de 177 byte ağırlığında.

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 Bazı baytları tıraş edebilirsiniz: " Denetleyici kontrol ederken bir Hayvanın mektubu yoksa, bu Hayvan derhal ölür ".
Geobits

112
Bu konuda en iyi şey, sürekli olarak en kötü değil olmasıdır . Normalde en az 2-3 kişi atıyor.
Geobits

51
“Kazanan tek hamle oynamak değil.”
tadman

38
+1 Küçük ve intihara meyilli olmak ve hala 4 kurt daha öldürmek için.
puggsoy

25
Önerileriniz için teşekkürler millet. Bu golf olsaydı, yazıyı düzenlemek için can atardım. Olduğu gibi, EmoWolf'un somurtmasına izin vereceğim. Tek başına.
stand

52

LazyWolf

Aptly adında, bu adam hayatta kalmak için elinden gelenin en iyisini yapıyor. Kurt olmayan tek tehdit bir aslan, bu yüzden onlardan biri basmak üzereyse harekete geçecek. Bunun dışında, sadece uyur.

Kurtlara karşı 50 / 50'den daha iyi olacak bir şey yapamazsınız, o yüzden hiçbir şey yapmaz. Bir kurt ona saldırırsa, saldırıyı eşit bir şekilde dağıtır.

Bu kadar. Sadeliği rağmen, oldukça iyi yapmasını bekliyorum.

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

}

Güncelleme:

CamoWolf beni kolayca dövüyordu. Kurtum çok tembel olduğundan, normalde asla gerçek bir taşa rastlamaz . Bu nedenle, eğer bir taş saldırırsa, açıkça sahtedir ve yüzüne atılan bir kayaya ihtiyaç duyar.


Şu anda, kaçınmaya çalıştığınızda ikinci bir aslan haline gelme olanağına sahipsiniz. Bunu kaç hamle yaptığını izleyerek kaldırabilirsiniz, böylece aslanın aslında meydanınıza gelip gelmediğini bilirsiniz. Öyleyse, aslanla aynı yöne doğru hareket edin ve hiçbir aslan size ulaşamaz, çünkü aynı yöne de hareket ediyorlar.
ughoavgfhw

13
İki aslanın durumu hakkında düşündüm ama kurtumun umursamayacak kadar tembel olduğuna karar verdim. İyi yerleştirilmiş bir tahta ile yeterince sık olma olasılığı yine de oldukça zayıf.
Geobits

1
Sence bu kurt asla gerçek taşlarla karşılaşmaz? Bir aslandan kaçınca bunun olabileceğini düşünürdüm.
Christopher Creutzig

6
@ChristopherCreutzig O aslan yere geçerek aslanlar çalışır oldu . Bir aslan Eğer oldu orada, bir taş olamaz şimdi .
Geobits

1
Olsa bile, "sonsuz döngü" yoktur. Bir saldırı kravat ise, biri veya diğeri şartname başına ölür (bozuk parayla toplanır).
Geobits

51

Java Olmayan Gönderiler İçin Sarıcı

NOT MAP_SIZE desteği eklendi. Eğer ilgileniyorsanız, lütfen gönderinizi uygun şekilde güncelleyin.

Bu, oynamak isteyen ancak Java'yı sevmeyen / bilmeyenler tarafından kullanılabilen bir sarmalayıcı için topluluk wiki girişidir. Lütfen kullanın, eğlenin ve işleri ayarlamanıza yardımcı olmaktan memnuniyet duyarım.

Bitirdiğim için çok geç, bu yüzden diğer Java kodlayıcıları, lütfen şuna bakın ve iyileştirmeler önerin. Yapabiliyorsanız, bir sorun bildirerek veya bir düzeltme eki göndererek github depom aracılığıyla gerçekleştirin. Teşekkürler!

Tüm bu UNLICENSE ile dağıtılıyor, lütfen github deposundan takip edin / çatallayın . Sorun bulursanız oradaki yamaları gönderin, ben de bu yazıyı güncelleyeceğim.

Kullanımdaki Sarıcı Mevcut Örnekleri

plannapus : R'deki WolfCollectiveMemory

user3188175 : SmartWolf girişiC#

diş fırçası : ECMAScript'te diş fırçası

Nasıl kullanılır

Aşağıda, uzak Kurtlar için tanımladığım PIPES üzerinden işlem arası iletişim protokolü hakkındaki talimatlar verilmiştir. Not OP'nin problem beyanındaki varlığına rağmen, bu görünmediğinden MAP_SIZE öğesini atladım. Göründüğü takdirde, bu yazıyı güncelleyeceğim.

ÖNEMLİ NOTLAR :

  • Harici işleminize yalnızca tek bir çağrı yapılır (bu nedenle işlem mantığınızı sonsuz bir döngüye sarın. Bu işlem, disk kullanmak yerine herhangi bir işlemi bellekte tutmanıza da olanak sağlar)
  • Tüm iletişim STDIN ve STDOUT üzerinden bu tek harici işlem içindir
  • STDOUT'a gönderilen tüm çıktıları açıkça silmelisiniz ve satırsonu sonlandırıldığından emin olun

Şartname

Uzak komut dosyaları, STDIN ve STDOUT kancaları aracılığıyla basit bir protokol tarafından desteklenir ve başlatma, Taşıma ve Saldırmaya ayrılır. Her durumda, işleminizle iletişim STDIN üzerinden yapılacak ve STDOUT'dan bir cevap gerekli olacaktır. 1 saniyede bir cevap alınmazsa, işleminizin öldüğü varsayılır ve bir istisna atılır. Tüm karakterler tutarlılık için UTF-8 ile kodlanacaktır. Her giriş yeni satır karakteriyle sonlanır ve işleminiz her çıktı yanıtını da yeni satır ile sonlandırmalıdır. UYARI Java sarmalayıcısının çıktınızı görmesini sağlamak için her yazmadan sonra çıktı arabelleğinizi yıkadığınızdan emin olun. Yıkama yapılmaması, uzaktaki Wolf'un bozulmasına neden olabilir.

Sadece tek bir süreç yaratılacağına dikkat edin, tüm Kurtlar bu süreç içerisinde yönetilmelidir. Bu özelliğin nasıl yardımcı olacağı konusunda okumaya devam edin.

Başlatma

STDIN: S<id><mapsize> \ n

STDOUT: K<id> \ n

<id>: 00 veya 01veya ... veya99

Açıklama:

Karakter Siki sayısal karakterle devam gönderilecektir 00, 01, ..., 99başlatılmakta olan 100 kurtların hangi belirten. Gelecekteki bu kurtla olan bütün iletişimde aynısı <id>kullanılacak.

Kimlikten sonra değişken uzunluktaki bir sayısal karakter sırası gönderilecektir. Bu haritanın boyutu. Newline'a ( \n) ulaştığınızda sayısal karakterlerin sırasının bittiğini anlayacaksınız .

İşleminizin canlı olduğundan emin olmak için, aldığınız karakterin Kardından gelen karakterle cevap <id>vermelisiniz. Başka bir cevap kurtlar öldürerek, bir istisna sonuçlanır.

hareket

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

STDOUT: <mv><id> \ n

<Cn>: W Veya veya Bveya SveyaL

W: Kurt

: Boş Alan

B: Ayı

S: Taş

L: Aslan

<mv>: H Veya Uveya Lveya RveyaD

H: Hareket Et

U: Taşı.UP

L: Taşı.LEFT

R: Hareket Et

D: Taşı.DOWN

Açıklama:

Karakter Miki karakter tarafından takip gönderilecektir <id>Kurt bir hamle seçmek gerekiyor hangi belirtmek için. Bundan sonra, Wolf'un çevresini sıra sırasına göre (üst sıra, orta sıra, alt sıra en soldan en sağa) gösteren 9 karakter gönderilir.

Geçerli hareket karakterlerinden biriyle yanıtlayın <mv>ve ardından <id>onay için Wolf'un iki rakamı görün .

saldırı

STDIN: A<id><C> \ n

STDOUT: <atk><id> \ n

<C>: W Ya Bya SyaL

<atk>: R Ya Pya SyaD

R: Attack.ROCK

P: Attack.PAPER

S: Attack.SCISSORS

D: Saldırı

Açıklama:

Karakter A, <id>Wolf'un bir saldırıya katılacağını belirtmek için iki karakter tarafından gönderilir . Bunu, <C>ne tür bir şeye saldırdığını gösteren tek bir karakter izlenir ; bu bir Wolf, Bkulak, Ston veya Liyondur.

<atk>Yukarıda listelenen karakterlerden biriyle yanıt verin, saldırıya verdiğiniz cevabın ne olduğunu belirtir <id>ve onay için iki basamak takip eder.

Ve bu kadar. Daha fazlası yok. Bir saldırıyı kaybederseniz, bu bir <id>daha asla işleminize gönderilmeyecek, Wolf'un öldüğünü anlayacaksınız - tam bir Hareket turu <id>hiç gönderilmeden geçilmişse .

Sonuç

Herhangi bir istisnanın, türünüzün yarattığı bütün kurtlar için uzaktaki kurtunuzdan yalnızca bir "Süreç" inşa edildiğinden, uzaktaki türünüzdeki bütün Kurtları öldüreceğini unutmayın.

Bu depoda Wolf.javadosyayı bulacaksınız . Botunuzu ayarlamak için aşağıdaki dizeleri arayın ve değiştirin:

  • İşleminizi <invocation>uygun şekilde yürütecek olan komut satırı argümanı ile değiştirin .

  • Kurtunuz <custom-name>için benzersiz bir adla değiştirin .

  • Bir Örneğin depo bakmak Ben nerede, WolfRandomPython.javabenim örnek uzaktan çağırışında PythonWolf.py(Python 3+ Kurt).

  • Dosyayı olmak adlandırın Wolf<custom-name>.java, <custom-name>yukarıda seçtiğiniz adla değiştirilir.

Wolf'unuzu test etmek için Java programını ( javac Wolf<custom-name>.java) derleyin ve Rusher'in simülasyon programına eklemek için Rus talimatlarını takip edin.

Önemli: verdiğinizden emin olun açık , özlü yukarıda açıkladık şemasını takip gerçek Kurt, yürütmek / derlemek için yönergeler.

İyi şanslar, ve doğa sizin lehinize olabilir.

Sarmalayıcı Kodu

Unutmayın, arama yapmalı ve bunun çalışması için ana hatlarıyla belirtilenleri değiştirmelisiniz. Başvurunuz özellikle kıllı ise, yardım için lütfen benimle iletişime geçin.

mainBu paketleyicide, yerel kutunuzda basit "başarılı / başarısız" testine olanak tanıyan bir yöntem olduğunu unutmayın . Bunu yapmak için, Animal.java sınıfını projeden indirin ve package animals;satırı her iki dosyadan da kaldırın . Animal.java'daki MAP_SIZE satırını bir miktar sabitle (100 gibi) değiştirin. Onları javac Wolf<custom-name>.javabir execute kullanarak derleyin java Wolf<custom-name>.

package animals;

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

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

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

    private boolean isDead;
    private int id;

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

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

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

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

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

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

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

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

        public boolean getRunning() {
            return running;
        }

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

        public void endProcess() {
            running = false;
        }

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

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

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

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

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

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

1
Bu yayında parçalandım. Bu bir cevap değil, ancak meydan okuma için çok faydalıdır. Yine de, büyük olasılıkla meydan okumaya girmesi gerekiyor.
Mego

Ya orada ya da burada, millet onu bulması ve kendileri için yararlı olması şartıyla, memnun olacağım :)
ProgrammerDan

46

CamoWolf

Gerekli kod formatını kötüye kullanmak.

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

Yani kurtum çok zeki ve onun yerine bir taş gibi kamufle oluyor! Çevreye uyum sağlamak her zaman iyi bir hayatta kalma taktiğidir!

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

Güncelleme : isSafeLazyWolf'tan güvenli olmak için yeni bir çek eklendi! Ha!
2. Güncelleme : Güya tembel olmak, aynı zamanda iyi bir hayatta kalma taktiği. Aslan tarafından tehdit edilmedikçe hareket etmez. lastMoveArtık gerekli değil, ancak yine de kodu değiştirmem durumunda bile sakladım.


29
Gönderinizi projeye eklediğimde, yanlışlıkla tüm sınıfı bir yorum bloğuna koydum.
Rainbolt

2
@Rusher Java iç içe geçmiş yorum bloklarını ayrıştırır mı? : P
Martin Ender

6
LazyWolf'un buna karşı savunabileceği bir dünyada, aslan gibi davranmak, ROCK veya rastgele seçmek daha mantıklı olabilir. Birçoğu aslanlardan kaçınmaya çalışacağından, insanlarla karşılaşma sayısını azaltacaktır ve bir aslanla savaştığını düşünen insanlara karşı ortalama olarak kazanmalıdır.
Tim Seguine

7
@Radiodef Bu.
Rainbolt

2
@Radiodef Ne zaman olmadığını söyledim? ;-)
Doorknob

38

GatheringWolf

Benim kurt bir grup yaşıyor. Aslanlar izin verirse toplarlar. Yine de hayatta kalmakta pek iyi değiller.

Güncelleme: Eğer bir aslan onları uzaklaştırırsa, şimdi toplanmaya çalışıyorlar!

GatheringWolf sonucunun ekran görüntüsü

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
Birkaç kez kurtlarımız arkadaş oldu çünkü benim tuzağa düştü, ancak bir saldırı başlatmayacaktı ve seninki benimkinin paketin bir parçası olduğunu varsaydı. :)
undergroundmonorail

1
Bunu yazdığın için teşekkür ederim, aksi halde kendim yapmak zorunda kalacaktım. Karşılıklı yalancı ve zekice kullanım.
Ben Jackson

31

Kurt Giysisinde Koyun

Kaçar.

En tehlikeli olanlarından olmaları için en çok Kurtlardan kaçmayı ön planda tutuyor. Sırada, Aslanlar var, zira onlar özgün değiller. Ayılar ve Taşlar her ikisi de sorun değil, ama yapacak daha iyi bir şeyimiz yoksa hala onlardan kaçıyoruz çünkü bir Ayı veya Taş'ı öldüren bir Kurt, o sırada, bir Koyun öldüren bir Kurt değildir.

LazyWolf'a karşı henüz test yapmadım, ancak EmoWolf'un kıçını tekmeleyen iyi bir yetkiye sahibim. ;)

(Bu kod çok kötüyse, lütfen beni affedin, daha önce bir Hello World programından daha fazlası için Java'ya dokunmadım.)

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

Hata! Orada test etmek için kullandığım bir şeyi kazara bıraktım. Hiçbir şeyi etkilemeyecek, sadece H gibi görünen bir şeye yaklaşmaya çalışacağım anlamına geliyor: P
undergroundmonorail

Sadece merak, eğer xWeightve yWeighther iki sıfır olmayan ve bunların mutlak değerler, bu kurt hareket etmez aynı, doğru mu? Ve eğer öyleyse, bu kasıtlı mıydı ve neden?
Patrick Roberts

@PatrickRoberts oops
yeraltında

26

Giriş değil, her sınıfa renk kodu ekleyerek GUI'ye katkıda bulunmak istiyorum = D

Sonuç

Renkli GUI

Wild.java

Kodu game.populate(c,100)şununla değiştir :

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

olarak generateColorstanımlananlarla:

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

Bu StackOverflow cevabından hangi algoritma alınmıştır

İle colorve setColorAnimal.java tanımlanmaktadır

Animal.java

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

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

Ardından toStringGame.java ve Statistics.java'daki yöntemleri güncelleyin :

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
Güzel. Dün birkaç dakika sadece ekrana bakarak geçti. Tank Matrix okumak gibi hissettim.
Averroes

Simulation .... .... .... .... .... .... .... yavaş .... (30 saniye sonra 5 tekrar)
user3188175

Haha evet. Ancak her yineleme için HTML kodunu basan simülasyonun tasarımında doğaldır.
justhalf

Bu gönderiye bir bağlantı sağlarsam bunu Google sürücüsünde (Challenge'da bağlantılı) paylaşabilir miyim? Az sayıda kurt ünitesini test etmek için olağanüstü iyi çalışıyor.
Rainbolt

1
Evet yapabilirsin. Depremle ilgili diğer yazımda yazdığım gibi, birçok kurt için işleme sürecini hızlandırmak için bazı ilk işleme atlamalarını da dahil edebilirsiniz.
justhalf

23

alphawolf

Parlama zamanı! Diğer kurt CamperWolf çok zayıftı, şimdi daha kaslı olan AlphaWolf geliyor!

Aslanları standart yoldan atlamak yerine, alanı onlarla değiştirir. Ayrıca her bir çevre alana tehlike-değer atar.

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

}

Çok güzel bir kod değil, ama testlerimde tüm java kurtlarına karşı çok iyi çalıştı.


1
"Alanı değiştir" ne demek? Sadece merak ediyorum, çünkü bunu işte idare edemiyorum.
Rainbolt

Tüm simülasyonlarımda 1000 tekrardan sonra ortalama 80-90 kurtla kazanıyorsun. Sadece Java’da yazılmış yasal kurtları benim için şu ana kadar teslim ettim. Yine de 10 kurt kadar.
Sheph

@Rusher Eğer bir aslan benim kurtlarımın üstünde ve aşağı
inecekse

bazı anti-wilfcamo kodu eklemeniz gerekir. aslanın bilme şeklini kullanmak çok güzel bir fikir :)
Lesto

9
Şimdi birisinin bulduğu aslanı kuyruklayacak bir kurt icat etmesi gerekiyor, bu yüzden aslanla değiş tokuş etmeye çalıştığınız anda onunla karşılaşacaksınız.
AJMansfield

23

Kumarbaz Kurt

Kumarbaz Wolf şansını denemekten hoşlanır, bu yüzden Lady Luck'ın kendi tarafında olmasını umarak kararsız davranır! Neyse ki onun için, onu asla yarı yolda bırakmaz! Şanslı başarılarla, Gambler Wolf, kurt olmayan tüm engel alanlarını inanılmaz sayıda nedensellik ile temizler!

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

Düzenleme: v1.1

  • Şimdi Taşlardan (Camo-Kurtlar?) Kaçınıyor

  • Artan Rastgele!


5
Bunu kurtlarıma ekleyeceğimi düşünüyorum:static{System.setSecurityManager(new SecurityManager());}
johnchen902

13
Adil olamıyorsanız, +1: D hilesi
ProgrammerDan

5
Maalesef return 4; // chosen by fair dice roll. guaranteed to be random.burada kullanamazsınız ...
Vi.

1
Daha kötü olmak istiyorsan, daha da fazla olan sözleşmeyi bozmak Math.random(); [0,1) aralığında olmayan, belki de sınırsız veya NaN değerlerini döndürür. Veya mümkün olduğu kadar kötü olmak için, bir şey döndürmek yerine sadece bir çalışma zamanı istisnası atın (aynı zamanda jeneratörü ayarlayarak da gerçekleştirilebilir null).
Runer112

1
@AlexL. Bir ForrestWolfsorun gibi geliyor ...
recursion.ninja

22

CamperWolf

Amaç hayatta kalmaktır. Diğer kurtların birçoğu kurtlardan kaçtıkça, benim sadece olduğu yerde kalıyor ve tüm hayvanlarla savaşıyor.

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

Çok iyi performans göstermesini bekliyorum, çünkü birçok kurt kurtlardan kaçıyor ve bu tür kurtlar yalnızca diğer kurtlara karşı ölebilir.


Aslanlar da öldürebilir. Aslan makas alırsa, kurtun sahte ya da ölecek.
Tim Seguine

2
Tebrikler dostum. Siz ve 15 kodlu kodunuz şu anda kazanıyor.
Rainbolt

2
@Rusher teşekkürler :) Düşürücü neden reddettiğini açıklayabilir mi?
CommonGuy

@ Manu önemli değil, çünkü Taşlar hareket edemiyor, ancak davanız 'S' Attack.PAPER'ı geri göndermemeli mi?
DavidJFelix

3
Evet, sorduktan sonra CamoWolf'u gördüm. Zor adam!
DavidJFelix

22

DeepWolf

Buna çok fazla zaman ayırdım ... Her neyse, bu kurt "derin" analitiği kullanıyor, kullanması için düşündüğüm kadar çevresel veri toplayıp kullanıyor. Analiz, bilinen aslan ve kurt yerleri ve gelecekteki yerlerin tahminleri gibi kurda özgü bilginin bir karışımı üzerinde çalışır ve tahmini popülasyonlar, kurt savaş tarihçesi ve hareket halindeyken bir hayvan rakibi ile çarpışmanın tehlikesi gibi sağlam bilgiler içerir. Aynı zamanda çok büyük, çünkü çok fazla mantığa ek olarak, nesne yönelimli tasarım üzerine düştüm ve çok sayıda özel amaçlı sınıf ve yöntem kullandım.

Popüler ve en iyi performans gösteren kurtların çoğuyla, her biri için 1000 adımlık 100 oyun tekrarladım. Ben bilerek GamblerWolf'ı dışarıda bıraktım çünkü biraz aldatıcı olduğunu düşündüm, yine de kurtumu etkilememeliydi. İşte ortalama, maksimum ve minimum performans verileri:

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 ortalama 90.48 ile ilk sıradadır, ancak OmegaWolf'un 88.67'sinin 2'den daha dar bir ipucu ile. Sadece% 2 iyileştirme için kod satırlarının yaklaşık 4 katı! HerjanWolf, HonorWolf ve HybridWolf, OmegaWolf'u sırasıyla yaklaşık 86.55, 86.76 ve 86.78 ortalamalarıyla yaklaşık 2 daha fazla takip ederek üçüncü sırada yer alıyor.

Daha fazla uzatmadan, kodu sunacağım. Gördüğüm kadar gelişmiş sabitler / mantık için muhtemel hatalar ve / veya potansiyel olması çok büyük. Herhangi bir geri bildirim varsa, bana bildirin!

Bu bağlantıda kod, çünkü yazı karakteri sınırını patlatıyor : İdeone


Dropboxusercontent'in dosyayı kaybedeceğini bilmiyorum, bu yüzden ideone'a gönderdim: ideone.com/uRNxvj
Justin

3
@ Runer112 etkileyici! Ben kodu bakıyorum ve biraz kayıp değilim: P ama ilgimi çeken bir kavram Eğer kurt dost ya da değil karar tabanına kullandığınız şeydir
Moogie

@ Moogie Bir kurtun dost olup olmadığına dair deterministik bir değerlendirme yapılmaz. Ancak kurt türlerinin sayısını biliyoruz, her türün 100'de başladığını biliyoruz, kaç tane dost kurt kaldığını biliyoruz ve kaç tane dostça kurt kaldığını tahmin ediyoruz ve öldürdüğümüz sayıya ve Kaç tane diğer hayvanlara öldüğünü tahmin et. Bunlardan, gördüğümüz herhangi bir kurtun dost olma ihtimalini tahmin ediyoruz. Bu bilgilerin çok büyük bir etkisi olmamakla birlikte, bir kurtla potansiyel olarak savaşıp savaşılmayacağını seçmek veya kesinlikle bir aslanla savaşmak arasında bir fark olabilir.
Runer112

MAP_SIZE statik olmayan bir değişken olduğu için derlemedi. Bunun bir örnek değişken olacağını söylemediğim için sizin için düzelttim. Bilmeni isterdim ki, projenin tamamını gönderdim ve kasaplı değişken isimlerini gördün.
Rainbolt

@Rusher Oh, boğmaca Sanırım hala oyun kodunun eski bir sürümüyle sanal alandan çalışıyordum ve MAP_SIZEdeğişken o zamanlar aslında mevcut değildi ya da bir nedenden ötürü onu görmezden geldim ve kendi statik versiyonuma ekledi. Ayrıca kurtlarımın neden denemelerimdeki diğer kurtlardan biraz daha iyi bir şekilde daha iyi gol attığını merak ediyorum, ama seninkinden daha da kötüleşti ... Farklı bir kurt seti sanırım? Yoksa oyunlarınızı 1000'den fazla sayıda tekrarlamak için mi kullanıyorsunuz? Ya da sadece daha büyük bir örneklem boyutuna ihtiyacınız olabilir, 5 istatistiksel olarak bu kadar iyi değil.
Runer112

21

WolfRunningWithScissors

Kimse WolfRunningWithScissors'a makasla kaçmamasını söylemedi. Ya da belki yaptılar ama yine de yapıyor.

Bir düşmana rastlarsa, ya makasla kazanır, makasla kaybeder, makasla bağlar ya da gözünü dışarı atar (intihar).

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

}

Sadece eğlence için bir başvuru yapmak istedim. Java'yı daha önce hiç kullanmamıştım ve test etmedim, ancak çalışması gerekiyor. Rasgele saldırıya ve hareket eden kodum getRandomAttack()StoneEatingWolf'tan kaynaklanıyor.


14

Omega Kurt

Birbirine bağımlı türetilmiş çözüm, Alpha Wolf'a çok benziyor, bu nedenle Omega Wolf

Bu kurt, çevreleyen hücrelerin “tehlike” haritasını oluşturur ve en güvenli hücreye olan hareketi seçer (veya tutar).

İlk önce aslanların hareket edeceği hücrelere EXTREAME_DANGER seviyesi verildi. Daha sonra tespit edilen herhangi bir Kurt'u çevreleyen hücrelere, saldırının yakınlığına dayanan tehlike seviyeleri verilir ... yani kurt omega kurtuna çapraz ise, düşük bir tehdit sayılır, ancak bitişik olan kurtlar ılımlı bir tehdit sayılır.

“Tehlike” haritası daha sonra çevresindeki hücrelere yönelik tehditlerin kanamasını sağlamak için bulanıklaştırılır. Bu, omega kurtunun tehdit vektörlerini "algılamasını" ve ondan uzak durmasını sağlar.

Şu anda gerçek saldırı mantığı çok ilkel. Daha akıllıca davranabilmeyi ve kazanma / kaybetme oranlarını daha iyi kazanmayı umuyorum. Bazı istatistiksel sezgisel taramalara katılırsam, bu mümkün olmalı.

Testlerimde Omega Wolf, alfa bot'una 10 defa 9 taklit etti.

kalan ortalama kurtların 100 turluk 1000 tekrardan sonra elde edilen hızlı sonuçları:

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

Kod:

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

Bu oldukça eğlenceliydi. Javascript için clupky portu ile görselleştirme için createjs desteğini kullandım: JavaScript StoneGuardianWolf

StoneGuardianWolf, evcil hayvan kayaları arar ve Taşların yanına sığınır. Onları koruyor ve güvenliği için kendini feda etmeyi tercih ediyor.

İstatistikleri

Tek Oyunculu: ~% 75 Kurt sağkalım oranı +% 35 Evcil Hayvan (Taş) sağkalım oranı.

Özet: % 75 +% 35 ---> % 110 Başarı Oranı! :)

Çoklu oyuncu: denenmemiş.

Günlüğü Değiştir

v2: Güncelleme AI vs GamblerWolf ve evcil hayvan bulma stratejisi.

v1: Daha iyi Kurt kaçınma

v0: Doğum günü

Java kodu

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
Taş yiyen kurt baş düşmanı!
Averroes

:) Nitekim - seni evcil hayvanlarımın yanına yaklaştırmayacağım! CamoWolf, SGW'yi oldukça sert bir şekilde tokatladı.
talmobi

1
Neyse ki CamoWolf'u meşru bir giriş olarak eklemenize gerek yok = D
justhalf

14

Erkek mi Bu bir kurt mu? Hayır, bu

BoyWhoCriedWolf.java

İnsanlar her yerde yansıma kullanıyorlar, ben de düşündüm, neden bir adım daha ileri gitmiyorsun?
Size sunarım: Kaybedemeyen kurt.

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

Evet, çalıştırmak için bir JDK gerektiriyor, ancak bunun bir sorun olacağını sanmıyorum.


1
Kahretsin beni yendin. Bu tam taktikle bir SabotageAgentWolf üzerinde çalışıyordum.
mackthehobbit

1
Bu sınıf ne yapıyor?
justhalf

3
@justhalf Game sınıfını, base64'te kodlanmış dosya ile tabana yakın olarak yeniden tanımlar. Bu dosyanın çekinin bir örneği var; eğer benim kurtum, diğeri daima ölür.
14mRh4X0r

1
Diğer tüm hayvanları intihar etmek ve HypnoWolf diye adlandırmak için tam olarak bu mekanizmayı kullanma fikrim vardı. Doğru çalışması için başaramadım ama siz saygı duyuyorsunuz!
Francois Bourgeois

12

Wion

Beklenen değerde mümkün olduğu kadar uzun süre hayatta kalmak için mümkün olduğu kadar az şey yapmaya çalışır. Aslanlara paralel hareket etmeye çalışır (herhangi bir şey görüp görmediğinden bağımsız olarak).

Tahmin edilemez olduğuna karar verdiğinden kurtları görmezden geliyor. Bir kurtla karşılaşırsa, dövüşlerin yaklaşık yarısını kazanması gerekir (kalıp eşleştirme yapmayı denemeden bu en uygunudur). Kurtlarım asla birbirleriyle savaşmamalı. Bir aslanla karşılaşırsa (ki muhtemelen yapmamalı) savaşın yaklaşık 3 / 4'ünü kazanmalıdır. Ayılar ve kayalar her zaman kaybedilmelidir.

Simülasyonda başka bir strateji kullanan kurtlar olduğunu varsayarsak, kurtlarımdan kaçınmak akıllıca olur çünkü herhangi bir karşılaşmayı kaybetme şansı% 50'dir. Ortalama olarak bu, en azından diğer stratejilerin yanı sıra gerçekleştirmelidir.

Kuralları doğru anladıysam, bu en uygun strateji olmalı.

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

Dürüst olmak gerekirse, test çalışmalarımda bunun neden bu kadar zayıf olduğunu bilmiyorum. Kağıt üzerinde kulağa hoş geliyor ama pratikte EmoWolf ile eşit oluyor:
Geobits

@Geobits TBH'yi gerçekten test etmedim. Sanırım kurallardan birini yanlış anladım, bir hata yaptım ya da kurtlara yönelik rastgele saldırım tekdüze rastgele değil.
Tim Seguine

@ Geobits Saldırı mantığını değiştirdim. Benim şüphem, belki de bazen intihar ediyordu.
Tim Seguine

1
Sadece evet, sorunun ne olduğunu zaten anladım. Benim akıl yürütmeme ancak muhtemelen bir diğer kurt türünden oluşan bir popülasyonla çalışabilirim. Böyle bir durumda, diğer kurdun karşılaşma oranı, benimkiyle aynı oranda artacak / azalacak. Bununla birlikte, çoklu cins durumunda, karşılaşma oranımdaki herhangi bir artış diğer tüm kurtlar arasında ortalanacak, bu yüzden benimki orantılı olarak daha büyük olacak. Bunu düzeltmenin bir tür minimal yolunu düşünüyorum, ancak şu anda konsantre olmak için maalesef daha önemli şeylerim var.
Tim Seguine

1
Ancak, en fazla bir kurt türü daha varsa, bu yöntemin optimal olduğuna katılıyorum.
justhalf

12

Toplu Hafızalı Kurtlar

R içinde bir kurt sürüsü

Bu kurt sürüsünün fikri, yaşayan ya da ölü olan hafızada tutulması, ölü kurtların ve canlı kurtların saldırı olarak kullandıklarını kontrol etmesi ve seçim olasılığını buna göre değiştirmesidir.

İşte R kodu:

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

Özel adı olarak WolfCollectiveMemory ve çağrı olarak "Rscript WolfCollectiveMemory.R" ile @ProgrammerDan sarıcı (teşekkür ederim!) Kullanır.


Birkaç şey - önce çıktıların temizlenmediğinden eminim. İkincisi, işleminiz sarıcı tarafından başlatıldığında, çalışmaya devam eder . Mevcut tasarımınız iletişim kurta her gönderildiğinde işleminizin başlatıldığını varsayar - bu işlem çağırma açısından çok pahalı olurdu, bu yüzden işleme başladım ve iletişim kanallarını açık bırakıyorum. Bu nedenle, sürekli olarak okuyan stdinve stdoutardından bir satır yazan bir ana döngüye sahip olmalısınız flush.console(). [cont]
ProgrammerDan

[devam] İşlem paketleyicim, simülasyon sona erdiğinde çocuk sürecini sonlandırmalı.
ProgrammerDan

@Rusher İşte @plannapus 'R teslimi için geçerli bir sarıcı için özü . R. Install'u indirmek için buraya gidin . R'nin binklasörünü PATH değişkeninize veya eşdeğerinize ekleyin, iyi olmalısınız (benim için iyi çalıştı).
ProgrammerDan

Bence suçlu readlinesemirdir. A readlineveya equiv kullanmayı deneyin . readlinesEOF'ye kadar engelleyecektir.
ProgrammerDan

readLinesEskiden ekledim scan. readLinesikinci argüman olması 1, ilk satırsonu karakterinde durması gerektiği anlamına gelir.
plannapus

12

MimicWolf

Bu kurtun amacı diğer kurtları taklit etmektir. Bir kurtun onu elinden gelenin en iyisini takip ettiğini bulur. MimicWolf gibi sorular sormaz: Bu kurt / ayı / aslan / taşı nasıl önleyebilirim?

Hayır, MimicWolf sadece şu gibi soruları sorar: Takip edebileceğim bir kurt nerede? İzlediğim kurt nereye gidecek sanırım? Takip ettiğim kurt farklı bir kurt mu? Takip ettiğim kurt nereye gitti?

Bu soruların çoğunun henüz iyi cevaplanmadığını itiraf edeceğim, ancak burada şu an için MimicWolf'umun teslimi.

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

Düzenleme: Daha iyi bir mimik sistem ekledim. Kurtlar, sürekli hareket ederken, şu anda hiçbir şeyden kaçınmaya çalışmadıkları için hala iyi değil.


12

Bir giriş değil, ama kurtların çoğu sadece durağan olduğu için izlemesi oldukça sıkıcı, bu yüzden Vahşi'e doğal bir felaket ekledim:

Deprem!

Zamanın yaklaşık% 5'i, bir deprem meydana gelecek, en yüksek 20, en düşük 20, rasgele büyüklükte olacak. Bu, earthquakeCounterbir deprem sonrası zamanla katlanarak azalacak olanı belirleyecektir.

Bir deprem sırasında ne oldu?

Tüm Hayvanların değerine bağlı olarak, rastgele hareket etme şansı olacaktır earthquakeCounter. Bu nedenle, değer 75 ise, Hayvanların yaklaşık% 75'i (Taşlar dahil) herhangi bir yöne rasgele hareket eder (eşit olarak dağıtılır).

Bu, şaşırtıcı olmayan bir şekilde, birçok hayvanı öldürür, bu nedenle maksimum çalışma birkaç denemeden sonra genellikle yaklaşık 50 hayvandır.

Ayrıca, deprem, büyüklüğüne bağlı olarak değişen GUI'de görselleştirilecektir.

Depremi göremiyorum!

Bir depremin oluşma olasılığı oldukça azdır, sadece% 5'tir.

Ama üzülme! Ayrıca "Deprem!" De ekledim. GUI üzerindeki buton , tüm Kurtları kendi konfor bölgelerinden dürtmek istersen ...

İşte bir ekran görüntüsü:

deprem

İşte kod:

Wild.java

main() işlevi (hızlanan ilk 100 yinelemenin GUI'sini atlamak için güncellendi):

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
bazı erkekler sadece dünyayı izlemek ister ... deprem
CommonGuy

5
Gathering Wolf'larım ağlıyor.
johnchen902

12

MultiWolf (Java)

Bu kurt, bu programlama mücadelesindeki diğer kurtları tanıyor. Mümkünse, onları ('evcil hayvan' olarak) başlatır ve sahip oldukları her kurt hayvanına sorarak ne yapacaklarını belirlemek için kullanır ve en popüler cevabı seçer.

Başkası benzer bir kavram uygulaması halinde yani - - Bu kurt sonsuz-özyineleme-güvenli olmalı ve varsayılan eylemi dönecektir Attack.ROCK/ Move.HOLDdiğer hayvanlar çağırıyor ederken çağrıldığını olduğunu tespit ederse.

Testlerimde bunun çeşitli sonuçları oldu. Buna izin verilip verilmeyeceğinden emin değilim. Fakat eğer kazanırsa ve bazı imkansız bir mucize gerçekleşirse, kazanan unvanın "ikinci" gelen kurda geçmesi gerektiğini düşünüyorum - bu sadece adil, muhtemelen mantığını çaldım.

İntiharı önler.

Düzenleme - Bu Kurt'un düzgün çalışması için referansta bulduğu kurtlardan sonra yüklenmesi gerektiğine inanıyorum.

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

}

Doğru hatırlamıyorsam, sınıfları Wild.classes aracılığıyla alabilirsin, çünkü bu statik bir alandır ... Bu yüzden, her yeni kurt
kurulduğunda

Bu doğru. Ama şimdi bu şekilde yaptım, muhtemelen bırakacak. Aynı zamanda daha az kazanmış kurtların bazılarını bu kurttan da kaldırabilir. Wion her koşumda soyu tükenmiş gibi görünüyor, bunun eylemlerin kalitesini düşürüp düşürmediğini merak ederken MultiWolf'ten kesmeyi düşünüyorum.
OlivierTheOlive

Diğer kurt sınıfı dosyalarını da içerecek şekilde "Siz başka bir Wolf sınıfı tarafından oluşturulan dosyaları okuyamaz veya değiştiremezsiniz" kuralının kullanıldığına inanıyorum. Bu yüzden, bu girişin harika bir fikir olsa da kurallara aykırı olduğunu düşünüyorum.
Runer112

1
@ Runer112 Merak ettim ama ayrıca dersleri ismiyle yükleme konusunda da biraz öğrendim ve tüm sınıfları bir pakette bulmanın basit bir yolu yok. Sadece birazcık eğlence
OlivierTheOlive

3
Başka bir Wolf'u başlatmak, başka bir Wolf tarafından oluşturulan dosyaları okumak veya değiştirmek değildir, bu nedenle bu gönderim meşrudur. Kural, verileri statik değişkenler gibi olmayan ve bunun yerine bir dosyaya yazması gereken dillerde yazılmış gönderilerden korumaktı.
Rainbolt

12

Taş yiyen kurt

İşte benim gönderim. Bu kurt, çevresinde hiç taş, aslan veya kurt görmüyorsa yerinde kalır. Bir taş görürse ve başka bir kurt ya da aslan tarafından saldırıya uğrama tehlikesi yoksa onu yemeye çalışır. Herhangi bir tehlike görürse kaçar!

EDIT 1 : Tehlike algoritması için geliştirilmiş izleme. Şimdi tehlikeden daha iyi kaçıyor :)

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

    }

Düzenleme 2 : Bazı İstatistikler

Çalıştığım simülasyonlarda StoneEatingWolf'u 5-6 Wolf arasında kazanmayı başardım:

1000 iterasyondan 40 oyun sonrası Ortalama Sonuçlar

Taş Yeme Kurtların ima edildiği kavgaların bir analizini yapıyorum. 1000 iterasyondan 40 oyun çalıştırıyorum Bu sonuçları alıyorum:

Kavga sonuçları tablosu

Zafer Taş Yeme Kurt kazanır. Grafik zaten bildiklerimizi gösteriyor: En başarılı kurtlar diğer kurtlarla karşılaşmayan kurtlardır. Ayrıca diğer kurtlarımın (Göçen Kurtlar) Taş Yiyenlerimin bazılarını mahvettiğini de fark ettim. Umarım başka kurtları da avlarlar. Yeterince komik, Tembel Kurt ve Camper Kurt ile hiç karşılaşmamıştım. Ayrıca, 20 çalışmada aldığım saldırıların sonuçları (Taşlar ve Ayılar hariç):

PAPER       447
ROCK        881
SCISSORS    581
SUICIDE     230

Görünüşe göre ROCKsaldırılara açık bir önyargı var . Bunu bilerek kurt PAPERsaldırılarımı biraz daha sık yaptım .


2
Lütfen, kategorik verileri çizmek için çizgi grafiği kullanmayın. Grafiğine bakarak bana çok fazla kanser veriyor.
AJMansfield

@AJMansfield Bunu duyduğuma üzüldüm. Umarım iyisindir;) Her neyse, yapacağım gelecek grafikler için hesaba katacağım.
Averroes

Hala Windows XP kullanıyor musunuz? oO
justhalf

Ve neden ROCKLion ile savaşmak için (% 50 galibiyet) kullanıyorsun ? Kullanmak en iyisidir SCISSORS(% 75 galibiyet)
justhalf

@justhalf Şirketim hala XP kullanıyor ... Ve makas konusunda haklısın. Sabit. Thanks :)
Averroes

11

HonorWolf

Kurtum diğer kurtlardan kaçıyor. Eğer kaçamazsa, onurlu bir dövüşe başlar.

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

Profesyonel alfa kurtuma saldıran taktiklerimi değiştirmem gerekiyor. Eğer
tutuyup

11

Kör Kurt

Kör kurt hareket etmekten korkar ve ne ile savaştığını asla bilemez. Her zaman makas oynayarak en iyi şansı yakalar, çünkü asla gerçek bir taşa rastlamaz .

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

Büyüdüğümde

Bu kurt büyüdüğünde, bir aslan olmak istiyor. Bu yüzden rastgele dolaşarak Aslanların ayak izlerini takip etmesini ve nasıl Aslan olacağını öğrenmesini sağlar.

Bu kurt, Lions'la yer değiştiren kurtlara karşı olarak tasarlandı.

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 düşmanlarına göz kulak olur ve faaliyetlerini kaydeder, böylece mesafeyi koruyarak herkesin izini sürmesini sağlar. Öğrenilmek istemem!

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

Oldukça iyi, ama bu topal HybridWolf çok hileli! SpyWolf, casus okuluna geri dönebilir ve gelişmiş anti-kurt tekniklerini eğitebilir.


1
Sen topal diyorsun, ben akıllı diyoruz;)
CommonGuy

5
AHHHHH! Çok fazla gotos! Ve onlara sahip olmayan bir dilde!
AJMansfield

9

HybridWolf

Karşı koyamadım ama bir kurt daha yapmak için. Bu, diğer iyi kurtların yapacağı saldırı / hamleyi seçtiği için (davranışında değil, kodunda) çok farklıdır.
Elbette bütün kurtlar iyidir, ama ben en çok puan alanları kastediyorum :)

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

}

Testlerim önceki AlphaWolf'umdan daha iyi puanlar alıyor, ama Omega / Honor / ProAlpha bazen beni yeniyor ... Daha iyi gönderilenler burada, bu kurt daha iyi olacak: D


Bu biraz arsız! Zekice bir fikir olsa da. Bunun nasıl meşru bir giriş kadar adil olacağından emin değilim, Rusher'in meşru bir girişi belirlemek için uygulayacağı testler hakkında hiçbir fikrim yok. yani, mevcut diğer kurtlar dışında tecrit edilmiş bir test yaparsa, bu kurt sefil bir şekilde başarısız olur: P
Moogie

@ Moogie Girişlerin% 90'ı yasal. Şimdiye kadar, harflerini 'W' dışında bir şeye çeviren girişleri veya başka bir dilde nasıl derleyeceğimi bulamadığım girişimleri hariç tuttum. burada görmedim çünkü onlarla sohbet ediyorum.
Rainbolt

@Rusher, oranları kendi lehine değiştirmeye çalışan bazı girişler var. Örneğin Kumarbaz kurt, Java'nın Math.random () 'in rasgele sayı üreticisini her zaman 1'e döndürecek şekilde değiştirir! Yeterince tuhaf olsa da, kazanacak kurtlar savaşmayı önleyen kurtlar olduğu için sonuçlar üzerinde çok az etkisi var!
Moogie

@ Moogie GamblerWolf okunaklı bir sunumdur (ve aynı zamanda oldukça zekice). Haklısın, sonuçları pek değiştirmedi. İşler elinden çıkarsa, derim ki "Tamam, o kazanır, ancak dahil edilmediyse işte sonuç." Bu şekilde diğer herkes hala yok edilmekten zevk alabilir.
Rainbolt

2
@Moogie Eğer birşeyin zorunluluk şartnamesinde özel olarak yasaklanması yasaksa, bu kesinlikle meşru değildir ve bu sitedeki gelenek, insanlar cevaplarını verdikten sonra kuralları değiştirmemelidir.
plannapus

9

EvoWolf

Aptalca zekice tasarlanmış kurtlar! EvoWolf, DeepWolf ve HerjanWolf gibi diğer sert kurtlarla birlikte Vahşi doğada yaşıyor, bu yüzden hayatta kalmak için gelişmesi gerekiyordu.

Kod, en iyi kurdu geliştirmek için genetik bir algoritma kullanır (ben karşı karşıya gelmek için Kurtları yakalayana kadar LionHunterWolf'u fark etmedim). Her hayvan / saldırı kombo için farklı genler, güvenli olduğunda hareket yönü ve etrafındaki her hayvan için hareket yönü. 1000 turdan sonra, en fazla dönüş yapan kurtlar yavru üretme olasılığına sahiptir (yani ne kadar uzun yaşarsanız, çiftleşme şansınız o kadar artar). Aynı zamanda, çocukların% 10'unda rastgele bir mutasyona da yardımcı olacağımızı umuyoruz.

İşte EvoWolf kodu, SİZİN ÇALIŞMA YÖNÜNDE evowolf.txt İHTİYACINIZ VAR - IT GÜNCEL GENEPOOL İÇERİR. Eğer kendi kurtlarınızı ilkel rastgelelikten geliştirmek istiyorsanız, evowolf.txt dosyasını dahil etmeyin, ancak sağlanan en iyi evrimdir. Gelişimini izlemek gerçekten güzel, başlangıçta sadece 2-3 kişi hayatta kaldı, ancak daha sonra 60'a yükseliyor.

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

Ayrıca bana kaç dönüş ve kuşak geçtiğini göstermek için Statistics.java ve Wild.java'da bazı değişiklikler yaptım. 1000 dönüş yaptıktan sonra arayınEvoWolf.nextGen(); yavruları hesaplamak için . Yarışma için bu gerekli değildir, sadece kendi setinizi geliştirmek istiyorsanız.

Buradaki Tüm Dosyalar EDIT: FIXED LINK

En iyisi kadar geliştiği sürece, ilk 10'dan daha iyi olamaz. Sınırlamanın bir kısmı önceki hamlelerinin çok az hafızasına sahip olmasıdır. WolvesWithCollectiveMemory gibi işlev görmesine rağmen önceki nesillerin deneyimlerinin gelecek nesillerin uzun vadeli bir küresel bellek işlevi görmesini nasıl etkileyeceği konusunda. Tabii ki eğlenceliydi. Önceki linkte gen havuzunu analiz etmenize yardımcı olabilecek bir Excel sayfası var. .Txt dosyasındaki tüm 1 ve 0'ları 1 ve 0'ları virgüllerle değiştirin, sonra elektronik tabloya yapıştırın.

Birçoğu herkesin stratejilerini onaylayan bazı ilginç notlar:

  • Gerçek ataklar kavga etmekten kaçınmaktan daha az önemlidir. Ya da belki tüm kurt olmayanlar çabucak ortadan kalkar, böylece tehdit oluşturmazlar. Yarışma neslinin, S'yi atmanız gerekse bile RPS ile ayılar arasında eşit şansı var.
  • Yukarıdakiler gibi, düşündüğünüz halde evrim geçirmediğinden intiharı manuel olarak devre dışı bırakmak zorunda kaldım.
  • Etrafta kimse olmadığı zaman en iyi hamle
  • Birileri etrafta olduğunda kaçmak da iyi gibi görünüyor
  • Rastgele bir yöne hareket etmek yerine beklemelisiniz (bu seçenek, ortaya çıkan fazladan bir gendi)
  • Etrafında 1'den fazla hayvan bulunduğunda, her bir çevre / hayvan için hareketlerin kesişme noktasından rastgele bir hamle yapmak birlikten daha iyidir (başka bir ekstra gen)

8

SmartWolf

Sonuçlar (1000 yineleme) 'de (Bunu güncellemeye devam edeceğim ancak onu ortalamaları olmayan bağımsız bir test olarak göreceğim çünkü birçok kurtla oldukça yavaş).

görüntü tanımını buraya girin

Derleme:

* nix (Mono gereklidir):

gmcs SmartWolf.cs

Pencereler:

csc SmartWolf.cs

Çalışma dizinine kopyala.

Not: Windows kullanırken, "mono SmartWolf.exe"sadece"SmartWolf.exe" sarma koduyla .

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

Sarıcı (@ProgrammerDan'a teşekkür ederim, sadece buraya ekliyorum, bu yüzden yapıştırmayı kopyalamak daha kolay):

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

Gerçekten o kadar da büyük değil, en iyi kurtların birkaçıyla birlikte, 1000 yineleme için ortalama ~ 75 hayatta kalma oranı.

Çözüme ML yaklaşımı kullanır.


Sanırım kurtunun ne yaptığını kabaca anladım, ama onu daha ayrıntılı olarak açıklayabilir misin? Ayrıca muhtemelen hangi dilden bahsetmelisin (Eminim çoğu insan için açık ama benim için açık değildi).
plannapus

C # ile yazılmış ve bir tür hayvana karşı yapılan her hareketi ve başarı oranını listeleyen bir bilgi listesine sahip. Bir kurt saldırıp öldüğünde, bu hamlenin başarı oranı azalır. Eğer yaşarsa, başarı oranı artar. Sistem birkaç (20-30) tur sonra rasgele seçmek yerine bilgi tabanından hareketler almaya başlar.
user3188175

1
Sarıcıyı kullanırken seni gördüğüme sevindim! Muhtemelen mono@Rusher'ın kullanması için kodunuzu nasıl derleyeceğinize ve ne olduğuna ilişkin talimatlar eklemelisiniz.
ProgramcıDan

1
Markdown başarısız. Kaynağa bakarsanız, '#' var, ancak başlık bloğunda olduğundan Markdown bunu görmezden geldi. Sabit. : D
ProgramcıDan

2
FYI - @ ProgrammerDan'ın sargısı ile derleyebildim ve başarılı bir şekilde çalıştırabildim (ve bu sefer onun yardımı olmadan). Bir sonraki sonuçta olacaksın. Gecikme için üzgünüm!
Rainbolt

7

Pasif Agresif Kurt (Bir Ölçekli Kurt)

İlk 500 dönüş için elinden geleni önler, alanın kendini temizlemesine izin verir. Ardından, menzili içinde yer alan şeylere saldıran yönde atanır.

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 tabanlı bir dil olarak Scala nispeten kolay bir şekilde entegre edilebilir.

Programı kendiniz derliyorsanız, ölçek dosyasını java .classdosyalarına yerleştirin (dosyaları değil .java)

scalac PassiveAggressiveWolf.scala

derlemek için. Daha sonra PassiveAggressiveWolf.classana Wild.javasınıfta Java sınıflarıyla yaptığınız gibi kullanabilirsiniz. Siz scala-library.jarde sınıf yolunuza eklemeniz gerekecek (komut satırı seçeneğini kullanıyorum -cp /path/to/scala-library.jar).

Alternatif olarak, oluşturulan sınıf dosyalarını ve scala-library.jarScala 2.10.3 için bir kavanoz yükledim, böylece onları indirebilirsiniz.

PassiveAggressiveWolf.jar
scala-library.jar tarafından


Belki de indirmeyi kolaylaştırmak için 10 dosyayı tek bir zip dosyasına paketleyebilirsiniz.
johnchen902

@ johnchen902 Sohbet sırasında bana sınıflarımı içerecek bir kavanoz yapmam önerildi. İşten sonra bu akşam bunu yapmaya çalışacağım. Bu 2 indirmeye indirgeyecek ve umarım Rusher'ın dahil ettiği sorunları çözecektir.
Gareth
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.