King of the Hill - Strażacy

27

Na prerii jest suche lato. Czterej rolnicy w okolicy zdają sobie sprawę, że mogą zaokrąglić rynek kukurydzy, spalając uprawy sąsiadów. Ale potrzebują do tego strategii; właśnie tam wchodzisz.

Twoim zadaniem jest napisanie bota, który powie rolnikom, co spalić. Celem jest ukończenie gry z największym obszarem niespalonej ziemi. Pole gry to siatka 32 x 32. Każda komórka może być jedną z następujących czynności:

. - Ground

@ - A bot

# - Ash

W - Wet ground

1,2,3,4,5, or 6 - Fire

Intensywność ognia wzrasta o 1 w każdej turze. Gdy osiągnie wartość 3 lub wyższą, podpali komórki obok niej (poziomo lub pionowo). Gdy ogień osiągnie 6, zamienia się w popiół.

W każdej turze boty otrzymują jako STDIN: bot startujący x, bot startujący y, bot bieżący x pozycja, bot bieżący y pozycja i plansza, oddzielone znakami nowej linii. Przykład:

8
22
6
24
................................
................................
................................
.....................1..........
....................1#1.........
...................1#363........
....................16@1........
.....................31.........
................................
.........1.1....................
........15#62...................
........15@2....................
.........32.....................
................................
................................
................................
................................
................................
................................
................................
................................
................................
....4.1.........................
.....1#3........................
.....@3.........................
.....W..........................
................................
................................
................................
................................
................................
................................

(w tym przypadku jesteś botem w lewym dolnym rogu).

Musisz wypisać trzy znaki, z opcjonalnym znakiem nowej linii, reprezentujące następujące elementy:

Przenieś - jeden z L, R, U, D, or S (stay)

Działanie - jeden z B (burn), P (pour water) or X (do nothing)

Kierunek - jeden z L, R, U, D or S- kontroluje, na której komórce wykonujesz akcję

Ogień nie wpływa na boty.

Kolejność kolei jest następująca: Wszystkie boty się poruszają; wszystkie boty wykonują akcje; wtedy mają miejsce reguły środowiskowe. Jeśli wylejesz wodę na ziemię, będzie ona mokra ( W) na jedną turę. Ogień nie rozprzestrzeni się na mokrą ziemię. Jeśli wylejesz wodę na mokrą ziemię, nadal będzie mokra. Jeśli wlejesz wodę do ognia, powróci ona do normalnego podłoża. Nie możesz nic zrobić.

Rundy są prowadzone z 4 botami jednocześnie. Runda kończy się po 50 turach lub gdy jeden bot skończy się z niespalonej ziemi, w zależności od tego, co nastąpi wcześniej. Twój wynik jest obliczany jako liczba naziemnych lub mokrych komórek naziemnych w kwadracie 9 x 9 wyśrodkowanym na początku twojego bota.

Oto przykładowy bot; wybiera losowo wszystkie trzy litery i na ogół spala własne pola.

RandomBurner:

#!/usr/bin/env python
import random
print random.choice('LRUDS')+random.choice('BPX')+random.choice('LRUDS')

Zasady:

  • Brak dostępu do systemu plików poza własnym folderem.
  • Możesz zapisywać do plików, jeśli chcesz przechowywać trwałe dane między kolejkami, ale tylko do 1 KB na bota
  • Nie możesz nadpisywać niczyich botów
  • Jeśli wydasz nieprawidłowy ruch, twój bot będzie siedział nieruchomo. Jeśli wydasz nieprawidłową akcję, twój bot nic nie zrobi.
  • Proszę trzymać się popularnych języków, które można uruchomić na systemie OSX lub Linux.

Kod kontrolera można znaleźć tutaj.

Wstępne wyniki:

Average of 15 rounds:
---------------------
81 Farmer
56 CautiousBot
42 GetOff
41 Visigoth
40 DontBurnMeBro
37 FireFighter
35 Pyro
11 Protector

Aktualizacja : Dodano Farmera, CautiousBota, GetOff, FireFighter i Pyro.

Skyler
źródło
1
Deska nie zawija się na krawędziach, prawda?
Zgarb
1
Dobrze. Jeśli spróbujesz przejść obok krawędzi, po prostu nie ruszaj się.
Skyler
4
Nie rozumiem jednego szczegółu. Jaka ziemia jest moja i jaka jest twoja?
kaine
3
Twoja ziemia jest tym, co było w obszarze bloku 9 x 9, na środku, od którego zacząłeś. Wszystkie boty rozpoczynają rundę co najmniej 8 bloków od siebie, więc nie nakładają się.
Skyler,
2
Nie jest pod warunkiem. Jeśli chcesz to jakoś nagrać, jest to opcja. Siedzenie w ogniu w celu ukrycia to ważna strategia.
Skyler

