Izgara Yönlendirme Savaşı


22

NOT: Bir eşleşme için gereken dilleri kuramadığım için bu zorluk şu anda öldü. Başkasının bunu yapmak için zamanı ve ilgisi varsa, ben karşı çıkmam.

Büyük afiş için gönderinin altına bakın.

Bu, yarı-kooperatif tepesi kralı mücadelesi, botların iki boyutlu bir ızgara grafiğiyle yolları çizdikleri. En fazla trafik çeken düğümleri kontrol eden bot kazanır. Bununla birlikte, aslında bir bağlantı yolu oluşturmak için birden fazla botun kaynağı gerekir, bu yüzden botların birlikte çalışması gerekir - bir dereceye kadar.

Oynanış

Aşağıda, N > 0oyundaki botların sayısı olalım .

Izgara

Oyun, sol alt koordinatı olan iki boyutlu bir tamsayı ızgarasında oynanır . Koordinat Her ile üç koordinat giden kenarları vardır , ve burada, yukarıda -coordinates modulo alınır . Bu, şebekenin doğu ve batı kenarlarında dolaştığı anlamına gelir. Her alt koordinat bir kaynaktır ve her üst koordinat bir lavabodur .⌊4/3N2⌋ × ⌊4/3N2(0,0)(x,y)0 ≤ y < ⌊4/3N2⌋-1(x-1,y+1)(x,y+1)(x+1,y+1)x⌊4/3N2(x,0)(x,⌊4/3N2⌋-1)

Aşağıdaki resimde bir 8 × 8ızgara gösterilmektedir.

8x8'lik bir ızgara.

Grafiğin her tepe noktası etkin değil , etkin veya bozuktur . Tüm köşeler etkin değildir ve daha sonra sahipleri olacak olan botlar tarafından etkinleştirilebilir. Ayrıca, botlar köşeleri kırabilir ve onarılamaz.

Siparişi ver

Bir dönüş, bir yıkım aşaması ve bir aktivasyon aşamasından oluşur . İmha aşamasında, her bot bir aktif olmayan tepe noktasını kırabilir. Bu köşe o andan itibaren kırılır ve hiç kimse tarafından etkinleştirilmeyebilir. Aktivasyon aşamasında, her bot bir aktif olmayan tepe noktasını aktif hale getirebilir. O andan itibaren, o köşeye sahipler ve başkası tarafından yeniden etkinleştirilemez. Birkaç bot, aynı sırayla etkinleştirmeleri durumunda, tek bir tepe noktasına sahip olabilir. Her aşamada, köşe seçimleri aynı anda yapılır.

puanlama

Bir tur tam dönüşler için sürer . Bundan sonra, tur aşağıdaki gibi puanlanır. Her bir aktif kaynak köşesinden, etkin köşeler boyunca rastgele derinlikli ilk bir arama gerçekleştiririz (bu, her bir köşenin çocuklarının rastgele bir sırada ziyaret edildiği anlamına gelir). Kaynaktan bir havuza bir yol bulunursa, o zaman yoldaki tüm köşeler için, tepe noktasının her sahibi bir puan alır.N2N

Tüm oyun 100 tur sürer ve toplamda en yüksek puana sahip olan bot kazanır. Puanların varyansı çok yüksekse, bu sayıyı arttırabilirim.

Ek Kurallar

  • Denetleyiciyle ya da diğer gönderilerle uğraşmak yok.
  • Yarışmacı başına en fazla bir başvuru.
  • Oyunun başında hiçbir özel metin dosyası dışında hiçbir harici kaynak silinmedi.
  • Botunuzu belirli rakipleri yenecek veya destekleyecek şekilde tasarlamayın.
  • Botunuzu derlemek ve çalıştırmak için komutlar verin. Debian Linux için serbestçe kullanılabilen herhangi bir derleyici / tercüman kabul edilebilir.

Kontrol eden, denetleyici

Kontrolör Python 3 ile yazılmıştır ve GitHub'da bulunabilir . Ayrıntılı talimatlar için README dosyasına bakın. İşte başlamanıza yardımcı olacak bir API:

  • Her turun başında botlar başlatılır ve turun sonuna kadar devam eder. Kontrolör ile STDIN ve STDOUT aracılığıyla, yeni satır sonlandırılmış mesajları kullanarak iletişim kurun.
  • BEGIN [num-of-bots] [num-of-turns] [side-length] başında girilir.
  • DESTROY [turn]Her yıkım evresinin başında girdi. Botunuz VERTEX x,ybir köşe seçmek için ya da ile cevap verecektir NONE.
  • BROKEN [turn] [your-choice] [other-choices]Her yıkım evresinin sonunda girilir. Diğer botların sırası her oyunun başında randomize edilir ancak oyun sırasında sabit kalır. Seçenekler x,yveya olarak sunulur N.
  • ACTIVATE [turn]ve OWNED [turn] [your-choice] [other-choices]aktivasyon aşaması için yukarıdakilerin eşdeğerleridir ve aynı semantiklere sahiptir.
  • SCORE [your-score] [other-scores] Oyunun sonunda girilir.
  • Sizin bot sahiptir 1 saniye sonraki köşe bir aşamasının sonuçlarını analiz etmek ve seçmek için ve 1 saniye puan verilen sonra çıkmak için. Gönderimleri nispeten eski dizüstü bilgisayarımda test edeceğim, bu yüzden burada biraz boşluk bırakmak daha iyi.

Lütfen çıktı tamponunuzu temizlemeyi unutmayın. Aksi halde kumandayı bazı ortamlarda asabilirsiniz.

Liderler Sıralaması

Güncelleme tarihi: 13.03.2015

Peacemaker çalışıyor ve çalışıyor, Funnelweb de bir güncelleme aldı. Skorlar büyüklük sırasına göre yükseldi. Bağlayıcı iki oyunda zaman sınırını aştı.

