Xây dựng một AI quyết định


11

Đây là một vấn đề thú vị mà tôi nghĩ đến vào một ngày khác, liên quan đến các bit mã cạnh tranh với các bit mã khác không chỉ trong một thuộc tính mà mã có, mà bằng cách chơi một trò chơi với các bit mã khác.

Nhiệm vụ của bạn là xây dựng một chương trình lấy trạng thái hiện tại của bảng Go và xác định di chuyển nào để thực hiện hoặc vượt qua.

Chương trình của bạn sẽ chấp nhận như sau:

  • 19 dòng, mỗi dòng có 19 ký tự, đại diện cho các mảnh hiện có trên bảng Go. Một nhân vật 0đại diện cho một hình vuông trống, 1màu đen và 2màu trắng.

  • Hai số đại diện cho số lượng tù nhân mà mỗi người chơi có (đen, rồi trắng).

  • Một số đại diện cho lượt của nó là di chuyển (đen hoặc trắng). Như trên, 1là màu đen, và 2là màu trắng.

và đầu ra một trong những điều sau đây:

  • Một cặp tọa độ a bđại diện cho tọa độ mà tại đó di chuyển. 1 1là hình vuông trên cùng bên trái và các số thứ nhất và thứ hai tương ứng di chuyển xuống và sang phải.

  • Chuỗi pass, đại diện cho một di chuyển để vượt qua.

Ví dụ, chương trình có thể nhận được đầu vào sau:

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

đại diện cho một trò chơi trong đó chỉ có một vài di chuyển đã được chơi.

Sau đó, chương trình có thể xuất ra 6 5, có nghĩa là "đặt một viên đá đen ở điểm thứ 6 từ trên xuống và thứ 5 từ bên trái". Điều này sẽ chụp đá trắng tại 7 5. Trạng thái của hội đồng sau đó sẽ thay đổi thành:

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

(Lưu ý rằng mặc dù một viên đá trắng đã bị bắt, nó được tính là tù nhân cho màu đen.)

Mã của bạn phải đáp ứng thêm các thuộc tính sau:

  • Nếu chương trình của bạn được đưa ra cùng một trạng thái đầu vào, nó phải luôn tạo ra cùng một đầu ra. Đây là yếu tố quyết định của AI đi. Nó không được có một thành phần ngẫu nhiên.

  • Chương trình của bạn không được mất hơn 60 giây để xác định di chuyển sẽ thực hiện. Quy tắc này sẽ không được áp dụng nghiêm ngặt do sự thay đổi trong khả năng tính toán, nhưng nó phải thực hiện một bước đi trong một khoảng thời gian hợp lý.

  • Mã nguồn chương trình của bạn không được vượt quá tổng số 1 megabyte (1.048.576 byte).

  • Chương trình của bạn phải luôn luôn thực hiện các động thái hợp pháp. Chương trình của bạn không thể thực hiện di chuyển nơi một viên đá đã tồn tại và không thể đặt một mảnh dẫn đến một nhóm đá của chính nó bị bắt giữ. (Một ngoại lệ đối với các quy tắc cho mục đích của thử thách này là chương trình được phép tạo một vị trí ban đầu ở đó - bởi vì nó chỉ được trao cho vị trí hiện tại của một bảng, nên không thể dự đoán được việc di chuyển đã được thực hiện trước.)

Bài dự thi của bạn sau đó sẽ chơi trong một giải đấu toàn chơi với tất cả các bài dự thi khác, trong trò chơi cờ vây, trong đó trạng thái của bảng bắt đầu trống rỗng, và mỗi chương trình thay phiên nhau được đưa vào vị trí của bảng và di chuyển .

Mỗi cặp bài nộp sẽ chơi hai vòng - một vòng với mỗi người chơi có màu đen. Bởi vì các AI trong vấn đề này hoàn toàn mang tính quyết định, hai trong số các AI giống nhau chơi cùng nhau sẽ luôn dẫn đến kết quả chính xác cùng một trò chơi đang được chơi.

Điều kiện để giành chiến thắng là như vậy:

  • Nếu chương trình của bạn chơi đến hết trò chơi, quy tắc tính điểm của người Trung Quốc sẽ được sử dụng để xác định người chiến thắng. Không có komi sẽ được áp dụng.

  • Nếu chương trình của bạn phát đến điểm đạt đến trạng thái trước đó, do đó gây ra một vòng lặp vô hạn, hai chương trình sẽ được tuyên bố là đã kết nối.