Odpowiedzi:

5

Visigoth

Visigoth próbuje spalić wrogów na ziemię. Ma nadzieję to zrobić, zanim ktokolwiek dotrze na jego ziemię.

Biegać: python visigoth.py

#!/usr/bin/python

''' Charge the enemy and burn them to the ground. '''

import sys

data = sys.stdin.readlines()

startx, starty, x, y = [int(i) for i in data[0:4]]
field = [list(i) for i in data[4:]]

otherbots = []
for i in range(32):
    for j in range(32):
        if field[i][j]=='@': #bot
            if i!=y and j!=x:
                otherbots.append([j,i])

min_bot = otherbots[0]
for bot in otherbots:
    if abs(bot[0]-x)+abs(bot[1]-y) < abs(min_bot[0]-x)+abs(min_bot[1]-y):
        min_bot = bot

dx = min_bot[0]-x
dy = min_bot[1]-y

if abs(dy)>abs(dx):
    if dy>0:
        move = 'U'
    else:
        move = 'D'
else:
    if dx>0:
        move = 'R'
    elif dx<0:
        move = 'L'
    else:
        move = 'S'

if max(abs(x-startx), abs(y-starty))>4:
    if 0<x<31 and 0<y<31:
        dirs = {'U':(-1,0), 'D':(1,0), 'L':(0,-1), 'R':(0,1)}
        for i in dirs:
            if field[dirs[i][0]][dirs[i][1]] in ('.', 'W'):
                action = 'B'+i
                break
        else:
            # No free land nearby, go out in a blaze of glory
            action = 'BS'
    else:
        action = 'BS'
else:
    # Don't set own field on fire
    action = 'XS'

print move+action

To mój pierwszy wpis, konstruktywna krytyka jest doceniana!

taixzo
źródło
„Ogień nie wpływa na boty”
Conor O'Brien
Visigoth wydaje się rzadko palić.
Skyler
Och, właśnie zauważyłem, że mam to, minco powinienem był max. Naprawiłem to.
taixzo
@ CᴏɴᴏʀO'Bʀɪᴇɴ W rzeczywistości nie próbuje spalić wrogich botów, zakładając, że pozostaną w pobliżu własnej bazy. Byłby bardzo słaby przeciwko sobie.
taixzo,
Rozumiem. To ma więcej sensu.
Conor O'Brien,
4

Java, Protector

Próbuje otoczyć swoje pole płotem popiołu.

Edycja: Ulepszona logika. Prawdopodobnie nie zrobi różnicy.

import java.awt.Point;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

/**
 * Created 10/6/15
 *
 * @author TheNumberOne
 */
public class Protecter {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Point start = new Point(in.nextInt(), in.nextInt());
        Point current = new Point(in.nextInt(), in.nextInt());
        in.nextLine();
        String output = "";
        char[][] board = new char[32][];
        for (int i = 0; i < 32; i++){
            board[i] = in.nextLine().toCharArray();
        }
        List<Point> danger = new ArrayList<>();
        List<Point> close = new ArrayList<>();
        List<Point> closeDanger = new ArrayList<>();
        List<Point> fence = new ArrayList<>();
        for (int i = 0; i < 32; i++){
            for (int j = 0; j < 32; j++){
                Point p = new Point(i, j);
                char c = board[j][i];
                if (Math.abs(p.x - start.x) < 10 && Math.abs(p.y - start.y) < 10){
                    if ((c + "").matches("\\d")){
                        danger.add(p);
                    }
                }
                if (distance(current, p) == 1){
                    close.add(p);
                }
                if ((Math.abs(p.x - start.x) == 10 || Math.abs(p.y - start.y) == 10) && !(c + "").matches("#|\\d|@")){
                    fence.add(p);
                }
            }
        }
        closeDanger = new ArrayList<>(danger);
        closeDanger.retainAll(close);
        danger.sort(Comparator.comparingInt(a -> distance(current, a) / (board[a.y][a.x] - '0')));
        if (danger.size() > 0){
            output += moveTo(current, danger.get(0));
        } else {
            fence.sort(Comparator.comparingInt(a -> distance(current, a)));
            if (fence.size() == 0){
                output += "S";
            } else {
                output += moveTo(current, fence.get(0));
            }
        }
        closeDanger.sort(Comparator.comparingInt(a -> board[a.y][a.x] - '0'));
        if (closeDanger.size() > 0){
            output += "P";
            output += moveTo(current, closeDanger.get(0));
        } else {
            if (danger.size() == 0) {
                List<Point> closeFence = new ArrayList<>(fence);
                closeFence.retainAll(close);
                if (closeFence.size() > 0) {
                    output += "B";
                    output += moveTo(current, closeFence.get(0));
                } else {
                    if (!fence.contains(current)){
                        output += "PS";
                    } else {
                        output += "BS";
                    }
                }
            } else {
                if (!fence.contains(current)){
                    output += "PS";
                } else {
                    output += "BS";
                }
            }
        }
        System.out.println(output);
    }

    private static String moveTo(Point from, Point to) {
        if (from.x > to.x){
            return "L";
        }
        if (from.x < to.x){
            return "R";
        }
        if (from.y > to.y){
            return "U";
        }
        if (from.y < to.y){
            return "D";
        }
        return "S";
    }

    private static int distance(Point p1, Point p2){
        return Math.abs(p1.x - p2.x) + Math.abs(p2.y - p1.y);
    }

}

