ปกป้องความสามารถของคุณกับชีวิตของคุณ!


10

ให้เล่น Kick The Can!

แม้ว่า Moogie จะเป็นผู้ชนะในปัจจุบันหากใครก็ตามที่สามารถสวมมงกุฎได้เขาก็ควรที่จะทำเช่นนั้น

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

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

มีความแตกต่างที่สำคัญในเกมนี้ ความแตกต่างที่สำคัญอันดับแรกคือเกมนี้มีผู้เล่นหลายคน (5v5) ความแตกต่างที่สำคัญที่สองคือบอททั้งสองชุดสามารถฆ่าและกำจัดผู้เล่นศัตรูด้วยระเบิดและระเบิด! บอตไม่สามารถมองเห็นเหมืองใด ๆ (โดยไม่คำนึงถึงระยะทาง) หรือผู้เล่นที่อยู่ห่างออกไปเกินห้าช่วงตึก!

แผนที่เป็นเขาวงกตดังนี้

เขาวงกต

เขาวงกตนี้สร้างขึ้นตามขั้นตอนโดยการสร้างเขาวงกตเป็นครั้งแรกโดยใช้อัลกอริทึมย้อนรอยซ้ำแบบย้อนกลับ จากนั้นวางช่องที่แสดงใน (รวมทั้งทำให้เขาวงกต "ไม่สมบูรณ์" มากขึ้นเขาวงกตมีความกว้าง 65x65 บล็อกและมีการจัดทำดัชนีเป็นศูนย์ดังนั้นธงสีฟ้า (สามารถ) ได้ที่ 1,1 และธงแดง (สามารถ) คือ ที่ 63,63. ทีมสีน้ำเงินวางไข่ที่ 2,2 และ 3,3 4,4 เป็นต้นทีมสีแดงวางไข่ที่ 62,62 และ 61,61, 60,60 ฯลฯ บล็อคในสีฟ้าเป็นบอทของทีมสีน้ำเงินและ บล็อกใน magenta คือบอตสีแดงเกมนี้มักจะห้าต่อห้าบอทในทีมแต่ละคนจะใช้รหัสของคุณ (แต่อาจเก็บตัวแปรอินสแตนซ์อื่น ๆ (หรือสร้างไฟล์ในเครื่อง) เพื่อติดตามสถานะและแยกแยะบทบาท


เพลย์

สามารถวางทุ่นระเบิดได้ตามที่เห็นเป็นสีเทา และสามารถโยนระเบิดได้ในระยะทางสูงสุดถึงสี่ช่วงตึก การเดินทางเหล่านี้มีมากถึงสี่ช่วงตึกผ่านกำแพงและผู้เล่นคนอื่นฆ่าเฉพาะศัตรูที่ขวางทางคุณ หลังจากแต่ละขั้นตอนพวกเขามีโอกาส 40% ที่จะล้มลง ดังนั้นพวกเขาจึงมีโอกาส 100% ของ 1 ช่วง 60% ที่ 2 ช่วง 36% ที่ 3 ช่วงและ 21.6% ที่สามช่วงการวางระเบิดหรือการขว้างระเบิดต้องใช้กระสุนหนึ่งนัด สิ่งนี้เริ่มต้นที่ 0 และสามารถเพิ่มขึ้นได้โดยการรวบรวมกล่องสีส้ม โปรดทราบว่าสี่ (4) ของแคชของกระสุนเหล่านี้จะอยู่กึ่งกลางโดยสะดวก บอทนั้นเรียงกันเป็นแถวสองสีแดงและสีน้ำเงินสองอัน IE RRRRRBBBBB อนุญาตให้ Gaurding ตั้งค่าสถานะได้ แต่ระวังว่าการเข้าใกล้ธง (เช่นน้อยกว่าห้าช่วงตึก) จะทำให้เกิดความเชื่องช้าและอนุญาตให้มีการเคลื่อนไหวเท่านั้น ทุกสามรอบ Arena เลือกสตาร์ทเตอร์แบบสุ่มสำหรับแต่ละเทิร์น ผม.

วัตถุประสงค์

ตั้งโปรแกรมบอททั้งห้าของคุณ (แต่ละไฟล์มีไฟล์คลาสเดียวกัน) เพื่อนำทางเขาวงกตที่ประสบความสำเร็จและสัมผัสกับฝ่ายตรงข้ามในขณะที่ระมัดระวังไม่ให้เผลอทำกระป๋องของตัวเองโดยไม่ตั้งใจ

การเขียนโปรแกรม

ขณะนี้รายการ arena และ bot อยู่ใน Java แต่ยังมี wrapper stdin / out สำหรับภาษาอื่น ๆ

รหัสอารีจะมีให้ แต่นี่คือรายละเอียดที่เกี่ยวข้อง

ระดับบอท

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

วิธีการสำคัญที่มีอยู่

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

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

ข้อกำหนดอินเทอร์เฟซสำหรับห่อหุ้ม StdIn / Out

อินเตอร์เฟสประกอบด้วยสองโหมด: การเริ่มต้นและการทำงาน

ในระหว่างโหมดการเริ่มต้นเฟรม INIT เดียวจะถูกส่งผ่าน stdout สเปคของเฟรมนี้เป็นดังนี้:

INIT
{Team Membership Id}
{Game Map}
TINI

โดยที่: {ID สมาชิกภาพของทีม} เป็นอักขระเดียว: R หรือ B. B หมายถึงทีมสีน้ำเงิน, R หมายถึงทีมสีแดง

{Game Map} คือชุดของแถวของอักขระ ASCII ที่แสดงถึงหนึ่งแถวของแผนที่ อักขระ ascii ต่อไปนี้ถูกต้อง: F = ธงฟ้า G = ธงแดง O = พื้นที่เปิดโล่ง W = กำแพง

เกมดังกล่าวจะส่งเฟรมเกมไปยังแต่ละบอทดังนี้:

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

ที่ไหน:

{Ammo} เป็นสตริงของตัวเลขค่าจะเป็น 0 หรือมากกว่า {Alive Bot Count} คือสตริงของตัวเลขค่าจะเป็น 0 หรือมากกว่า {Box X} เป็นสตริงของตัวเลขที่แสดง X ที่ประสานกันของ bot บนแผนที่เกม ค่าจะเป็น 0 <= X <ความกว้างของแผนที่ {Box Y} คือสตริงตัวเลขที่แสดงถึงพิกัด Y ของบอตบนแผนที่เกม ค่าจะเป็น 0 <= Y <ความสูงของแผนที่ {Local Map} เป็นชุดของแถวของอักขระ ASCII ที่แสดงถึงแผนที่ทั้งหมดรอบ ๆ บอท อักขระ ascii ต่อไปนี้ถูกต้อง: F = ธงสีน้ำเงิน G = ธงแดง O = พื้นที่เปิดโล่ง W = ผนัง R = ทีมบ็อตสีแดง B = ทีมบ็อตทีมสีน้ำเงิน M = ระเบิด A = กระสุน

คอนโทรลเลอร์คาดว่าบอทของคุณจะส่งออก (ไปยัง stdout) การตอบสนองบรรทัดเดียวในรูปแบบ:

{Action},{Direction}

ที่ไหน:

{Action} เป็นหนึ่งในนั้น: ย้าย Defuse Mine Throw

{Direction} เป็นตัวเลขหนึ่งหลักระหว่าง 0 ถึง 4 (ดูข้อมูลทิศทางก่อนหน้า)

หมายเหตุ: สตริงทั้งหมดจะถูกคั่นด้วย \ n ตัวอักษร End of Line

นี่จะเป็นการกำจัดรายการแข่งขัน บอทตัวอย่างของฉันจะเข้าร่วมเป็นฟิลเลอร์ แต่ฉันจะไม่ให้รางวัลกับตัวเอง ในกรณีที่มีชัยชนะจากบอทของฉันชื่อนั้นจะถูกส่งไปยังสมาชิกที่สองและจะดำเนินต่อไปจนกว่าจะมีบอทที่ไม่ได้เป็นของฉัน แต่ละการแข่งขันประกอบด้วยการเตะกระป๋อง 11 รอบ หากไม่มีทีมใดชนะการแข่งขันครั้งเดียวพวกเขาทั้งคู่จะตกรอบ หากมีการเสมอกันของคะแนนที่ไม่เป็นศูนย์จะมีการแข่งขันแมทช์เบรคเกอร์คนเดียว หากเสมอกันจะถูกกำจัดออก รอบต่อมาอาจประกอบด้วยการแข่งขันที่มากขึ้น การเพาะของทัวร์นาเมนต์จะขึ้นอยู่กับจำนวนของ upvotes ณ 7/31/16 (วันที่อาจมีการเปลี่ยนแปลง)

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

อย่าลังเลที่จะดูรหัสหรือวิจารณ์ได้ที่ GitHub Repo นี้

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


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

  • ตอบสนองในเวลาที่เหมาะสม (พูดได้ 250 ms)
  • จะไม่เกิดความเสียหายกับเครื่องโฮสต์ของฉัน

@ Moogie ฉันได้ตัดสินใจที่จะปล่อยนี้
Rohan Jhunjhunwala

ในแผนที่ท้องถิ่นมันแสดงให้เห็นอะไรบ้างสำหรับกระเบื้องที่อยู่เหนือวิสัยทัศน์ของบอท
justhalf

มันแสดงให้เห็นแผนที่ สิ่งเดียวคือคุณไม่สามารถมองเห็นบอทในระยะไกล บอทของคุณจะได้รับแผนที่จริงของเวที แต่พวกเขาอาจไม่ซ่อนตัวฝ่ายตรงข้ามที่หลบซ่อนตัวอยู่ @justhalf
Rohan Jhunjhunwala

@Moogie ผมสงสัยว่าถ้าคุณสามารถเขียนบอหลามสำหรับฉันดังนั้นฉันสามารถทดสอบ stdin / stdout เสื้อคลุม
Rohan Jhunjhunwala

แผนที่ที่อยู่นอกเหนือการมองเห็นของบอทจะแสดงเป็นพื้นที่ว่างใช่ไหม?
justhalf

คำตอบ:


4

NavPointBot, Java 8

ป้อนคำอธิบายรูปภาพที่นี่ บอทเป็นสีขาว / น้ำเงิน

บอทนี้จะเสนอชื่อผู้นำจากบอทที่เป็นมิตรในแต่ละเฟรมซึ่งจะกำหนดแต้มนำทางสำหรับแต่ละบ็อตเพื่อนำทางไปยัง

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

ฉันพบว่าเกมนี้ขึ้นอยู่กับตำแหน่งเริ่มต้นของคลังเก็บ เช่นนี้ฉันไม่สามารถพูดได้ว่าบอทนี้ดีกว่าที่อื่น

ทำงานด้วย 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();

    }

}

แอนิเมชันที่สวยงามเพียงแค่อยากรู้ว่าเปอร์เซ็นต์การชนะโดยประมาณของบอทของฉันคือเท่าใด
Rohan Jhunjhunwala

ฉันไม่ได้ทำสถิติจริงใด ๆ แต่ฉันจะเสี่ยง 60% บอทของฉันและ 40% บอทของคุณ? แต่ขึ้นอยู่กับตำแหน่งของกระสุนจริงๆ
Moogie

ตกลงรับรางวัล!
Rohan Jhunjhunwala

ฉันควรมีกระสุนมากกว่านี้หรือฉันควรกำหนดกระสุนให้มีไข่เท่ากัน?
Rohan Jhunjhunwala

@RohanJhunjhunwala ฉันคิดว่ามันคือสิ่งที่มันสายเกินไปที่จะเปลี่ยนพฤติกรรมในขณะนี้ ใช้มันเป็นประสบการณ์การเรียนรู้สำหรับคำถามถัดไปถาม :)
Moogie

1

Pathfinder ที่ปรับให้เหมาะสม JAVA

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

/*
 * 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");
     }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.