Concurso concluído! Leia os comentários nos blobs para ver a pontuação deles.
Este KoTH é inspirado livremente pela simulação de seleção natural da Primer . Seu bot é um blob. Para sobreviver, você deve comer pellets para recuperar a energia, que é usada para se mover. Com energia extra, os blobs podem se dividir em dois.
Energia e Movimento
Seu blob começa a cada rodada com 100 de energia e não tem limite na quantidade de energia que pode coletar. Cada rodada é executada em turnos, com cada blob tendo a opção de mover para o norte, leste, sul ou oeste em qualquer turno ou ficar parada. Mover usa 1 energia e ficar parado usa 0,25 energia. O comprimento lateral do mapa éceil(0.25 * blobCount) * 2 - 1
unidades, com um mínimo de 9 unidades. Todos os blobs começam na borda do mapa, com um colocado em cada canto e cada blob subseqüente sendo colocado a 2 unidades de qualquer outro. A cada 30 turnos, uma onda de pellets é colocada em pontos aleatórios ao redor do mapa, a pelo menos 1 unidade de qualquer borda. Cada vez que uma onda de pellets aparece, a quantidade de pellets (originalmente duas vezes o número de blobs ou a largura do mapa, o que for maior) na próxima onda é reduzida em 1, forçando o número de blobs a diminuir ao longo do tempo. Cada pellet restaura entre 5 e 15 energia. Quando a energia de um blob é menor ou igual a 0, ela morre.
Comendo
Se dois ou mais blobs tentarem ocupar o mesmo local, aquele com mais energia consumirá os outros, recebendo sua energia. Se ambos têm energia igual, ambos desaparecem.
Detecção e Informação
Os blobs podem ver pellets ou outros blobs a uma distância de 4 unidades. Quando suas funções são chamadas, os blobs são fornecidos com:
- O comprimento lateral do mapa
- A posição do blob no mapa
- As posições de todos os pellets dentro do raio de pesquisa e os valores
- As posições de todos os blobs dentro do raio de pesquisa, assim como a energia e os UIDs
- A energia, o UID e os locais do blob cuja função está sendo executada
- Um objeto de armazenamento exclusivo para o blob
- Um objeto de armazenamento compartilhado por todos os blobs relacionados ao blob através da divisão
Divisão
Se um blob tiver mais de 50 de energia, poderá optar por dividir. A divisão custa 50 de energia e a energia restante é dividida igualmente entre os dois blobs. Todos os blobs são originais ou cópias divididas, com cada cópia retornando a um original. Todos esses juntos são "parentes". Todos os parentes têm um objeto de armazenamento comum. Os parentes ainda podem comer um ao outro e podem se dividir, usar seu próprio objeto de armazenamento ou coletar energia sem afetar os outros.
Transferencia de energia
Se dois blobs estiverem próximos um do outro (após o movimento), um dos bots pode transferir energia para o outro. Isto é feito através da devolução SendNorth(amt)
, SendEast(amt)
, SendSouth(amt)
, ou SendWest(amt)
, com amt
sendo um número que representa a quantidade enviada. Pode ser qualquer quantia que o remetente possa pagar, incluindo toda a sua energia. Recomenda-se que o blob que está recebendo energia fique parado durante o armazenamento comunitário, para que ele não se afaste quando a energia estiver sendo transferida (embora a energia não seja deduzida do total do remetente nesse caso).
Funções, armazenamento e UIDs
Para permitir comportamentos de aprendizado mais complexos, todos os blobs receberão um UID inteiro (Identificador Único). Esses UIDs serão gerados aleatoriamente a cada mapa, impedindo estratégias baseadas em destinos individuais. Quando a função de um blob é chamada, são transmitidos quatro argumentos:
- O comprimento lateral do mapa como um número inteiro
- Um objeto com duas matrizes:,
pellets
eblobs
. Ambas as matrizes contêm objetos, ambos com umapos
propriedade contendo a posição do pellet ou blob formatada como[x,y]
. Os pellets terão umaenergy
propriedade, enquanto os blobs terão umauid
propriedade e umaenergy
propriedade - Um objecto contendo várias propriedades da gota que é passado para:
energy
,uid
, epos
. Apos
matriz está formatada como[x,y]
- Um objeto que contém os dois objetos de armazenamento do blob. Uma
self
propriedade contém um objeto de armazenamento individual que pode ser modificado da maneira que o blob considerar adequado (manipulando propriedades do objeto que é passado) e umacommunal
propriedade que pode ser modificada por qualquer parente.
Os blobs não são movidos imediatamente para evitar que as curvas anteriores / posteriores tenham uma vantagem. Todos os movimentos são processados em grupos. energia independente de se isso traria sua energia total acima de 0.
Para que os blobs relativos se reconheçam, o armazenamento comum deve ser usado para que cada blob registre seu UID em uma matriz ou através de algum outro sistema.
Retornar valores
Para mover ou dividir, o valor de retorno da função é usado. Primeiro, o significado das direções cardinais em termos de coordenadas:
- Norte = -Y
- Leste = + X
- Sul = + Y
- Oeste = -X
Observe que [0,0]
é o canto superior esquerdo e Y aumenta à medida que você desce. O valor de retorno da função deve seguir estas regras:
- Para não fazer nada: não retorne nada, 0, nulo, indefinido, falso ou qualquer outro valor que seja igual a falso
- Para mover: retorne uma das quatro variáveis globais: norte, leste, sul ou oeste, que equivale a "norte", "leste", "sul" ou "oeste" (que também pode ser usado como valor de retorno)
- Para dividir: retorne a variável global SplitNorth, SplitEast, SplitSouth ou SplitWest, a direção que indica onde colocar o novo blob
Se um comando de divisão for retornado e a quantidade de energia necessária for maior ou igual à energia do blob, nada acontecerá. Os blobs não poderão sair do mapa.
Funções de biblioteca predefinidas
Existem algumas funções básicas disponíveis por padrão, para economizar tempo:
taxiDist (pt1, pt2)
Retorna a distância do táxi entre dois pontos (distância X mais distância Y).
taxiDist([0, 0], [2, 2]) //4
taxiDist([3, 4], [1, 5]) //3
taxiDist([1.25, 1.3], [1.3, 1.4]) //0.15
taxiDist([0, 0], [5, 2.5], 2.5) //3
taxiDist([0, 0], [2, 4], 2.5) //2.4
hypotDist (pt1, pt2)
Retorna a distância entre dois pontos de acordo com o teorema de Pitágoras
hypotDist([0, 0], [5, 12]) //13
hypotDist([4, 6], [8, 9]) //5
hypotDist([0, 1], [2, 1]) //2
hypotDist([1, 1], [2, 2]) //sqrt(2)
modDir (dir, amt)
Toma a direção inserida, gira 90 graus no sentido amt
horário e retorna o novo valor.
modDist(North, 1) //East
modDist(East, 2) //West
modDist(West, 3) //South
modDist(South, 4) //South
Blob de exemplo
Este blob não se moverá até encontrar um pellet próximo. Então, ele se moverá na direção que achar mais provável de recompensá-lo. Se sua energia estiver sempre acima de 150, ela se dividirá.
function(map, near, me, storage) {
if (me.energy > 150)
return SplitNorth;
if (!near.pellets.length)
return null;
var dirs = [0, 0, 0, 0];
for (let p, i = 0; i < near.pellets.length; i++) {
p = near.pellets[i];
dirs[0] += me.pos[1] - p.pos[1];
dirs[1] += p.pos[0] - me.pos[0];
dirs[2] += p.pos[1] - me.pos[1];
dirs[3] += me.pos[0] - p.pos[0];
}
return [North, East, South, West][dirs.indexOf(Math.max(...dirs))];
}
Regras
- As brechas padrão são proibidas. Além disso, não há brechas incomuns.
- Nenhum blob pode tentar modificar ou ler quaisquer dados que não foram passados para ele através de seus parâmetros
- Nenhum blob pode tentar modificar uma variável de valor de retorno para sabotar outros blobs
- Uma rodada dura até que os únicos blobs restantes sejam parentes
- Nenhum blob pode modificar dados injetando funções em seus parâmetros que modificam valores usando a
this
palavra - chave - Todos os envios devem estar em Javascript ou em um idioma que não seja muito diferente do Javascript (Python, por exemplo). Todas as respostas serão convertidas em Javascript para a competição.
- O vencedor é o blob que coletou a maior quantidade de energia no total em todas as rodadas (de bolinhas ou consumindo blobs menores que não são parentes)
Controlador: https://gist.github.com/RedwolfPrograms/1facc0afe24c5dfd3ada8b8a2c493242
Chatroom: https://chat.stackexchange.com/rooms/93370/hungry-blobs-koth