Umieść w pliku o nazwie Protector.java.

Kompiluj z: javac Protector.java
Uruchom z:java Protector

Numer jeden
źródło
Najpierw musiał zmienić nazwę na Protecter.java, aby go skompilować. Ale kiedy go uruchamiam, generuje wyjątek java.lang.ArrayIndexOutOfBoundsException w wierszu 29.
Skyler
@ Skyler naprawił to :)
TheNumberOne
Dzięki, dodałem to do wyników. Obrońca nie zawsze gasi pożary, które rozpala.
Skyler,
2
W
pewnym sensie
@Fatalize Właśnie tego nauczono mnie, gdy zostałem przyłapany na pożarze lasu / pustyni :)
TheNumberOne
2

GetOff, Python

GetOff chce po prostu zachować swoją ziemię dla siebie i nie boi się ścigać tych cholernych botów po całej swojej ziemi, wyrzucając je z pistoletu na wodę, dopóki nie odejdą. Chociaż jego własność nie jest naruszana, dokłada wszelkich starań, aby jego ziemia nie uległa spaleniu.

#!/usr/bin/env python

import sys

fire = ['1','2','3','4','5','6']

move = ''
ad = ''

data = sys.stdin.readlines()

startx, starty, x, y = [int(i) for i in data[0:4]]
board = [list(i) for i in data[4:]]

top = starty-4
bottom = starty+5
right = startx+5
left = startx-4

bots = []
for i in range(32):
    for j in range(32):
        if board[i][j]=='@':
            if i != y and j != x:
                bots.append([j,i])

fires = []
for i in range(32):
    for j in range(32):
        if board[i][j] in fire: #fire
            fires.append([j,i])

for bot in bots:
    if left < bot[0] < right and top < bot[1] < bottom: # if there's a bot in the field
        if bot[0] > x:
            move = 'R'
        elif bot[0] < x:
            move = 'L'
        elif bot[1] > y:
            move = 'D'
        elif bot[1] < y:
            move = 'U'
        else:
            move = 'S'
    else:
        nearest_fire = []
        for f in fires:
            if left < f[0] < right and top < f[1] < bottom:
                if nearest_fire == []:
                    nearest_fire = f
                elif (f[0]-x)+(f[1]-y) < (nearest_fire[0]-x)+(nearest_fire[1]-y):
                    nearest_fire = f
        if nearest_fire == []:
            move = 'S'
        else:
            if nearest_fire[0] > x:
                move = 'R'
            elif nearest_fire[0] < x:
                move = 'L'
            elif nearest_fire[1] > y:
                move = 'D'
            elif nearest_fire[1] < y:
                move = 'U'
            else:
                move = 'S'

if board[x-1][y] in fire: # position immediately to the left
    ad = 'L'
elif board[x+1][y] in fire: # position immediately to the right
    ad = 'R'
elif board[x][y-1] in fire: # position immediately up
    ad = 'U'
elif board[x][y+1] in fire: # position immediately down
    ad = 'D'
else:
    ad = 'S'

print(move+'P'+ad)
The Beanstalk
źródło
Czy a < b < cskładnia działa w języku Python? Myślałam, że ma wartość (a < b) < c, która jest albo 1 < calbo 0 < c. Popraw mnie, jeśli się mylę. (Znaleziony w pierwszym stanie pętli bota).
Conor O'Brien,
To zawsze działało dla mnie, ale nie jestem pewien, czy działa w każdej wersji Pythona ...
The Beanstalk
@ CᴏɴᴏʀO'Bʀɪᴇɴ wierzy, że tak, 1<3>2ocenia Truena moim komputerze (gdyby je zgrupować, zwróciłoby wartość false: 1>2i 1<1są możliwości).
cole
@Cole Thanks. Byłem w trybie myślenia JavaScript. Właśnie wypróbowałem to na repl.it. Więcej powodów, dla których Python jest piękny.
Conor O'Brien,
2

