Jeu de la faim - Manger ou mourir
Si tu ne manges pas, tu meurs. Si vous mangez, vous vivez (jusqu'à votre mort). Vous allez mourir, alors essayez de mourir en dernier.
Vue d'ensemble
Il y a une île peuplée d'un troupeau de proies. Vous contrôlez un groupe de cinq prédateurs. Votre but est de garder votre sac en vie. Faites cela en mangeant une proie. La proie a tendance à fuir les prédateurs et à essayer de rester dans un troupeau autrement. Bien sûr, votre paquet sera sur le même terrain que tous les autres , alors la compétition essaiera de les manger avant que vous puissiez. Ne laissez pas cela vous décourager, sinon vous mourrez de faim.
Comment jouer
Créez et soumettez un programme en ligne de commande pour diriger votre pack. Il recevra les informations d'état du programme de contrôle sur STDIN et les commandes de sortie sur STDOUT. Le format est décrit en détail ci-dessous. Chaque programme ne sera exécuté qu'une seule fois et doit rester actif jusqu'à ce qu'il ne reste plus aucun membre du pack en vie. Vous devrez lire les commentaires dès leur réception et réagir rapidement. Il y a un délai d'attente strict de 200 ms pour chaque réponse. Si vous n'avez pas répondu à ce moment-là, votre pack ne recevra pas de nouvelles instructions pour le tour en cours.
Si votre programme ne peut pas être exécuté par le contrôleur, il ne sera pas considéré comme valide. Veuillez inclure la chaîne de ligne de commande que je devrai utiliser pour exécuter votre soumission. S'il y a des instructions spéciales (pour installer les compilateurs, etc.), veuillez les inclure. Si je ne parviens pas à le faire fonctionner, je vous demanderai de l’aide pour vos commentaires. Si vous ne répondez pas, je ne serai pas en mesure d'accepter votre soumission.
Le tournoi se déroulera sur un système Linux 64 bits. Gardez cela à l'esprit lorsque vous donnez les instructions nécessaires.
Détails
La position et la direction de chaque créature se présentent sous la forme d'une paire de nombres à virgule flottante double précision (p
double
. Ex. ) Représentant leurs coordonnéesx
ety
.Chaque créature est considérée comme un point. Cela signifie qu'ils peuvent se chevaucher et occuper le même espace. Vous ne serez pas mis de côté et il n'y a pas de concept de collision avec d'autres créatures.
L'île est une place, 500 unités sur le côté. Si vous essayez d'aller au-delà de ces limites, vous serez coincé sur le bord. L'origine
{0,0}
est en haut à gauche, avec unex
augmentation à droite ety
une diminution. Encore une fois, la carte ne se termine pas .Le jeu commence avec plus de 1500 proies (packCount * 50) . Ils seront rassemblés au centre de l'île, mais décident rapidement de commencer à bouger.
Les paquets seront disposés dans un cercle uniformément espacé autour du périmètre. La commande du paquet est mélangée, alors ne comptez pas commencer dans un endroit particulier.
Les animaux proies peuvent voir tous les autres animaux dans un rayon de 30 unités. Ils peuvent se déplacer à un maximum de 6,0 unités par tour.
Les prédateurs peuvent voir tous les autres animaux dans un rayon de 50 unités. Ils peuvent se déplacer à un maximum de 6,1 unités par tour. Cela signifie qu'ils peuvent voir leurs proies avant d'être vues et (à peine) les distancer.
Les prédateurs vivent et meurent en fonction de leur faim . Il commence à 1000 et diminue d'un tour à chaque tour. Si, après le déplacement, un prédateur se trouve à moins d'une unité de proie, il le mangera automatiquement. Cela supprime la proie et règle la faim du prédateur à 1 000. Chaque prédateur ne peut manger qu'une seule proie par tour. S'il y en a plus d'un dans la plage, il mangera celui que la boucle arrive en premier (pas nécessairement le plus proche). Un prédateur meurt si sa faim atteint zéro.
Les packs commencent par cinq membres chacun. Tous les 5000 tours, tous les packs encore en jeu engendreront un nouveau membre. Il sera placé à portée visible d'un membre du groupe. Assurez-vous que vos entrées peuvent gérer plus de cinq membres.
Tous les 1000 tours, plus de proies vont apparaître. Le nombre de nouvelles proies sera le nombre de prédateurs vivants moins un.
Les prédateurs ne peuvent pas attaquer d'autres prédateurs. Ils mangent des proies quand ils l'attrapent. C'est ça.
L'ordre dans un tour est:
- Toutes les proies prennent des décisions
- Tous les prédateurs prennent des décisions
- Toutes les proies bougent
- Tous les prédateurs bougent / mangent
L'ordre dans lequel chaque pack prend ses décisions / se déplace sera randomisé à chaque tour.
Protocole (général)
Toutes les communications sont effectuées au format chaîne US-ASCII
. Les nombres sont convertis en chaînes avec Java Double.toString()
ou Integer.toString()
. Votre sortie doit être formatée pour pouvoir être lue par Java Double.valueOf(String)
(vous ne produirez pas d’entiers). Pour plus de détails sur les formats analysables, voir la documentation deDouble
. Tous les champs d'une ligne sont séparés par le \t
caractère standard et les nouvelles lignes le sont \n
. La chaîne entière sera terminée sera un octet nul \0
.
Dans les exemples ci-dessous, j'utilise <>
pour marquer les champs à des fins de lisibilité. Ce ne sont pas présents dans les chaînes réelles.
Protocole (entrée)
La longueur de la chaîne d’entrée varie en fonction du nombre de créatures visibles par votre pack. Il peut dépasser 100 000 caractères, alors préparez-vous à cela. La configuration de base est la suivante:
Ligne 0: informations de base sur le jeu.
turn
est le numéro de tour actuel et les comptes représentent le nombre total de proies et de prédateurs laissés sur le terrain. Ce sontinteger
sous forme de chaîne.<turn>\t<preyCount>\t<predatorCount>\n
Ligne 1: Identifiants uniques et niveaux de faim des membres de votre meute. Celles-ci ne sont pas données dans le même ordre pour chaque entrée. Utilisez les identifiants uniques pour suivre les membres individuels, pas l'ordre dans lequel ils apparaissent dans l'entrée. Encore une fois, ce sont des
integer
chaînes. Pour un paquet de deux, ce serait:<id[0]>\t<hunger[0]>\t<id[1]>\t<hunger[1]>\n
Ligne 2: Les positions de vos membres du groupe, dans le même ordre que celui indiqué à la ligne 1 . Ce sont
double
comme chaîne:<x[0]>\t<y[0]>\t<x[1]>\t<y[1]>\n
Les lignes suivantes représentent la visibilité de chaque membre du pack, dans le même ordre que celui indiqué à la ligne 1 . Celles-ci seront données comme deux lignes par membre.
Le premier pour chacun consiste en des emplacements pour la proie qu'il peut voir. La seconde est l’emplacement des prédateurs qu’il peut voir. Ces endroits ne sont pas uniques dans leur ensemble. Par exemple, si deux membres du groupe peuvent voir le même animal, il sera dans la chaîne des deux membres. De plus, vos propres membres du pack seront inclus. Si vous souhaitez les exclure, vous pouvez comparer les emplacements avec vos propres membres. Tous les emplacements sont au double
format chaîne.
Pour chaque membre vivant:
<prey[0].x>\t<prey[0].y>\t<prey[1].x>\t<prey[1].y>\n
<predator[0].x>\t<predator[0].y>\t<predator[1].x>\t<predator[1].y>\n
Enfin, le dernier caractère sera \0
au début de la ligne suivante.
Exception: si vous recevez une entrée dead\0
, votre pack est mort. Terminez votre programme avec grâce, s'il vous plaît. Le contrôleur doit arrêter tous les processus en cours lorsqu'il est fermé, mais je préférerais ne pas avoir de processus zombies partout. Par courtoisie, vous pouvez inclure un délai d’entrée. Par exemple, mon exemple de classe se termine s'il ne reçoit aucune entrée pendant 15 secondes.
Protocole (sortie)
La sortie est simple. Vous donnerez une paire de double
valeurs pour chaque membre du pack live. Ceux-ci représentent le mouvement que vous voudriez qu'ils prennent ce tour-ci. Par exemple, si votre créature est actuellement sur {100.0, 100.0}
et que vous lui en donnez la commande {-1.0, 1.0}
, ils se déplaceront vers {99.0, 101.0}
. Tous les numéros seront sur une seule ligne, séparés par des tabulations.
Par exemple, si vous aviez 3 membres du pack en vie, cette réponse serait valide:
1.0\t-1.0\t2.0\t-2.0\t3.0\t-3.0\0
Cela déplacer vos créatures par {1.0,-1.0}
, {2.0,-2.0}
et {3.0,-3.0}
. L'ordre est le même que celui reçu dans l'entrée. N'oubliez pas la fin \0
!
Si vous donnez une entrée invalide, vous obtiendrez de mauvais résultats. Si un nombre unique ne peut pas être analysé comme un double
, il deviendra zéro. Si la chaîne dans son ensemble ne peut pas être analysée, aucune nouvelle instruction ne sera donnée et l'ensemble de votre pack utilisera les instructions du tour précédent.
Toutes les directions seront serrées à une distance maximale de 6,1 unités. Vous pouvez vous déplacer plus lentement que cela si vous le souhaitez. Par exemple, {1, 0}
vous déplacerez une unité. {6,8}
(distance 10) ne vous déplacera que 6,1 unités et sera réduit à environ {3.66, 4.88}
. La direction reste constante.
Important: le programme de contrôle lit votre STDOUT et votre STDERR. Si vous générez une exception et imprimez sur STDERR, il est très peu probable que le message se présente sous la forme d'une réponse valide. Essayez d'éviter de faire cela.
Programme de contrôle / test
La source du contrôleur peut être trouvée ici à bitbucket.org . Vous aurez besoin de le compiler avant de lancer. La classe principale est Game
, et toutes les classes sont dans le package par défaut. Pour exécuter, incluez la commande de chaque pack en tant qu'argument séparé. Par exemple, si vous souhaitez exécuter un Java ChaserPack et un Python LazyPack.py, vous pouvez utiliser:
java Game "java ChaserPack" "python LazyPack.py"
Sur la carte, les proies apparaissent en vert et les prédateurs en rouge. Cependant, quel que soit le paquet, le premier paquet donné en argument sera coloré en bleu. Ceci est destiné à les distinguer plus facilement à des fins de test. Les prédateurs clignotent également en blanc pendant cinq images lorsqu'ils mangent.
Le jeu se poursuivra jusqu'à ce que le dernier prédateur meure de faim, écrivant sur la console à mesure que des événements de famine ou d'extinction se produisent. Une fois le jeu terminé, le score sera attribué à chaque groupe. Si vous ne voulez pas voir les événements de famine / extinction, vous pouvez utiliser l' -silent
argument. Ensuite, il ne sortira que le score final Vous devez passer ceci comme premier argument :
java Game -silent "java ChaserCat" "./someOtherPack"
Inclus est un pack Java squelette nommé GenericPack
. Il comprend les opérations d'entrée / sortie de base nécessaires. Il est là pour donner un exemple clair de la façon d’analyser et de répondre. Si vous souhaitez ajouter un modèle dans une autre langue, faites-le moi savoir.
Un prédateur basé sur le modèle est également inclus ChaserPack
. Il ne sera pas inclus dans le tournoi et est uniquement inclus à des fins de test. Il fonctionne assez mal en raison d'un défaut de ciblage intentionnel. Si vous ne pouvez pas le battre, continuez d'essayer.
Vous trouverez ci-dessous un exemple d'exécution du programme de contrôle (cliquez pour voir la vidéo). La qualité vidéo n'est pas excellente (désolée), mais vous pouvez avoir une idée de la façon dont la proie bouge. ( attention: audio )
Notation
Le gagnant sera déterminé par tournoi, en gagnant des points à chaque tour.
Chaque tour se poursuit jusqu'à ce que tous les prédateurs soient morts. Chaque meute sera notée en fonction du moment où son dernier membre est décédé de faim. Ils se verront attribuer des points en fonction de la commande. Les points seront cumulés pendant dix tours et le vainqueur est le groupe qui totalise le plus de points.
La première place pour chaque tour recevra 100 points. Après chaque place, la récompense sera réduite de 20% (arrondi à la baisse). Cela continuera jusqu'à ce que les points atteignent zéro (après la 17ème place). Les places de 18 ans et plus ne recevront aucun point pour la ronde. Les packs ex aequo recevront des points égaux. Par exemple:
1st : 100
2nd : 80
3rd : 64 (T)
3rd : 64 (T)
4th : 51
...
17th: 1
18th: 0
19th: 0
Le maximum de points possibles au cours du tournoi est de 1000, de la première place tous les dix fois.
Si plusieurs programmes mettent fin au tournoi à égalité pour la première place, un autre tournoi de dix tours sera organisé avec uniquement les inscriptions de la première place soumises. Cela continuera jusqu'à ce qu'un vainqueur émerge.
Je vais essayer d’organiser un tournoi environ toutes les semaines ou au fur et à mesure de l’arrivée de nouvelles propositions.
Règles additionnelles (fair play!)
Vous ne pouvez pas lire ou écrire sur des ressources externes. Comme vous n'allez pas appeler votre programme plusieurs fois, toute information d'état peut être stockée en interne.
Ne pas interférer avec d'autres processus / soumissions. Cela ne signifie pas qu'il ne faut pas essayer de voler leur proie, de les distancer, etc. Cela ne veut pas nuire au bon déroulement du processus. Ceci est à ma discrétion.
Les candidats sont limités à un maximum de trois inscriptions. Si vous soumettez plus, je ne marquerai que les trois premiers. Si vous souhaitez en révoquer un, supprimez-le.
Les entrées peuvent ne pas exister uniquement pour soutenir d'autres entrées. Chacun devrait jouer pour gagner sur son propre mérite.
Votre programme peut générer au maximum un processus enfant à la fois ( nombre total de descendants et non direct). Quoi qu'il en soit, assurez-vous de ne pas dépasser le délai d'attente. Vous ne pouvez en aucun cas invoquer la
Game
classe elle-même.
Résultats - 29 avril 2014
Voici les résultats du dernier tournoi de dix rounds:
Clairvoyant : 1000
EcoCamels : 752
Netcats : 688
RubySpiders : 436
RubyVultures : 431
CivilizedBeasts : 382
LazyPack : 257
Les packs soumis avant 09h00 EDT le 2014/04/29 sont inclus dans cette analyse.
Vous pouvez également afficher les détails de chaque tour . Pour une raison quelconque, j'ai décidé de numéroter les tours en arrière, donc cela commence par "tour 10".
Mises à jour
2014/04/23: FGreg a signalé un bogue lié aux délais d'attente (merci!). Un correctif a été implémenté. Les testeurs souhaitent donc mettre à jour le code de leur programme de contrôle.