Funnelweb: 30911
Connector: 18431
Watermelon: 3488
Annoyance: 1552
Explorer: 735
Checkpoint: 720
Random Builder: 535
FaucetBot: 236
Peacemaker: 80

ASCII sanat grafikleri ile dolu günlük, kontrol ünitesinin deposunda, içinde bulunabilir graphical_log.txt.

Bazı gözlemler:

  • Bağlayıcı, önünde tek bir tepe kesilerek kolayca durdurulabilir. Annoyance sık sık bunu yapıyor şüpheli. Ancak, şu anda çok az anlam ifade etmektedir çünkü yalnızca Bağlayıcı akla uygun bir yol inşa edebilir.
  • Karpuz, basitçe bağlantı yolunda (DFS'nin köşelerini kullanması muhtemel olduğu için) gerçekleşerek iyi bir puan alabilir.
  • Explorer karpuzlardan üzüm yetiştirmeyi sever.
  • Güncellenen Funnelweb gerçekten iyi puanlar alır, çünkü Connector genellikle kılavuzun alt yarısında kilitlenir.
  • Oyunlar oldukça uzuyor, ortalama tur makinemde yaklaşık 25 saniye sürüyor.

1
@Alex İntihar botlarının her şeyi mahvetmemesi için mücadeleyi tasarlamaya çalıştım. İyi tasarlanmış üç bot, birlikte çalışırlarsa daima geçerli bir yol oluşturabilmelidir.
Zgarb

2
@Zgarb İntihar karışıklık o kadar olmamalı, ancak birlikte çalışarak bir çift trol-botların büyük olasılıkla da olabilir engellemek oyunu mahvediyor, bütün yolları.
Geobits,

2
@CarpetPython Aktif düğümler yok edilemez.
Zgarb

1
Şu anki oyuncu ve kurallarla ilginç oyunlar görme ihtimalimiz yok gibi görünüyor. İlginç oyunlar için fırsatlar yaratmak amacıyla kuralları biraz değiştirmenizi öneririm. Izgara boyutunu 2 * N ^ 2 yerine 1,5 * N ^ 2 olarak değiştirmek iyi olmalı ve mevcut robotları çok fazla karıştırmamalıdır.
Mantık Şövalyesi

1
Sadece bu doğru. Kütükteki oyunlar daha da azalan ızgara büyüklüğü ile oynandı 4/3*N^2ve hatta robotlar geçerli yollar oluşturmakta zorlandı. Ancak, Connector bir hata nedeniyle geçici olarak diskalifiye edildi ve şimdi düzeltildi, oyunların daha ilginç olmasını bekliyorum. Bu gece başka bir parti yapacağım.
Zgarb

Yanıtlar:


7

Bağlayıcı (Java)

Rasgele bir konumda bir yol oluşturmaya çalışır. Kendi başına bir yol oluşturamadığı için aktif hücreleri arar ve bunları kullanır. Kredi, bazı kodları çaldığım Geobits'e gidiyor. Ayrıca, bu gönderi henüz bitmedi, çünkü yol yapıldığı anda herhangi bir şeyi yapmayı bıraktı.

Düzenleme: Bir yol oluşturulmuşsa, Bağlayıcı varolan yol boyunca birden çok yol oluşturmaya çalışır.

import java.awt.Point;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Connector {
    private static final int INACTIVE = 0;
    private static final int ACTIVE   = 1;
    private static final int BROKEN   = 2;
    private static final int MINE     = 3;

    private int size = 0;
    private int[][] grid = new int[size][size];
    private Point previousCell = null;
    private final List<Point> path = new ArrayList<>();

    public static void main(String[] args) {
        new Connector().start();
    }

    private void start() {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while(true) {
            try {
                String input = reader.readLine();
                act(input);
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(0);
            }
        }
    }

    private void act(String input) throws Exception {
        String[] msg = input.split(" ");
        String output = "";
        int turn;
        switch(msg[0]){
        case "BEGIN":
            size = Integer.parseInt(msg[3]);
            grid = new int[size][size];
            break;
        case "DESTROY":
            output = "NONE";
            break;
        case "BROKEN":
            update(msg, true);
            break;
        case "ACTIVATE":
            turn = Integer.parseInt(msg[1]);
            output = activate(turn);
            break;
        case "OWNED":
            update(msg, false);
            break;
        case "SCORE":
            System.exit(0);
            break;
        }
        if (output.length() > 0) {
            System.out.println(output);
        }
    }

    private String activate(int turn) {
        if (turn == 0) {
            Random r = new Random();
            previousCell = new Point(r.nextInt(size), 0);
            return "VERTEX " + previousCell.x + "," + 0;
        }
        Point lastCell = findLastPathCell(previousCell.x, previousCell.y);
        if (lastCell.y == size-1) {
            //path is done
            Point extendingPathPoint = findExtendingPathPoint();
            if (extendingPathPoint == null) {
                return "NONE";
            }
            return "VERTEX " + extendingPathPoint.x + "," + extendingPathPoint.y;
        } else {
            int x = findBestX(lastCell.x, lastCell.y);
            return "VERTEX " + x + "," + (lastCell.y + 1);
        }
    }

    private int findBestX(int x, int y) {
        int bestScore = Integer.MIN_VALUE;
        int bestX = 0;
        for (int i = -1; i <= 1; i++) {
            int newY = y + 1;
            int newX = (x + i + size) % size;
            int score = calcCellScore(newX, newY, 10);
            if (score > bestScore) {
                bestScore = score;
                bestX = newX;
            } else if (score == bestScore && Math.random() < 0.3) {
                bestX = newX;
            }
        }
        return bestX;
    }

    private int calcCellScore(int x, int y, int depth) {
        int newY = y + 1;
        if (depth < 0) {
            return 1;
        }
        if (newY >= size)
            return 100;
        int cellScore = 0;
        for (int i = -1; i <= 1; i++) {
            int newX = (x + i + size) % size;
            if (grid[newX][newY] == ACTIVE || grid[newX][newY] == MINE) {
                cellScore += 5;
            } else if (grid[newX][newY] == INACTIVE) {
                cellScore += 1;             
            } else {
                cellScore -= 2;
            }
            cellScore += calcCellScore(newX, newY, depth -1);
        }
        return cellScore;
    }

    private Point findLastPathCell(int x, int y) {
        Point thisCell = new Point(x,y);
        int newY = y + 1;
        if (newY >= size) {
            return thisCell;
        }
        List<Point> endCells = new ArrayList<>();
        endCells.add(thisCell);
        path.add(thisCell);
        for (int i = -1; i <= 1; i++) {
            int newX = (x + i + size) % size;
            if (grid[newX][newY] == ACTIVE || grid[newX][newY] == MINE) {
                endCells.add(findLastPathCell(newX, newY));
            }
        }
        int bestY = -1;
        Point bestPoint = null;
        for (Point p : endCells) {
            if (p.y > bestY) {
                bestY = p.y;
                bestPoint = p;
            }
        }
        return bestPoint;
    }

    private Point findExtendingPathPoint() {
        if (path.size() == 0)
            return null;
        Random rand = new Random();
        for (int i = 0; i < size; i++) {
            Point cell = path.get(rand.nextInt(path.size()));
            for (int j = -1; j <= 1; j += 2) {
                Point newCellX = new Point((cell.x + j + size) % size, cell.y);
                if (grid[newCellX.x][newCellX.y] == INACTIVE)
                    return newCellX;

                Point newCellY = new Point(cell.x, cell.y + j);
                if (cell.y < 0 || cell.y >= size)
                    continue;
                if (grid[newCellY.x][newCellY.y] == INACTIVE)
                    return newCellY;
            }
        }
        return null;
    }

    private void update(String[] args, boolean destroyPhase) {
        for(int i = 2; i < args.length; i++) {
            String[] tokens = args[i].split(",");
            if(tokens.length > 1){
                int x = Integer.parseInt(tokens[0]);
                int y = Integer.parseInt(tokens[1]);
                if (grid[x][y] == INACTIVE) {
                    if (destroyPhase) {
                        grid[x][y] = BROKEN;
                    } else if (i == 2) {
                        grid[x][y] = MINE;
                        path.add(new Point(x,y));
                        previousCell = new Point(x,y);
                    } else {
                        grid[x][y] = ACTIVE;
                    }
                }
            }
        }
    }
}

@ Zgarb Üzgünüm, diğerini düzeltirken bir hata oluşturdum. Şimdi çalışıyor
CommonGuy 5:15

@Manu, oyuna geri dönmen iyi. Çok fazla sömürücü var ve inşaatçılar yetmiyor. Bağlayıcı çalışırken, oyunlar daha ilginç hale gelebilir (100'lü 1 puandan fazla oyun).
Mantık Şövalye

Bağlayıcı, en son oyunlardan birine yanıt vermek için 28 saniye sürdü (günlüğe bakın). Karpuz içine koştu ve bir sonraki nereye gideceğine karar vermek zor zamanlar gibiydi.
Zgarb

Ben geliştirilmiş Peacemaker ile tekrar bazı oyunlar ran ve Bağlayıcı bir hata attı: java.lang.ArrayIndexOutOfBoundsException: -1 at Connector.findExtendingPathPoint(Connector.java:166).
Zgarb

7

Funnelweb, Python 2

sürüm 1.2 - Daha iyi birleştirme kodu, yeni animasyon eklendi

Avustralya'nın daha az dostu olan örümceklerinden birini seçti. Bu bot ilk önce üst sıralarda huni şeklindeki bir yuva oluşturur, daha sonra diğer botları yuvaya giden trafik için bina yollarına çeker.

İşte 4 / 3N ^ 2 tahtasında 6 bot oyunun yeni bir animasyonu olan funnelweb'i ve daha basit botları gösteren:

bots6.gif

Funnelweb'in Python kodu:

from random import *
import sys
ME = 0
def pt(x,y): return '%u,%u' % (x % side_len, y)

while True:
    msg = raw_input().split()

    if msg[0] == 'BEGIN':
        turn = 0
        numbots, turns, side_len = map(int, msg[1:])
        R = range(side_len)
        top = side_len - 1
        grid = dict((pt(x, y), []) for x in R for y in R)
        mynodes = set()
        deadnodes = set()
        freenodes = set(grid.keys())
        mycol = choice(R)
        extra = sample([pt(x,top) for x in R], side_len)
        path = [(mycol, y) for y in range(top, top - side_len/6, -1)]
        moves = []
        fence = []
        for x,y in path:
            moves.append( [pt(x,y), pt(x+1,y), pt(x-1,y)] )
            fence.extend( [pt(x+1,y), pt(x-1,y)] )
        for dx in range(2, side_len):
            fence.extend( [pt(x+dx,y), pt(x-dx,y)] )
        for x,y in [(mycol, y) for y in 
                range(top - side_len/6, top - 3*side_len/4, -1)]:
            moves.append( [pt(x,y), pt(x+1,y), pt(x-1,y)] )

    elif msg[0] == 'DESTROY':
        target = 'NONE'
        while fence:
            loc = fence.pop(0)
            if loc in freenodes:
                target = 'VERTEX ' + loc
                break
        print target
        sys.stdout.flush()

    elif msg[0] == 'BROKEN':
        for rid, loc in enumerate(msg[2:]):
            if loc != 'N':
                grid[loc] = None
                deadnodes.add(loc)
                freenodes.discard(loc)
                if loc in extra: extra.remove(loc)

    elif msg[0] == 'ACTIVATE':
        target = 'NONE'
        while moves:
            loclist = moves.pop(0)
            goodlocs = [loc for loc in loclist if loc in freenodes]
            if goodlocs:
                target = 'VERTEX ' + goodlocs[0]
                break
        if target == 'NONE':
            if extra:
                target = 'VERTEX ' + extra.pop(0)
            else:
                target = 'VERTEX ' + pt(choice(R), choice(R))
        print target
        sys.stdout.flush()

    elif msg[0] == 'OWNED':
        for rid, loc in enumerate(msg[2:]):
            if loc != 'N':
                grid[loc].append(rid)
                if rid == ME:
                    mynodes.add(loc)
                freenodes.discard(loc)
                if loc in extra: extra.remove(loc)
        turn += 1

    elif msg[0] == 'SCORE':
        break

Örümcek ile çalıştırılır python funnelweb.py.


Değişen algoritma ve test edildi. Şimdi koşmalı.
Mantık Şövalyesi

Şimdi harika çalışıyor!
Zgarb

6

Denetim noktası, Java

Bu bot kontrol noktaları oluşturmaya çalışır, böylece herhangi bir geçerli yol köşelerimden birinden geçer. N 2 dönüş olduğundan ve kart 2N 2 boyunca olduğundan, ilk düğümü tek bir yatay çizgi üzerinde etkinleştirebilir / kırabilirim (ilk önce orada olduğumu varsayarak). Bunu alternatif bir düzende yapın ( xkırılır, obenimdir):

xoxoxoxoxoxox...

Bir yol açmak istiyorsan benim kontrol noktalarımdan geçmelisin :)

Şimdi, bunun karşılaşabileceği birkaç sorun var. Birincisi, çok fazla yol olmadıkça, hiç de iyi sonuç vermeyecek. O yapmaz yana herhangi üretken yolları kendisi, o gerçekten bazı rakipler var olmanın tamamen bağımlıdır. Tek bir yol oluşturmak için bir araya gelen birkaç rakip bile, bulduğu her yol için yalnızca bir puan aldığı için pek yardımcı olmaz. Parlaması gereken şey, muhtemelen birkaç farklı yol yapan birkaç bot. O zaman bile, çok yüksek puan alamayabilir, ama sohbet ettim bir fikirdi, bu yüzden ...

Satırdaki boşluklardan biri zaten engellenirse / talep edilirse, kullanabileceğim yakındaki bir noktayı ararım (tercihen aynı xhatta, sadece dikey olarak kaydırılır).


import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Checkpoint {
    public static void main(String[] args) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while(true)
            try {
                String input = reader.readLine();
                act(input);
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(0);
            }
    }

    static void act(String input) throws Exception{
        String[] msg = input.split(" ");
        String output = "";
        int turn;
        boolean found = false;
        switch(msg[0]){
        case "BEGIN":
            size = Integer.parseInt(msg[3]);
            grid = new int[size][size];
            target = size/2;
            break;
        case "DESTROY":
            turn = Integer.parseInt(msg[1]);
            for(int x=0;x<size;x+=2)
                for(int y=0;y<size&&!found;y++)
                    if(grid[(x+turn*2)%size][(y+target)%size]==INACTIVE){
                        output = "VERTEX " + ((x+turn*2)%size) + "," + ((y+target)%size);
                        found = true;
                    }
            if(output.length() < 1)
                output = "NONE";
            break;
        case "BROKEN":
            for(int i=2;i<msg.length;i++){
                String[] tokens = msg[i].split(",");
                if(tokens.length>1){
                    int x = Integer.parseInt(tokens[0]);
                    int y = Integer.parseInt(tokens[1]);                    
                    if(grid[x][y]==INACTIVE)
                        grid[x][y] = BROKEN;
                }
            }
            break;
        case "ACTIVATE":
            turn = Integer.parseInt(msg[1]);
            for(int x=1;x<size;x+=2)
                for(int y=0;y<size&&!found;y++)
                    if(grid[(x+turn*2)%size][(y+target)%size]==INACTIVE){
                        output = "VERTEX " + ((x+turn*2)%size) + "," + ((y+target)%size);
                        found = true;
                    }
            if(output.length() < 1)
                output = "NONE";
            break;
        case "OWNED":
            for(int i=2;i<msg.length;i++){
                String[] tokens = msg[i].split(",");
                if(tokens.length>1){
                    int x = Integer.parseInt(tokens[0]);
                    int y = Integer.parseInt(tokens[1]);
                    if(i==2){
                        if(grid[x][y]==INACTIVE)
                            grid[x][y] = MINE;
                    }else{
                        if(grid[x][y]==INACTIVE)
                            grid[x][y]=ACTIVE;
                    }
                }
            }
            break;
        case "SCORE":
            System.exit(0);
            break;
        }
        if(output.length()>0)
            System.out.println(output);
    }

    static int size = 2;
    static int target = size/2;
    static int[][] grid = new int[size][size];

    static final int INACTIVE = 0;
    static final int ACTIVE   = 1;
    static final int BROKEN   = 2;
    static final int MINE     = 3;
}