Farmer, Java

Rolnik dba tylko o swoje uprawy. Stale obserwuje swoje pole pod kątem ewentualnych pożarów lub najeźdźców.

import java.awt.Point;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

public class Farmer {

    public static void main(String[] args) {
        //row == y
        //col == x
        Scanner in = new Scanner(System.in);
        Point start = new Point(in.nextInt(), in.nextInt());
        Point current = new Point(in.nextInt(), in.nextInt());
        in.nextLine();
        char[][] board = new char[32][];
        for (int row = 0; row < 32; row++){
            board[row] = in.nextLine().toCharArray();
        }
        final List<Point> firesInField = new ArrayList<>();
        final List<Point> enemiesInField = new ArrayList<>();
        for (int row = 0; row < 32; row++) {
            for (int col = 0; col < 32; col++) {
                Point p = new Point(col, row);
                if (!isInField(start, p))
                    continue;
                char c = board[row][col];
                if (isFire(c)) {
                    firesInField.add(p);
                } else if (c == '@' && col != current.x && row != current.y) {
                    enemiesInField.add(p);
                } 
            }
        }
        List<Point> destinations = firesInField.size() > 0 ? firesInField : enemiesInField;

        if (destinations.size() > 0) {
            //take short paths to eliminate more fires
            destinations.sort(Comparator
                    .comparingInt((Point p) -> distance(p, current))
                    .thenComparingInt(p -> -1 * (board[p.y][p.x] - '0')));
            Point dest = destinations.get(0);
            print(moveTo(current, dest), "P", moveTo(current, dest));
        }

        //TODO start fires if an enemy has more intact ground

        //walk back to center
        print(moveTo(current, start), "P", moveTo(current, start));
    }

    private static void print(String move, String action, String actionMove) {
        System.out.println(move + action + actionMove);
        System.exit(0);
    }

    private static boolean isInField(Point centerOfField, Point toTest) {
        //add one extra, to prevent fires that are very near
        return distance(centerOfField, toTest) <= 10 && Math.abs(centerOfField.x - toTest.x) <= 5 && Math.abs(centerOfField.y - toTest.y) <= 5;
    }

    private static boolean isFire(char c) {
        return c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6';
    }

    private static String moveTo(Point from, Point to) {
        if (from.x > to.x){
            from.x--;
            return "L";
        }
        if (from.x < to.x){
            from.x++;
            return "R";
        }
        if (from.y > to.y){
            from.y--;
            return "U";
        }
        if (from.y < to.y){
            from.y++;
            return "D";
        }
        return "S";
    }

    private static int distance(Point p1, Point p2){
        return Math.abs(p1.x - p2.x) + Math.abs(p2.y - p1.y);
    }
}
CommonGuy
źródło
1
Niewielka poprawa, w isFirektórej można Character.isDigitzamiast tego użyć .
J Atkin,
2

Pyro, python

Pyro lubi ogień. Pyro uwielbia ogień. Pyro żyje w ogniu. Myślę o „Pyro z TF2”. Pyro lubi palić rzeczy. Nie spali własnego terytorium, ale spróbuje się z niego wydostać, używając prostego algorytmu „znajdowania ścieżki”.

import sys
import random
inpu          = sys.stdin.readlines()
ox,oy,x,y     = [int(i) for i in inpu[0:4]]
board         = [list(i) for i in inpu[4:]]
adjacentcells = [[[board[y+b][x+c],b,c] for b in range(-1,2)] for c in range(-1,2)]
action        = ""
infield=max(abs(ox-x),abs(oy-y))<=9
# let's find out what Pyro will do!
if not infield: # Pyro won't burn what's in his field.
    for row in adjacentcells:
        for entry in row:
            cell,a,b=entry
            if(a!=b):   # Can't act on these cells.
                if cell==".":   # burn it!!!!!!
                    action = "B"
                    if(a==0):
                        direction = {-1:"L",1:"R"}[b]
                    else:
                        direction = {-1:"D",1:"U"}[a]
            if action: break;
        if action: break;
    # Pyro doesn't care where he goes, so long as
    # Pyro's not in the field of Pyro.
    move = random.choice("LRUDS")
