To wyzwanie KOTH dla gry aukcyjnej za dolary w teorii gier. W nim dolar jest sprzedawany oferentowi, który zaoferował najwyższą cenę. Oferty rosną w krokach co 5 centów, a przegrany płaci również swoją ofertę. Chodzi o to, że obaj gracze eskalują wojnę przetargową znacznie przekraczającą wartość dolara, aby zmniejszyć straty.
Miejmy nadzieję, że twoje boty są mądrzejsze.
Będziesz tworzyć bota, aby zagrać w tę grę, rozszerzając net.ramenchef.dollarauction.DollarBidder
klasę. Musisz wdrożyć nextBid
metodę, która zwraca następną ofertę twojego bota, biorąc pod uwagę poprzednią ofertę innego bota. W razie potrzeby możesz także użyć newAuction
metody resetowania dla każdej aukcji z klasą bota przeciwnika.
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);
}
Licytacja trwa do momentu spełnienia jednego z poniższych warunków:
nextBid
zgłasza wyjątek. Jeśli tak się stanie, bot, który zgłosił wyjątek, płaci swoją poprzednią ofertę, a drugi bot dostaje dolara za darmo.- Żaden bot nie płaci wystarczająco dużo, aby przewyższyć poprzednią ofertę. Jeśli tak się stanie, oba boty płacą swoje oferty (przegrany płaci poprzednią ofertę), a zwycięzca dostaje dolara.
- Oba boty licytują ponad 100 $. Jeśli tak się stanie, oba boty płacą 100 USD, a żaden bot nie dostaje dolara.
Dla każdej kombinacji botów odbywają się 2 aukcje. Boty są oceniane na podstawie całkowitego zysku, jaki osiągnęły na tych aukcjach. Najwyższy wynik wygrywa.
Przykłady
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
Nie używaj tego jako szablonu dla analitycznie nastawionych botów; użyj ImprovedAnalystBot
zamiast tego.
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;
}
}
Dodatkowe zasady
- Standardowe luki są zabronione.
- Sabotowanie innych botów jest dozwolone, ale próba zmiany widoczności pola / metody spowoduje tajemnicze
SecurityException
s. Wyjątek powoduje, że inny bot przekroczy limit 500ms. - Boty nie mogą uzyskać dostępu do pakietu runnera, z wyjątkiem rozszerzenia
DollarBidder
klasy. - Wszystkie metody powinny zostać zwrócone w ciągu 500 ms lub mniej.
- Boty nie muszą być deterministyczne.
- Twoja oferta nie musi być wielokrotnością 5 ¢.
- 1 USD = 100 ¢
- Wyniki zostaną opublikowane 24 kwietnia 2018 r.
Wyniki
Zobacz poszczególne rundy tutaj.
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
Gratulacje MTargetedBot
z zyskiem 14,30 $!
źródło
LuckyDiceBot
na przykład oferty w przyrostach2-12
losowych ..Odpowiedzi:
MTargetedBot
źródło
MimicBot
Święta krowa. Spodziewałem się, że będzie to łatwe do napisania, a następnie spędziłem nad nim 3 godziny.
Zasadniczo
MimicBot
utrzymuje bieżącą listę dostępnych botów. Gdy idzie na nową aukcję, przegląda listę w poszukiwaniu najbardziej efektywnej z aktualnym przeciwnikiem. Następnie używa tego bota jako „odniesienia” na aukcji.Do celów testowych najlepiej byłoby użyć losowego podzestawu zgłoszeń lub pełnego zestawu. Zaczyna się od
GreedyBot
,MimicBot
i jeszcze jednego bota, który licytuje tylko 5 centów.źródło
InsiderTradingBot
W duchu odpowiedzi @ StephenLeppik InsiderTradingBot zna wszystkich swoich przeciwników i rozumie ich strategie. Twój ruch, Stephen.
źródło
RichJerk
bot zrobił wyjątek dla twojego bota i zaoferował za niego 0 $.AnalystBot
nieAnalyst
.MirrorBot
Sprawia, że wróg gra przeciwko sobie.
źródło
Analyst
spektakularnie.Edycja : Ukierunkowane zmiany w klasie DollarBidder spowodowały uszkodzenie tego bota.
ScoreOverflowBot
Po 1 aukcji jego wynik wyniesie -2147483645, ale następnym razem straci 5 ¢ lub 105 ¢, co daje wynik pozytywny i bardzo duży. Wszystkie pozostałe straty byłyby wówczas nieistotne.
Na pierwszej aukcji GreedyBot postawiłby również na -2147483646, co nie jest podzielne przez 5.
źródło
score
jest chroniony paczką. Twoje boty nie mają do niego dostępu.TargetValueBot
W tej chwili nie można tego przetestować, więc daj mi znać, jeśli jest uszkodzony.
Zasadniczo wybierz wartość dolara i przebijaj przeciwnika, aż przekroczymy tę wartość.
źródło
MarginalBot
Bardzo proste, próbuje ustalić, czy przeciwnik podważy minimalną ofertę, a jeśli nie, stawia ją.
MarginalerBot
Nowa, inteligentniejsza wersja MarginalBot, która sprawdza, czy może wykonać jakiś zarabianie pieniędzy bez rywalizacji, a nie tylko ma nadzieję wygrać z minimum.
Ponieważ jest w tej samej rodzinie co mój poprzedni bot, ale strategie, które próbują go pokonać, pomyślałem, że nowy wpis w tym samym poście był najbardziej rozsądnym sposobem przedstawienia go.
Edycja 1: Wprowadzono niewielką zmianę w metodzie newAuction w celu optymalizacji w stosunku do innych botów typu analizatora.
Edycja 2: Dokonano zmiany w MarginalerBot, aby zminimalizować straty w stosunku do podstępnych lub niedeterministycznych strategii.
źródło
BorkBorkBot
Poddaje się, jeśli nie da rady.
źródło
RandBot
To musiało być zrobione.
źródło
DeterrentBot
Próbuje przekonać analitycznie nastawionych botów, że jedynym zwycięskim ruchem nie jest gra.
źródło
LuckyDiceBot
LuckyDiceBot ufa tylko jego kościom. Rzuca dwiema kostkami, dodaje sumę do wartości aktualnego licytanta i tyle licytuje. Jeśli nie wystarczy pokonać ofertę przeciwnika, zmniejsza straty i idzie dalej.
źródło
opponentsBid
wnextBid(int opponentsBid)
trzyma całkowitą ofertę, którą twój przeciwnik złożył do tej pory, a nie kolejną. Lepszym terminem dla tej metody byłobyraise
(jako termin pokera) imho. 2. Twój bot nie gryzie w krokach co 5, dlatego sprawdza jedną z reguł. Jeśli te problemy zostaną rozwiązane, nadal podoba mi się ta koncepcja, ponieważ boty analityczne nie będą w stanie przeciwdziałać, więc najprawdopodobniej wygrasz dość często.DeterredBot
DeterredBot robi fortunę z nielegalnego hazardu w LuckyDiceBot. Oczywiście, kiedy przybywa policja (DeterrentBot), musi on szybko w jakiś sposób pozbyć się swoich zarobków, takich jak licytacja na następnej aukcji.
źródło
InflationBot
W tej chwili nie można tego przetestować, więc daj mi znać, jeśli jest uszkodzony.
W każdej rundzie wartość dolara rośnie.
źródło
opponentsBid
wciąż jest 0)?Niekonkurencyjny: AbstractAnalystCounterBot
Nie jest to zamierzone jako prawdziwe podporządkowanie, ale raczej jako pewna płyta dla innych, aby powstrzymać boty trzymające zwierzęta domowe, takie jak
MirrorBot
iMimicBot
.Ponieważ jest to domyślny konstruktor, nie ma potrzeby wywoływania go w podklasie. Implementuje
isPeeking
metodę określania, czy inny bot szpieguje.źródło
BreakEvenAsap
Scenariusze
<= 0
, przegrywa.[5,95]
: sam licytuj 100. Albo twój przeciwnik się zatrzyma, albo licytuje łącznie powyżej 100, w takim przypadku przestajesz licytować, aby pozwolić mu wygrać i wyrównać.>= 100
: postaw 0 za siebie, by przegrać, ale wyrównaj.źródło
EvilBot
Zgłasza błąd zamiast wyjątku, aby zmylić analityków.
źródło
BuzzardBot
Próbuje ocenić przeciwnika, z którym się mierzy, i upewnij się, że nie odgryzasz więcej, niż może przeżuć.
źródło
AnalystOptimizer
brukowane razem z części innych botów. ten gra próbując być AnalystBot, a jeśli się nie powiedzie, staje się BorkBorkBot.
Nie sądzę, żeby to zrobiło tak dobrze.
źródło
AnalystKiller
.CounterBot
Liczniki:
DarthVader
przeciwdziała samemu powodując aSecurityException
przed rozpoczęciem licytacji, ale na wszelki wypadek licytuję 5.AnalystBot
iAnalystOptimizer
oboje spojrzą na moją odpowiedź, kiedy licytuję 95, w takim przypadku pokażę, że licytuję 100, więc sama licytuje 95. Będę jednak licytować 5, jeśli zacznę (lub 100, jeśli rozpoczęły), więc tracą 95 centów i albo wygrywam rachunek 1 USD, licytując tylko 5 centów, lub osiągając próg rentowności.MirrorBot
licytuje to, co ja licytowałbym przeciwko niemu. Więc licytuję 5, a ktokolwiek zacznie wygrywać 95 centów, a drugi traci 5 centów.MarginalBot
licytuje 5, jeśli licytujebym mniej niż 10 (lub to, co zaczyna), w przeciwnym razie licytuje 0. Więc jeśli po prostu licytuję 5, gdy zaczynam lub 10, gdy zaczyna, wygrywam 95 lub 90 centów, a oni przegrywają 5 centów.GreedyBot
zawsze licytuje o 5 więcej ode mnie, więc po prostu licytuj 0, aby osiągnąć próg rentowności i pozwolić im wygraćOnlyWinningMove
iAnalystKiller
oba zawsze licytują 0, więc po prostu licytuj 5, aby wygraćTargetValueBot
będzie licytować w zakresie[100,200]
, więc licytuj o 5 więcej za każdym razem, dopóki nie osiągną 190, w takim przypadku podbijamy do 200, aby wyrównać, wygrywając dolara (i pozwalamy im stracić 190 lub 195 w zależności od tego, kto zaczął)BorkBorkBot
będzie licytować w tym zakresie[5,95]
, więc za każdym razem licytuj również o 5 więcej. Gdy tylko licytują 85 lub 90 (w zależności od tego, kto zaczął), licytuj 95 samodzielnie. Stracą 85 lub 90 centów, a ty wygrasz rachunek 1 USD za zysk 5 centów.DeterrentBot
licytuje 5, jeśli zaczynają, lub 100, jeśli zaczynamy, więc po prostu licytuj 105, więc liczą 100, powodując, że tracą 100, a my tracimy tylko 5 centów, wygrywając rachunek 1 USD.BreakEvenAsap
od razu licytuje 100. Więc jeśli rozpoczęli licytację 100, skontruj 105, aby wygrać 95 centów i pozwolić im stracić 100. Jeśli możemy zacząć, licytuj tylko 100, więc oboje osiągniemy próg rentowności.RichJerk
licytuje od razu 10,001, więc po prostu licytuj 0, aby wyrównać i pozwolić im stracić 9,901.DeterredBot
mnie nie zna i dlatego licytuje 0, więc po prostu licytuj 5, aby wygrać.LuckyDiceBot
licytuje, aż wygra. Więc jeśli zaczniemy, licytuj 5 w nadziei, że licytują jak najwyższą kwotę, aby wygrać dolara. Jeśli zaczęli, po prostu licytuj 0, aby pozwolić im wygrać i wyrównać.RandBot
będzie licytować losowo w zakresie[5,100]
, więc po prostu licytuj o 5 więcej, aż się zatrzyma, w którym to przypadku wygrałeś 95 centów i przegrali0-100
.UpTo200
będzie (jak sama nazwa wskazuje) licytować do 200. Więc po prostu licytuj o 5 wyżej, aż się zatrzymają. Wygramy rachunek za 1 USD i poniesiemy całkowitą stratę 105 centów, ale oni stracą 200 centów.InsiderTradingBot
nie zna mnie, więc po prostu licytuj 5 centów, aby wygraćMimicBot
było najtrudniejsze. Po prostu licytuj 10, aby zacząć od lub licytować ich pierwszą ofertę 5. Jeśli spróbują uzyskać do mnie dostęp, rzucę wyjątek RuntimeException (który złapią, w którym to przypadku działałoby to tak, jakbym miał licytować 100 - chociaż spowoduje to przerwanie wewnętrzna pętla while). W zależności od wrogów, których ma w HashSet, dzieje się coś innego. Będę musiał ponownie odwiedzić i przyjrzeć się bliżej, aby sprawdzić, czy istnieje prawdziwy licznik.RiskRewardBot
nie zna mnie, więc po prostu licytuje 5, w takim przypadku licytuję 5, aby wygrać.MarginalerBot
ugryzę do 100 w zależności od tego, co chciałbym licytować Jeśli mogę zacząć, licytuję 90, następnie licytuję 95, następnie licytuję 100, więc licytuję 0 i tracę 95 centów, podczas gdy wygrywam rachunek 1 USD i osiągam rentowność. Jeśli zacznie się zamiast tego, zobaczy, że postawiłbym przeciwko niemu 90, więc licytuje sam 90, wtedy licytuję 95, więc licytuje 0 i tracę 90 centów, a ja wygrywam rachunek 1 USD z zyskiem 5 centów.BuzzardBot
przeanalizuje wszystkie moje liczniki w zakresie[0,100)
. Jeśli100
od razu licytuję, użyj,oppFlag = 0
a pełna tablica 100 będzie zawierać 100x wartość 100. W przełącznikucase 0
pętla znów znajdzie się w zakresie[0,100)
, a ponieważi + 5
co najwyżej 104,bids[i] < i + 5
nigdy nie będzie prawdą , więc stawka, którą robi, wynosi 0.ImprovedAnalystBot
zawsze tak będzie,this.enemy = null
ponieważ jego przeciwnikiem jestCounterBot
nie jest sobą. Więc zawsze będzie licytować 0, co ja po prostu liczę z ofertą 5.InflationBot
licytuje 0, aby przełamać, nawet gdy się zacznie, w przeciwnym razie będzie licytować 5. Więc po prostu licytuj 0, aby od razu wyrównać i pozwolić im wygrać.ScoreOverflowBot
albo licytuje w pobliżu,Integer.MAX_VALUE
jeśli mogą zacząć, w przeciwnym razie będą licytować105
. Więc jeśli licytują 105, po prostu sami licytują 110 (przegrają 105, my stracimy 10), w przeciwnym razie po prostu licytuj 0, aby pozwolić im wygrać.MBot
jest taki sam jakMarginalerBot
, ale z dodatkową ochroną przed „zerkającymi” przeciwnikami. Ponieważ nie „podglądam”, jest to w zasadzie to samo coMarginalerBot
.SecretBot
spowoduje, że jegoisPeeking()
metoda zwróci false, więc jeśli może się rozpocząć lub jeśli licytuję 5, odpowiednio licytuje 5 lub 10. W przeciwnym razie będzie licytować 0. Więc czy zacznę, czy nie,opponentsBid + 5
spowodowałbym wygraną w obu kierunkach, zarówno z moimi 10 centami, jak i 15 centów, powodując, że przegrali 5 lub 10 centów.BluffBot
spojrzy na to, co licytuję, gdy jego oferta wynosi 95, a jeśli jest ona większa lub równa 100, zaoferuje 0, aby się przebić, w przeciwnym razie będzie licytowaćopponentsBid + 5
. Więc po prostu licytujęopponentsBid + 5
. Wybije nawet niezależnie od tego, kto zacznie, i wygrywam 100 lub 95 centów w zależności od tego, czy zacząłem, czy nie.StackTraceObfuscaterBot
będzie działać tak samo jakMarginalerBot
.EvilBot
zawsze licytuje 5, więc po prostu licytujopponentsBid + 5
. Tak czy inaczej stracą te 5 centów, a my wygramy licytację 1 USD (albo 5 centów, jeśli zaczniemy, albo 10 centów, jeśli zaczną).MSlowBot
jest taki sam jakMBot
i dlatego teżMarginalerBot
.Daj mi znać, jeśli zobaczysz jakieś literówki lub wady w moich licznikach.
źródło
MirrorBot
nazywa newAuction z własną klasą, więc to jest problem. Cieszę się również, że 3 godziny spędzone na MimicBot nie poszły na marne.newAuction
ponieważ często by się nie udawał . Nie mogę przeciwdziałaćMirrorBot
ani nie może mi się przeciwstawić. Ktokolwiek zaczyna z tych dwóch, wygrywa 95 centów, a drugi traci 5 centów.BorkBorkBot
nie powinieneś przebijać do 95, gdy osiągną 85? W przeciwnym razie oboje licytujesz 95, jeśli zaczną.RiskRewardBot
W tej chwili nie można tego przetestować, więc daj mi znać, jeśli jest uszkodzony.
Celem jest uzyskanie jak najwyższego wyniku, więc nie przejmuj się nikim. Po prostu weź łatwe wygrane i nie marnuj pieniędzy na ewentualne straty.
źródło
BluffBot
Znany szpieg jest cenniejszy niż żaden szpieg ...
Jeśli ktoś inny spróbuje wywołać metodę getBid, BluffBot odpowiada kwotą 100 $, aby nakłonić ich do rezygnacji lub obstawienia naprawdę wysokich.
W przeciwnym razie sprawdź, czy można wygrać za mniej niż 1 $, i po prostu nie licytuj, jeśli nie jest.
źródło
UpTo200
źródło
SecretBot
Ten bot podejmuje minimalne próby wygrania przez licytację 5 lub 10. Sprawdza również ślad stosu, aby sprawdzić, czy został powołany przez innego Bota, a następnie okłamuje ich, jakie stawki złoży.
źródło
isPeeking
doAbstractAnalystCounterBot
?Jeden dodatkowy
Licytuje o 6 więcej niż ostatnia oferta, tylko dlatego, że może.
źródło
StackTraceObfuscaterBot
Ten bot śmieje się z prób wykrycia odbicia za pomocą śladu stosu. Najbliższą rzeczą, jaką widzą,
DollarBidder
jest stworzona przez nią klasa lambda. Najwyraźniej żaden inny bot nie próbuje ich odzwierciedlić. Niewiele wiedzą, że ta klasa lambda faktycznie pracuje dlaDollarBidder
. Poza tym zachowuje się jakMarginalerBot
.źródło
Darth Vader
Ten próbuje zmusić bota przeciwnika do przepłacenia, ustawiając całkowitą pamięć podręczną na wartość przekraczającą limit 100 $.
źródło
return opponentsBid <= 195 ? opponentsBid + 5 : 0
i zrobićreturn opponentsBid <= 100001 ? opponentsBid + 100001 : 100001
.ImprovedAnalystBot
(niekonkurujący)Wydaje się, że wiele osób używa
AnalystBot
kodu jako szablonu, nawet jeśli jest to celowo zły kod. Więc tworzę lepszy szablon.źródło
AnalystBot
jest celowo złym kodem, dzięki czemu może zademonstrowaćAnalystKiller
sabotaż.MBot
Lekko dopracowany MarginalerBot
źródło
nextBid
rzuceniaClassCastException
.Niekonkurencyjny: MSlowBot
Ta sama logika co MBot, po prostu użyj limitu czasu zamiast wyjątku podczas walki z wrogiem. Jak dotąd nikt nie broni limitu czasu, więc powinno być skuteczne
źródło