Derlemek için bu javac Checkpoint.java. Koşmak için java Checkpoint. Nerede olursa olsun yansıtmak için yolu eklemek / değiştirmek isteyeceksiniz.


5

Karpuz

Izgaraya karpuz çekmeye çalışır.

import java.awt.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Watermelon {

    private static int numberOfBots;
    private static int numberOfTurns;
    private static int sideLength;

    private static int turn = 0;

    private static int[][] theGrid;

    private static final int INACTIVE = -2;
    private static final int BROKEN   = -1;
    private static final int MINE     =  0;
    private static final int ACTIVE   =  1;

    private static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    private static PrintStream out = System.out;

    public static void main(String[] args) throws IOException {
        while (true){
            String[] input = in.readLine().trim().split(" ");
            String instruction = input[0];
            switch (instruction){
                case "BEGIN":
                    begin(input);
                    break;
                case "DESTROY":
                    destroy(input);
                    break;
                case "BROKEN":
                    broken(input);
                    break;
                case "ACTIVATE":
                    activate(input);
                    break;
                case "OWNED":
                    owned(input);
                    break;
                default:
                    return;
            }
            out.flush();
        }
    }

    private static void begin(String[] input) {
        numberOfBots = Integer.parseInt(input[1]);
        numberOfTurns = Integer.parseInt(input[2]);
        sideLength = Integer.parseInt(input[3]);
        theGrid = new int[sideLength][sideLength];
        for (int x = 0; x < sideLength; x++){
            for (int y = 0; y < sideLength; y++){
                theGrid[x][y] = INACTIVE;
            }
        }
    }

    private static void owned(String[] input) {
        turn = Integer.parseInt(input[1]);
        for (int i = input.length - 1; i >= 2; i--){
            if (input[i].equals("N")){
                continue;
            }
            String[] coordinates = input[i].split(",");
            int x = Integer.parseInt(coordinates[0]);
            int y = Integer.parseInt(coordinates[1]);
            int player = i - 2;
            if (player == 0){
                theGrid[x][y] = MINE;
            } else {
                theGrid[x][y] = ACTIVE;
            }
        }
    }

    private static void activate(String[] input) {
        turn = Integer.parseInt(input[1]);
        double[][] values = new double[sideLength][sideLength];
        List<Point> pointList = new ArrayList<>();
        for (int x = 0; x < sideLength; x++){
            for (int y = 0; y < sideLength; y++){
                if (theGrid[x][y] == MINE || theGrid[x][y] == ACTIVE){
                    for (int x1 = 0; x1 < sideLength; x1++){
                        for (int y1 = 0; y1 < sideLength; y1++){
                            double distance = Math.pow(x - x1, 2) + Math.pow(y - y1, 2);
                            values[x1][y1] += 1 / (distance + 1);
                        }
                    }
                }
                pointList.add(new Point(x, y));
            }
        }
        pointList.sort(Comparator.comparingDouble((Point a) -> values[a.x][a.y]).reversed());
        for (Point point : pointList){
            if (theGrid[point.x][point.y] == INACTIVE){
                out.println("VERTEX " + point.x + "," + point.y);
                return;
            }
        }
        out.println("NONE");
    }

    private static void broken(String[] input) {
        turn = Integer.parseInt(input[1]);
        for (int i = 2; i < input.length; i++){
            if (input[i].equals("N")){
                continue;
            }
            String[] coordinates = input[i].split(",");
            int x = Integer.parseInt(coordinates[0]);
            int y = Integer.parseInt(coordinates[1]);
            theGrid[x][y] = BROKEN;
        }
    }

    private static void destroy(String[] input) {
        turn = Integer.parseInt(input[1]);
        double[][] values = new double[sideLength][sideLength];
        List<Point> pointList = new ArrayList<>();
        for (int x = 0; x < sideLength; x++){
            for (int y = 0; y < sideLength; y++){
                if (theGrid[x][y] == MINE){
                    for (int x1 = 0; x1 < sideLength; x1++){
                        for (int y1 = 0; y1 < sideLength; y1++){
                            double distance = Math.pow(x - x1, 2) + Math.pow(y - y1, 2);
                            values[x1][y1] -= 1 / (distance + 1);
                        }
                    }
                }
                if (theGrid[x][y] == ACTIVE){
                    for (int x1 = 0; x1 < sideLength; x1++){
                        for (int y1 = 0; y1 < sideLength; y1++){
                            double distance = Math.pow(x - x1, 2) + Math.pow(y - y1, 2);
                            values[x1][y1] += 1 / (distance + 1) / (numberOfBots - 1);
                        }
                    }
                }
                pointList.add(new Point(x, y));
            }
        }
        pointList.sort(Comparator.comparingDouble((Point a) -> values[a.x][a.y]).reversed());
        for (Point point : pointList){
            if (theGrid[point.x][point.y] == INACTIVE){
                out.println("VERTEX " + point.x + "," + point.y);
                return;
            }
        }
        out.println("NONE");
    }
}