else:   # Thought Pyro hates water, Pyro must protect SOMETHING.
    action    = "P"
    direction = "S"
    # get the direction towards the center
    # Pyro will move away from ox and oy to
    # towards the center, if in the field.
    # Pyro will do this by first going right/left,
    # then going up/down. (This behaviour is
    # removed when he leaves his field.)
    cx = cy = 16
    while max(abs(cx-x),abs(cy-y))<=9:
        cx = random.randint(0,31)
        cy = random.randint(0,31)
    if(cx-x>0): #is to the left of the center
        move = "R"
    elif(cx-x<0): #is to the right of the cenetr
        move = "L"
    elif(cy-y>0): # is above center
        move = "D"
    elif(cy-y<0): # is below center
        move = "U"
    else:   # is at center (something went wrong!)
        move   = "S"
        action = "B"
if not move:
    move = "S"
if not action:
    action = "B"
if not direction:
    direction = "S"
print(move+action+direction)


""" Here, have a face!
MMMMMMMMMMMMMMMMMMMMMMMdyo/:-.````.:+sdMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMNs/....----...``````.omMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMh/``..-://+//:-..````````/mMMMMMMMMMMM
MMMMMMMMMMMMMMMm:````..-:////:--..``````````sMMMMMMMMMM
MMMMMMMMMMMMMMs```````....--....`````````````/NMMMMMMMM
MMMMMMMMMMMMM/````````````````````````````````:NMMMMMMM
MMMMMMMMMMMM/```......``````````````````.......+mMMMMMM
MMMMMMMMMMMo.:::::::::::-````````````.-:::::::::/+yNMMM
MMMMMMMMMNs:-..-------::::.`````````://:-------..-:/hMM
MMMMMMMMm+:..---:::::---:::.```````::::---:::::--.`-/sM
MMMMMMMN+:`.---:::/:/:---:::``````.:::.--:::/:/:--.`:/h
MMMMMMMh:-`---://o+///:---::.`````-::---://oo///:--..:+
MMMMMMMs:..--:/+/sss+//:-.::.`````-::.-://+osyo//:-.-::
MMMMMMMs:----///+sosso/:--::``````.::.-://+oosso+:-.::/
MMMMMMMd:::-:/++/osyso+/--::```````::-://+/osyso+/--::s
MMMMMMMMs:/::::+ooos+o+/:::.```````.::::/+ooos/o+/:/:+N
MMMMMMMMMs://:+osooo+o+/::.``.....``.:/:/osoos+o+//:+mM
MMMMMMMMMM--:/++ysyoo+/:-...........`.-:/+ssso++/:-yNMM
MMMMMMMMMMs``.-:://::-..`.....---....``..--::::-.`.MMMM
MNNMddhyys+-.```````````...--:::::-...````````````+MMMM
////.-:///:-..``````````.:///++o/o+/:/.```````````yMMMM
---.`.-:::--..`````````..+//+ooo+++///.```````````mMMMM
/.--``..--...``````````..--:/+oo+/:--..``````````.MMMMM
s --.```...````````````...--/+++++/-...````````.`/MMMMM
d .--```````````````````...-::::::-...````````.-/+MMMMM
M.`--`  ````````````````....------....````````.-/.dMMMM
M+ .-.  `````````````````.:::::::::::.`````````.-sMMMMM
Mm``--`  ``````````````-://///////////:-````````/MMMMMM
MM: --.  ````````````.://::--......-::///-``````yMMMMMM
MMd`.-.  ``````````.:/::-..-:::::::.``-::::.````NMMMMMM
MMM+.--`  `````````:::-.-::-.......-::-`--::```+MMMMMMM
MMMN---`  ````````.--..:-.```````````..-`.--.``dMMMMMMM
MMMMd--.` `````..`.-.`-````````````````.-`...`/MMMMMMMM
MMMMMNh+ss/oydNMd``.`.`````````````````````.`.NMMMMMMMM
MMMMMMMMMMMMMMMMMd.``.```````````````````````dMMMMMMMMM
MMMMMMMMMMMMMMMMMMm:```````````````````````-dMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMy.```````````````````.oNMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMNs-```````````````:sNMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMmy+:-.````.:+ymMMMMMMMMMMMMMMMM
"""
Conor O'Brien
źródło
2
Za mało dwuznaczności co do płci Pyro w opisie i komentarzach.
cole
@Cole Oh darn. Zapomniałem o tym dziwactwie. Na pewno będę edytować z pewną dwuznacznością;)
Conor O'Brien
Nie działa, ponieważ po wyrażeniu else w wierszu 21. nie ma nic
Skyler
Teraz pęka w wierszu 5 („dane” nie są zdefiniowane)
Skyler,
@ Skyler Naprawiono ponownie. Tak mi przykro. Zrobiłem to bez mojego interpretera Pythona.
Conor O'Brien,
2

DontBurnMeBro

Kolejny wpis w języku Python. Z pewnością nie umrze jako pierwszy (tak myślę).

#!/usr/bin/python

