Résultats finaux disponibles
introduction
Après mon précédent KOTH avec des thèmes lourds ( guerre fantastique , pandémie mondiale ...), je suis de retour avec un nouveau jeu léger. Cette fois, vous vous retrouvez face à une situation de "jeu de société". Une pile de pièces à l'envers est placée au centre d'une très grande table, et vous êtes déterminé à obtenir votre part du butin!
Glossaire
Pièces : jetons qui peuvent être retournés ou non.
Non retourné : pièces placées sur la table avec leur valeur pointant vers le bas. Il s'agit de l'état par défaut des pièces.
Renversé : pièces placées sur la table avec leur valeur pointant vers le haut.
Local : fait référence à votre pile de pièces.
Global : fait référence à la pile de pièces au centre.
Principe
Au début de la partie, chaque joueur commence avec 0 points et 0 pièces (retournées ou non). Le jeu est au tour par tour. Pendant leur tour, les joueurs peuvent effectuer jusqu'à 3 actions interagissant soit avec la pile de pièces au centre de la table, leur propre pile de pièces ou avec d'autres joueurs.
L'ordre de jeu est défini de manière aléatoire au début de la partie. L'ordre des joueurs dans la liste d'arguments représente l'ordre du tour, et il va de gauche à droite dans cette liste. "Suivant" et "Précédent" se réfèrent respectivement à "à droite dans cette liste" et "à gauche dans cette liste" avec une boucle si vous êtes le dernier de chaque côté.
Le jeu dure 50 tours ou jusqu'à ce qu'il y ait 0 pièces au centre à la fin d'un tour de joueur (ce qui signifie que vous terminerez vos 3 actions même si la pile est vide après votre première action, et vous pouvez remettre des pièces à laisser le jeu continue). Le nombre de pièces mondiales de départ est défini de manière aléatoire avec cette formule:
(2 ^ nb_players) + (nb_players * 10) - random(1 + (nb_players ^ 2))`
Chaque action vous rapportera des points (ou vous fera en perdre) et à la fin de la partie, chaque pièce que vous aurez sera ajoutée à vos points ( -1 pour non retourné, +2 pour retourné ). Le joueur avec le score le plus élevé gagne.
Le contrôleur vous fournit une entrée via des arguments de commande, et votre programme doit sortir via stdout.
Syntaxe
Contribution
Chaque fois que votre programme est appelé, il recevra des arguments dans ce format:
Round;YourPlayerId;Coins;PlayerId_Points_Flipped_Unflipped;PlayerId_Points_Flipped_Unflipped;...
Les tours sont indexés 1.
Exemple d'entrée
6;2;52;1_20_3_12;0_-2_0_1;2_12_1_0
Ici, vous voyez que c'est le 6ème round et vous êtes le joueur 2. Il y a 52 pièces dans la pile centrale. Vous avez 12 points, 1 pièce retournée et 0 pièce non retournée. Les points peuvent être négatifs.
Sortie
Vous devez produire trois caractères (pas d'espace, pas de séparateur), qui correspondent chacun à une action que vous effectuerez ce tour-ci. L'ordre des personnages détermine l'ordre des actions. Vous pouvez générer plusieurs fois les mêmes actions. Dans le cas où il n'y a pas assez de pièces pour terminer votre action, il utilisera le maximum de pièces disponibles et ne comptera que les pièces utilisées.
N
: Ne rien faire
1
: Prendre 1 pièce de la pile centrale [Effets: +1 local non retourné / -1 point / -1 global non retourné]
2
: Prendre 2 pièces de la pile centrale [Effets: +2 local non retourné / -2 points / -2 global non retourné]
3
: Prenez 3 pièces de la pile centrale [Effets: +3 local non retourné / -3 points / -3 global non retourné]
A
: Remettez 1 pièce de votre pile [Effets: -1 local non retourné / +1 point / +1 global non retourné]
B
: Remettez 2 pièces de votre pile [Effets: -2 local non retourné / +2 points / +2 global non retourné]
C
: Remettez 3 pièces de votre pile [Effets: -3 local non retourné / +3 points / +3 global unflipped]
X
: Retirez 1 pièce de votre pile[Effets: -1 local non retourné / 0 point]
Y
: Retirez 2 pièces de votre pile [Effets: -2 local non retourné / 0 point]
Z
: Retirez 3 pièces de votre pile [Effets: -3 local non retourné / 0 point]
R
: Faites pivoter les pièces au joueur précédent [Effets: -1 point par reçu non retourné, +2 points par reçu retourné / s'applique à tous les joueurs]
T
: Tournez les pièces vers le joueur suivant [Effets: -1 point par reçu non retourné, +2 points par reçu retourné / s'applique à tous les joueurs]
F
: lancer 1 pièce [Effets: -1 local non retourné / +1 local retourné / +2 point]
U
: défaire 1 pièce [Effets: +1 local non retourné / -1 local retourné / -2 point]
Exemple de sortie
2FF
: Prend deux pièces et lance deux pièces, marquant -2 + 2 + 2 = 2 points
Si votre sortie est incorrecte, le contrôleur assumera NNN
.
Manette
Vous pouvez trouver le contrôleur sur GitHub . Il contient également deux exemples de robots, écrits en Java. Pour le faire fonctionner, consultez le projet et ouvrez-le dans votre IDE Java. Le point d'entrée dans la main
méthode de la classe Game
. Java 8 requis.
Pour ajouter des bots, vous devez d'abord avoir la version compilée pour Java (fichiers .class) ou les sources des langages interprétés. Placez-les dans le dossier racine du projet. Ensuite, créez une nouvelle classe Java dans le players
package (vous pouvez prendre exemple sur les bots déjà existants). Cette classe doit implémenter Player
pour remplacer la méthode String getCmd()
. La chaîne renvoyée est la commande shell pour exécuter vos bots. Vous pouvez par exemple faire un travail de robot Ruby avec cette commande: return "C:\Ruby\bin\ruby.exe MyBot.rb";
. Enfin, ajoutez le bot dans le tableau des joueurs en haut de la Game
classe.
Règles
- Les bots ne doivent pas être écrits pour battre ou soutenir d'autres bots spécifiques.
- L'écriture dans des fichiers est autorisée. Veuillez écrire à "votrenomdemission.txt", le dossier sera vidé avant le début du jeu. D'autres ressources externes sont interdites.
- Votre soumission a 1 seconde pour répondre.
- Fournissez des commandes pour compiler et exécuter vos soumissions.
Langues prises en charge
Je vais essayer de prendre en charge toutes les langues, mais elles doivent être disponibles en ligne gratuitement. Veuillez fournir des instructions pour l'installation si vous n'utilisez pas un langage "courant".
En ce moment, je peux exécuter: Java 6-7-8, PHP, Ruby, Perl, Python 2-3, Lua, R, node.js, Haskell, Kotlin, C ++ 11.
Résultats finaux
Ce sont les résultats de 100 matchs (les points sont additionnés):
1. BirdInTheHand: 1017790
2. Balance: 851428
3. SecondBest: 802316
4. Crook: 739080
5. Jim: 723440
6. Flipper: 613290
7. Wheeler: 585516
8. Oracle: 574916
9. SimpleBot: 543665
10. TraderBot: 538160
11. EgoisticalBot: 529567
12. RememberMe: 497513
13. PassiveBot: 494441
14. TheJanitor: 474069
15. GreedyRotation: 447057
16. Devil: 79212
17. Saboteur: 62240
Les résultats individuels des jeux sont disponibles ici: http://pasted.co/63f1e924 (avec les pièces de départ et le nombre de tours par partie).
Une récompense de 50 réputations est attribuée au lauréat: Bird In The Hand de Martin Büttner .
Merci à tous pour votre participation, à la prochaine KOTH ~
la source
Réponses:
Oiseau dans la main, rubis
Si aucun de nous n'a de bogue dans ses programmes, l'algorithme principal de celui-ci est probablement très similaire à Oracle de Mathias. En supposant qu'avant le tour final, nous ne pouvons pas savoir avec quelles pièces nous nous retrouverons, nous évaluons l'ensemble actuel de mouvements uniquement sur la base des points reçus immédiatement, en ignorant complètement le type de pièces que nous finirons. avec. Puisqu'il n'y a que 14 3 = 2744 ensembles de mouvements possibles, nous pouvons facilement les simuler tous pour déterminer combien de points ils apporteront.
Cependant, si un ensemble de coups met fin au jeu (soit parce qu'il réduit le pot global à zéro, soit parce que c'est le tour 50 et que nous sommes les derniers à bouger), il prend également en compte les pièces détenues à la fin de l'ensemble de mouvements pour déterminer la valeur de l'ensemble de mouvements. J'ai d'abord envisagé de mettre fin au jeu autant que possible, mais cela entraînerait un mouvement horrible
333
lorsqu'il ne reste que 9 pièces dans le pot.S'il y a plusieurs ensembles de mouvements donnant le même résultat, nous choisissons un ensemble aléatoire. (Je pourrais changer cela pour le biaiser en faveur des ensembles de coups de fin de jeu.)
la source
Oracle, Python 3
Mise à jour: modification de l'ordre des différentes tentatives pour privilégier les piles de pièces basses aux rotations.
Essaie toutes les sorties possibles et garde celle qui rapporte le maximum de points pour ce tour.
la source
deepcopy
complexité de l'espace (donc du temps [ ]) en ne gardant que des voisins pertinents. Je ne sais pas comment cela affectera les choses.filter_neighbors
et modifiéinvalid_move
pour tenir compte des clarifications dans la question. Je ne peux pas reproduire l'erreur cependant:$ python oracle.py '4;7;2040;8_-28_1_10;9_-43_0_9;2_-10_4_3;6_-24_6_3;0_6_2_12;1_48_3_0;10_21_4_8;5_6_5_1;4_-12_3_7;7_10_1_3;3_1_1_0'
imprimeTTR
Rotation gourmande, rubis
Ceci est assez similaire à l'approche d'ArtOfCode, sauf que cela vérifie de quel voisin nous pouvons obtenir plus de points, et il choisit
C
plutôt queF
si nous nous retrouvons avec 3 pièces ou plus après la rotation.Après avoir écrit ceci, je suis presque sûr qu'une meilleure approche serait juste de choisir goulûment le meilleur de tous les mouvements à chaque fois, en précédant la rotation en prenant si possible (au lieu de s'en tenir à un fixe " de motif "non retourné").
Cela ne prend pas non plus en compte les points implicites représentés par les pièces réellement détenues (en supposant que le jeu va durer suffisamment de tours que je ne finirai probablement pas par garder mes pièces de toute façon).
la source
Flipper, Python 2
Flipper rassemble des pièces et essaie de tourner non retourné à retourné. Flipper n'est pas un joueur intelligent mais essaie d'être une force positive dans le jeu.
Flipper a juste besoin
python flipper.py <arg>
de fonctionner.la source
SimpleBot, Python 3
SimpleBot est, eh bien, simple. Il a élaboré une stratégie et il va s'y tenir.
Courir:
où le contenu du
main.py
fichier est:la source
Balance, Lua
Balance essaiera de maintenir l'équilibre dans son jeton, minimisant la perte au cas où quelqu'un utiliserait les actions
R
etT
contre lui. Il pense que ce style de vie est le vrai et devrait être appliqué à toute personne qui ne maintient pas un bon équilibre entre les pièces retournées et non retournées, de sorte que tous ses proches seront punis dès qu'ils pourraient leur faire perdre des points.Il a besoin de la commande suivante pour s'exécuter:
Où le fichier balance.lua contient le code suivant:
la source
Le concierge, Python 3
Il essaie de nettoyer le gâchis que les autres joueurs font avec toutes ces pièces et les remet dans le pool.
Il essaie de rendre toutes ses pièces non retournées, s'il a des pièces coincées, il les déverrouillera et s'il se débarrasse de toutes ses pièces, il obtiendra quelqu'un d'autre.
la source
Crook, R
Courir:
Rscript Crook.R
Fondamentalement, il échange ses pièces avec ses voisins uniquement si l'échange n'est pas en sa faveur. Si aucun échange bénéfique n'est possible, il échange des pièces avec la pile globale d'une manière qui maintient son ratio intact mais génère des points.
Edit: J'ai ajouté un peu de profondeur à ce bot en le faisant vérifier les piles de joueurs 2 et 3 suivantes et précédentes au lieu de juste la suivante et vérifier si, dans l'ensemble, il est avantageux de faire pivoter ce nombre de fois.
2nd Edit : Suivant l'idée de @ MartinBüttner, le bot effectue maintenant un "RT", ou "TR", si cela lui serait plus bénéfique que pour ses voisins (si je ne me trompais pas en l'implémentant :)).
la source
RTR
sorte que vous obteniez le score de ses pièces deux fois.Jim, Ruby
basé sur Greedy Rotation de Martin Büttner .
tournera dans un sens ou dans l'autre, selon ce qui lui donnera le plus de points par rapport au meilleur autre joueur. Ensuite, il retourne pour de l'argent rapide.
la source
TraderBot
Ce bot essaie de tourner chaque fois que c'est celui qui prend le plus de points dans cette action. S'il ne peut pas pivoter, il essaie de se débarrasser des pièces non retournées ou de prendre un peu plus pour les changer dans les actions suivantes.
import java.util.List;
public class TraderBot {
Pour exécuter: ajoutez-le simplement dans le même dossier que les bots par défaut, puis créez la classe suivante
Ajoutez ensuite cette classe au
Player[] players
tableau.la source
Wheeler
Wheeler a calculé le meilleur mouvement possible lors de la rotation des pièces.
la source
Saboteur, Python 2
Le caractère aléatoire signifie qu'il ne sabotera probablement pas très bien, mais plus tard, je pense que je vais l'attendre jusqu'à la `` fin '' (combien de tours / pièces il reste) et ALORS tourner, après avoir regardé les joueurs accessibles à proximité pour voler ... en fait, une seule rotation semble vraiment médiocre, étant donné que d'autres personnes sont également susceptibles d'utiliser des rotations. Je ne pense pas que cela fonctionnera très bien ...
la source
SecondBest, Python 3
Ce programme passera par toutes les combinaisons de 3 coups possibles et choisira la deuxième meilleure.
Parce que si vous avez le mouvement parfait, c'est probablement un piège.
Modifier: suppression de l'entrée commentée
Modifier: le code imprimait un mouvement légal aléatoire. Il devrait maintenant renvoyer le deuxième meilleur résultat.
la source
Bot du diable
Bien que sa production ne soit que la moitié du nombre du diable, les résultats devraient être assez désastreux. Prenant 9 pièces à chaque tour, il épuise finalement la pile de pièces. Étant donné que ce bot ne retourne jamais aucune des pièces qu'il prend, il est extrêmement mauvais pour quiconque assis à côté de lui lorsqu'il y a une rotation (-9 points pour chaque tour pris par ce bot).
Commander:
python3 devil.py
J'espère faire de vrais robots plus tard.
la source
Souviens-toi de moi, Python 3
Ce programme contient une quantité importante de données intégrées d'un test contre le bot SecondBest fixe.
Il devrait savoir quels mouvements sont les meilleurs à utiliser, mais il n'utilise pas la contribution des autres joueurs.
Modifier: suppression du calcul de point inutile
Edit: entrée de lecteur non commentée
la source