5

Musluk Musluğu (R cinsinden)

İkinci satırda bir darboğaz oluşturur ve arkasındaki yolda bulunan düğümleri etkinleştirir.

infile <- file("stdin")
open(infile)
repeat{
    input <- readLines(infile,1)
    args <- strsplit(input," ")[[1]]
    if(args[1]=="BEGIN"){
        L <- as.integer(args[4])
        M <- N <- matrix(0,nrow=L,ncol=L)
        x0 <- sample(2:(L-1),1)
        }
    if(args[1]=="DESTROY"){
        if(args[2]==0){
            X <- x0
            Y <- 2
            }else{
                free <- which(M[,2] == 0)
                mine <- which(N[,2] == 1)
                X <- free[which.min(abs(free-mine))]
                Y <- 2
                }
        if(length(X)){cat(sprintf("VERTEX %s,%s\n",X-1,Y-1))}else{cat("NONE\n")}
        flush(stdout())
        }
    if(args[1]=="BROKEN"){
        b <- strsplit(args[args!="N"][-(1:2)],",")
        o <- strsplit(args[3],",")[[1]]
        b <- lapply(b,as.integer)
        if(o[1]!="N") N[as.integer(o[1])+1,as.integer(o[2])+1] <- -1
        for(i in seq_along(b)){M[b[[i]][1]+1,b[[i]][2]+1] <- -1}
        }
    if(args[1]=="ACTIVATE"){
        if(args[2]==0){
            broken <- which(M[,2] == -1)
            free <- which(M[,2] == 0)
            X <- free[which.min(abs(broken-free))]
            Y <- 2
            }else{
                y <- 3
                X <- NULL
                while(length(X)<1){
                    lastrow <- which(N[,y-1]==1)
                    newrow <- unlist(sapply(lastrow,function(x)which(M[,y]==0 & abs((1:L)-x)<2)))
                    if(length(newrow)){
                        X <- sample(newrow,1)
                        Y <- y
                        }
                    y <- y+1
                    if(y>L){X <- x0; Y <- 1}
                    }
                }
        cat(sprintf("VERTEX %s,%s\n",X-1,Y-1))
        flush(stdout())
        }
    if(args[1]=="OWNED"){
        b <- strsplit(args[args!="N"][-(1:2)],",")
        o <- strsplit(args[3],",")[[1]]
        b <- lapply(b,as.integer)
        if(o[1]!="N") N[as.integer(o[1])+1,as.integer(o[2])+1] <- 1
        for(i in seq_along(b)){M[b[[i]][1]+1,b[[i]][2]+1] <- 1}
        }
    if(args[1]=="SCORE") q(save="no")
    }

