Bảo vệ bạn có thể với cuộc sống của bạn!


10

Hãy chơi Kick The Can!

Mặc dù Moogie là người chiến thắng hiện tại, nhưng nếu bất cứ ai có thể lấy vương miện của mình, họ được khuyến khích làm như vậy

Kick the can là một trò chơi của trẻ em. Liên quan đến một hậu vệ, và nhiều kẻ tấn công. Ngày nay nó không còn là một trò chơi như vậy nữa! Công việc của bạn là viết một bot chơi nó, để giành chiến thắng, theo phong cách !

https://en.wikipedia.org/wiki/Kick_the_can

Có một số khác biệt chính trong trò chơi này. Sự khác biệt quan trọng đầu tiên là trò chơi là nhiều người chơi (5v5). Sự khác biệt quan trọng thứ hai là cả hai bộ bot có thể tiêu diệt và loại bỏ người chơi của kẻ thù bằng cả mìn và bom ném! Bots không thể nhìn thấy bất kỳ mỏ nào (bất kể khoảng cách) hoặc người chơi ở cách xa hơn năm khối!

Bản đồ là một mê cung như sau.

mê cung

Mê cung này được tạo theo thủ tục bằng cách trước tiên tạo ra một mê cung bằng thuật toán quay lui đệ quy sâu đầu tiên. Và sau đó đặt các lỗ được hiển thị vào (cũng như làm cho mê cung trở nên "không hoàn hảo" hơn. Mê cung rộng 65x65 khối và không có chỉ số. Do đó, cờ xanh (có thể) ở mức 1,1 và cờ đỏ (có thể) là ở 63,63. Đội màu xanh sinh sản ở 2,2 và 3,3 4,4, v.v ... đội đỏ sinh ra ở 62,62 và 61,61, 60,60, v.v ... Các khối màu lục lam là bot trong đội màu xanh và Các khối trong màu đỏ tươi là các bot màu đỏ. Trò chơi luôn có năm so với năm. Mỗi bot trong nhóm sẽ sử dụng mã của bạn (nhưng có thể lưu trữ các biến thể hiện khác (hoặc tạo tệp cục bộ) để theo dõi trạng thái và phân biệt vai trò.


Trò chơi

Mỏ có thể được đặt như bạn có thể nhìn thấy trong màu xám. Và bom có ​​thể được ném một khoảng cách tối đa lên tới bốn khối. Những người này di chuyển tới bốn khối xuyên tường và những người chơi khác chỉ giết những kẻ thù cản đường bạn. Sau mỗi bước, họ có 40% cơ hội rơi xuống. Vì vậy, họ có 100% cơ hội 1 phạm vi 60% ở 2 phạm vi 36% ở 3 phạm vi và 21,6% ở ba phạm vi Đặt một quả mìn hoặc ném bom mất một viên đạn. Điều này bắt đầu từ 0 và có thể tăng lên bằng cách thu thập các hộp màu cam. Lưu ý rằng bốn (4) bộ đệm đạn này sẽ được tập trung thuận tiện. Các Bots được xếp thành một mảng gồm hai màu đỏ và hai màu xanh. RRRRRBBBBB IE. Giành cờ được cho phép, nhưng hãy cẩn thận khi ở gần cờ (tức là ít hơn năm khối) dẫn đến chậm, và chỉ cho phép di chuyển. cứ ba lượt. Đấu trường chọn một khởi đầu ngẫu nhiên cho mỗi lượt. TÔI.

Mục tiêu

Lập trình năm bot của bạn (mỗi bot có cùng một tệp lớp) để điều hướng thành công mê cung và chạm vào hộp đối thủ trong khi cẩn thận không vô tình đánh bật lon của chính chúng, hoặc bước lên mỏ.

Lập trình

Các mục đấu trường và bot hiện đang có trong Java tuy nhiên trình bao bọc stdin / out tồn tại cho các ngôn ngữ khác.

Mã đấu trường sẽ được cung cấp nhưng đây là chi tiết có liên quan.

Lớp học Bot

public class YourUniqueBotName extends Bot{
public YourUniqueBotName(int x , int y, int team){
super(x,y,team);
//optional code
}
public Move move(){//todo implement this method 
//it should output  a Move();
//A move has two paramaters
//direction is from 0 - 3 as such
//         3
//       2-I-0
//         1
// a direction of 4 or higher means a no-op (i.e stay still)
//And a MoveType. This movetype can be    
//MoveType.Throw
//MoveType.Mine
//MoveType.Defuse defuse any mine present in the direction given
//MoveType.Move
}
}

Phương pháp chính có sẵn

Lưu ý rằng việc sử dụng bất kỳ kỹ thuật nào để sửa đổi hoặc truy cập dữ liệu mà bạn thường không có quyền truy cập là không được phép và sẽ dẫn đến việc không đủ tiêu chuẩn.

Arena.getAmmo()[team];//returns the shared ammo cache of your team

Arena.getMap();//returns an integer[] representing the map. Be careful since all enemies more than 5 blocks away (straight line distance) and all mines are replaced with constant for spaces
//constants for each block type are provided such as Bot.space Bot.wall Bot.mine Bot.redTeam Bot.blueTeam Bot.redFlag Bot.blueFlag

Arena.getAliveBots();//returns the number of bots left

getX();//returns a zero indexed x coordinate you may directly look at (but not change X)

getY();//returns a zero indexed y coordinate (y would work to, but do not change y's value)

//Although some state variables are public please do not cheat by accessing modifying these

Đặc tả giao diện của trình bao bọc StdIn / Out

Giao diện bao gồm hai chế độ: khởi tạo và chạy.

Trong chế độ khởi tạo, một khung INIT duy nhất được gửi qua thiết bị xuất chuẩn. Thông số kỹ thuật của khung này như sau:

INIT
{Team Membership Id}
{Game Map}
TINI

Trong đó: {Id thành viên nhóm} là một ký tự đơn: R hoặc B. B có nghĩa là đội màu xanh, R có nghĩa là đội màu đỏ.

{Bản đồ trò chơi} là một chuỗi các hàng ký tự ascii đại diện cho một hàng của bản đồ. Các ký tự ascii sau đây là hợp lệ: F = cờ xanh G = cờ đỏ O = không gian mở W = tường

Sau đó, trò chơi sẽ tiến hành gửi các khung trò chơi qua thiết bị xuất chuẩn đến từng bot như sau:

FRAME
{Ammo}
{Alive Bot Count}
{Bot X},{Bot Y}
{Local Map}
EMARF

Ở đâu:

{Ammo} là một chuỗi các chữ số, giá trị sẽ là 0 hoặc lớn hơn {Alive Bot Count} là một chuỗi các chữ số, giá trị sẽ là 0 hoặc lớn hơn {Box X} là một chuỗi các chữ số đại diện cho tọa độ X của bot trên bản đồ trò chơi. Giá trị sẽ là 0 <= X <Chiều rộng bản đồ. {Box Y} là một chuỗi các chữ số đại diện cho tọa độ Y của bot trên bản đồ trò chơi. Giá trị sẽ là 0 <= Y <Chiều cao bản đồ. {Bản đồ địa phương} là một chuỗi các hàng ký tự ascii đại diện cho toàn bộ bản đồ xung quanh bot. Các ký tự ascii sau đây là hợp lệ: F = cờ xanh G = cờ đỏ O = không gian mở W = wall R = đội đỏ bot B = đội xanh bot M = mine A = ammo

Bộ điều khiển hy vọng rằng bot của bạn sau đó sẽ xuất ra (để xuất chuẩn) một phản hồi dòng đơn theo định dạng:

{Action},{Direction}

Ở đâu:

{Action} là một trong những: Di chuyển Defuse Mine Ném

{Direction} là một chữ số duy nhất trong khoảng từ 0 đến 4. (xem thông tin hướng dẫn trước đó)

LƯU Ý: tất cả các chuỗi sẽ được phân cách bằng ký tự \ n Cuối dòng.

Đây sẽ là một giải đấu loại bỏ. Các bot mẫu của tôi sẽ tham gia dưới dạng chất độn, nhưng tôi sẽ không tự thưởng cho mình chiến thắng. Trong trường hợp chiến thắng của một trong những bot của tôi, tiêu đề sẽ thuộc về thành viên vị trí thứ hai và sẽ tiếp tục cho đến khi có một bot không phải là một trong những bot của tôi. Mỗi trận đấu bao gồm 11 vòng đá. Nếu cả hai đội đều không thắng được một trận nào thì cả hai đều bị loại. Nếu có một tỷ số hòa không bằng 0, một trận đấu ngắt kết nối sẽ được chơi. Nếu một cà vạt vẫn còn cả hai được loại bỏ. Các vòng đấu sau có thể bao gồm nhiều trận đấu hơn. Việc gieo hạt của giải đấu sẽ dựa trên số lượng upvote kể từ ngày 31/7/16 (ngày có thể thay đổi).

Mỗi trận đấu kéo dài 4096 lượt. Một chiến thắng cho một điểm. Một tie hoặc mất cho điểm không. Chúc may mắn!

Hãy xem mã hoặc phê bình nó tại GitHub Repo này.

https://github.com/rjhunjhunwala/BotCTF/blob/master/src/botctf/Arena.java


Lưu ý rằng tôi không có trình thông dịch cho quá nhiều ngôn ngữ trên máy tính của mình và tôi có thể cần tình nguyện viên để chạy mô phỏng trên máy tính của họ. Hoặc tôi có thể tải về trình thông dịch ngôn ngữ. Hãy đảm bảo rằng bot của bạn.

  • Trả lời trong một khoảng thời gian hợp lý (giả sử 250 ms)
  • Sẽ không làm hỏng máy chủ của tôi

@Moogie Tôi đã quyết định phát hành này
Rohan Jhunjhunwala

Trong bản đồ địa phương, nó hiển thị những gì cho gạch ngoài tầm nhìn của các bot?
cần

Nó cho thấy bản đồ. Điều duy nhất là bạn không thể nhìn thấy các bot ở khoảng cách lớn hơn. Các bot của bạn được cung cấp một bản đồ thực tế của đấu trường, nhưng chúng có thể không ở nơi có những đối thủ lén lút đang ẩn nấp. @justhalf
Rohan Jhunjhunwala

@Moogie, tôi đã tự hỏi nếu bạn có thể viết bot python cho tôi để tôi có thể kiểm tra trình bao bọc stdin / stdout
Rohan Jhunjhunwala

Vì vậy, bản đồ ngoài tầm nhìn của bot sẽ chỉ hiển thị dưới dạng không gian trống, phải không?
ngay

Câu trả lời:


4

NavPointBot, Java 8

nhập mô tả hình ảnh ở đây Bot có màu trắng / xanh

Bot này chỉ định một nhà lãnh đạo từ các bot thân thiện mỗi khung hình sau đó sẽ gán các điểm điều hướng cho mỗi bot để điều hướng đến.

Ban đầu, tất cả các bot đang ở trong kho tìm kiếm nhiệm vụ, sau đó hai bot được chỉ định làm lính canh với phần còn lại tìm kiếm đạn và sau đó tấn công cờ của kẻ thù.

Tôi đã thấy rằng trò chơi rất phụ thuộc vào vị trí bắt đầu của kho. Vì vậy, tôi không thể thực sự nói rằng bot này tốt hơn bất kỳ bot nào khác.

Chạy với java NavPointBot

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

public final class NavPointBot implements Serializable 
{
    private static final int[][] offsets = new int[][]{{-1,0},{0,-1},{1,0},{0,1}};
    private static final List<int[]> navPointsBlue = Arrays.asList(new int[][]{{1,2},{2,1}});
    private static final List<int[]> navPointsRed = Arrays.asList(new int[][]{{63,62},{62,63}});
    transient private static int mapWidth=0;
    transient private static int mapHeight=0;
    transient private char[][] map;
    transient private char team;
    transient private int ammo;
    transient private int botsAlive;
    transient private int enemyFlagX;
    transient private int enemyFlagY;
    private int frameCount;
    private int botX;
    private int botY;
    private String id;
    private int navPointX;
    private int navPointY;

    transient static Object synchObject = new Object(); // used for file read/write synchronisation if multiple instances are run in the same VM

    final static class Data implements Serializable
    {
        int frameCount;
        boolean[][] diffusedMap = new boolean[mapWidth][mapHeight];
        Map<String,NavPointBot> teamMembers = new HashMap<>();
    }

    interface DistanceWeigher
    {
        double applyWeight(NavPointBot p1Bot, PathSegment p1);
    }

    static class PathSegment
    {
        public PathSegment(int tileX, int tileY, int fscore, int gscore, PathSegment parent, int direction, int targetX, int targetY)
        {
            super();
            this.tileX = tileX;
            this.tileY = tileY;
            this.fscore = fscore;
            this.gscore = gscore;
            this.parent = parent;
            this.direction = direction;
            this.targetX = targetX;
            this.targetY = targetY;
        }
        public PathSegment(PathSegment parent)
        {
            this.parent = parent;
            this.targetX = parent.targetX;
            this.targetY = parent.targetY;
        }
        int tileX;
        int tileY;
        int fscore;
        int gscore;
        int direction;
        PathSegment parent; 
        int targetX;
        int targetY;
    }

    public static void main(String[] args) throws Exception
    {
        new NavPointBot(UUID.randomUUID().toString());
    }

    private NavPointBot(String id) throws Exception
    {
        this.id = id;
        System.err.println("NavPointBot ("+id+") STARTED");

        Data data;
        while(true)
        {
            String line=readLine(System.in);

            // decode initial frame
            if ("INIT".equals(line))
            {
                // read team membership
                team = readLine(System.in).charAt(0);

                // get the map
                line = readLine(System.in);

                List<char[]> mapLines = new ArrayList<>();
                while(!"TINI".equals(line))
                {
                    mapLines.add(line.toCharArray());
                    line = readLine(System.in);
                }
                map = mapLines.toArray(new char[][]{});
                mapHeight = map.length;
                mapWidth = map[0].length;

                out:
                for (int y = 0; y<mapHeight;y++)
                {
                    for (int x=0; x<mapWidth;x++)
                    {
                        if (map[y][x]==(team=='B'?'G':'F'))
                        {
                            enemyFlagX = x;
                            enemyFlagY = y;
                            break out;
                        }
                    }
                }
                data = readSharedData();
                data.diffusedMap=new boolean[mapWidth][mapHeight];
                writeSharedData(data);

            }
            else
            {
                System.err.println("Unknown command received: "+line);
                return;
            }

            line = readLine(System.in);
            while (true)
            {
                // decode frame
                if ("FRAME".equals(line))
                {
                    frameCount = Integer.parseInt(readLine(System.in));
                    ammo = Integer.parseInt(readLine(System.in));
                    botsAlive = Integer.parseInt(readLine(System.in));
                    line = readLine(System.in);
                    String[] splits = line.split(",");
                    botX = Integer.parseInt(splits[0]);
                    botY = Integer.parseInt(splits[1]);

                    // get the map
                    line = readLine(System.in);

                    int row=0;
                    while(!"EMARF".equals(line))
                    {
                        map[row++] = line.toCharArray();
                        line = readLine(System.in);
                    }
                }
                else
                {
                    System.err.println("Unknown command received: "+line);
                    return;
                }


                data = readSharedData();

                // this bot is nomitated to be the leader for this frame
                if (data.frameCount<frameCount || (frameCount==0 && data.frameCount > 3))
                {
                    data.frameCount=frameCount;

                    List<NavPointBot> unassignedBots = new ArrayList<>(data.teamMembers.values());

                    // default nav points to be enemy flag location.
                    unassignedBots.forEach(t->{t.navPointY=enemyFlagY;t.navPointX=enemyFlagX;});

                    // after 700 frames assume dead lock so just storm the flag, otherwise...
                    if (frameCount<700)
                    {
                        // if the after the initial rush then we will assign guard(s) while we have enemies
                        if (frameCount>70 && botsAlive > data.teamMembers.size())
                        {
                            Map<NavPointBot, PathSegment> navPointDistances = assignBotShortestPaths(unassignedBots,team=='B'?navPointsBlue:navPointsRed,true, new DistanceWeigher() {

                                @Override
                                public double applyWeight( NavPointBot owner ,PathSegment target) {
                                    return target.gscore;
                                }
                            });
                            navPointDistances.keySet().forEach(s->{s.navPointX=navPointDistances.get(s).targetX;s.navPointY=navPointDistances.get(s).targetY;});
                        }


                        // the remaining bots will go to ammo depots with a preference to the middle ammo depots
                        List<int[]> ammoDepots = new ArrayList<>();
                        for (int y = 0; y<mapHeight;y++)
                        {
                            for (int x=0; x<mapWidth;x++)
                            {
                                if (map[y][x]=='A')
                                {
                                    ammoDepots.add(new int[]{x,y});
                                }
                            }
                        }

                        System.err.println("ammoDepots: "+ammoDepots.size());
                        if (ammoDepots.size()>0)
                        {
                            Map<NavPointBot, PathSegment> ammoDistances = assignBotShortestPaths(unassignedBots,ammoDepots,true, new DistanceWeigher() {

                                @Override
                                public double applyWeight( NavPointBot owner ,PathSegment target) {
                                    return target.gscore + (Math.abs(target.targetX-mapWidth/2)+Math.abs(target.targetY-mapHeight/2)*10);
                                }
                            });


                            // assign ammo depot nav points to closest bots
                            ammoDistances.keySet().forEach(s->{s.navPointX=ammoDistances.get(s).targetX;s.navPointY=ammoDistances.get(s).targetY;});
                        }
                    }

                    System.err.println("FRAME: "+frameCount+" SET");
                    data.teamMembers.values().forEach(bot->System.err.println(bot.id+" nav point ("+bot.navPointX+","+bot.navPointY+")"));
                    System.err.println();
                }


                // check to see if enemies are in range, if so attack the closest
                List<int[]> enemies = new ArrayList<>();
                for (int y = 0; y<mapHeight;y++)
                {
                    for (int x=0; x<mapWidth;x++)
                    {
                        if (map[y][x]==(team=='B'?'R':'B'))
                        {
                            int attackDir = -1;
                            int distance = -1;
                            if (x==botX && Math.abs(y-botY) < 4) { distance =  Math.abs(y-botY); attackDir = botY-y<0?1:3;}
                            if (y==botY && Math.abs(x-botX) < 4) { distance =  Math.abs(x-botX); attackDir = botX-x<0?0:2;}
                            if (attackDir>-1)
                            {
                                enemies.add(new int[]{x,y,distance,attackDir});
                            }
                        }
                    }
                }

                enemies.sort(new Comparator<int[]>() {

                    @Override
                    public int compare(int[] arg0, int[] arg1) {
                        return arg0[2]-arg1[2];
                    }
                });

                String action;

                // attack enemy if one within range...
                if (enemies.size()>0)
                {
                    action = "Throw,"+enemies.get(0)[3];
                }
                else
                {
                    // set action to move to navpoint
                    PathSegment pathSegment = pathFind(botX,botY,navPointX,navPointY,map,true);
                    action = "Move,"+pathSegment.direction;

                    // clear mines if within 5 spaces of enemy flag

                    if ((team=='B' && botX>=mapWidth-5 && botY>=mapHeight-5 ) ||
                        (team=='R' && botX<5 && botY<5 ))
                    {
                        if (!data.diffusedMap[pathSegment.parent.tileX][pathSegment.parent.tileY])
                        {
                            action = "Defuse,"+pathSegment.direction;
                            data.diffusedMap[pathSegment.parent.tileX][pathSegment.parent.tileY]=true;
                        }
                    }

                }

                writeSharedData(data);
                System.out.println(action);
                line = readLine(System.in);
            }
        }
    }

    /**
     * assigns bots to paths to the given points based on distance to the points with weights adjusted by the given weigher implementation 
     */
    private Map<NavPointBot, PathSegment> assignBotShortestPaths(List<NavPointBot> bots, List<int[]> points, boolean exact, DistanceWeigher weigher) {

        Map<Integer,List<PathSegment>> pathMap = new HashMap<>();
        final Map<PathSegment,NavPointBot> pathOwnerMap = new HashMap<>();

        for (NavPointBot bot : bots)
        {
            for(int[] navPoint: points)
            {
                List<PathSegment> navPointPaths = pathMap.get((navPoint[0]<<8)+navPoint[1]);
                if (navPointPaths == null)
                {
                    navPointPaths = new ArrayList<>();
                    pathMap.put((navPoint[0]<<8)+navPoint[1],navPointPaths);
                }
                PathSegment path = pathFind(bot.botX,bot.botY,navPoint[0],navPoint[1],map,exact);
                pathOwnerMap.put(path, bot);
                navPointPaths.add(path);
            }
        }


        // assign bot nav point based on shortest distance
        Map<NavPointBot, PathSegment> results = new HashMap<>();
        for (int[] navPoint: points )
        {
            List<PathSegment> navPointPaths = pathMap.get((navPoint[0]<<8)+navPoint[1]);

            if (navPointPaths !=null)
            {
                Collections.sort(navPointPaths, new Comparator<PathSegment>() {

                    @Override
                    public int compare(PathSegment p1, PathSegment p2) {

                        NavPointBot p1Bot = pathOwnerMap.get(p1);
                        NavPointBot p2Bot = pathOwnerMap.get(p2);
                        double val = weigher.applyWeight(p1Bot, p1) - weigher.applyWeight(p2Bot, p2);
                        if (val == 0)
                        {

                            return p1Bot.id.compareTo(p2Bot.id);
                        }
                        return val<0?-1:1;
                    }
                });

                for (PathSegment shortestPath : navPointPaths)
                {
                    NavPointBot bot = pathOwnerMap.get(shortestPath);

                    if (!results.containsKey(bot) )
                    {
                        results.put(bot,shortestPath);
                        bots.remove(bot);
                        break;
                    }
                }
            }
        }
        return results;
    }

    /**
     * reads in the previous bot's view of teammates aka shared data
     */
    private Data readSharedData() throws Exception
    {
        synchronized(synchObject)
        {
            File dataFile = new File(this.getClass().getName()+"_"+team);

            Data data;
            if (dataFile.exists())
            {
                FileInputStream in = new FileInputStream(dataFile);
                try {
                    java.nio.channels.FileLock lock = in.getChannel().lock(0L, Long.MAX_VALUE, true);
                    try {
                        ObjectInputStream ois = new ObjectInputStream(in);
                        data = (Data) ois.readObject();
                    } catch(Exception e)
                    {
                        System.err.println(id+": CORRUPT shared Data... re-initialising");
                        data = new Data();
                    }
                    finally {
                        lock.release();
                    }
                } finally {
                    in.close();
                }
            }
            else
            {
                System.err.println(id+": No shared shared Data exists... initialising");
                data = new Data();
            }

            //purge any dead teammates...
            for (NavPointBot bot : new ArrayList<>(data.teamMembers.values()))
            {
                if (bot.frameCount < frameCount-3 || bot.frameCount > frameCount+3)
                {
                    data.teamMembers.remove(bot.id);
                }
            }

            // update our local goals to reflect those in the shared data
            NavPointBot dataBot = data.teamMembers.get(id);
            if (dataBot !=null)
            {
                this.navPointX=dataBot.navPointX;
                this.navPointY=dataBot.navPointY;
            }

            // ensure that we are a team member
            data.teamMembers.put(id, this);

            return data;
        }
    }

    private void writeSharedData(Data data) throws Exception
    {
        synchronized(synchObject)
        {
            File dataFile = new File(this.getClass().getName()+"_"+team);
            FileOutputStream out = new FileOutputStream(dataFile);

            try {
                java.nio.channels.FileLock lock = out.getChannel().lock(0L, Long.MAX_VALUE, false);
                try {
                    ObjectOutputStream oos = new ObjectOutputStream(out);
                    oos.writeObject(data);
                    oos.flush();
                } finally {
                    lock.release();
                }
            } finally {
                out.close();
            }
        }
    }

    /**
     * return the direction to move to travel for the shortest route to the desired target location
     */
    private PathSegment pathFind(int startX, int startY, int targetX,int targetY,char[][] map,boolean exact)
    {
        // A*
        if (startX==targetX && startY==targetY)
        {
            return new PathSegment(targetX,targetY,0, 0,null,4,targetX,targetY);//PathSegment.DEFAULT;
        }
        else
        {
            int[][] tileIsClosed = new int[mapWidth][mapHeight];

            // find an open space in the general vicinity if exact match not required
            if (!exact)
            {
                out:
                for (int y=-1;y<=1;y++)
                {
                    for (int x=-1;x<=1;x++)
                    {
                        if (startX == targetX+x && startY==targetY+y)
                        {
                            return new PathSegment(targetX,targetY,0, 0,null,4,targetX,targetY);//PathSegment.DEFAULT;
                        }
                        else if (targetY+y>=0 && targetY+y<mapHeight && targetX+x>=0 && targetX+x < mapWidth && map[targetY+y][targetX+x]=='O')
                        {
                            targetX+=x;
                            targetY+=y;
                            break out;
                        }
                    }
                }
            }

            PathSegment curSegment = new PathSegment(targetX,targetY,1,1,null,4,targetX,targetY);
            PathSegment newSegment;
            Set<PathSegment> openList = new HashSet<PathSegment>();
            openList.add(curSegment);

            do
            {
                if (openList.isEmpty())
                {
                    break;
                }
              PathSegment currentBestScoringSegment = openList.iterator().next();
              //  Look for the lowest F cost square on the open list
              for (PathSegment segment : openList)
              {
                if (segment.fscore<currentBestScoringSegment.fscore)
                {
                  currentBestScoringSegment = segment;
                }
              }
              curSegment = currentBestScoringSegment;

              // found path
              if (startX==curSegment.tileX && startY==curSegment.tileY)
              {
                break;
              }

              // if not in closed list
              if (tileIsClosed[curSegment.tileX][curSegment.tileY]==0)
              {
                    // Switch it to the closed list.
                    tileIsClosed[curSegment.tileX][curSegment.tileY]=1;
                    // remove from openlist
                    openList.remove(curSegment);


                    // add neigbours to the open list if necessary
                    for (int i=0;i<4;i++)
                    {

                        int surroundingCurrentTileX=curSegment.tileX+offsets[i][0];
                        int surroundingCurrentTileY=curSegment.tileY+offsets[i][1];
                        if (surroundingCurrentTileX>=0 && surroundingCurrentTileX<mapWidth &&
                            surroundingCurrentTileY>=0 && surroundingCurrentTileY<mapHeight )
                        {
                            newSegment = new PathSegment( curSegment);
                            newSegment.tileX = surroundingCurrentTileX;
                            newSegment.tileY = surroundingCurrentTileY;
                            newSegment.direction = i;

                            switch(map[surroundingCurrentTileY][surroundingCurrentTileX])
                            {
                                case 'W':
                                case 'F':
                                case 'G':
                                    continue;
                            }

                          int surroundingCurrentGscore=curSegment.gscore+1 + ((surroundingCurrentTileX!=startX && surroundingCurrentTileY!=startY && map[surroundingCurrentTileY][surroundingCurrentTileX]==team)?20:0);//+map[surroundingCurrentTileY][surroundingCurrentTileX]!='O'?100:0;
                          newSegment.gscore=surroundingCurrentGscore;
                          newSegment.fscore=surroundingCurrentGscore+Math.abs( surroundingCurrentTileX-startX)+Math.abs( surroundingCurrentTileY-startY);
                          openList.add(newSegment);
                        }
                    }
              }
              else
              {
                  // remove from openlist
                  openList.remove(curSegment);    
              }
            } while(true);

            return curSegment;
        }
     }

    /**
     * Reads a line of text from the input stream. Blocks until a new line character is read.
     * NOTE: This method should be used in favor of BufferedReader.readLine(...) as BufferedReader buffers data before performing
     * text line tokenization. This means that BufferedReader.readLine() will block until many game frames have been received. 
     * @param in a InputStream, nominally System.in
     * @return a line of text or null if end of stream.
     * @throws IOException
     */
    private static String readLine(InputStream in) throws IOException
    {
       StringBuilder sb = new StringBuilder();
       int readByte = in.read();
       while (readByte>-1 && readByte!= '\n')
       {
          sb.append((char) readByte);
          readByte = in.read();
       }
       return readByte==-1?null:sb.toString();

    }

}

Hoạt hình đẹp, chỉ vì tò mò tỷ lệ thắng gần đúng của bot của tôi là bao nhiêu?
Rohan Jhunjhunwala

Tôi chưa thực hiện bất kỳ số liệu thống kê thực tế nào nhưng tôi sẽ nguy hiểm 60% bot của tôi so với 40% bot của bạn? nhưng thực sự phụ thuộc vào vị trí của đạn
Moogie

Ok, gg về chiến thắng!
Rohan Jhunjhunwala

Tôi nên có nhiều đạn hơn, hay tôi nên cấu hình đạn để sinh sản như nhau?
Rohan Jhunjhunwala

@RohanJhunjhunwala tôi nghĩ đó là những gì nó đã quá muộn để thay đổi hành vi bây giờ. Sử dụng nó như một kinh nghiệm học tập cho câu hỏi tiếp theo được hỏi :)
Moogie

1

Tối ưu hóa Pathfinder JAVA

Cảm ơn @Moogie đã giúp tôi tối ưu hóa việc tìm đường ngập lụt lộn xộn của mình. Đây là nguồn cho bot. Anh chàng này biết tầm quan trọng của việc bảo vệ lá cờ của mình. Anh ta sắp xếp ba người bảo vệ và hai kẻ tấn công. Những người bảo vệ treo lại và bảo vệ / thu thập đạn, hai kẻ tấn công đi (một đường khá thẳng) đến cờ (và thu thập đạn ở giữa). Anh ta bắn bất cứ ai anh ta nhìn thấy, và nên cạnh tranh khốc liệt. Những người bảo vệ đặt mìn xung quanh cờ và cắm trại cho đến khi không còn phe đối lập để họ có thể đi và đá cái lon.

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 * todo fight
 */
package botctf;

import botctf.Move.MoveType;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

/**
 *
 * @author rohan
 */
public class PathFinderOptimised extends Bot {
    private static final int[][] offsets = new int[][]{{0,-1},{1,0},{0,1},{-1,0}};
    public static boolean shouldCampingTroll = true;
    private int moveCounter = -1;//dont ask
    public boolean defend;

    public PathFinderOptimised(int inX, int inY, int inTeam) {

        super(inX, inY, inTeam);
        //System.out.println("Start");
        //floodFillMap(getX(), getY());
        //System.out.println("Finish");
        defend=inX%2==0;
    }
    public static int[][] navigationMap;

    boolean upMine = false;
    boolean sideMine = false;

        int[][] myMap;

    @Override
    public Move move() {
                moveCounter++;
        myMap=getMap();
        int targetX, targetY;
        int enemyTeam=team==redTeam?blueTeam:redTeam;
        ArrayList<Coord> enemyCoordinates=new ArrayList<>();
        for(int i = 0; i<65;i++){
            for(int j = 0;j<65;j++){
                if(map[i][j]==enemyTeam){
                    enemyCoordinates.add(new Coord(i,j));
                }
            }
        }
        for(Coord enemy:enemyCoordinates){
            int enemyX=enemy.x;
            int enemyY=enemy.y;
         int dX= enemy.x-this.x;
            int dY= enemy.y-this.y;
            //System.out.println(dX+"|"+dY);
            if((dX==0||dY==0)){

                if(Arena.getAmmo()[this.team]>0){

                    if(dX>0&&dX<5){
                    return new Move(0,MoveType.Throw);
                }
                if(dX<0&&dX>-5){
                    return new Move(2,MoveType.Throw);
                }
                if (dY>0&&dY<5){
                    return new Move(1, MoveType.Throw);
                }
                if(dY<0&&dY>-5){
                    return new Move(3,MoveType.Throw);
                }
            }
        }
        }
        if(myMap[x+1][y]==ammo){
            return new Move(0,MoveType.Move);
        }
                if(myMap[x-1][y]==ammo){
            return new Move(2,MoveType.Move);
        }
                                if(myMap[x][y+1]==ammo){
            return new Move(1,MoveType.Move);
        }
                                                                if(myMap[x][y-1]==ammo){
            return new Move(3,MoveType.Move);
        }


int bestOption = 4;                                                             
        if (defend) {
if(Arena.getAliveBots()==1){
    defend=false;
}
            int bestAmmoX = -1;
            int bestAmmoY = -1;
            int bestAmmoDist = Integer.MAX_VALUE;
            for (int i = 0; i < 65; i++) {
                for (int j = 0; j < 65; j++) {
                    if (myMap[i][j] == ammo) {
                        int path = pathFind(getX(),getY(),i,j,myMap);
                        if ((path & 0xFFFFFF) < bestAmmoDist) {
                            bestAmmoX = i;
                            bestAmmoY = j;
                            bestAmmoDist = (path & 0xFFFFFF);
                            bestOption = path >> 24;
                        }
                    }
                }
            }
            if (bestAmmoDist<15||Arena.getAmmo()[this.team]==0){
                targetX = bestAmmoX;
                targetY = bestAmmoY;
            } else {
                targetX = team == redTeam ? 62 : 2;
                targetY = team == redTeam ? 62 : 2;
            }
        } else {

            if(this.x>18&this.x<42&&this.y>16&&this.y<44&&myMap[33][33]==ammo){
                targetX=33;
                targetY=33;
            }else{
            if (this.team == redTeam) {
                targetX = 1;
                targetY = 1;
            } else {
                targetX = 63;
                targetY = 63;
            }
            }
        }
        if(upMine&&sideMine){
            if(targetX==2||targetX==62){
                if(targetY==2||targetY==62){
                    targetX+=targetX==2?3:-3;
                    targetY+=targetY==2?3:-3;
                }
            }
        }else if (targetX == getX() && targetY == getY()) {
            if (!upMine) {
                upMine = true;
                if (this.team == redTeam) {
                    return new Move(0, MoveType.Mine);
                } else {
                    return new Move(2, MoveType.Mine);
                }
            }else if(!sideMine){
                sideMine=true;      
                if (this.team == redTeam) {
                    return new Move(1, MoveType.Mine);
                } else {
                    return new Move(3, MoveType.Mine);
                }
            }   else {
                return new Move(5, MoveType.Move);
            }
        }

        bestOption = pathFind(getX(),getY(),targetX,targetY,myMap) >> 24;


MoveType m=MoveType.Move;
if(moveCounter%2==0){
    if(this.team==redTeam?x<25&&y<25:x>39&&y>39){
        m=MoveType.Defuse;
    }
}
//System.out.println(bestOption);
        return new Move(bestOption, m);
    }

    /**
     * returns a result that is the combination of movement direction and length of a path found from the given start position to the target
     * position. result is ((direction) << 24 + path_length)
     */
    private int pathFind(int startX, int startY, int targetX,int targetY,int[][] map)
    {
        class PathSegment
        {
            public PathSegment(int tileX, int tileY, int fscore, int gscore, PathSegment parent)
            {
                super();
                this.tileX = tileX;
                this.tileY = tileY;
                this.fscore = fscore;
                this.gscore = gscore;
                this.parent = parent;
            }
            public PathSegment(PathSegment parent)
            {
                this.parent = parent;
            }
            int tileX;
            int tileY;
            int fscore;
            int gscore;
            PathSegment parent; 
        }
        // A*
        if (startX==targetX && startY==targetY)
        {
            return 4;
        }
        else
        {
            int[][] tileIsClosed = new int[64][64];

            PathSegment curSegment = new PathSegment(targetX,targetY,1,1,null);
            PathSegment newSegment;
            Set<PathSegment> openList = new HashSet<PathSegment>();
            openList.add(curSegment);

            do
            {
                if (openList.isEmpty())
                {
                    break;
                }
              PathSegment currentBestScoringSegment = openList.iterator().next();
              //  Look for the lowest F cost square on the open list
              for (PathSegment segment : openList)
              {
                if (segment.fscore<currentBestScoringSegment.fscore)
                {
                  currentBestScoringSegment = segment;
                }
              }
              curSegment = currentBestScoringSegment;

              // found path
              if (startX==curSegment.tileX && startY==curSegment.tileY)
              {
                break;
              }

              // if not in closed list
              if (tileIsClosed[curSegment.tileX][curSegment.tileY]==0)
              {
                    // Switch it to the closed list.
                    tileIsClosed[curSegment.tileX][curSegment.tileY]=1;
                    // remove from openlist
                    openList.remove(curSegment);


                    // add neigbours to the open list if necessary
                    for (int i=0;i<4;i++)
                    {
                        final int surroundingCurrentTileX=curSegment.tileX+offsets[i][0];
                        final int surroundingCurrentTileY=curSegment.tileY+offsets[i][1];
                        if (surroundingCurrentTileX>=0 && surroundingCurrentTileX<64 &&
                            surroundingCurrentTileY>=0 && surroundingCurrentTileY<64 )
                        {
                            newSegment = new PathSegment( curSegment);
                            newSegment.tileX = surroundingCurrentTileX;
                            newSegment.tileY = surroundingCurrentTileY;

                          if (map[surroundingCurrentTileX][surroundingCurrentTileY]=='W')
                          {
                              continue;
                          }

                          int surroundingCurrentGscore=curSegment.gscore+1;
                          newSegment.gscore=surroundingCurrentGscore;
                          newSegment.fscore=surroundingCurrentGscore+Math.abs( surroundingCurrentTileX-startX)+Math.abs( surroundingCurrentTileY-startY);
                          openList.add(newSegment);
                        }
                    }
              }
              else
              {
                  // remove from openlist
                  openList.remove(curSegment);    
              }
            } while(true);

            if (curSegment.parent.tileX-startX<0) return (2 << 24) | curSegment.gscore;
            else if (curSegment.parent.tileX-startX>0) return (0 << 24) | curSegment.gscore;
            else if (curSegment.parent.tileY-startY<0) return (3 << 24) | curSegment.gscore;
            else if (curSegment.parent.tileY-startY>0) return (1 << 24) | curSegment.gscore;
        }
        throw new RuntimeException("Path finding failed");
     }
}
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.