Belirleyici bir Go AI oluşturun


11

İşte geçen gün düşündüğüm ilginç bir sorun, sadece kodun sahip olduğu bir özellikte değil, diğer kod parçalarına karşı bir oyun oynayarak diğer kod parçalarına karşı rekabet eden kod parçalarını da içeriyor.

Göreviniz, bir Go panosunun geçerli durumunu alan ve hangi hareketin yapılacağını veya geçeceğini belirleyen bir program oluşturmaktır.

Programınız aşağıdakileri girdi olarak kabul edecektir:

  • Her biri 19 karakterden oluşan ve şu anda Go panosundaki parçaları temsil eden 19 satır. Karakterinin karakteri 0boş bir kareyi temsil eder 1, siyahtır ve 2beyazdır.

  • Her oyuncunun sahip olduğu mahkum taşlarının sayısını temsil eden iki sayı (siyah sonra beyaz).

  • Sırasının hareket etmesini temsil eden bir sayı (siyah veya beyaz). Yukarıdaki gibi, 1siyahtır ve 2beyazdır.

ve aşağıdakilerden birini çıktılayın:

  • a bHareket ettirilecek koordinatları temsil eden bir çift koordinat . 1 1sol üst karedir ve birinci ve ikinci sayılar sırasıyla aşağı ve sağa hareket etmeyi temsil eder.

  • passGeçmek için bir hareketi temsil eden dize .

Örneğin, program aşağıdaki girdiyi alabilir:

0000000000000000000
0000000000000000000
0000000000000000000
0001000000000002000
0000000000000000000
0000000000000000000
0001210000000000000
0000100000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0002000000000001000
0000000000000000000
0000000000000000000
0000000000000000000
0 0 1

ki bu sadece birkaç hamlenin oynandığı bir oyunu temsil eder.

Sonra program çıktı alabilir 6 5, yani "üstten 6. ve soldan 5. noktaya siyah bir taş koyun". Bu beyaz taşı ele geçirirdi 7 5. Bu durumda kurulun durumu şu şekilde değişir:

0000000000000000000
0000000000000000000
0000000000000000000
0001000000000002000
0000000000000000000
0000100000000000000
0001010000000000000
0000100000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0002000000000001000
0000000000000000000
0000000000000000000
0000000000000000000
1 0 2

(Beyaz bir taş ele geçirilse de, siyah için esir sayıldığını unutmayın.)

Kodunuz ayrıca aşağıdaki özellikleri de sağlamalıdır:

  • Programınıza aynı giriş durumu verilirse, her zaman aynı çıkışı üretmelidir. Go AI'nin determinizmi budur. Rastgele bir bileşeni olmamalıdır.

  • Hangi hareketin yapılacağını belirlemek için programınızın yaklaşık 60 saniyeden fazla sürmemesi gerekir. Bu kural, hesaplama gücündeki farklılıklar nedeniyle kesinlikle uygulanmayacaktır, ancak makul bir süre içinde hareket etmelidir.

  • Programınızın kaynak kodu toplam 1 megabaytı (1.048.576 baytı) geçmemelidir.

  • Programınız her zaman yasal adımlar atmalıdır. Programınız zaten bir taşın bulunduğu yerde hareket edemez ve bir grup kendi taşının yakalanmasıyla sonuçlanacak bir parça yerleştiremez. (Bu zorluğun amaçları için kuralların bir istisnası, bir programın başlangıçta orada olan bir pozisyon oluşturmasına izin verilmesidir - çünkü sadece bir tahtanın mevcut pozisyonu verildiğinden, hangi hareketlerin yapıldığını depolaması beklenemez. önce.)

Daha sonra gönderiminiz, diğer tüm gönderilere karşı tümüyle oynayabileceğiniz bir turnuvada, yönetim kurulu durumunun boş olarak başladığı bir Go oyununda oynayacak ve her program sırayla yönetim kurulu pozisyonunun beslenip bir hamle yapacaktır. .

Her başvuru çifti iki tur oynayacaktır - her tur siyah olacak şekilde bir tur. Bu problemdeki AI'lar tamamen deterministik olduğundan, birlikte oynayan aynı AI'lardan ikisi her zaman tam olarak aynı oyunun oynanmasına neden olacaktır.

Kazanma koşulları şöyledir:

  • Programınız oyunun sonuna kadar oynarsa, kazananı belirlemek için Go'nun Çin puanlama kuralları kullanılacaktır. Hiçbir komi uygulanmayacak.

  • Programınız daha önceki bir duruma ulaşıldığı ve sonsuz bir döngüye neden olduğu noktaya kadar oynarsa, iki programın bağlandığı bildirilir.

Gönderiminiz diğer gönderilere göre kaç puan aldığını gösterir. Bir galibiyet 1 puan ve bir kravat yarım puan değerindedir. En çok puana sahip olan başvuru genel kazanandır.


Bu, herkesin herhangi bir zamanda yeni bir giriş gönderebileceği ve sıralamalar gerçekleştiğinde periyodik olarak yeniden değerlendirilecek olan bir tepenin kralı mücadelesidir.


7
Tamam, diğer tüm başvuruları beklemek ve sonra onları yenmek için kendim yazmak - çözümler deterministik olduğundan mümkün olmalıdır.
Howard

1
Bir önceki pozisyonun tekrarlanmasına izin verecek şekilde ko'da oynuyor gibi görünüyor, ancak derhal çekime neden oluyor (çünkü bir döngüye neden oluyor). İlginç ...
FireFly

2
Görünüşe göre sorununuz çok düpedüz ve kimse değerli bir cevap verecek kadar çok çalışmayacak (gerçekten çok fazla iş). Bu güzel bir problem, ama gitmek çalışmak için çok zor.
Victor Stafusa