Berbat etmediysem, son yapılandırma şöyle olmalı:

........    .a..aa..
..aaa...    ..aaa...
.xxaxx..    xxxaxxx.    etc.
........    ........

Komuta Rscript FaucetBot.R.


5

Peacemaker, Java

Manu koduna göre.

Peacemaker arama çakışma bölgeleri (çoğu BROKEN veya ACTIVE vertex konsantrasyonu) ve yakındaki rastgele bir verteksi etkinleştirir.

import java.awt.Point;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.IntStream;

public class Peacemaker {
    private static final int INACTIVE = 0;
    private static final int ACTIVE   = 1;
    private static final int BROKEN   = 2;
    private static final int MINE     = 3;

    private int size = 0;
    private int[][] grid = new int[size][size];
    private int startingPoint = 0;

    public static void main(String[] args) {
        new Peacemaker().start();
    }

    private void start() {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while(true) {
            try {
                String input = reader.readLine();
                act(input);
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(0);
            }
        }
    }

    private void act(String input) throws Exception {
        String[] msg = input.split(" ");
        String output = "";
        int turn;
        switch(msg[0]){
        case "BEGIN":
            size = Integer.parseInt(msg[3]);
            grid = new int[size][size];
            break;
        case "DESTROY":
            output = "NONE";
            break;
        case "BROKEN":
            update(msg, true);
            break;
        case "ACTIVATE":
            turn = Integer.parseInt(msg[1]);
            output = activate(turn);
            break;
        case "OWNED":
            update(msg, false);
            break;
        case "SCORE":
            System.exit(0);
            break;
        }
        if (output.length() > 0) {
            System.out.println(output);
        }
    }