print "SPS"
taixzo
źródło
4
Na podstawie specyfikacji wody wlewającej Pnie ma W.
randomra
Ups, dzięki.
taixzo
1

FireFighter, Java

Zwalcza wszystkie pożary.

import java.awt.Point;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

/**
 * Created 10/7/15
 *
 * @author TheNumberOne
 */
public class FireFighter {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Point start = new Point(in.nextInt(), in.nextInt());
        Point current = new Point(in.nextInt(), in.nextInt());
        in.nextLine();
        String output = "";
        char[][] board = new char[32][];
        for (int i = 0; i < 32; i++) {
            board[i] = in.nextLine().toCharArray();
        }

        List<Point> danger = new ArrayList<>();
        List<Point> close = new ArrayList<>();
        List<Point> closeDanger;
        for (int i = 0; i < 32; i++){
            for (int j = 0; j < 32; j++){
                Point p = new Point(i, j);
                char c = board[j][i];
                if ((c + "").matches("\\d")){
                    danger.add(p);
                }
                if (distance(current, p) == 1){
                    close.add(p);
                }
            }
        }
        closeDanger = new ArrayList<>(danger);
        closeDanger.retainAll(close);

        Comparator<Point> comparator = Comparator.comparingInt((Point a) -> board[a.y][a.x]).reversed();

        danger.sort(comparator);
        danger.sort(Comparator.comparingInt(a -> distance(start, a)));
        if (danger.size() > 0){
            output += moveTo(current, danger.get(0));
        } else {
            output += moveTo(current, start);
        }
        closeDanger.sort(comparator);
        if (closeDanger.size() > 0){
            output += "P" + moveTo(current, closeDanger.get(0));
        } else {
            output += "PS";
        }
        System.out.println(output);
    }

    private static String moveTo(Point from, Point to) {
        if (from.x > to.x){
            return "L";
        }
        if (from.x < to.x){
            return "R";
        }
        if (from.y > to.y){
            return "U";
        }
        if (from.y < to.y){
            return "D";
        }
        return "S";
    }

    private static int distance(Point p1, Point p2){
        return Math.abs(p1.x - p2.x) + Math.abs(p2.y - p1.y);
    }

}
Numer jeden
źródło
0

Keeper, Python 2

import sys

Out = ["S", "P", "S"]

StX = int(sys.stdin.readline()) - 1
StY = int(sys.stdin.readline()) - 1
NowX = int(sys.stdin.readline()) - 1
NowY = int(sys.stdin.readline()) - 1
Map = []
for i in range(32):
    Map.append(sys.stdin.readline())

Pos = [NowX, NowY]
Area = [[StX, StY]]
for x in range(StX-4, StX+4):
    for y in range(StY-4, StY+4):
        Area.append([x, y])

Fires = []
for y in range(32):
    for x in range(32):
        if Map[y][x] in "123456":
            Fires.append([x, y])

Danger = []
for Tile in Area:
    if Map[Tile[1]][Tile[0]] in "123456":
        Danger.append(Tile)

Distance = {}
i = -1
for Fire in Danger:
    i += 1
    Distance[(Pos[0] - Fire[0], Pos[1] - Fire[1])] = i

i = min(Distance)
Closest = Danger[Distance[i]]

if Closest[0] > Pos[0]:
    Out[0] = Out[2] = "R"
    Pos[0] += 1
if Closest[0] < Pos[0]:
    Out[0] = Out[2] = "L"
    Pos[0] -= 1
if Closest[0] == Pos[0]:
    if Closest[1] > Pos[1]:
        Out[0] = Out[2] = "D"
        Pos[1] += 1
    if Closest[1] < Pos[1]:
        Out[0] = Out[2] = "U"
        Pos[1] -= 1

if Closest[0] + 1 == Pos[0] and Closest[1] == Pos[1]:
    Out[2] = "L"
if Closest[0] - 1 == Pos[0] and Closest[1] == Pos[1]:
    Out[2] = "R"
if Closest[1] + 1 == Pos[1] and Closest[0] == Pos[0]:
    Out[2] = "U"
if Closest[1] - 1 == Pos[1] and Closest[0] == Pos[0]:
    Out[2] = "D"
if Closest[0] == Pos[0] and Closest[1] == Pos[1]:
    Out[2] = "S"


print "".join(Out)

Można to uprościć, ale jestem zmęczony.

Opiekun próbuje uchronić swoje pole przed krzywdą. Jeśli pojawi się ogień, podbiega do niego i gasi go tak szybko, jak to możliwe.

Mogę również dodać zakwaterowanie na nadchodzące pożary.