Bài nộp của bạn sẽ được tính bằng số điểm mà bài đó ghi được. Một chiến thắng có giá trị 1 điểm, và một cà vạt có giá trị một nửa điểm. Bài nộp có nhiều điểm nhất là người chiến thắng chung cuộc.


Đây là một thử thách trên đỉnh đồi, trong đó bất kỳ ai cũng có thể đăng một mục mới bất cứ lúc nào và bảng xếp hạng sẽ được đánh giá lại định kỳ khi điều này xảy ra.


7
Ok, chờ đợi tất cả các đệ trình khác và sau đó viết riêng của tôi để đánh bại chúng - nên có thể vì các giải pháp là xác định.
Howard

1
Có vẻ như chơi trong ko sao cho vị trí trước đó được lặp lại được cho phép nhưng dẫn đến rút thăm ngay lập tức (vì nó gây ra một vòng lặp). Thú vị ...
FireFly

2
Có vẻ như vấn đề của bạn quá khó khăn và không ai sẽ làm việc chăm chỉ để đưa ra một câu trả lời xứng đáng (nó thực sự là rất nhiều công việc). Đó là một vấn đề tốt, nhưng đi là quá khó để làm việc với.
Victor Stafusa

1
Tại sao không sử dụng một bảng nhỏ hơn? 9x9 là đủ phổ biến cho người chơi mới bắt đầu. Nó cắt giảm không gian tìm kiếm xuống đáng kể, nhưng nó không nhỏ đến mức nó bị "đánh bại" bằng cách phân tích (tôi nghĩ rằng cái lớn nhất đã được giải quyết hoàn toàn là 5x6).
Geobits

1
Làm thế nào để đầu vào hoạt động? stdin hay đối số dòng lệnh?
Ypnypn

Câu trả lời:


7

Đây là mục nhập của tôi để đưa thách thức này lên khỏi mặt đất. Mã Python:

print "pass"

Theo quy tắc của bạn, luôn luôn chơi "vượt qua" là một chiến lược hợp lệ (mặc dù xấu).


Mã của bạn sẽ luôn thua trước bất kỳ ai thực hiện bất kỳ trò chơi nào chống lại nó. Tuy nhiên, câu trả lời cơ bản tốt đẹp.
Joe Z.

1
@JoeZ. Và từ vẻ ngoài của nó, anh đã giành chiến thắng với nó: P
David Mulder

4

Java: Chọn một vị trí, bất kỳ vị trí nào

Đơn giản chỉ cần chọn các điểm trên bảng để kiểm tra tính hợp lệ. Nó sử dụng PRNG, nhưng với một hạt giống được thiết lập nên nó mang tính quyết định. Nó sử dụng các đoạn khác nhau của chu trình PRNG tùy thuộc vào số lượt đã qua.

Đối với mỗi vị trí ứng cử viên, họ kiểm tra xem đó là một nước đi hợp lệ (nhưng không phải là một bước đi thông minh ). Nếu không, nó sẽ chuyển sang ứng cử viên tiếp theo. Nếu nó không thể tìm thấy một động thái hợp lệ sau 1000 lần thử, nó sẽ vượt qua.

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

Một số Scala:

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

Từ việc đọc Wikipedia, tôi nghĩ rằng điều này sẽ đánh bại giải pháp hiện tại.


Trên thực tế, nó sẽ giành được 361 điểm trong cả hai trường hợp.
Joe Z.

Trên thực tế, tôi sẽ phải lấy lại, nó không tuân theo thông số kỹ thuật. AI được cho là không quốc tịch. Nó chỉ thực sự được in một thứ với trạng thái của bảng, và bạn đã làm cho nó in hai ( 1 1pass).
Joe Z.

@JoeZ. Đã sửa nó. Dù sao cũng sẽ không biên dịch.
yayestechlab

Điều đó sẽ luôn luôn được in 1 1, vì chương trình luôn được chạy một lần nữa mỗi khi bảng thay đổi.
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++;
      }
    }
  }
}

Chọn không gian trống đầu tiên. Thắng bất kỳ AI nào tại thời điểm đăng bài.


2
Điều này không đảm bảo một động thái hợp pháp. Nếu không gian trống đầu tiên không có tự do, nó không thể được phát. Chẳng hạn, nếu AI này tự phát: Sau hàng đầu tiên của các mảnh xen kẽ, 1 1sẽ bị bắt bởi màu trắng (bây giờ trống) và không thể được chơi bằng màu đen ở lượt tiếp theo.
Geobits
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.