    private String activate(int turn) {
        Random r = new Random();
        if (turn == 0) {
            startingPoint = r.nextInt(size);
            return "VERTEX " + startingPoint + "," + 0;
        } else {

            Point point = searchConflicts();

            int posX = point.x;
            int posY = point.y;

            while (grid[posX][posY] != INACTIVE) {
                 int previousX = (posX - 1 < 0 ? size - 1 : posX - 1);
                 int nextX = (posX + 1 > size - 1 ? 0 : posX + 1);
                 int previousY = (posY - 1 < 0 ? size - 1 : posY - 1);
                 int nextY = (posY + 1 > size - 1 ? 0 : posY + 1);

                 int choice = r.nextInt(4);
                 switch (choice) {
                     case 0: posX = previousX; break;
                     case 1: posX = nextX; break;
                     case 2: posY = previousY; break;
                     case 3: posY = nextY; break;
                 }
            }

            return "VERTEX " + posX + "," + posY;
        }
    }

    private Point searchConflicts() {

        int previousCellScore = 0;
        int cellX = 0;
        int cellY = 0;
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j ++) {
                if (previousCellScore < adjacentCellsScore(i, j)) {
                    cellX = i; cellY = j;
                    previousCellScore = adjacentCellsScore(i, j);
                }
            }
        }
        return new Point(cellX, cellY);
    }

    /*  Format of adjacent cells :
     * 
     *   0 1 2
     *   3 . 4
     *   5 6 7
     */
    private int adjacentCellsScore(int x, int y) {

        int[] scores = new int[8];

        int previousX = (x - 1 < 0 ? size - 1 : x - 1);
        int nextX = (x + 1 > size - 1 ? 0 : x + 1);
        int previousY = (y - 1 < 0 ? size - 1 : y - 1);
        int nextY = (y + 1 > size - 1 ? 0 : y + 1);

        scores[0] = calcScore(previousX, nextY);
        scores[1] = calcScore(x, nextY);
        scores[2] = calcScore(nextX, nextY);
        scores[3] = calcScore(previousX, y);
        scores[4] = calcScore(nextX, y);
        scores[5] = calcScore(previousX, previousY);
        scores[6] = calcScore(x, previousY);
        scores[7] = calcScore(nextX, previousY);

        return IntStream.of(scores).reduce(0, (a, b) -> a + b);
    }

    private int calcScore(int x, int y) {
        int activeScore = 2;
        int mineScore = 1;
        int inactiveScore = 0;
        int brokenScore = 3;

        if (grid[x][y] == ACTIVE) 
            return activeScore;
        else if (grid[x][y] == MINE)
            return mineScore;
        else if (grid[x][y] == INACTIVE) 
            return inactiveScore;
        else if (grid[x][y] == BROKEN) 
            return brokenScore;
        else
            return 0;
    }


    private void update(String[] args, boolean destroyPhase) {
        for(int i = 2; i < args.length; i++) {
            String[] tokens = args[i].split(",");
            if(tokens.length > 1){
                int x = Integer.parseInt(tokens[0]);
                int y = Integer.parseInt(tokens[1]);
                if (grid[x][y] == INACTIVE) {
                    if (destroyPhase) {
                        grid[x][y] = BROKEN;
                    } else if (i == 2) {
                        grid[x][y] = MINE;
                    } else {
                        grid[x][y] = ACTIVE;
                    }
                }
            }
        }
    }       
}