The_Basset_Hound
źródło
Linia 36: ValueError: min() arg is an empty sequence- generuje błędy, jeśli jeszcze nic nie jest w płomieniach.
Skyler
@Skyler Naprawię za chwilę, przepraszam.
The_Basset_Hound
0

CautiousBot, Node.js (ES5)

Ten bot wychodzi i próbuje podpalić ziemię innych botów. Siedzi nawet na szczycie ognia przez 3 tyknięcia, aby go ukryć! Jednak nigdy nie można być zbyt ostrożnym, dlatego zawsze upewnia się, że jest wystarczająco blisko, aby ugasić pożar na własnej ziemi.

Uwagi:

  • Wykorzystuje plik stanu o nazwie state.jsonprzechowywany w swoim katalogu roboczym, służący do przechowywania informacji o początkowych pozycjach innych botów i określania, jak długo ukrywać rozpoczęty pożar. Należy to usunąć po zakończeniu rundy (np. Gdy wygrał jakiś bot). W przeciwnym razie bot będzie zdezorientowany w następnej rundzie. (Daj mi znać, jeśli to złamie zasady).
  • Wymaga splitmodułu.
#!/usr/bin/env node

// imports
var fs       = require("fs");
var splitmod = require("split");

// variables
var startX, startY, currentX, currentY, board = [], state = {};
var DEBUG = false;

// utility functions
function debug(){
    if(DEBUG) console.log.apply(console, arguments);
}

// calculates manhattan distance which is also the number of turns it will take to get somewhere
function manhattan(x1, y1, x2, y2){
    return Math.abs(x2 - x1) + Math.abs(y2 - y1);
}

// calculates chebyshev distance (mostly used for determining if a bot is within someone's plot)
function chebyshev(x1, y1, x2, y2){
    return Math.max(Math.abs(x2 - x1), Math.abs(y2 - y1));
}

// gets the board character at x, y
function get(x, y){
    return board[y][x];
}

function readState(){
    try {
        state = JSON.parse(fs.readFileSync('state.json').toString());
        debug("Opened state file");
    } catch(e){
        // it must be the first turn
        createState();
    }
}

function writeState(){
    fs.writeFileSync('state.json', JSON.stringify(state));
    debug("Wrote state file");
}

// finds out where all the other bots are
function getBotPositions(){
    var positions = [];
    for(var x = 0; x < 32; x++){
        for(var y = 0; y < 32; y++){
            if(get(x, y) == '@' && x != currentX && y != currentY){
                positions.push({x: x, y: y});
            }
        }
    }
    return positions;
}

function createState(){
    debug("Creating state");
    // take a loot at where other bots are to record their land locations
    var botLands = getBotPositions();
    state['botLands'] = botLands;

    state['turn'] = 0; // which turn is it?
    state['lastFireTurn'] = -999; // which turn was the last one where this bot set a fire?
}


// finds whether a plot of land (defined by its center) has fire on it
function isLandBurning(x, y){
    for(var dx = -4; dx < 5; dx++){
        for(var dy = -4; dy < 5; dy++){
            if(get(x + dx, y + dy).match(/[1-6]/) != null) return true;
        }
    }
    return false;
}

// finds the fire with the highest number (and therefore the one to put out first)
function findFire(x, y){
    var highestNum = 0;
    var fire = {x: x, y: y};
    for(var dx = -4; dx < 5; dx++){
        for(var dy = -4; dy < 5; dy++){
            if(get(x + dx, y + dy).match(/[1-6]/) != null){
                var num = parseInt(get(x + dx, y + dy));
                if(num > highestNum){
                    highestNum = num;
                    fire = {x: x + dx, y: y + dy};
                }
            }
        }
    }
    return fire;
}

// figures out where to go to get somewhere
function getDirection(x1, y1, x2, y2){
    var direction = 'S';
    var cycx = Math.abs(y2 - y1) / Math.abs(x2 - x1);

    if(cycx < 1){
        if(x2 > x1) direction = 'R';
        if(x2 < x1) direction = 'L';
    } else {
        if(y2 > y1) direction = 'D';
        if(y2 < y1) direction = 'U';
    }

    debug("Getting direction", x1, y1, x2, y2, "result", direction);

    return direction;
}