1
Neden daha küçük bir tahta kullanmıyorsunuz? 9x9, yeni başlayanlar için yeterince yaygındır. Arama alanını önemli ölçüde azaltır, ancak analizle "dövüldüğü" o kadar küçük değildir (bence tamamen çözülen en büyük 5x6'dır).
Geobits

1
Girdi nasıl çalışır? stdin veya komut satırı bağımsız değişkenleri?
Ypnypn

Yanıtlar:


7

İşte bu zorluğu ortadan kaldırmak için benim giriş. Python kodu:

print "pass"

Kurallarınıza göre her zaman "pass" oynamak geçerli (kötü de olsa) bir stratejidir.


Kodunuz her zaman ona karşı oyun oynayan herkese karşı kaybeder. Yine de güzel bir baz-durum yanıtı.
Joe Z.

1
@JoeZ. Ve görünüşüyle ​​onunla kazandı: P
David Mulder

4

Java: Bir yer seçin, herhangi bir yer

Geçerliliği test etmek için tahtadaki noktaları seçmeniz yeterlidir. PRNG'yi kullanır, ancak belirli bir tohumla bu yüzden deterministiktir. Kaç tur geçtiğine bağlı olarak PRNG döngüsünün farklı parçalarını kullanır.

Her aday pozisyonu için geçerli bir hamle olup olmadığını kontrol eder (ama akıllı bir hamle olmadığını). Değilse, bir sonraki adaya geçer. 1000 denemeden sonra geçerli bir hamle bulamazsa geçer.

import java.util.Random;
import java.util.Scanner;

public class GoNaive {

    int[][] board;
    boolean[] checked;
    int me;

    public static void main(String[] args) {
        new GoNaive().run();
    }

    void run(){
        int turns = init();
        Random rand = new Random(seed);

        for(int i=0;i<turns*tries;i++)
            rand.nextInt(size*size);

        for(int i=0;i<tries;i++){
            int pos = rand.nextInt(size*size);
            for(int c=0;c<size*size;c++)
                checked[c]=false;
            if(board[pos%size][pos/size] == 0)
                if(hasLiberties(pos, me)){
                    System.out.print((pos%size+1) + " " + (pos/size+1));
                    System.exit(0);
                }
        }
        System.out.print("pass");
    }

    boolean hasLiberties(int pos, int color){
        if(checked[pos])
            return false;
        checked[pos] = true;

        int x = pos%size, y=pos/size, n;

        if(x>0){
            n = board[x-1][y];
            if(n==0 || (n==me && hasLiberties(y*size+x-1, color)))
                return true;
        }
        if(size-x>1){
            n = board[x+1][y];
            if(n==0 || (n==me && hasLiberties(y*size+x+1, color)))
                return true;
        }
        if(y>0){
            n = board[x][y-1];
            if(n==0 || (n==me && hasLiberties((y-1)*size+x, color)))
                return true;
        }
        if(size-y>1){
            n = board[x][y+1];
            if(n==0 || (n==me && hasLiberties((y+1)*size+x, color)))
                return true;
        }
        return false;
    }

    int init(){
        int turns = 0;
        board = new int[size][size];
        checked = new boolean[size*size];
        turns = 0;
        Scanner s = new Scanner(System.in);
        String line;
        for(int i=0;i<size;i++){
            line = s.nextLine();
            for(int j=0;j<size;j++){
                board[j][i] = line.charAt(j)-48;
                if(board[j][i] > 0)
                    turns++;
            }
        }
        String[] tokens = s.nextLine().split(" ");
        turns += Integer.valueOf(tokens[0]);
        turns += Integer.valueOf(tokens[1]);
        me = Integer.valueOf(tokens[2]);
        s.close();
        return turns;
    }

    final static int size = 19;
    final static int seed = 0xdeadface;
    final static int tries = 1000;
}

2

Bazı Scalalar:

package go;

class Go {
  def main(args : Array[String]) {
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    System.out.printLn("1 1")
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    System.out.printLn("pass")
  }
}

Wikipedia okuduktan sonra, bunun mevcut çözümü yeneceğini düşünüyorum.


Aslında, her iki durumda da 361 puan kazanacak.
Joe

Aslında, onu geri almak zorundayım, spesifikasyona uymuyor. AI'nın vatansız olması gerekiyordu. Aslında yönetim kurulu durumu göz önüne alındığında bir şey yazdırılması gerekiyordu ve siz iki ( 1 1ve pass) yazdırın .
Joe Z.

@JoeZ. Onu düzeltti. Yine de derlenmiş olmazdı.
yayestechlab

Bu her zaman yazdırılacaktır 1 1, çünkü tahta her değiştiğinde program her zaman yeniden çalıştırılır.
Joe Z.

1

Java

public class Go {
  public static void main(String[] args) {
    Scanner s = new Scanner(System.in);
    for (int i = 0; i < 361;) {
      char c = s.nextChar();
      if (c != '\n') {
        if (c == '0') {
          System.out.println((i % 19 + 1) + " " + (i / 19 + 1));
          System.exit(0);
        }
        i++;
      }
    }
  }
}

İlk boş alanı seçer. Gönderme zamanı itibariyle tüm AI'lara karşı kazanır.


2
Bu yasal bir hareketi garanti etmez. Kullanılabilir ilk alanda özgürlük yoksa oynatılamaz. Örneğin, bu yapay zeka kendini oynarsa: Alternatif parçaların ilk sırasından sonra 1 1beyaz (şimdi boş) ile yakalanır ve bir sonraki dönüşte siyah tarafından oynatılamaz.
Geobits
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.