@Zgarb Teşekkürler, bu sorunu şimdi çözmeliydim.
Thrax

Peacemaker şimdi çalışıyor ve büyük karede yer alıyor. Ancak, fazla bir şey görünmüyor, bu yüzden muhtemelen hala bazı hatalar kalmış.
Zgarb

Aslında, kodunuza bakıldığında, sorunun yöntem whiledöngüsünde olduğunu düşünüyorum activate. Kendinizin olmayan ve kırılmayan bir tepe noktası bulduktan sonra aramayı durdurursunuz - ancak başka birine ait olabilir, bu nedenle etkinleştiremezsiniz.
Zgarb

@Zgarb Özellikleri yanlış okudum ve birden fazla oyuncunun her zaman aynı köşeyi etkinleştirebileceğini düşündüm. Sanırım aramamı değiştirmem ve yalnızca etkin olmayan tepe noktası aramam gerekiyor.
Thrax

2

Rastgele Oluşturucu, Python 3

Bu, hiçbir şeyi mahvetmeyen ve her turda rastgele bir tepe noktası etkinleştirmeye çalışan aptal bir örnek bottur. Köşenin etkin olup olmadığını kontrol etmesi gerekmediğini unutmayın; kontrolör bununla ilgilenir.

import random as r

while True:
    msg = input().split()
    if msg[0] == "BEGIN":
        side_len = int(msg[3])
    elif msg[0] == "DESTROY":
        print("NONE")
    elif msg[0] == "ACTIVATE":
        print("VERTEX %d,%d"%(r.randrange(side_len), r.randrange(side_len)), flush=True)
    elif msg[0] == "SCORE":
        break

Komutla çalıştır

python3 random_builder.py

Sen değiştirmeniz gerekebilir python3tarafından pythonPython kurulumu bağlı. Bunu yapmak için sadece bots.txtdosyayı düzenleyin . Denetleyiciyi güncelledim ve artık dosya yollarını karıştırmaya gerek kalmadı.


Python 3'ü kullandığınızdan beri, yerine sys.stdout.flush()sadece flush=Truebir argüman olarak yapabilirsiniz print.
matsjoyce

@ matsjoyce Teşekkürler, bunu bilmiyordum. Depo sürümünü daha sonra düzenleyeceğim.
Zgarb

2

Kaşif, Python 3

Aktivasyon stratejisi:

Her düğümün durumuna göre (etkin / etkin değil / bozuk) bir ısı haritası oluşturur ve bunu seçerse kişi başına beklenen en büyük ısı haritası değerine sahip olan düğümü seçer.

İmha stratejisi:

Asla hiçbir şeyi yok etmeyecek, çünkü botlara pek yardımcı olmuyor.

import sys

class bd:

    def __init__(s, l):

        s.l=l
        s.b=[]
        s.v=[]
        s.m=[]
        s.bm=[]
        s.utd=False #up_to_date
        s.bmc=1

        for i in range(s.l):
            s.b+=[[]]
            s.v+=[[]]
            s.m+=[[]]
            s.bm+=[[]]
            for k in range(s.l):
                s.b[i]+=[0]
                s.v[i]+=[0]
                s.m[i]+=[0]
                s.bm[i]+=[s.bmc]

    def update(s):
        s.utd=True

        vu=[]
        vd=[]
        for i in range(s.l):
            vu+=[[]]
            vd+=[[]]
            for k in range(s.l):
                vu[i]+=[1]
                vd[i]+=[1]

        #spread up
        for i in range(s.l):
            vu[i][0]*=s.bm[i][0]

        for k in range(1,s.l):
            for i in range(s.l):
                sumv=vu[(i-1)%s.l][k-1]+vu[(i)%s.l][k-1]+vu[(i+1)%s.l][k-1]  
                vu[i][k]*=sumv*s.bm[i][k]/3

        #spread down
        t=s.l-1
        for i in range(s.l):
            vd[i][t]*=s.bm[i][t]

        for k in range(s.l-2,-1,-1):
            for i in range(s.l):
                sumv=vd[(i-1)%s.l][k+1]+vd[(i)%s.l][k+1]+vd[(i+1)%s.l][k+1]  
                vd[i][k]*=sumv*s.bm[i][k]/3

        #mult
        for i in range(s.l):
            for k in range(s.l):
                if s.b[i][k]==-1 or s.m[i][k]==1:
                    s.v[i][k]=float(-1)
                else:
                    s.v[i][k]=vu[i][k]*vd[i][k]/(s.b[i][k]+1)

    def add_act(s,al):
        s.utd=False

        for ind, ap in enumerate(al):
            i,k=ap
            s.b[i][k]+=1            
            s.bm[i][k]=2*s.bmc            
            #doesn't work alone WHY???
            if ind==0: s.m[i][k]=1

    def add_ina(s,il):
        s.utd=False

        for ind, ip in enumerate(il):
            i,k=ip
            s.b[i][k]=-1
            s.bm[i][k]=0                    

    def get_newact(s):
        s.update()
        vm=-28
        pm=None
        for i in range(s.l):
            for k in range(s.l):
                if s.v[i][k]>vm:
                    vm=s.v[i][k]
                    pm=(i,k)
        #doesn't work alone WHY???
        s.m[pm[0]][pm[1]]=1
        return pm


b=None

