Бережіть своє вміння своїм життям!


10

Давайте грати Kick The Can!

Хоча Moogie - теперішній переможець, якщо хтось може взяти його корону, їм рекомендується це зробити

Удар бляшанки - це дитяча гра. Залучення одного захисника та кількох нападників. Сьогодні це вже не така гра! Ваше завдання - написати бота, який грає в нього, щоб виграти, стиль!

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

У цій грі є деякі ключові відмінності. Перша ключова відмінність полягає в тому, що гра є багатокористувацькою (5v5). Друга ключова відмінність полягає в тому, що обидва набори ботів можуть вбивати та знищувати ворожих гравців з обох мін та кинутих бомб! Боти не можуть бачити жодної міни (незалежно від відстані) та гравців, розташованих на відстані понад п’ять блоків!

Карта - це лабіринт наступним чином.

Лабіринт

Цей лабіринт процедурно генерується спочатку створення лабіринту, використовуючи алгоритм зворотного відстеження першого глибини. А потім розміщуючи показані отвори (а також зробіть лабіринт більш "недосконалим". Лабіринт шириною блоків 65x65 та нульовим індексом. Таким чином, синій прапор (can) знаходиться на рівні 1,1, а червоний прапор (can) - в 63,63. Блакитна команда породжує в 2,2 і 3,3 4,4 і т.д. червона команда породжує в 62,62 і 61,61, 60,60 і т. д. Блоки в блакитному кольорі - боти на синій команді, і блоки в пурпуровий колір - це червоні боти. Гра завжди п'ять проти п'яти. Кожен бот команди використовує ваш код (але може зберігати інші змінні екземпляри (або створювати локальні файли) для відстеження стану та диференціації ролей.


Ігровий процес

Міни можна розмістити, як ви бачите, сірим кольором. А бомби можна кидати на максимальну відстань до чотирьох блоків. Вони подорожують до чотирьох блоків через стіни та інших гравців, вбиваючи лише ворогів, які стоять на вашому шляху. Після кожного кроку у них є 40% шансу впасти. Таким чином, у них 100% шанс на 1 дальність 60% при 2 дальності 36% на 3 дальності і 21,6% на три дальності Розміщення міни або метання бомби займає боєприпаси однієї команди. Це починається з 0 і може бути збільшено, зібравши помаранчеві поля. Зауважте, що чотири (4) цих сховища боєприпасів будуть зручно розміщені по центру. Боти вишикуються у масив із двох червоних та двох синіх. IE RRRRRBBBBB. Гаурдінг прапора дозволений, але слід пам’ятати, що перебування біля прапора (тобто менше п’яти блоків) призводить до повільності, і дозволяє лише нахиляти. кожні три витки. Арена вибирає випадковий стартер на кожен крок. Я

Об'єктивна

Програмуйте свої п'ять ботів (кожен має один і той самий файл класу), щоб успішно орієнтуватися в лабіринті і торкатися протилежної банки, одночасно стежачись, щоб випадково не перебити їх власну банку або наступити на міну.

Програмування

Записи на арені та боті зараз перебувають на Java, однак для інших мов існує обгортка 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

Де: {Ідентифікація членства команди} - це один символ: R або B. B означає синю команду, R означає червону команду.

{Game Map} - це ряд рядків символів ascii, що представляють один рядок карти. Наступні такі символи ascii: F = синій прапор G = червоний прапор O = відкритий простір W = стіна

Потім гра перейде до надсилання ігрових кадрів через stdout кожному боту:

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

Де:

{Ammo} - рядок цифр, значення буде 0 або більше {Alive Bot Count} - рядок цифр, значення буде 0 або більше {Box X} - рядок цифр, що представляють координату X бота на ігровій карті. Значення буде 0 <= X <Ширина карти. {Box Y} - рядок цифр, що представляють координату Y бота на ігровій карті. Значення буде 0 <= Y <Висота карти. {Local Map} - це ряд рядків символів ascii, що представляють всю карту навколо бота. Наступні такі символи ascii: F = синій прапор G = червоний прапор O = відкритий простір W = стіна R = червоний бот команди B = синій бот команди M = мій A = боєприпаси

Контролер очікує, що ваш бот потім виведе (для викреслювання) відповідь однієї лінії у форматі:

{Action},{Direction}

Де:

{Action} є одним із: Перемістити знешкодження мінного кидання

{Напрям} - це одна цифра від 0 до 4 включно. (див. інформацію про напрямок раніше)

ПРИМІТКА: всі рядки будуть обмежені символом \ n Кінець рядка.

Це буде елімінаційний турнір. Мої боти-зразки братимуть участь в якості наповнювачів, але я не буду присуджувати собі перемогу. У разі перемоги одного з моїх ботів титул переходить до другого учасника та продовжуватиметься, поки не знайдеться бот, який не є моїм. Кожен матч складається з 11 раундів удару по банці. Якщо жодна команда не виграла жодного матчу, вони обидва виключаються. Якщо виграв равний нульовий бал, буде розіграний матч з вимикачем. Якщо краватка залишилася, обидва усуваються. Пізніші раунди можуть складатися з більшої кількості матчів. Посів турніру буде ґрунтуватися на кількості оновлених даних станом на 31.07.16 (дата може змінюватися).

Кожен матч триває 4096 оборотів. Перемога дає один бал. Равномірний чи збитковий результат дає нульові бали. Удачі!

Не соромтеся ознайомитись з кодом або критикувати його в цьому GitHub Repo.

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


Зауважте, що у мене на комп’ютері немає перекладачів для занадто багато мов, і мені можуть знадобитися добровольці для запуску моделювання на своєму комп’ютері. Або я можу завантажити перекладача мови. Будь ласка, переконайтесь, що ваші боти.

  • Відповідайте за розумну кількість часу (скажімо, 250 мс)
  • Не пошкодить мій хост-апарат

@Moogie Я вирішив випустити це
Rohan Jhunjhunwala

На локальній карті, що це показує для плиток, що не бачать ботів?
justhalf

На ній показана карта. Єдине, що ви не можете побачити ботів на більшій відстані. Вашим ботам надається фактична карта арени, але вони можуть не там, де там ховаються приховані противники. @justhalf
Rohan Jhunjhunwala

@Moogie, мені було цікаво, чи можете ви написати бота python для мене, щоб я міг протестувати обгортку 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

Дякуємо @Moogie за те, що він допомагає мені оптимізувати мою безладну пролягання заливного шляху. Ось джерело для бота. Цей хлопець знає, як важливо захищати свій прапор. Він виділяє трьох захисників та двох нападників. Захисники звисають і захищають / збирають боєприпаси, двоє нападників прямують (досить прямим) шляхом до прапора (і збирають боєприпаси посередині). Він стріляє будь-кого, кого бачить, і має бути жорстка конкуренція. Захисники розміщують міни навколо прапора і табору, поки не залишиться опозиції, щоб вони могли піти і вибити канку.

/*
 * 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");
     }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.