Si vous avez déjà joué à Spacewar! , vous savez que c'était un jeu amusant. Sinon, sachez ceci: c’était (et est) l’un des tout premiers et des plus importants jeux d’ordinateur. Et c'est toujours amusant! Le clone sur lequel j'ai grandi est celui-ci , qui n'est, apparemment et malheureusement, que sous Windows. Alors je l'ai recréé!
Le KotH est hébergé ici: PPCG - Spacewar! Roi de la colline . Je vous encourage à jouer en tant qu’être humain contre au moins un autre bot pour avoir une idée du fonctionnement du jeu.
Le jeu
- Une image correspond à 30 millisecondes (soit environ 33 images par seconde).
- Le champ mesure 800 pixels de large et 600 pixels de haut.
- Le champ est toroïdal, ce qui signifie que les vaisseaux spatiaux et les missiles qui se déplacent à l'extérieur du champ réapparaissent de l'autre côté.
- Il y a deux vaisseaux spatiaux, rouge et bleu.
- Le rouge est positionné à x = 50 et le y aléatoire entre 50 pixels (hauteur du champ - 50).
- Le bleu est positionné à x = (largeur de champ - 50) et y aléatoire entre 50 (hauteur de champ - 50) pixels.
- Les deux faces x = (largeur du champ) / 2.
- Les contrôles disponibles sont:
- Tournez à gauche - 5 degrés par image dans le sens antihoraire.
- Tourner à droite - 5 degrés par image dans le sens des aiguilles d'une montre.
- Missile anti-feu - parcourt 10 pixels supplémentaires par image, en plus de la vitesse du navire, dans la direction indiquée par celui-ci.
- Fire engine - accélère le vaisseau spatial à 0,30 pixel par image dans la direction indiquée par le vaisseau spatial.
- Saut hyperespace: téléporte sur des coordonnées aléatoires sur le terrain, avec 25% de chances d’exploser. Ces coordonnées aléatoires peuvent être au-dessus du soleil.
- La vitesse maximale des navires est de 15 pixels par image sous la puissance du moteur et de 40 pixels par image lorsque la gravité est renforcée.
- Lorsque la vitesse de déplacement dépasse 15 pixels par image, la poussée du moteur peut uniquement changer de direction ou ralentir.
- En ce qui concerne les missiles:
- Les missiles se déplacent en ligne droite.
- Les missiles peuvent être lancés à une cadence maximale de 1 toutes les 0,1 secondes.
- Les missiles ont une durée de vie de 2,25 secondes.
- Les navires ont chacun un maximum de 20 missiles.
- Les missiles sont des particules ponctuelles internes.
- Il y a un soleil au centre même qui est extrêmement dangereux pour votre navire. Le moindre contact est fatal. Ce soleil détruit aussi les missiles.
- Le soleil a la gravité. L'accélération résultante est de 5000 / (distance ^ 2) pixels / image ^ 2, où la distance est exprimée en pixels. Les vaisseaux spatiaux et les missiles sont touchés.
- Les deux navires ont trois zones d’attaque: le nez, l’aile gauche et l’aile droite.
- Un coup sur le nez est la mort instantanée.
- Un coup sur l'une ou l'autre aile réduit de moitié le taux de virage et l'accélération du moteur du vaisseau spatial.
- Si les deux ailes sont détruites, le vaisseau spatial ne peut pas être manœuvré et ne peut tirer que des missiles.
- Les navires peuvent entrer en collision les uns avec les autres.
- Un impact nez-nez est fatal pour les deux navires.
- Un impact de nez-aile détruit l'aile.
- Un impact d'aile détruit les deux ailes.
- Les navires morts sont solides et gelés jusqu'à ce qu'ils explosent 1 seconde plus tard.
- Après la mort d'au moins un navire, le champ est réinitialisé 3 secondes plus tard. Jusque-là, le soleil et tous les missiles restants sont toujours dangereux.
Le jeu original a aussi des astéroïdes mortels et indestructibles, mais je ne les inclurai pas.
Les règles
- Votre bot doit être écrit en JavaScript.
- Votre bot devrait limiter sa décision à environ 10 millisecondes. Si je remarque un décalage constant à cause de votre bot , je le disqualifie et vous le fais savoir afin que vous puissiez le réparer.
- Les robots auront accès aux éléments suivants:
- Largeur et hauteur du champ
- Position et rayon du soleil
- La position, la rotation, la vitesse, la forme, le stock de missiles et l'état dans l'hyperespace des deux navires
- La position et la vitesse de tous les missiles
- Lorsque vous y êtes invité, votre bot doit renvoyer une liste de chaînes.
- Ces chaînes devraient être l' un des éléments suivants:
turn left
,turn right
,fire engine
,fire missile
,hyperspace
. Toute autre chaîne sera ignorée. - S'il y a des doublons, seul le premier sera noté.
hyperspace
a priorité sur tous les autres.turn left
etturn right
en même temps n'aura aucun effet.fire engine
n'aura aucun effet si le navire n'a que le nez ou est mort.fire missile
n'aura aucun effet si un missile a été tiré trop récemment.
- Ces chaînes devraient être l' un des éléments suivants:
- Contrairement à l'habitude, votre bot est autorisé à exploiter le comportement des autres robots. Je veux encourager un métagame.
- Les bots ne peuvent pas imiter d'autres bots. (Ie, pas de lecture de l'esprit.)
- Les robots ne peuvent définir aucune variable utilisée par le code du jeu et de la physique. (C'est-à-dire, pas de triche.)
Détails d'implémentation du bot
Je vais stocker votre bot dans son propre fichier JavaScript qui est automatiquement inclus, avec le nom du fichier bot_<name>.js
. Donc, ne mettez pas d'espaces ou de caractères qui pourraient interférer avec cela ou pour nommer une fonction en JavaScript. C'est parce que vous devez définir les fonctions suivantes: <name>_setup(team)
et <name>_getActions(gameInfo, botVars)
. Plus bas dans la page, il existe des zones de texte pour l' utilisateur , que vous pouvez modifier pour tester votre code.
<name>_setup(team)
Cette fonction vous permet de définir les variables que vous souhaitez conserver. team
sera soit "red"
ou "blue"
. Cette fonction doit retourner un objet. Définissez les variables comme suit:
var vars = {};
vars['example'] = "example";
return vars;
Cet vars
objet sera transmis à l'autre fonction:
<name>_getActions(gameInfo, botVars)
botVars
est l'objet renvoyé par <name>_setup(team)
. gameInfo
est un objet contenant les variables suivantes:
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
Votre bot a un accès complet à ceux-ci. Je suis sûr que vous pouvez leur écrire sans affecter les variables d'origine, mais ne le faites pas quand même. Remarque sur les rotations: les navires pointent dans la direction + y, vers le bas, de sorte que tout ce que vous souhaitez aligner sur le navire doit être décalé de 90 degrés. En outre, la rotation positive est dans le sens des aiguilles d'une montre.
Cette fonction doit renvoyer une liste de chaînes, représentant les actions de votre bot. Par exemple, ["turn right","thrust"]
. Plus de détails à ce sujet se trouvent dans la section Règles .
Détails supplémentaires
Vous pouvez également utiliser les éléments suivants:
LineIntersection(L1, L2)
L1 et L2 sont des tableaux à deux éléments de tableaux à deux éléments. C'est, L1 := [[x1,y1],[x2,y2]]
et L2 := [[u1,v1],[u2,v2]]
. Cette fonction calcule l'intersection de deux lignes et renvoie ceci: [[x,y], [a,b]]
. [x,y]
sont les coordonnées du point d'intersection et [a,b]
sont une paire de ratios qui expriment la distance le long de chaque ligne du point d'intersection. Comme dans, a = 0.25
cela signifierait que le point d'intersection est à un quart du chemin de [x1,y1]
à [x2,y2]
, et de même pour b
. S'il n'y a pas d'intersection, un tableau vide est renvoyé.
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]]
};
Ce sont les coordonnées des polygones des navires. Pour obtenir plus facilement les coordonnées actuelles, vous pouvez également utiliser ...
getShipCoords(<color>)
getShipCoords("red")
renverra les coordonnées actuelles des sommets du vaisseau de Red, ainsi que pour getShipCoords("blue")
et Blue. Ces coordonnées sont dans une liste comme ceci: [[x1,y1],[x2,y2],[x3,y3],...]
. Les polygones étant implicitement fermés, il y a une ligne entre la première et la dernière paire de coordonnées.
Vous ne pouvez pas accéder ni modifier aucune autre variable ou fonction utilisée par le jeu / site web. Et ne nommez pas vos fonctions de la même manière. Je ne prévois pas que ce sera un problème, mais si votre bot casse le code du jeu, c'est une possibilité. Il n'y a pas de journalisation ou de capture d'exceptions.
Gagnant
- Chaque paire de robots doit être jouée au moins 10 fois, dans les deux sens. (Donc, au moins 20 jeux au total.)
- Essayez d’obtenir les ratios de gains / pertes les plus élevés au total . Si votre bot réussit très bien contre un autre, mais perd contre les trois autres, ce n'est pas aussi bon que de gagner contre deux et de perdre contre deux (en règle générale).
- Pour chaque bot, les ratios (gains + 1) / (pertes + 1) seront calculés, puis la moyenne et l'écart type de ces ratios seront calculés. Une moyenne plus élevée sera prioritaire, et si les moyennes sont à moins d'une unité les unes des autres, la variance la plus faible aura la priorité.
- La notation commencera soit dans une semaine à compter d’aujourd’hui, soit après trois jours sans nouvelle soumission. C'est pour que je n'ai pas à répéter les paires de robots.
Surtout, amusez-vous!
Classement (2016-01-08 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
Note: Ceci est sujet à changement car je lance plus de jeux. De plus, l'ordre des rangs 9-13 me dérange, je peux donc modifier la méthode de notation pour mieux correspondre à l'intuition de la manière dont elle devrait être classée.
(Les moyennes et les écarts-types ont été arrondis à trois chiffres décimaux. De plus, cela Hyper
devrait être, HYPER
mais cela gâchera la mise en évidence.: P)
LineIntersection
sur des segments ne se croisant pas renvoie un tableau vide.