Jogos Vorazes - Eat or Die
Se você não comer, você morre. Se você come, você vive (até morrer). Você vai morrer, então tente morrer por último.
visão global
Há uma ilha povoada com um rebanho de presas. Você controla um pacote de cinco predadores. Seu objetivo é manter sua mochila viva. Faça isso comendo presas. As presas tendem a fugir de predadores e tentam permanecer em um rebanho de outra maneira. Naturalmente, seu bando estará no mesmo campo que todos os outros bando , então a competição tentará comê-los antes que você possa. Não deixe isso desanimar você, ou você vai morrer de fome.
Como jogar
Crie e envie um programa de linha de comando para direcionar seu pacote. Ele receberá informações de estado do programa de controle no STDIN e comandos de saída no STDOUT. O formato é descrito em detalhes abaixo. Cada programa será executado apenas uma vez e deve permanecer em execução até que não haja mais membros do pacote ativos. Você precisará ler as entradas assim que chegar e responder rapidamente. Há um tempo limite estrito de 200ms para cada resposta. Se você ainda não respondeu, seu pacote não receberá novas instruções para o turno atual.
Se o seu programa não puder ser executado pelo controlador, ele não será considerado válido. Inclua a string da linha de comando que precisarei usar para executar seu envio. Se houver instruções especiais (para configurar compiladores, etc.), inclua-as. Se eu não conseguir fazê-lo funcionar, solicitarei ajuda nos comentários. Se você não responder, não poderei aceitar seu envio.
O torneio será realizado em um sistema Linux de 64 bits. Lembre-se disso ao fornecer as instruções necessárias.
Detalhes
A posição e direção de cada criatura estão na forma de um par de números de ponto flutuante de precisão dupla (por exemplo
double
) representando suasx
ey
coordenadas, respectivamente.Cada criatura é considerada um ponto. Isso significa que eles podem se sobrepor e ocupar o mesmo espaço. Você não será deixado de lado, e não há conceito de colisão com outras criaturas.
A ilha é uma praça, 500 unidades ao lado. Se você tentar se aventurar além desses limites, ficará preso na borda. A origem
{0,0}
está no canto superior esquerdo,x
aumentando para a direita ey
aumentando para baixo. Novamente, o mapa não quebra .O jogo começa com 1500 + (packCount * 50) presas. Eles estarão reunidos no centro da ilha, mas rapidamente decidem começar a se mover.
Os pacotes serão organizados em um círculo uniformemente espaçado ao redor do perímetro. A ordem dos pacotes é embaralhada; portanto, não conte com a partida em um local específico.
Presas podem ver todos os outros animais em um raio de 30 unidades. Eles podem se mover no máximo 6,0 unidades por turno.
Os predadores podem ver todos os outros animais em um raio de 50 unidades. Eles podem se mover a um máximo de 6,1 unidades por turno. Isso significa que eles podem ver presas antes de serem vistos e (apenas) fugir deles.
Os predadores vivem e morrem de acordo com o nível de fome . Começa às 1000 e diminui um a cada turno. Se, após o movimento, um predador estiver dentro de 1 unidade de presa, ele o comerá automaticamente. Isso remove a presa e define a fome do predador para 1000. Cada predador pode comer apenas uma presa por turno. Se houver mais de um dentro do alcance, ele comerá o que o loop chegar primeiro (não necessariamente o mais próximo). Um predador morre se sua fome chegar a zero.
Os pacotes começam com cinco membros cada. A cada 5000 turnos, todos os pacotes ainda no jogo geram um novo membro. Será colocado dentro do alcance visível de um membro do bando. Verifique se suas entradas podem lidar com mais de cinco membros.
A cada 1000 turnos, mais presas aparecem. O número de novas presas será o número de predadores vivos menos um.
Predadores não podem atacar outros predadores. Eles comem presas quando pegam. É isso aí.
A ordem dentro de um turno é:
- Todas as presas tomam decisões
- Todos os predadores tomam decisões
- Todas as presas
- Todos os predadores se movem / comem
A ordem em que cada pacote toma suas decisões / movimentos será aleatória a cada turno.
Protocolo (Geral)
Todas as comunicações são feitas no formato de sequência US-ASCII
. Os números são convertidos em strings usando Java Double.toString()
ou Integer.toString()
. Sua saída deve ser formatada para que possa ser lida pelo Java Double.valueOf(String)
(você não estará produzindo números inteiros). Para detalhes sobre formatos analisáveis, consulte a documentação paraDouble
. Todos os campos em uma linha são separados pelo \t
caractere padrão e as novas linhas \n
. A cadeia inteira será encerrada com um byte nulo \0
.
Nos exemplos abaixo, estou usando <>
para marcar os campos por questões de legibilidade. Eles não estão presentes nas strings reais.
Protocolo (entrada)
A sequência de entrada varia em comprimento, dependendo de quantas criaturas são visíveis para o seu pacote. Pode exceder 100k caracteres, esteja preparado para isso. A configuração básica é:
Linha 0: informações básicas sobre o jogo.
turn
é o número do turno atual e as contagens são o número total de presas e predadores restantes no campo. Estes estãointeger
em forma de string.<turn>\t<preyCount>\t<predatorCount>\n
Linha 1: IDs e níveis de fome exclusivos dos membros do seu grupo. Estes não são fornecidos na mesma ordem para todas as entradas. Use os IDs exclusivos para rastrear membros individuais, não a ordem em que eles aparecem na entrada. Novamente, estes são
integer
como strings. Para um pacote de dois, isso seria:<id[0]>\t<hunger[0]>\t<id[1]>\t<hunger[1]>\n
Linha 2: As posições dos membros do seu bando, na mesma ordem que a linha 1 . Estes são
double
como string:<x[0]>\t<y[0]>\t<x[1]>\t<y[1]>\n
As seguintes linhas são a visibilidade de cada membro do pacote, na mesma ordem que a linha 1 . Estes serão dados em duas linhas por membro.
O primeiro para cada um consiste em locais para a presa que ele pode ver. O segundo são os locais para os predadores que ele pode ver. Esses locais não são únicos como um todo. Por exemplo, se dois membros da matilha puderem ver o mesmo animal, ele estará na sequência de ambos os membros. Além disso, seus próprios membros do bando serão incluídos. Se você quiser excluí-los, compare os locais com seus próprios membros. Todos os locais estão no double
formato de sequência.
Para cada membro vivo:
<prey[0].x>\t<prey[0].y>\t<prey[1].x>\t<prey[1].y>\n
<predator[0].x>\t<predator[0].y>\t<predator[1].x>\t<predator[1].y>\n
Finalmente, o último caractere será \0
, no início da próxima linha.
Exceção: Se você receber a entrada dead\0
, seu pacote está morto. Termine seu programa normalmente, por favor. O controlador deve desligar todos os processos vivos quando fechado, mas eu prefiro não ter processos zumbis por todo o lado. Como cortesia, você pode incluir um tempo limite de entrada. Por exemplo, minha classe de exemplo termina se não receber entrada por 15 segundos.
Protocolo (Saída)
A saída é simples. Você fornecerá um par de double
valores para cada membro do live pack. Eles representam o movimento que você gostaria que eles realizassem neste turno. Por exemplo, se sua criatura estiver atualmente em {100.0, 100.0}
e você der um comando {-1.0, 1.0}
, eles irão para {99.0, 101.0}
. Todos os números estarão em uma única linha, separados por tabulação.
Por exemplo, se você tivesse 3 membros da matilha vivos, isso seria uma resposta válida:
1.0\t-1.0\t2.0\t-2.0\t3.0\t-3.0\0
Este seria mover suas criaturas por {1.0,-1.0}
, {2.0,-2.0}
, e {3.0,-3.0}
. O pedido é o mesmo que o recebido na entrada. Não esqueça o final \0
!
Se você fornecer informações inválidas, ocorrerão maus resultados. Se um número único não puder ser analisado como a double
, ele se tornará zero. Se a string como um todo não puder ser analisada, nenhuma nova instrução será dada e todo o seu pacote seguirá as instruções da curva anterior.
Todas as direções serão fixadas a uma distância máxima de 6,1 unidades. Você pode se mover mais devagar que isso, se quiser. Por exemplo, {1, 0}
você moverá uma unidade. {6,8}
(distância 10) moverá você apenas 6,1 unidades e reduzirá para cerca de {3.66, 4.88}
. A direção permanece constante.
Importante: O programa de controle lê seu STDOUT e STDERR. Se você lançar uma exceção e imprimir no STDERR, é muito improvável que a mensagem esteja na forma de uma resposta válida. Tente evitar fazer isso.
Programa de Controle / Teste
A fonte do controlador pode ser encontrada aqui em bitbucket.org . Você precisará compilá-lo antes de executar. A classe principal é Game
e todas as classes estão no pacote padrão. Para executar, inclua o comando de cada pacote como um argumento separado. Por exemplo, se você deseja executar um Java ChaserPack e um Python LazyPack.py, você pode usar:
java Game "java ChaserPack" "python LazyPack.py"
No mapa, as presas aparecem em verde e os predadores em vermelho. No entanto, o pacote que for o primeiro pacote fornecido como argumento será colorido em azul. O objetivo é distingui-los mais facilmente para fins de teste. Os predadores também piscarão em branco por cinco quadros quando comerem.
O jogo continuará até o último predador morrer de fome, gravando no console quando ocorrerem eventos de fome ou extinção. Quando o jogo terminar, a pontuação será dada para cada pacote. Se você não quiser ver os eventos de inanição / extinção, use o -silent
argumento Então ele produzirá apenas a pontuação final. Você deve passar isso como o primeiro argumento :
java Game -silent "java ChaserCat" "./someOtherPack"
Incluído é um pacote Java esqueleto chamado GenericPack
. Inclui as operações básicas de entrada / saída necessárias. Está aqui para dar um exemplo claro de como analisar e responder. Se você deseja adicionar um modelo em outro idioma, entre em contato.
Também está incluído um predador baseado no modelo ChaserPack
,. Não será incluído no torneio e é incluído apenas para fins de teste. Ele tem um desempenho muito ruim, devido a uma falha de segmentação intencional. Se você não pode vencê-lo, continue tentando.
Abaixo está um exemplo de execução do programa de controle (clique para o vídeo). A qualidade do vídeo não é ótima (desculpe), mas você pode ter uma ideia de como a presa se move. ( cuidado: áudio )
Pontuação
O vencedor será determinado pelo torneio, ganhando pontos em cada rodada.
Cada rodada prossegue até que todos os predadores estejam mortos. Cada pacote será pontuado com base em quando seu último membro morreu de fome. Eles receberão pontos com base no pedido. Os pontos serão acumulados por dez rodadas, e o vencedor é o pacote com o maior número total de pontos.
O primeiro lugar de cada rodada receberá 100 pontos. Para cada lugar depois disso, a recompensa será reduzida em 20% (arredondado para baixo). Isso continuará até que os pontos cheguem a zero (após o 17º lugar). Os lugares com mais de 18 anos não receberão pontos pela rodada. Os pacotes que empatarem receberão pontos iguais. Por exemplo:
1st : 100
2nd : 80
3rd : 64 (T)
3rd : 64 (T)
4th : 51
...
17th: 1
18th: 0
19th: 0
O máximo de pontos possíveis ao longo do torneio é de 1000, desde o primeiro lugar todas as dez vezes.
Se vários programas terminarem o torneio empatado em primeiro lugar, outro torneio de dez rounds será realizado apenas com as entradas do primeiro colocado . Isso continuará até que um vencedor apareça.
Vou tentar executar um torneio aproximadamente semanalmente, ou à medida que novas inscrições chegarem.
Regras adicionais (jogar limpo!)
Você não pode ler ou gravar em nenhum recurso externo. Como você não invocará o programa várias vezes, qualquer informação de estado pode ser armazenada internamente.
Não interfira com outros processos / envios. Isso não significa não tentar roubar suas presas, fugir delas, etc. Isso significa não interferir na execução do processo. Isso é a meu critério.
Os participantes estão limitados a um máximo de três entradas. Se você enviar mais, pontuarei apenas os três primeiros enviados. Se você deseja revogar um, exclua-o.
As entradas podem não existir apenas para apoiar outras entradas. Cada um deve jogar para ganhar por seu próprio mérito.
Seu programa pode gerar no máximo um processo filho por vez ( total de descendentes, não diretos). De qualquer forma, verifique se você não excedeu o tempo limite. Você não pode invocar a
Game
própria classe de forma alguma.
Resultados - 29 abril 2014
Aqui estão os resultados do último torneio de dez rounds:
Clairvoyant : 1000
EcoCamels : 752
Netcats : 688
RubySpiders : 436
RubyVultures : 431
CivilizedBeasts : 382
LazyPack : 257
Pacotes enviados antes das 09:00 EDT 2014/04/29 estão incluídos nesta execução.
Você também pode ver os detalhes de cada rodada . Por alguma razão, decidi numerar as rodadas para trás, para que comece com a "rodada 10".
Atualizações
23/04/2014: FGreg relatou um bug relacionado a tempos limite (obrigado!). Uma correção foi implementada, para que os testadores desejem atualizar o código do programa de controle.