while True:
    inp=input()
    msg = inp.split()
    if msg[0] == "BEGIN":        
        b = bd(int(msg[3]))
    elif msg[0] == "DESTROY":
        print("NONE")
    elif msg[0] == "BROKEN":
        pl=[]
        for m in msg[2:]:
            if m!='N':
                pl+=[tuple(map(int,m.split(',')))]
        b.add_ina(pl)
    elif msg[0] == "ACTIVATE":
        at=b.get_newact()
        print("VERTEX %d,%d"%(at[0], at[1]))
    elif msg[0] == "OWNED":
        pl=[]
        for m in msg[2:]:
            if m!='N':
                pl+=[tuple(map(int,m.split(',')))]        
        b.add_act(pl)
    elif msg[0] == "SCORE":
        break       

    sys.stdout.flush()

1

Sıkıntı, Bash

#!/bin/bash

declare -A avail
broken=
owned=

while read c p
    case "$c" in
        ACTIVATE|BROKEN) v=broken;;
        *) v=owned
    esac
    case "$c" in
        BEGIN)
            read b t n <<<"$p"
            list=$(
                eval "echo {0..$((n-1))},{0..$((n-1))}\$'\\n'" |
                shuf
            )
            for i in $list; do
                avail[$i]=1
            done;;
        DESTROY|ACTIVATE)
            for t in $(
                for i in ${!v}; do
                    [ "$i" != N ] &&
                    if [ "$c" = ACTIVATE ]; then
                        echo $(((${i%,*}+2)%n)),${i#*,}
                        echo $(((${i%,*}-2+n)%n)),${i#*,}
                    else
                        echo ${i%,*},$(((${i#*,}+1)%n))
                        echo ${i%,*},$(((${i#*,}-1+n)%n))
                    fi
                done |
                shuf
            ) $list; do
                [ "${avail[$t]}" ] && echo VERTEX $t && break
            done ||
            echo NONE;;
        BROKEN|OWNED)
            read x m $v <<<"$p";
            for i in $m ${!v}; do
                unset avail[$i]
            done;;
        SCORE)! :
    esac
do :;done

Sonuç daha ilginç görünmeye çalıştı.

İle koş bash annoyance.sh.


1
Botunuz tüm girişlerini STDERR'ye yazdırıyor. Bu yasak veya herhangi bir şey değil, sadece bir sıkıntı (amaçlanan).
Zgarb

@ Zgarb Üzgünüm, yanlış sürümü yapıştırdım. Sabit.
jimmy23013

1

Orta adam

Bazı botların üstten, bazılarının alttan inşa edildiğini gördüm. Bu ilk (sanırım) ortadan başlamak ve yukarı ve aşağı çalışmaktır.

(Kontrol cihazı ile test edilmemiştir, bu nedenle dozu işe yaramazsa, bana bildirin.)

class Node

  def self.set_size s
    @@grid = Array.new(s,Array.new(s,0))
  end

  def initialize x,y
    @x=x
    @y=y
  end

  def offset dx,dy
    return Node.new @x+dx,@y+dy
  end

  def state
    return -1 if @x<0 || @y<0 || @x>=@@grid.length || @y>=@@grid.length
    @@grid[@x][@y]
  end

  def state= n
    return -1 if @x<0 || @y<0 || @x>=@@grid.length || @y>=@@grid.length
     @@grid[@x][@y]=n
  end

  def active?
    state > 0
  end

  def open?
    state == 0
  end
  attr_reader :x,:y

  def to_s
    "VERTEX #{@x},#{@y}"
  end


  def scan_down
    ans = nil
    [0,-1,1].each do|offset|
      n = Node.new @x+offset,@y-1
      ans = (ans||n) if n.open?
      ans = (n.scan_down||ans) if n.active?
    end
    return ans
  end

  def scan_up
    ans = nil
    [0,-1,1].each do|offset|
      n = Node.new @x+offset,@y+1
      ans = (ans||n) if n.open?
      ans = (n.scan_up||ans) if n.active?
    end
    return ans
  end

end

input = gets.split
input.shift

BotCount = input.shift.to_i
Turns = input.shift.to_i
GridSize = input.shift.to_i

Node.set_size GridSize

midRow = GridSize/2

toDestroy = (0...GridSize).map{|i|Node.new i,midRow}
toDestroy.reject!{|n| n.x==midRow}

chain = []
Turns.times do
  gets;
  toDestroy.each{|x|
    if x.active?
      toDestroy.push x.offset 0,1
      toDestroy.push x.offset 1,1
      toDestroy.push x.offset -1,1
    end
  }
  toDestroy.reject!{|x|!x.open?}
  puts toDestroy.sample
  input = gets.split
  input.shift;input.shift
  input.each{|str|
    a,b = str.split ','
    (Node.new a.to_i,b.to_i).state=1
  }
  gets;

  if chain.length == 0
    n = Node.new midRow,midRow
    until n.open?
      n = Node.new n.x+1,midRow
    end
    puts chain[0]=n
  elsif rand>0.5
    n=nil
    loop do
      h=chain[0]
      n = h.scan_down
     break if !n
      chain.shift
    end
    h.unshift n
    puts n
  else
    loop do
      h=chain[-1]
      n = h.scan_up
      h.pop if !n
      brake if n
    end
    chain.push n
    puts n
  end

  input = gets.split
  input.shift;input.shift
  input.each{|str|
    a,b = str.split ','
    (Node.new a,b).state=-1
  }

end
gets
exit

Gönderdiğiniz için teşekkür ederiz! Ne yazık ki, bu zorluk neredeyse yarım yıldır devam ediyor ve şu anda birçok botu çalıştıramıyorum, çünkü dilleri yükleyebileceğim bir bilgisayara erişimim yok.
Zgarb

1
@ Zgarb anlıyorum. belki bir gün makul bir zaman diliminde bir mücadeleye cevap vereceğim ...
MegaTom
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.