Rei da Colina - Bombeiros


27

É um verão seco na pradaria. Os quatro agricultores da região percebem que podem controlar o mercado de milho queimando as colheitas de seus vizinhos. Mas eles precisam de uma estratégia para fazê-lo; é aí que você entra.

Sua tarefa é escrever um bot para dizer aos agricultores o que queimar. O objetivo é terminar o jogo com a maior área de terra não queimada. O campo de jogo é uma grade 32x32. Cada célula pode ser uma das seguintes:

. - Ground

@ - A bot

# - Ash

W - Wet ground

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

O fogo cresce em intensidade em 1 a cada turno. Quando tiver 3 anos ou mais, incendiará as células próximas a ela (horizontal ou verticalmente). Depois que o fogo atinge 6, ele se transforma em cinza.

Em cada turno, os bots recebem como STDIN o seguinte: bot inicial x, bot inicial y, posição atual do bot x, posição atual do bot y, e o tabuleiro, separados por novas linhas. Um exemplo:

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

(neste caso, você é o bot no canto inferior esquerdo).

Você deve gerar três caracteres, com uma nova linha opcional, representando o seguinte:

Mover - um dos L, R, U, D, or S (stay)

Ação - um dos B (burn), P (pour water) or X (do nothing)

Direction - one of L, R, U, D or S- controla em qual célula você executa a ação

O fogo não afeta os bots.

A ordem dos turnos é a seguinte: Todos os bots se movem; todos os bots realizam ações; então as regras ambientais acontecem. Se você derramar água no chão, ela ficará molhada ( W) por uma volta. O fogo não se espalhará para o chão molhado. Se você derramar água no chão molhado, ele continuará molhado. Se você derramar água no fogo, ela volta ao solo normal. Você não pode fazer nada com cinzas.

As rodadas são executadas com 4 bots por vez. A rodada termina após 50 turnos, ou quando um bot fica fora do chão não queimado, o que ocorrer primeiro. Sua pontuação é calculada como o número de células do solo ou do solo úmido no quadrado 9x9, centralizado no local em que o bot foi iniciado.

Aqui está um exemplo de bot; ele pega as três letras aleatoriamente e geralmente acaba queimando seus próprios campos.

RandomBurner:

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

Regras:

  • Nenhum acesso ao sistema de arquivos fora da sua própria pasta.
  • Você pode gravar em arquivos se precisar armazenar dados persistentes entre turnos, mas apenas até 1kb por bot
  • Você não pode substituir o bot de mais ninguém
  • Se você emitir uma jogada inválida, seu bot ficará parado. Se você emitir uma ação inválida, seu bot não fará nada.
  • Por favor, atenha-se a idiomas comuns que podem ser executados em uma caixa OSX ou Linux.

O código do controlador pode ser encontrado aqui.

Resultados iniciais:

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

Atualização : Adicionado Farmer, CautiousBot, GetOff, FireFighter e Pyro.


1
O quadro não se enrola nas bordas, certo?
Zgarb

1
Direita. Se você tentar ultrapassar a borda, ficará parado.
Skyler #

4
Eu não entendo um detalhe. Que terra é minha e qual é a sua?
kaine

3
Sua terra é o que estava dentro da área do bloco 9x9, centralizada em onde você começou. Todos os bots iniciam a rodada pelo menos 8 blocos um do outro, portanto não há sobreposição.
Skyler #

2
Não é fornecido. Se você quiser gravá-lo de alguma forma, essa é uma opção. Sentado no fogo para esconder é uma estratégia válida.
Skyler

Respostas:


5

Visigodo

Visigodo tenta queimar seus inimigos no chão. Ele espera fazer isso antes que mais alguém chegue à sua terra.

Corre: 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

Esta é a minha primeira entrada, críticas construtivas são apreciadas!


"O fogo não afeta os bots"
Conor O'Brien

Visigodo raramente parece queimar alguma coisa.
Skyler

Oh, apenas notei que eu tinha minonde deveria ter max. Eu consertei isso.
Taixzo # 7/15

@ CᴏɴᴏʀO'Bʀɪᴇɴ Na verdade, não está tentando queimar os robôs inimigos, apenas assumindo que eles fiquem perto de sua própria base. Seria muito fraco contra si mesmo.
Taixzo # 7/15

Ah eu vejo. Isso faz mais sentido.
Conor O'Brien

4

Java, Protetor

Tenta cercar seu campo com uma cerca de cinzas.

Edit: Lógica aprimorada um pouco. Provavelmente não fará diferença.

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

}

Coloque em um arquivo chamado Protector.java.

Compilar com: javac Protector.java
Executar com:java Protector


