Ceci est un défi KOTH pour le jeu d' enchères d' un billet d'un dollar dans la théorie des jeux. Dans ce document, un dollar est vendu au plus offrant. Les offres augmentent par incréments de 5 ¢, et le perdant paie également leur offre. L'idée est que les deux joueurs intensifient la guerre des enchères bien au-delà de la valeur d'un dollar afin de réduire leurs pertes.
Espérons que vos robots sont plus intelligents que cela.
Vous allez créer un bot pour jouer à ce jeu en prolongeant la net.ramenchef.dollarauction.DollarBidder
classe. Vous devez implémenter la nextBid
méthode qui renvoie la prochaine enchère de votre bot compte tenu de la précédente enchère. Si nécessaire, vous pouvez également utiliser la newAuction
méthode pour réinitialiser chaque vente aux enchères avec la classe du bot de l'adversaire.
public abstract class DollarBidder {
/**
* Used by the runner to keep track of scores.
*/
long score = 0;
/**
* (Optional) Prepare for the next auction.
*
* @param opponent The class of the opponent's bot.
*/
public void newAuction(Class<? extends DollarBidder> opponent) {}
/**
* Bid on the dollar. Bidding ends if the bid is
* not enough to top the previous bid or both bids
* exceed $100.
*
* @param opponentsBid How much money, in cents,
* that the opponent bid in the previous round. If
* this is the first round in the auction, it will
* be 0.
* @return How much money to bid in this round, in
* cents.
*/
public abstract int nextBid(int opponentsBid);
}
Les enchères vont jusqu'à ce que l'une des situations suivantes se produise:
nextBid
jette une exception. Si cela se produit, le bot qui a lancé l'exception paie son enchère précédente et l'autre bot reçoit le dollar gratuitement.- Les deux robots ne paient pas assez pour dépasser l'enchère précédente. Si cela se produit, les deux robots paient leurs enchères (le perdant paye leur offre précédente) et le gagnant reçoit un dollar.
- Les deux robots ont offert plus de 100 $. Si cela se produit, les deux robots paient 100 $ et aucun des deux ne récupère le dollar.
2 enchères sont organisées pour chaque combinaison de robots. Les bots sont évalués en fonction du bénéfice total qu'ils ont réalisé sur ces enchères. Le score le plus élevé gagne.
Exemples
GreedyBot
import net.ramenchef.dollarauction.DollarBidder;
public class GreedyBot extends DollarBidder {
@Override
public int nextBid(int opponentsBid) {
return opponentsBid + 5;
}
}
OnlyWinningMove
import net.ramenchef.dollarauction.DollarBidder;
public class OnlyWinningMove extends DollarBidder {
@Override
public int nextBid(int opponentsBid) {
return 0;
}
}
AnalystBot
Ne l'utilisez pas comme modèle pour les robots dotés d'un esprit d'analyse; utiliser à la ImprovedAnalystBot
place.
import net.ramenchef.dollarauction.DollarBidder;
// yes, this is a poor implementation, but I'm not
// going to waste my time perfecting it
public class AnalystBot extends DollarBidder {
private DollarBidder enemy;
@Override
public void newAuction(Class<? extends DollarBidder> opponent) {
try {
enemy = opponent.newInstance();
enemy.newAuction(this.getClass());
} catch (ReflectiveOperationException e) {
enemy = null;
}
}
@Override
public int nextBid(int opponentsBid) {
if (enemy == null)
return 0;
return enemy.nextBid(95) >= 100 ? 0 : 95;
}
}
AnalystKiller
import net.ramenchef.dollarauction.DollarBidder;
public class AnalystKiller extends DollarBidder {
private static int instances = 0;
private final boolean tainted;
public AnalystKiller() {
this.tainted = instances++ != 0;
}
@Override
public int nextBid(int opponentsBid) {
if (tainted)
throw new RuntimeException("A mysterious error occurred! >:)");
return 0;
}
}
Règles additionnelles
- Les échappatoires standard sont interdites.
- Saboter d'autres robots est autorisé, mais tenter de modifier la visibilité du champ / de la méthode donnera lieu à des
SecurityException
s mystérieux . Une exception provoque un autre bot pour dépasser la limite de 500 ms. - Les robots ne peuvent pas accéder au package du coureur, sauf pour étendre la
DollarBidder
classe. - Toutes les méthodes doivent revenir dans 500 ms ou moins.
- Les robots n'ont pas besoin d'être déterministes.
- Votre enchère n'a pas besoin d'être un multiple de 5 ¢.
- 1 $ = 100 ¢
- Les résultats seront affichés le 24 avril 2018.
Résultats
Voir les tours individuels ici.
MTargetedBot: $14.30
BuzzardBot: $9.83
BluffBot: $9.40
RiskRewardBot: $9.35
SecretBot: $8.50
LuckyDiceBot: $7.28
CounterBot: $6.05
MBot: $5.40
StackTraceObfuscaterBot: $5.20
EvilBot: $4.80
MarginalBot: $4.60
TargetValueBot: $4.59
InflationBot: $4.27
UpTo200: $4.20
InsiderTradingBot: $1.90
MimicBot: $1.50
BorkBorkBot: $1.22
DeterrentBot: $0.95
MarginalerBot: $0.00
RandBot: $-4.45
BreakEvenAsap: $-7.00
AnalystOptimizer: $-13.95
DeterredBot: $-1997.06
ScoreOverflowBot: $-21474844.15
MirrorBot: $-21475836.25
Félicitations à MTargetedBot
avec un bénéfice de 14,30 $!
la source
LuckyDiceBot
exemple, des enchères par incréments d'2-12
au moins ..Réponses:
MTargetedBot
la source
MimicBot
Vache sacrée. Je m'attendais à ce que ce soit simple à écrire, puis j'ai ensuite passé 3 heures dessus.
Essentiellement,
MimicBot
conserve une liste de tous les robots disponibles. Lorsqu'il passe à une nouvelle enchère, il parcourt la liste à la recherche de la plus efficace contre l'adversaire actuel. Il utilise ensuite ce bot comme "référence" dans la vente aux enchères.À des fins de test, il serait préférable d’utiliser un sous-ensemble aléatoire des soumissions ou l’ensemble complet. Cela commence par
GreedyBot
,MimicBot
et il y a encore un bot qui ne demande que 5 ¢.la source
InsiderTradingBot
Dans l'esprit de la réponse de @ StephenLeppik, InsiderTradingBot connaît tous ses adversaires et comprend leurs stratégies. Votre déménagement, Stephen.
la source
RichJerk
bot faisait une exception spécifique pour votre bot et enchérissait à 0 $.AnalystBot
pasAnalyst
.MirrorBot
Fait jouer l'ennemi contre lui-même.
la source
Analyst
spectaculaire.Edit : Des modifications ciblées dans la classe DollarBidder ont endommagé ce bot.
ScoreOverflowBot
Après une enchère, son score sera de -2147483645 mais la prochaine fois, il perdra 5 ¢ ou 105 ¢, ce qui en fera un résultat positif et très important. Toutes les autres pertes seraient alors négligeables.
Lors de la première enchère, cela ferait également un pari de GreedyBot -2147483646 qui n’est pas divisible par 5.
la source
score
est protégé par un paquet. Vos robots ne peuvent pas y accéder.TargetValueBot
Je ne peux pas tester cela pour le moment, alors laissez-moi savoir s'il est cassé.
En gros, choisissez une valeur pour le dollar et surenchérissez jusqu'à ce que votre adversaire dépasse cette valeur.
la source
MarginalBot
Très simple, il essaie de déterminer si un adversaire peut contester une enchère minimale et, dans le cas contraire, la place.
MarginalerBot
Une nouvelle version plus intelligente de MarginalBot qui vérifie si elle peut faire de l’argent sans effort, au lieu d’espérer gagner au minimum.
Étant donné qu'il fait partie de la même famille que mon précédent bot, mais qu'il évite les stratégies qui tentent de le vaincre, j'ai pensé qu'une nouvelle entrée dans le même poste était la manière la plus raisonnable de la présenter.
Edit 1: Modifiez légèrement la méthode newAuction afin de l’optimiser par rapport à d’autres robots de type analyseur.
Edit 2: Fait un changement de MarginalerBot pour minimiser les pertes ou les stratégies contre sournoise non déterministe.
la source
BorkBorkBot
Abandonne s'il ne peut pas atteindre le seuil de rentabilité.
la source
RandBot
Il devait être fait.
la source
Dissuasif
Les tentatives visant à persuader les robots à l'esprit analytique que le seul coup gagnant est de ne pas jouer.
la source
LuckyDiceBot
LuckyDiceBot ne fait confiance qu'à ses dés. Il lance deux dés, ajoute la somme à la valeur du soumissionnaire actuel et enchérit. Si ce n'est pas suffisant pour surmonter l'offre de l'adversaire, il réduit ses pertes et continue son chemin.
la source
opponentsBid
innextBid(int opponentsBid)
détient l'enchère totale que votre adversaire a misé jusqu'à présent, et non l'enchère suivante. Un meilleur terme pour la méthode seraitraise
(comme le terme Poker) à mon humble avis. 2. Votre bot ne mord pas par incréments de 5 et valide donc l’une des règles. Si ces problèmes sont résolus, j'aime quand même le concept, car les robots d'analyse ne pourront pas contrer et vous gagnerez donc très souvent.DeterredBot
DeterredBot tire une fortune de son jeu illégal avec LuckyDiceBot. Alors bien sûr, lorsque la police (DeterrentBot) arrive, il doit rapidement disposer de ses revenus, par exemple en passant une enchère lors de la prochaine enchère.
la source
InflationBot
Je ne peux pas tester cela pour le moment, alors laissez-moi savoir s'il est cassé.
À chaque tour, la valeur du dollar augmente.
la source
opponentsBid
est-il toujours 0)?Non-concurrent: AbstractAnalystCounterBot
Ceci n'est pas conçu comme une vraie soumission, mais plutôt comme un passe-partout que d'autres peuvent utiliser pour dissuader les bots élevant des animaux de compagnie comme
MirrorBot
etMimicBot
.Comme il s'agit du constructeur par défaut, il n'est pas nécessaire de l'appeler dans votre sous-classe. Il implémente une
isPeeking
méthode pour déterminer si un autre bot surveille.la source
BreakEvenAsap
Scénarios
<= 0
il perd.[5,95]
: enchérissez à 100. Soit votre adversaire s'arrête maintenant, soit une enchère supérieure à 100, auquel cas vous arrêtez d'enchérir pour lui permettre de remporter la victoire et de vous équilibrer vous-même.>= 100
: enchérissez 0 pour perdre mais égaliser.la source
EvilBot
Lance une erreur au lieu d'une exception pour dérouter les analystes.
la source
BuzzardBot
Essaye d'évaluer l'adversaire auquel il est confronté et veille à ne pas mordre plus qu'il ne peut mâcher.
la source
AnalystOptimizer
bricolé à partir de parties d'autres robots. celui-ci joue en essayant d’être AnalystBot et, en cas d’échec, devient BorkBorkBot.
Je ne pense pas que celui-ci le fera bien.
la source
AnalystKiller
.CounterBot
Compteurs:
DarthVader
se rétablit en provoquant unSecurityException
avant que l’enchère ne commence, mais je vais enchérir au cas où.AnalystBot
etAnalystOptimizer
les deux regarderont ma réponse quand j'aurai misé 95, auquel cas je montrerai que j'ai misé 100 pour qu'il mette 95 lui-même. Je vais en faire 5 cependant si je commence (ou 100 s'ils ont commencé), donc ils perdent 95 cents et je gagne soit le billet d'un dollar en n'enchérissant que 5 cents, ou en atteignant le seuil de rentabilité.MirrorBot
va dire ce que je voudrais dire contre. Donc, je vais juste enchérir 5, et celui qui commence gagne 95 cents, et l’autre perd 5 cents.MarginalBot
Enchérirai 5 si j'enchéris moins de 10 (ou ce qu'il commence), sinon il enchérira 0. Donc si je mets juste 5 quand je commence, ou 10 quand il commence, je gagne soit 95 ou 90 cents, et ils perdent 5 centimesGreedyBot
toujours plus 5 fois que moi, alors offrez simplement 0 à l'équilibre et laissez-les remporterOnlyWinningMove
etAnalystKiller
tous les deux toujours 0, alors enchérissez 5 pour gagnerTargetValueBot
les enchères dans la fourchette[100,200]
, alors 5 au moins chaque fois jusqu'à 190, auquel cas nous relançons à 200 pour atteindre le seuil de rentabilité en gagnant le dollar (et les laissons perdre 190 ou 195 selon le joueur qui a commencé)BorkBorkBot
va enchérir dans la fourchette[5,95]
, donc 5 en plus à chaque fois. Dès qu'ils enchérissent 85 ou 90 (selon celui qui a commencé), enchérissez vous-même à 95. Ils vont perdre 85 ou 90 cents et vous gagnerez la facture de 1 USD pour un bénéfice de 5 cents.DeterrentBot
ils miseront 5 s'ils débutent ou 100 si nous commençons, donc il suffit de miser 105 pour qu'ils se remettent avec 100, ce qui leur fait perdre 100 et nous ne perdons que 5 cents en gagnant le billet d'un dollar.BreakEvenAsap
va enchérir 100 tout de suite. Donc, s'ils ont commencé avec leur enchère de 100, contre avec 105 pour gagner 95 centimes et les laisser en perdre 100. Si nous commençons par enchérir à 100, nous ferons tous les deux en équilibre.RichJerk
va miser 10 001 tout de suite, donc misez 0 pour atteindre le seuil de rentabilité et laissez-les perdre 9 901.DeterredBot
ne me connaît pas et va donc enchérir sur 0, donc enchérir sur 5 pour gagner.LuckyDiceBot
continue à enchérir jusqu'à ce qu'il gagne. Donc, si nous avons commencé, enchérissons 5 dans l'espoir qu'ils gagnent le plus possible. S'ils ont commencé, enchérissez simplement sur 0 pour leur permettre de remporter la victoire et de vous équilibrer vous-même.RandBot
enchérirons au hasard dans la fourchette[5,100]
, alors enchérissez 5 fois de plus jusqu'à la fin, auquel cas vous avez gagné 95 cents et ils ont perdu0-100
.UpTo200
va (comme son nom l'indique) enchérir jusqu'à 200. Alors, enchérissez de 5 jusqu'à ce qu'ils s'arrêtent. Nous allons gagner la facture de 1 USD et prendre une perte totale de 105 cents, mais ils perdent 200 cents.InsiderTradingBot
ne me connaît pas, alors enchérissez 5 cents pour gagnerMimicBot
était le plus difficile. Il suffit de miser 10 pour commencer ou contrer leur première enchère de 5. Si ils essaient de me contacter, je lève une exception RuntimeException (qu’ils attraperont dans ce cas, ce serait comme si j’avais misé 100 à la place - mais cela romprait la boucle intérieure en boucle). En fonction des ennemis présents dans HashSet, il se produit une chose différente. Je devrai revenir et regarder de plus près pour voir s'il y a un compteur réel.RiskRewardBot
ne me connait pas alors je vais juste enchérir 5, auquel cas je vais enchérir 5 pour gagner.MarginalerBot
mordra jusqu'à 100 en fonction de ce que je ferais une offre. Si je peux commencer, je vais enchérir à 90 €, puis à 95 €, puis à 100 €, pour qu'il mette 0 et qu'il perde 95 cents, pendant que je gagne le billet de 1 USD et que nous équilibrons. Si elle peut commencer à la place, elle verra que je miserais 90 contre elle, donc elle mordra à 90, alors je miserai sur 95 pour miser sur 0 et perdre 90 cents, tandis que je gagnerai la facture de 1 USD avec un profit de 5 cents.BuzzardBot
analysera tous mes compteurs de la gamme[0,100)
. Si j'enchéris100
tout de suite, il utiliseraoppFlag = 0
et le tableau complet de taille 100 contiendra 100x la valeur 100. Dans le commutateurcase 0
, la boucle sera à[0,100)
nouveau dans la plage , et puisquei + 5
au maximum sera 104, le ifbids[i] < i + 5
ne sera jamais vrai , donc l'offre reste 0.ImprovedAnalystBot
aura toujoursthis.enemy = null
parce que son adversaire estCounterBot
, pas lui-même. Donc, il enchérira toujours 0, ce que je viens de contrer avec une enchère de 5.InflationBot
va miser sur 0 pour atteindre le seuil de rentabilité au début, sinon il continuera à enchérir sur 5. Donc, il suffit de miser sur 0 pour atteindre le seuil de rentabilité immédiatement et les laisser remporter la victoire.ScoreOverflowBot
soit les enchères prochesInteger.MAX_VALUE
s’ils peuvent commencer, sinon ils vont enchérir105
. Donc, s'ils ont enchéri sur 105, il leur suffit d'en mettre 110 à leur tour (ils en perdront 105, nous en perdrons 10), sinon, enchérissez simplement 0 pour leur permettre de remporter la victoire.MBot
est identique àMarginalerBot
, mais avec une protection supplémentaire contre les adversaires "furtifs". Puisque je ne «jette pas un œil», c'est fondamentalement la même chose queMarginalerBot
.SecretBot
saisPeeking()
méthode retournera false, donc si elle peut commencer ou si j'en ai offert 5, elle enchérira 5 ou 10 respectivement. Sinon, il enchérira 0. Ainsi, que je commence ou non,opponentsBid + 5
je gagnerai de toute façon, avec mes enchères de 10 cents ou de 15 cents, ce qui leur fera perdre soit 5 ou 10 cents.BluffBot
examinera ce que je voudrais enchérir lorsque son offre est de 95, et si cela est supérieur ou égal à 100, il enchérira 0 pour atteindre le seuil de rentabilité, sinon, il enchériraopponentsBid + 5
. Donc, je vais juste enchériropponentsBid + 5
. Quel que soit le départ, ça va casser, et je gagne soit 100 ou 95 cents, que je sois parti ou non.StackTraceObfuscaterBot
agira de la même manière queMarginalerBot
.EvilBot
toujours enchérir 5, alors enchérissezopponentsBid + 5
. Dans les deux cas, ils perdront ces 5 cents et nous remporterons l’offre d’un dollar (soit avec une offre de 5 cents si nous partons, soit une offre de 10 cents s’ils ont commencé).MSlowBot
est le même queMBot
et donc aussiMarginalerBot
.Faites-moi savoir si vous voyez des fautes de frappe ou des défauts dans mes compteurs.
la source
MirrorBot
appelle newAuction avec votre propre classe, donc c'est un problème. En outre, je suis heureux de savoir que les 3 heures passées sur MimicBot n’ont pas été vaines.newAuction
car il échouerait le plus souvent .. Je ne peux pas contrerMirrorBot
ni me contrer. Celui qui commence des deux gagne 95 cents et l'autre perd 5 cents.BorkBorkBot
, ne devriez-vous pas relancer à 95 quand ils atteignent 85? Sinon, vous enchérissez tous les deux à 95 s'ils commencent.RiskRewardBot
Je ne peux pas tester cela pour le moment, alors laissez-moi savoir s'il est cassé.
L'objectif est d'obtenir le score total le plus élevé, alors ne vous inquiétez pas de battre quelqu'un. Prenez simplement les victoires faciles et ne gaspillez pas votre argent en pertes possibles.
la source
BluffBot
Un espion que vous connaissez est plus précieux que pas d'espion du tout ...
Si quelqu'un d'autre essaie d'appeler la méthode getBid, BluffBot lui répond avec 100 dollars pour l'inciter à cesser de fumer ou à miser très haut.
Sinon, voyez s'il est possible de gagner pour moins de 1 $ et n'enchérissez pas si ce n'est pas le cas.
la source
UpTo200
la source
SecretBot
Ce bot fait des tentatives minimes pour gagner en miser sur 5 ou 10. Il vérifie également la trace de la pile pour voir s’il a été appelé par un autre bot et leur ment ensuite sur les enchères qu’il va faire.
la source
isPeeking
enAbstractAnalystCounterBot
?Un extra
Enchère 6 fois plus que la dernière enchère, simplement parce qu'il le peut.
la source
StackTraceObfuscaterBot
Ce robot se moque des tentatives de détection de la réflexion via la trace de pile. La chose la plus proche qu’ils voient
DollarBidder
est une classe lambda qu’elle a créée. Clairement pas un autre bot essayant de les refléter. Peu savent-ils que cette classe lambda travaille réellement pour unDollarBidder
. Au-delà, il agit commeMarginalerBot
.la source
Dark Vador
Celui-ci essaie de forcer le bot de l'adversaire à surpayer en définissant le cache d'entiers sur une valeur supérieure à la limite de 100 $.
la source
return opponentsBid <= 195 ? opponentsBid + 5 : 0
et de les fairereturn opponentsBid <= 100001 ? opponentsBid + 100001 : 100001
.ImprovedAnalystBot
(non-concurrent)Beaucoup de gens semblent utiliser le
AnalystBot
code comme modèle, même s'il est délibérément mauvais. Donc, je fais un meilleur modèle.la source
AnalystBot
est délibérément un mauvais code pour pouvoir démontrer sonAnalystKiller
sabotage.MBot
MarginalerBot légèrement raffiné
la source
nextBid
lancerClassCastException
.Non concurrent: MSlowBot
Même logique que MBot, utilisez simplement timeout au lieu de Exception lorsque vous combattez un ennemi. Jusqu'à présent, personne ne défend le délai d'expiration, alors il devrait être efficace
la source