Nesse desafio, você deve projetar uma espécie de organismo unicelular para lutar até a morte na arena da placa de Petri. A arena é representada como uma grade retangular, onde cada célula ocupa um espaço:
.....x....
...x...o..
...x.c..o.
.......o..
Atributos
Cada célula possui três atributos. Ao especificar sua espécie de célula no início do jogo, você aloca 12 pontos entre esses atributos.
- Hit Points (HP): se o HP de uma célula cair para zero, ele morre. Novas células têm HP completo.
- Quando uma célula morre, deixa para trás um cadáver que pode ser comido por outras células em busca de energia.
- Uma célula não pode recuperar o HP perdido, mas pode criar uma nova célula com o HP completo ao dividir.
- Energia : a maioria das ações que uma célula pode executar requer energia. Ao descansar ativamente, uma célula pode recuperar a energia perdida até o máximo de sua espécie.
- É provável que uma espécie de célula com menos de 5 energia falhe, porque não pode se dividir para criar novas células.
- Uma célula não pode recuperar energia além do valor máximo de sua espécie.
- Uma célula recém-criada possui um valor inicial de energia copiado de seu pai (e um valor máximo ditado pela especificação de sua espécie).
- Acidez : se uma célula optar por explodir, o nível de acidez da célula é usado no cálculo de danos às células adjacentes.
Ações
A cada turno, cada célula pode executar uma ação:
Mover: a célula move um espaço em qualquer direção (N / S / E / A / NE / NW / SE / SW) a um custo de 1 energia.
- Uma célula não pode se mover para um espaço ocupado por outra célula viva.
- Uma célula não pode sair da grade.
- Mover-se para um cadáver de célula destrói o cadáver.
Ataque: Uma célula ataca uma célula adjacente, causando 1 a 3 de dano, gastando 1 a 3 pontos de energia.
- Uma célula pode atacar em qualquer direção (N / S / E / W / NE / NW / SE / SW).
- É legal atacar células amigas.
Dividir: a célula divide e cria uma nova célula em um espaço adjacente, a um custo de 5 de energia.
- Uma célula pode se dividir em qualquer direção (N / S / E / A / NE / NW / SE / SW).
- A nova célula possui HP completo, de acordo com a especificação original da célula.
- A nova célula tem tanta energia quanto sua célula-mãe depois de subtrair o custo da divisão. (Por exemplo, uma célula-mãe com 8 pontos de energia iniciais será reduzida para 3 energia e produzirá uma célula-mãe com 3 energia).
- Uma nova célula não pode atuar até o próximo turno.
- Uma célula não pode se dividir em um espaço ocupado por uma célula viva, mas pode se dividir em um espaço ocupado por um cadáver de célula morta (isso destrói o cadáver).
Comer: Uma célula come um cadáver adjacente, ganhando 4 de energia.
- Uma célula pode comer em qualquer direção (N / S / E / A / NE / NW / SE / SW).
Descanso: Uma célula não faz nada por um turno, recuperando 2 de energia.
Explodir: Quando uma célula tem 3 ou menos HP e mais energia que HP, pode optar por explodir, causando dano às oito células adjacentes.
- Danos a cada célula adjacente são
(exploding cell HP) + (explodng cell acidity)
- Uma célula explodida morre e deixa para trás um cadáver, assim como todas as células mortas na explosão.
- Danos a cada célula adjacente são
Protocolo
Configuração
Seu programa será executado com a string BEGIN
fornecida no stdin. Seu programa deve escrever para stdout uma lista separada por espaços de 3 números inteiros não negativos, representando HP, energia e acidez para suas espécies de células: por exemplo 5 6 1
,. Os números devem somar 12. A acidez pode ser 0
, se você desejar. (Outros atributos também podem ser zero, mas fazê-lo funcionalmente perde o jogo!)
Você começa com uma célula, no canto noroeste ou sudeste, a um espaço de cada borda. A célula inicial tem HP e energia completos.
Todas as células atuam
A cada turno, seu programa será chamado uma vez para todas as células ativas em sua equipe (exceto as células que acabaram de criar essa vez) para que a célula possa agir. Seu programa é fornecido com dados sobre stdin que incluem o estado da placa de Petri e informações sobre esta célula específica:
10 4
..........
..xx.c....
...c...o..
......o...
6 3 5 7
Os dois primeiros números indicam a largura e a altura da arena: aqui, existe uma arena de 10 por 4.
- As
o
células são suas; asx
células são seus inimigos. (Isso sempre é verdade; cada jogador sempre vê suas próprias células comoo
.) - Os
.
espaços estão vazios. - Os
c
espaços representam cadáveres de células comestíveis.
Os números após a linha vazia representam informações sobre esta célula:
- Os dois primeiros números são
x,y
coordenadas, indexadas0,0
no canto superior esquerdo (então,6 3
aqui se refere ao lado sul)o
célula ). - O terceiro número é o HP da célula; o quarto número é a energia da célula.
Seu programa deve gerar (para stdout) uma ação. Nos exemplos abaixo, usaremos N
como uma direção de exemplo, mas pode ser qualquer direção legal para essa ação ( N
/ S
/ E
/ W
/ NE
/ NW
/ SE
/ SW
). Toda a saída do programa não diferencia maiúsculas de minúsculas, mas os exemplos usarão maiúsculas. Qualquer ação de saída inválida (porque possui sintaxe inválida ou tenta uma ação ilegal) é ignorada e resulta na célula REST
(e, assim, ganhando 2 de energia).
MOVE N
DIVIDE N
EAT N
ATTACK N 2
- o número representa a força do ataque (1 - 3)REST
EXPLODE
A vez de sua equipe consiste em todas as suas células terem a oportunidade de agir, uma a uma. Todas as suas células agem antes de qualquer célula do oponente. Quando todas as suas células agem, seu turno termina e o turno do seu oponente começa. Uma vez que todas as células do seu oponente atuem, seu turno começa novamente. No seu turno, cada célula recebe prioridade para agir com base em sua idade: as células mais antigas de sua equipe agem primeiro antes das células mais novas.
Exemplo
Veja como um programa pode se comportar. A entrada de stdin é indicada aqui com >
setas à esquerda (separadas da entrada real por um espaço de esclarecimento) e a saída no stdout possui <
setas.
> BEGIN
< 5 6 1
Em seguida, o programa é chamado novamente:
> 10 4
> ..........
> .o........
> ........x.
> ..........
>
> 1 1 5 6
< DIVIDE SE
Após o turno do seu oponente (que decidiu DIVIDE W
com a única célula inicial), seu programa é invocado duas vezes, uma vez para cada célula:
> 10 4
> ..........
> .o........
> ..o....xx.
> ..........
>
> 1 1 5 1
< MOVE E
Para a segunda invocação no seu turno:
> 10 4
> ..........
> ..o.......
> ..o....xx.
> ..........
>
> 2 2 5 1
< MOVE SE
Observe que esta segunda célula vê o estado atualizado da placa com base no movimento da outra célula anteriormente no seu turno. Observe também que essa célula foi criada com 1 energia, porque a célula-mãe tinha 6 de energia quando executou a divisão no último turno (portanto, a 6 original, menos o custo de divisão de 5 energia, criou uma célula-mãe com 1 energia).
Agora o seu turno acabou e o turno do seu oponente começa. As duas células opostas terão a chance de agir, e então seu próximo turno começa.
Vitória
Você pode ganhar por:
- Destruindo todas as células opostas ou
- Ter mais células que seu oponente após cada jogador completar 150 turnos
A pontuação será baseada no número de vitórias em 100 jogos entre si. Na metade das simulações, seu programa poderá começar primeiro.
Jogos de empate (ou seja, exatamente o mesmo número de células após 150 turnos, ou as únicas células restantes são mortas juntas em uma explosão) não são contados no total de vitórias de nenhum dos jogadores.
Outra informação
- Seu programa não deve tentar manter o estado (além de usar o estado da placa de Petri): organismos monocelulares não têm uma memória muito boa e reagem ao mundo momento a momento. Em particular, a gravação em um arquivo (ou outro armazenamento de dados), a comunicação com um servidor remoto ou a definição de variáveis de ambiente são explicitamente proibidas.
- As submissões serão executadas / compiladas no Ubuntu 12.04.4.
- As especificidades dos 100 jogos de pontuação ainda não foram confirmadas, mas provavelmente envolverão vários tamanhos de arena (por exemplo, 50 corridas em uma arena pequena e 50 corridas em uma arena maior). Para uma arena maior, posso aumentar a contagem máxima de turnos para garantir que uma batalha adequada possa ocorrer.
Recursos
Aqui está o código do driver que executa a simulação, escrita para Node.js, chamada por node petri.js 'first program' 'second program'
. Por exemplo, colocar uma célula gravada em Python em uma célula gravada em Java pode parecer node petri.js 'python some_cell.py' 'java SomeCellClass'
.
Além disso, entendo que ler e analisar várias linhas no stdin pode ser uma grande dor, por isso elaborei algumas células de amostra completas em diferentes idiomas nos quais você pode criar, revisar completamente ou ignorar completamente.
- Célula Java
- Célula Python
- Célula JavaScript (para uso com Node.js)
Claro que você é livre para escrever uma célula em um idioma diferente; esses são simplesmente três idiomas para os quais decidi escrever um código padrão para ajudar a economizar tempo.
Se você tiver algum problema ao executar o driver, sinta-se à vontade para me enviar um ping na sala de bate-papo que criei para esse desafio . Se você não tem reputação suficiente para o bate-papo, deixe um comentário.
fonte
'node c:/cell/cell_template.js'
para cada argumento, assim como você precisará especificar'java CellTemplate'
para o código Java. Vou deixar isso mais claro no texto do desafio. Se você ainda estiver com problemas, nós (e qualquer outra pessoa com problemas técnicos) podemos continuar essa discussão em uma sala de bate-papo que acabei de criar .Respostas:
Aqui está o meu bot relativamente simples, que eu programei em Ruby. Basicamente, ele prioriza a divisão primeiro, e tenta se dividir em direção aos inimigos, a fim de obter controle sobre o campo. Sua segunda prioridade é comer e a terceira é atacar. Ele venceu facilmente a célula Python de amostra.
fonte
$
.$
é usado para indicar uma variável global. Sim, eles são maus, mas neste pequeno programa, não importa muito.Ameba
Primeiro se divide em quatro e depois tenta chegar ao meio termo para limitar o espaço de replicação do oponente. Então começa a replicar. Ao mover ou replicar, encontra o caminho ideal para o inimigo mais próximo e se move ou se divide em direção a ele, para tentar cortar o espaço disponível no inimigo.
Se um inimigo estiver adjacente ou a um espaço de distância, sempre o atacará ou se moverá em sua direção, permitindo que a linha atrás não faça nada para preencher os espaços vazios.
Não testei isso com nenhum outro envio, por isso não faço ideia de como será o desempenho.
fonte
Célula simples feita em
node.js
. Testado contra células de nó de exemplos e contra o Kostronor, as vence.Atualizar
Ainda bastante simples, tente avançar em direção ao inimigo ou dividir.
fonte
Evolução
Essa submissão evoluiu e não é mais um organismo simples de célula única! Ele tenta atacar / explodir sempre que possível, caso contrário ele se divide ou se move em direção ao inimigo. A movimentação deve resolver o problema de uma célula cercada por células amigas com energia máxima, incapaz de fazer algo útil.
Depois de se mover, há sempre 3 energia sobrando para atingir o inimigo o mais forte possível.
fonte
Berserker
Como usei o Clojure, que tem algumas limitações, principalmente o enorme tempo de inicialização, tomei um pouco de libré. Quando o programa é fornecido,
BEGIN
ele exibe4 6 2 LOOP
, indicando que não para. Em seguida, recebe as entradas como um fluxo contínuo e termina comEND
. Ele não salva nenhum estado, o que fica claro ao não usar nenhuma variável global ou reutilizar valores de retorno. Como a implementação dessa ação em loop ainda não foi concluída, não pude testar completamente o código (espero que o código seja suficientemente claro).A célula ganhou esse nome por sua natureza de explodir sempre que possível (e, portanto, ter acidez) e priorizar o ataque logo após a divisão.
Carreguei o arquivo jar gerado no meu Dropbox . Correr com
java -jar petridish-clojure.jar
Só para esclarecer:
Atualizar log
fonte
Bot faminto, faminto
Aqui está uma entrada em R. Espero ter entendido corretamente quais eram as especificações técnicas de como se comunicar com seu programa. Deve ser acionado com
Rscript Hungryhungrybot.R
.Se possui pelo menos 6 de energia, divide-se preferencialmente na direção do inimigo. Caso contrário, ele come o que estiver ao lado ou o que estiver ao alcance. Se nenhum alimento for alcançável, ele explodirá quando houver mais inimigos ao redor do que as células irmãs ou lutará com inimigos próximos. Descansa apenas se a energia for 0 e não houver nada para comer.
fonte
Error: unexpected 'else' in "else"
seu código. Receio não conhecer o R, então não posso começar a resolver esse erro. Para referência, recebo esse erro quando o executo no driver e simplesmente quando executo o programa e digito manualmenteBEGIN
.Error in if (dir[1] < 0) where <- paste(where, "N", sep = "") : missing value where TRUE/FALSE needed
Error: object 'food' not found
(quando enfrenta fora contra a submissão do rubi de Alex, possivelmente outros)Bactérias coordenadas
Espero que não seja tarde demais.
Vença contra outros oponentes (e sempre matando todos eles), nos meus testes, e a batalha nunca terminará se ela se enfrentar, uma evidência de que a estratégia é forte.
Quando você é unicelular, pode memorizar o estado anterior, mas pode explorar sua própria posição para se comportar de maneira diferente! =)
Isso dividirá as bactérias em divisor e motor, e, ao fazer isso, manterá mais bactérias úteis em vez de apenas na linha de frente, mantendo a linha de defesa alinhada.
Ele também coordena seus ataques para se concentrar em inimigos específicos, para que os inimigos sejam mortos mais rapidamente (isto é para enfrentar minha outra célula única, que se concentra na HP).
No meio do jogo, que é detectado pelo número de células no tabuleiro, eles tentam entrar no território inimigo flanqueando-os. Esta é a principal estratégia vencedora.
Essa tem a maior taxa de crescimento em comparação com todos os outros adversários atualmente, mas tem um início lento, portanto funciona melhor em grandes áreas.
Execute-o com
java CoordinatedBacteria
fonte
Acho que vou postar minha submissão, já que você é muito generoso em adicionar a lógica do clichê ...
Havia um problema em sua lógica, em que a ação de comer emitia um ATAQUE em vez de um COMA e desperdiçava o cadáver.
Eu modifiquei sua essência tanto para ter uma solução que funcione, que deve ter um desempenho relativamente bom. Começa com 4 hp e 8 de energia; portanto, após uma divisão e um descanso, ambas as células podem se dividir novamente. Ele tentará se multiplicar, atacar inimigos, comer cadáveres e descansar, nesta ordem. Assim, as células internas armazenam seus 8 pontos de energia, para substituir rapidamente as células externas mortas e deixam 3 pontos de energia para fazer um ataque de 3 pontos ou se multiplicar após um turno de descanso. Os 4 hp devem sobreviver a pelo menos um ataque com força total.
ácido parece ser um desperdício de pontos para mim, então eu mantive-o fora ...
Eu não testei a submissão, pois era uma coisa de 2 minutos;)
aqui está o meu código:
fonte
Bombardeiro pouco espalhado
Como você gentilmente forneceu o código padrão, decidi criar minha própria célula simples; Esta célula possui 4 acidez, apenas 1 hp e 7 energia. Ele tenta sair do leque de amistosos e depois espera lá (ou come, se possível) até ter a chance de explodir ou replicar. Ataques apenas se for a única opção.
É uma estratégia bastante ousada e provavelmente terá um desempenho ruim, mas estou curioso para ver como funciona. Vou testá-lo e melhorá-lo hoje mais tarde, talvez.
fonte
node c:/cells/petri.js 'node c:/cells/bomber.js' 'node c:/cells/sample.js
. Quando digito isso no console de aplicativos do nó, recebo apenas três pontos; quando tento executá-lo no cmd do windows, recebo: 'node' não é reconhecido como um comando interno ou externo, programa operável ou arquivo em lote. Salvei todos os arquivos como arquivos .js na pasta correta. Alguma ajuda para um noob? Eu iria ao chat ou comentaria em outro lugar, mas meu representante é muito baixo.if((nearbyEnemies.length - nearbyFriendlies.length > 1 ¦¦
- eles¦¦
não parecem ser um operador válido e você tem parênteses incompatíveis. Acho que talvez a formatação do código tenha sido confusa quando você a postou?=
) quando o que você quer é comparação de igualdade (==
).