Primeiro, tive que renomear para Protecter.java para compilá-lo. Mas, quando eu executá-lo, ele lança uma exceção java.lang.ArrayIndexOutOfBoundsException na linha 29.
Skyler

@Skyler corrigiu :)
TheNumberOne

Obrigado, eu adicionei aos resultados. Protetor nem sempre consegue apagar os incêndios que começa.
Skyler


@Fatalize Isso foi o que me ensinaram a ver se eu estava preso em um incêndio florestal / deserto :)
TheNumberOne

2

GetOff, Python

GetOff só quer manter sua terra para si, e ele não tem medo de perseguir aqueles malditos bots por toda a terra, esguichando-os com sua pistola de água até que eles saiam. Enquanto sua propriedade não está sendo violada, ele faz o possível para garantir que sua terra não seja queimada.

#!/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)

A a < b < csintaxe funciona em Python? Eu pensei que avalia para (a < b) < c, que é 1 < cou 0 < c. Corrija-me se eu estiver errado. (Encontrado em primeiro condicional de circuito bot.)
Conor O'Brien

É sempre funcionou para mim, mas eu não tenho certeza se ele faz em cada versão do python ...
O Beanstalk

@ CᴏɴᴏʀO'Bʀɪᴇɴ acredita que sim, 1<3>2avalia Truena minha máquina (se os agrupasse, retornaria falso: 1>2e 1<1são as possibilidades).
cole

@ Obrigado Obrigado. Eu estava no modo de pensar em JavaScript. Apenas tentei em repl.it. Mais razões pelas quais o Python é bonito.
Conor O'Brien

2

Agricultor, Java

O fazendeiro só se preocupa com suas colheitas. Ele constantemente observa seu campo em busca de possíveis incêndios ou invasores.

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

1
Pequena melhoria, em que isFirevocê poderia usar Character.isDigit.
precisa

2

Pyro, python

Pyro gosta de fogo. Pyro adora fogo. Pyro vive em chamas. Estou pensando "Pyro from TF2". Pyro gosta de queimar coisas. Ele não queimará seu próprio território, mas tentará sair dele, usando um simples algoritmo de "busca de caminhos".

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

2
Não há ambiguidade suficiente quanto ao gênero do Pyro em sua descrição e comentários.
cole

@ Oh Oh droga. Eu esqueci essa peculiaridade. Vou editar com alguma ambiguidade, com certeza;)
Conor O'Brien

Não é executado, porque não há nada após a instrução else na linha 21.
Skyler

Agora quebra na linha 5 ('dados' não está definido)
Skyler

@ Skyler Corrigido novamente. Eu sinto muito. Eu fiz isso sem o meu intérprete python.
Conor O'Brien

2

DontBurnMeBro

Outra entrada do Python. Garantido para não ser o primeiro a morrer (eu acho).

#!/usr/bin/python

print "SPS"

4
Com base na especificação de vazamento de água Pnão é W.
Aleatório # 8/15

Opa, obrigado.
Taixzo

1

Bombeiro, Java

Combate a todos os incêndios.

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

}

0

Depositário, 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)

Pode ser simplificado, mas estou cansado.

O Guardião tenta evitar danos ao seu campo. Se um incêndio aparecer, ele se aproxima dele e o apaga o mais rápido possível.

Também posso adicionar acomodações para incêndios.


Linha 36: ValueError: min() arg is an empty sequence- gera erros se nada estiver pegando fogo ainda.
Skyler #

@ Skyler eu vou consertar um pouco, desculpe.
The_Basset_Hound

0

CautiousBot, Node.js (ES5)

Este bot sai e tenta atear fogo na terra de outros bots. Até fica em cima do fogo por 3 carrapatos para escondê-lo! No entanto, nunca se pode ser muito cauteloso, por isso sempre garante que esteja perto o suficiente para apagar qualquer incêndio em sua própria terra.

Notas:

  • Usa um arquivo de estado chamado state.jsonarmazenado em seu diretório de trabalho, usado para armazenar informações sobre as posições iniciais de outros bots e determinar por quanto tempo ocultar um incêndio iniciado. Isso deve ser excluído assim que a rodada terminar (por exemplo, quando algum bot vencer). Caso contrário, o bot ficará confuso na próxima rodada. (Deixe-me saber se isso viola as regras.)
  • Requer o splitmódulo.
#!/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);
});

Ele lança um erro na linha 340: Error: Cannot find module 'split'. Estou usando o Node.js v0.10.30.
Skyler

cd botdir npm install splitpor algum nó razão não gosta instalada globalmente para mim, mas você pode tentar isso também
DankMemes
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.