// read input
var dataCycle = 0;
process.stdin.pipe(splitmod()).on('data', function(line){
    switch(dataCycle){
    case 0:
        startX = parseInt(line);
        break;
    case 1:
        startY = parseInt(line);
        break;
    case 2:
        currentX = parseInt(line);
        break;
    case 3:
        currentY = parseInt(line);
        break;
    default:
        board.push(line);
    }

    dataCycle++;
}).on('end', function(){
    // main bot code
    readState();
    state['turn']++;
    debug("It is turn", state['turn']);

    // get bot positions
    var botPositions = getBotPositions();

    var action = {type:'X', direction:'S'};
    var move   = 'S';

    var isMyLandBurning = isLandBurning(startX, startY);
    if(isMyLandBurning){ // hurry over there ASAP!
        debug("Bot land is burning!");
        var pos = findFire(startX, startY);
        debug("Fire found at", pos);
        move = getDirection(currentX, currentY, pos.x, pos.y);
        // simulate the move and figure out if/where to dump the water
        var newX = currentX + (move == 'R') - (move == 'L');
        var newY = currentY + (move == 'D') - (move == 'U');
        if(chebyshev(newX, newY, pos.x, pos.y) < 5){
            // on its own land, start dropping water like a madman
            debug("Dropping water");
            action.type = 'P';

            // if it can put out the target fire, then do that
            if(manhattan(newX, newY, pos.x, pos.y) == 1) action.direction = getDirection(newX, newY, pos.x, pos.y);
            // it's not in range of the target fire, so use the time to put out other fires
            // if it's moving on top of a fire, put that out
            else if(get(newX, newY).match(/[1-6]/) != null) action.direction = 'S';
            // if there's a fire around it then put that out
            else if(get(newX + 1, newY).match(/[1-6]/) != null) action.direction = 'R';
            else if(get(newX - 1, newY).match(/[1-6]/) != null) action.direction = 'L';
            else if(get(newX, newY + 1).match(/[1-6]/) != null) action.direction = 'D';
            else if(get(newX, newY - 1).match(/[1-6]/) != null) action.direction = 'U';
            else action.direction = 'S';
        }
    } else {
        // are there any bots that could start a fire when this bot is 6+ tiles away?
        var headBack = false;
        for(var i = 0; i < botPositions.length; i++){
            var otherBot = botPositions[i];
            var dist = manhattan(otherBot.x, otherBot.y, startX, startY) - 4;
            var myDist = manhattan(currentX, currentY, startX, startY);
            if(dist + 6 < myDist){
                headBack = true;
                break;
            }
        }
        if(headBack){ // they're probably up to no good
            debug("Bots are dangerously close, heading back");
            move = getDirection(currentX, currentY, startX, startY);
        } else if(state['turn'] - state['lastFireTurn'] < 3) { // no bots near own plot, time to consider other options
            debug("Hiding fire");
            // sneakily hide the fire if one was set :)
        } else { // last option is to go find land to burn
            debug("Finding land to burn");
            var closestX = 999, closestY = 999;
            for(var i = 0; i < state.botLands.length; i++){
                var otherLand = state.botLands[i];
                if(!isLandBurning(otherLand.x, otherLand.y) && chebyshev(currentX, currentY, otherLand.x, otherLand.y) > 4){ // find someone to burn
                    // use [-3, 3] here because on the first turn, the bots could have moved before this bot had a chance to see them
                    // meaning that the [-3, 3] region is the only one that is guaranteed to be on their land
                    for(var dx = -3; dx < 4; dx++){
                        for(var dy = -3; dy < 4; dy++){
                            var type = get(otherLand.x + dx, otherLand.y + dy);
                            var distThere = manhattan(currentX, currentY, otherLand.x + dx, otherLand.y + dy);
                            var distShortest = manhattan(currentX, currentY, closestX, closestY);
                            // find normal land, or wet land that will dry by the time the bot gets to it
                            if((type == '.' || type == '@' || (type == 'W' && distThere > 1)) && distThere < distShortest){
                                closestX = otherLand.x + dx;
                                closestY = otherLand.y + dy;
                            }
                        }
                    }
                }
            }
            if(closestX != 999 && closestY != 999){ // land found; go there
                debug("Target acquired", closestX, closestY);
                debug("Burning land");
                move = getDirection(currentX, currentY, closestX, closestY);
                if(move == 'S'){ // is it on the land? If so, then burn it
                    action.type = 'B';
                    action.direction = 'S';
                    state['lastFireTurn'] = state['turn']; // record when the fire was set
                }
            } else { // everyone else's land already has a fire
                debug("Default action");
                // default to heading back; one can never be too safe!
                move = getDirection(currentX, currentY, startX, startY);
            }
        }
    }

    // save the state file
    writeState();
    // output the action
    console.log(move + action.type + action.direction);
});
DankMemes
źródło
To wygeneruje błąd na linii 340: Error: Cannot find module 'split'. Używam Node.js v0.10.30.
Skyler
cd botdir npm install splitz jakiegoś powodu węzeł nie podoba mi się, że został zainstalowany globalnie, ale ty też możesz spróbować
DankMemes 14.10.15