Se você já jogou Spacewar! , você sabe que foi um jogo divertido. Caso contrário, saiba disso: foi (e é) um dos primeiros e mais importantes jogos de computador. E ainda é divertido! O clone em que cresci é este , que é, aparentemente e infelizmente, apenas o Windows. Então eu o recriei!
O KotH está hospedado aqui: PPCG - Spacewar! Rei da colina . Convido você a jogar como humano contra pelo menos um outro bot para ter uma ideia de como o jogo funciona.
O jogo
- Um quadro tem 30 milissegundos (portanto, cerca de 33 quadros por segundo).
- O campo tem 800 pixels de largura e 600 pixels de altura.
- O campo é toroidal, o que significa que naves espaciais e mísseis que se movem para fora do campo reaparecem no lado oposto.
- Existem duas naves espaciais, vermelha e azul.
- O vermelho é posicionado em x = 50 e y aleatoriamente entre 50, (altura do campo - 50) pixels.
- O azul está posicionado em x = (largura do campo - 50) e y aleatório entre 50, (altura do campo - 50) pixels.
- Ambas as faces x = (largura do campo) / 2.
- Os controles disponíveis são:
- Vire à esquerda - 5 graus por quadro no sentido anti-horário.
- Vire à direita - 5 graus por quadro no sentido horário.
- Míssil de fogo - viaja a 10 pixels extras por quadro, além da velocidade do navio, na direção em que o navio estava apontando.
- Motor de incêndio - acelera a nave espacial em 0,30 pixels por quadro na direção em que a nave está apontando.
- Salto no hiperespaço - teleporta-se para algumas coordenadas aleatórias no campo, com 25% de chance de explodir. Essas coordenadas aleatórias podem estar em cima do sol.
- A velocidade máxima para navios é de 15 pixels por quadro sob potência do motor e 40 pixels por quadro quando aumentados pela gravidade.
- Ao viajar mais de 15 pixels por quadro, o impulso do motor pode mudar de direção ou diminuir a velocidade.
- Em relação aos mísseis:
- Mísseis viajam em linha reta.
- Mísseis podem ser disparados a uma taxa máxima de 1 por 0,1 segundos.
- Os mísseis têm uma vida útil de 2,25 segundos.
- Os navios têm no máximo 20 mísseis cada.
- Mísseis são partículas pontuais internamente.
- Há um sol no centro que é extremamente perigoso para o seu navio. O menor contato é fatal. Este sol também destrói mísseis.
- O sol tem gravidade. A aceleração resultante é de 5000 / (distância ^ 2) pixels / quadro ^ 2, onde a distância está em pixels. Naves espaciais e mísseis são afetados.
- Ambos os navios têm três zonas de ataque: o nariz, a asa esquerda e a asa direita.
- Um golpe no nariz é a morte instantânea.
- Um golpe em qualquer uma das asas reduz a taxa de giro da nave espacial e a aceleração do motor pela metade.
- Se ambas as asas são destruídas, a nave espacial não pode ser manobrada e só pode disparar mísseis.
- Os navios podem colidir entre si.
- Um impacto nariz-nariz é fatal para os dois navios.
- Um impacto na asa do nariz destrói a asa.
- Um impacto de asa destrói as duas asas.
- Navios mortos são sólidos e congelados até explodir 1 segundo depois.
- Após a morte de pelo menos um navio, o campo é redefinido 3 segundos depois. Até então, o sol e quaisquer outros mísseis ainda são perigosos.
O jogo original também possui asteróides mortais e indestrutíveis, mas não os incluirei.
As regras
- Seu bot deve ser escrito em JavaScript.
- Seu bot deve limitar sua decisão a cerca de 10 milissegundos. Se eu notar um atraso consistente por causa do seu bot , eu o desqualificarei e informarei para que você possa corrigi-lo.
- Os bots terão acesso ao seguinte:
- Largura e altura do campo
- Posição e raio do sol
- A posição, rotação, velocidade, forma, estoque de mísseis e status no hiperespaço de ambos os navios
- A posição e velocidade de todos os mísseis
- Quando solicitado, seu bot deve retornar uma lista de strings.
- Essas cordas deve ser um dos seguintes:
turn left
,turn right
,fire engine
,fire missile
,hyperspace
. Qualquer outra string será ignorada. - Se houver duplicatas, somente a primeira será anotada.
hyperspace
tem precedência sobre todos os outros.turn left
eturn right
ao mesmo tempo não terá efeito.fire engine
não terá efeito se o navio tiver apenas o nariz ou estiver morto.fire missile
não terá efeito se um míssil for disparado muito recentemente.
- Essas cordas deve ser um dos seguintes:
- Em uma mudança do habitual, seu bot tem permissão para explorar o comportamento de outros bots. Eu quero incentivar um metagame.
- Os bots não podem emular outros bots. (Ou seja, sem leitura da mente.)
- Bots não podem definir nenhuma variável usada pelo jogo e pelo código de física. (Ou seja, sem trapaça.)
Detalhes da implementação do bot
Eu armazenarei seu bot em seu próprio arquivo JavaScript automaticamente incluído, com o nome do arquivo bot_<name>.js
. Portanto, não coloque espaços ou caracteres que possam interferir nisso ou nomear uma função em JavaScript. Isso porque você deve definir as seguintes funções: <name>_setup(team)
e <name>_getActions(gameInfo, botVars)
. Mais abaixo na página, existem áreas de texto para o userbot , que você pode editar para testar seu código.
<name>_setup(team)
Esta função é para você definir quaisquer variáveis que deseja persistir. team
será ou "red"
ou "blue"
. Esta função deve retornar um objeto. Defina variáveis da seguinte forma:
var vars = {};
vars['example'] = "example";
return vars;
Este vars
objeto será passado para a outra função:
<name>_getActions(gameInfo, botVars)
botVars
é o objeto retornado por <name>_setup(team)
. gameInfo
é um objeto que contém as seguintes variáveis:
redScore
blueScore
timeLeft
fieldWidth
fieldHeight
sun_x
sun_y
sun_r //sun's radius
gravityStrength //acceleration in pixels/frame^2 at 1 pixel away from the sun's center
engineThrust //acceleration in pixels/frame^2
speedLimit //maximum speed under engine power
maxSpeed //maximum speed from gravity boosts
red_x
red_y
red_rot //rotation in degrees
red_xv //x velocity
red_yv //y velocity
red_shape //one of "full ship", "left wing", "right wing", "nose only"
red_missileStock //the number of missiles red has left
red_inHyperspace //true if red is in hyperspace
red_exploded //until red explodes, it is still solid and hazardous
red_alive
// likewise for blue //
numMissiles
missiles //this is a list of objects, each with the following variables
x
y
xv
yv
Seu bot tem acesso total a eles. Tenho certeza de que você pode escrever nelas e não afetar as variáveis originais, mas não faça isso de qualquer maneira. Uma observação sobre as rotações: os navios apontam na direção + y, para baixo, para que qualquer coisa que você queira alinhar com o navio precisa ser deslocada em 90 graus. Além disso, a rotação positiva é no sentido horário.
Esta função deve retornar uma lista de strings, representando as ações do seu bot. Por exemplo ["turn right","thrust"]
,. Mais detalhes sobre isso estão na seção Regras .
detalhes adicionais
Você também pode fazer uso do seguinte:
LineIntersection(L1, L2)
L1 e L2 são matrizes de dois elementos de matrizes de dois elementos. Isto é, L1 := [[x1,y1],[x2,y2]]
e L2 := [[u1,v1],[u2,v2]]
. Esta função calcula a intersecção de duas linhas e devolve este: [[x,y], [a,b]]
. [x,y]
são as coordenadas do ponto de interseção e [a,b]
são um par de relações que expressam a distância em cada linha que o ponto de interseção está. Como em, a = 0.25
significaria que o ponto de intersecção é um quarto do caminho a partir [x1,y1]
de [x2,y2]
, e da mesma forma para b
. Se não houver interseção, uma matriz vazia será retornada.
window["shipShapes"]
var shipShapes = {
'full ship': [[-8,16],[0,-8],[8,16]],
'left wing': [[-8,16],[0,-8],[4,4],[0,8],[0,16]],
'right wing':[[-4,4],[0,-8],[8,16],[0,16],[0,8]],
'nose only': [[-4,4],[0,-8],[4,4],[0,8]]
};
Estas são as coordenadas dos polígonos dos navios. Para facilitar a obtenção das coordenadas atuais, você também pode usar ...
getShipCoords(<color>)
getShipCoords("red")
retornará as coordenadas atuais dos vértices do navio de Red, e também para getShipCoords("blue")
Blue. Essas coordenadas estão em uma lista assim: [[x1,y1],[x2,y2],[x3,y3],...]
. Os polígonos são implicitamente fechados, portanto há uma linha entre o primeiro e o último par de coordenadas.
Você não pode acessar ou alterar quaisquer outras variáveis ou funções em uso pelo jogo / site. E definitivamente não dê o mesmo nome às suas funções. Não prevejo que isso seja um problema, mas se o seu bot quebrar o código do jogo, essa é uma possibilidade. Não há registro ou captura de exceções.
Ganhando
- Todo par de bots deve ser jogado pelo menos 10 vezes, nos dois sentidos. (Portanto, pelo menos 20 jogos no total.)
- Procure ter as maiores taxas de ganhos / perdas em geral . Se seu bot se sai super bem contra um outro bot, mas perde contra os outros três, isso não é tão bom quanto vencer dois e perder contra dois (como regra geral).
- Para cada bot, as razões (vitórias + 1) / (perdas + 1) serão calculadas e, em seguida, a média e o desvio padrão dessas relações serão calculados. Uma média mais alta terá prioridade e, caso as médias estejam dentro de 1 unidade uma da outra, a variação menor terá prioridade.
- A pontuação começará dentro de uma semana a partir de hoje ou após três dias sem novos envios. Isso é para que eu não precise repetir nenhum emparelhamento de bots.
Acima de tudo, divirta-se!
Classificação (08-01-2016 05:15):
# Name Mean StdDev
1. Helios 13.625 6.852
2. EdgeCase 8.335 8.155
3. OpponentDodger 8.415 8.186
4. OrbitBot 5.110 6.294
5. SunAvoider 5.276 6.772
6. DangitBobby 3.320 4.423
7. SprayAndPray 3.118 4.642
8. Engineer 3.903 6.315
9. RighthandedSpasms 1.805 2.477
10. AttackAndComeBack 2.521 2.921
11. PanicAttack 2.622 3.102
12. FullSpeedAhead 2.058 3.295
13. UhhIDKWhatToCallThisBot 2.555 3.406
14. MissilesPlusScore 0.159 0.228
15. Hyper 0.236 0.332
16. RandUmmm 0.988 1.329
17. Kamikaze 0.781 1.793
Nota: Isso está sujeito a alterações à medida que eu corro mais jogos. Além disso, a ordenação das fileiras 9 a 13 me incomoda, então posso ajustar o método de pontuação para melhor corresponder à intuição de como devem ser classificadas.
(As médias e os desvios-padrão foram arredondados para três dígitos decimais. Além disso, Hyper
deve ser, HYPER
mas isso atrapalha o destaque.: P)
fonte
LineIntersection
em segmentos sem interseção retorne uma matriz vazia.Respostas:
Helios
Esse bot é o centro do universo, ou pelo menos ele pensa que é. A primeira coisa que ele faz é corrigir um erro grave e se colocar no centro do sistema de coordenadas. Então ele gira qualquer coisa ao seu redor.
Ele não gosta do outro sol (falso) e, portanto, tenta ficar longe dele. Ele também não gosta de outros bots, portanto atira neles, se estiver em uma boa posição de tiro.
fonte
SunAvoider
Este apenas tenta ficar longe do sol. Faz tão bem ... até que uma ou ambas as asas sejam destruídas, geralmente é apenas uma questão de tempo até que caia.
fonte
EdgeCase
Voa a toda velocidade, longe do sol, em direção à borda do mapa! Quando se vê apontado para o sol, começa a disparar enquanto se afasta para voltar à borda. Ele também entra no hiperespaço quando está prestes a atingir o sol.
fonte
OrbitBot
Atualmente, não há segmentação
ou prevenção de colisões. Ele tenta orbitar o sol.Edit: Agora entra no hiperespaço quando o impacto é iminente.
fonte
Espasmos para a direita
O nome é bastante descritivo. Escolhe
turn right
com probabilidade 0,5,fire engine
com probabilidade 0,5 efire missile
com probabilidade 0,8. Surpreendentemente difícil, principalmente porque é realmente imprevisível.fonte
RandUmmm
Esse desafio precisava de um bot aleatório. Pontos de bônus por golfiness?
fonte
Engenheiro
Gosta de usar o hiperespaço quando em perigo. Para ver seu verdadeiro poder, abra o console do seu navegador e digite
overideHyperspace = 0;
. Se você esquecer o ponto e vírgula, receberá o ASI no Natal.fonte
Espalhe e reze
Incêndios descontroladamente em todas as direções. Não é muito eficaz!
fonte
Kamikaze
Não é muito competitivo, mas achei que seria divertido! Apenas voa direto em direção ao oponente durante o disparo.
fonte
UhhIDKWhatToCallThisBot
Apenas coisas aleatórias.
fonte
OpponentDodger
Afaste-se de mim oponente !!!
Obrigado a user81655 por algum código!
fonte
Espião
A história
O protótipo desse bot era um bot que tinha dois modos: modo louco e modo normal. Quando estava no modo louco, ficava lá por um número constante de carrapatos. Havia uma probabilidade constante de entrar no modo louco. Também hiperespaçou quando estava perto do sol. No modo louco, ele apontou para o outro bot e disparou constantemente. No modo normal, ele voou para longe do outro bot, não disparando.
Apertei esse protótipo para que ele estivesse no modo louco, se e somente se o inimigo estivesse perto o suficiente. Então eu tive uma ideia maluca: e se ele continuasse no modo louco? Após algumas experiências (eu adicionei fazendo o bot disparar aleatoriamente quando estava no modo normal), encontrei um novo bot para vencer todos os bot, menos o Helios. Este é o meu código no final deste processo, mas antes da limpeza.
Eu escrevi meu bot inteiro na área de texto KotH ou no embelezador JS. (Usei brevemente o editor Atom durante a limpeza - mas por duas linhas de código)
O bot
Este bot contém muitos códigos emprestados de outros bots. Ele inverte o código do Kamikaze para fugir do outro bot em vez de executá-lo e leva o código do EdgeCase para hiperespaçamento quando está perto do sol.
Seu arqui-inimigo é Helios. Sendo o único fora e conversas longas com um martini.
Ele foge do outro robô com 70% de chance de disparar um míssil e hiperespaços quando está perto do sol. Tão simples como isso. Sim.
Edit: Eu testei meu bot com o novo código e ele falha em todos os outros bot. Estou trabalhando para consertá-lo. Acabei de confirmar que isso é apenas para o meu novo bot.
O código
O misc
Nota: Eu posso ter quebrado alguma coisa ao limpar o código porque não testei o bot depois de limpar o código.
Também é muito, muito melhor do que todos os meus outros bots - na verdade, venceu todos os outros bot, exceto Helios (editar) , SetCourseFor30Degrees e OrbitBot! Está ligado ao SunAvoider.
Nota lateral: sou péssimo em javascript, não sei por quê.
fonte
AttackAndComeBack
Em vez de girar, ele entra na parte superior e sai na parte inferior (retornando na parte superior), disparando muito rapidamente. Geralmente evita o sol.
fonte
Velocidade máxima a frente
Sempre aciona os motores e os mísseis sem virar. Às vezes dura surpreendentemente muito tempo antes de atingir o sol.
fonte
Ataque de pânico
Tem 50% de chance de disparar e 80% de chance de virar à esquerda; mas se não virar à esquerda, vire à direita. Depois que ficar sem mísseis, o tempo acabará parando devido ao sol.
EDIT: Adicionado alguma lógica para não disparar quando o inimigo está vivo, porque ele pode ser morto por seus próprios mísseis.
fonte
DangitBobby
Bobby Hill não se importa com o que os outros pensam sobre ele - ele está bastante contente em andar preguiçosamente pelo campo e esperar pacientemente que seu oponente fique sem vapor antes de atacar como uma cobra "rouca".
"Essa é a minha bolsa! Eu não sei você!"
fonte
Franco atirador
Eu tenho jogado com a previsão por um tempo para criar um bot de atirador que rouba seus inimigos. Meu javascript é muito grande para caber em uma resposta, então aqui está um link, bot_Sniper .
fonte
SmartArrow
Como Arrow, mas inteligente
fonte
Kamikaze-
Também não foi projetado para ser competitivo. Apenas por diversão. Hiperespacial quando perto do sol e persegue o jogador sem disparar balas. É divertido ver esse bot perseguir uma versão desarmada do Spy, mas você não pode ter mais de um userbot, infelizmente.
El'endia: já pensou em adicionar mais de um userbot;)
Apenas peguei o código do Kamikaze + e se livrou da parte de disparo de mísseis.
fonte
MissilesPlusScore
Alguma idéia estranha que eu tive que leva o valor absoluto da diferença das pontuações e usa uma lista de movimentos aleatoriamente com base na maneira do jogo. Funciona bem contra bots com uma estratégia, mas falha contra tempestades de mísseis. Também o meu primeiro rei da colina .
HYPER
HYPERSPACE ESTÁ FRESCO !!!!!!!!!!!!!!!!
CoordinateInfluence
Baseado nas coordenadas, surpreendentemente eficaz:
fonte
SetCourseFor30Degrees
Não faço ideia por que o capitão é tão insistente em colocar o navio em um curso de 30 graus, mas ei, como um alferes humilde, quem é você para questionar? Pelo menos você recebeu permissão para evitar o sol! E você tem permissão para disparar os mísseis ... apenas não tem como apontá-los ...
fonte
Seta
Simplesmente persiga seu inimigo, hiperespaça quando ele está em perigo e ocioso quando seu inimigo está morto.
fonte
Kamikaze +
Não foi projetado para ser competitivo. Apenas por diversão. Tecnicamente, ele faz o oposto do Spy: persegue o jogador, hiperespaça quando está perto do sol, lança mísseis 70% do tempo. Eu só quero ver o KamikazePlus perseguindo Spy e Spy fugindo como um louco.
Basicamente, apenas pegou o código de Spy e virou "left" e "right".
fonte
overideHyperspace = 0;
; eles simplesmente continuam desaparecidos quando tentam ir um para o outro.