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)
LineIntersection
em segmentos sem interseção retorne uma matriz vazia.