STAN WYZWANIA: OTWARTY
Komentuj, otwieraj PR lub w inny sposób krzycz na mnie, jeśli brakuje mi twojego bota.
Dylemat więźnia ... z trzema wyborami. Szalony, co?
Oto nasza matryca wypłat. Gracz A po lewej, B na górze
A,B| C | N | D
---|---|---|---
C |3,3|4,1|0,5
N |1,4|2,2|3,2
D |5,0|2,3|1,1
Matryca wypłat jest zaprojektowana tak, aby obaj gracze zawsze współpracowali, ale możesz (zwykle) zyskać, wybierając Neutralny lub Usterkę.
Oto niektóre (konkurujące) przykładowe boty.
# turns out if you don't actually have to implement __init__(). TIL!
class AllC:
def round(self, _): return "C"
class AllN:
def round(self, _): return "N"
class AllD:
def round(self, _): return "D"
class RandomBot:
def round(self, _): return random.choice(["C", "N", "D"])
# Actually using an identically-behaving "FastGrudger".
class Grudger:
def __init__(self):
self.history = []
def round(self, last):
if(last):
self.history.append(last)
if(self.history.count("D") > 0):
return "D"
return "C"
class TitForTat:
def round(self, last):
if(last == "D"):
return "D"
return "C"
Twój bot jest klasą Python3. Nowa instancja jest tworzona dla każdej gry i round()
jest wywoływana w każdej rundzie, z wyborem przeciwnika z ostatniej rundy (lub Brak, jeśli jest to pierwsza runda)
Zwycięzca otrzyma nagrodę w wysokości 50 powtórzeń za miesiąc.
Specyfika
- Każdy bot zagrywa co drugiego bota (1 na 1), w tym siebie, w rundach [ZMIENIONO].
- Standardowe luki zabronione.
- Bez bałaganu z czymkolwiek poza klasą lub innymi podstępnymi shenanigains.
- Możesz przesłać do pięciu botów.
- Tak, możesz wprowadzić uzgadnianie.
- Wszelkie odpowiedzi inne niż
C
,N
lubD
będą po cichu traktowane jakoN
. - Punkty każdego bota z każdej gry będą sumowane i porównywane.
Kontroler
Inne języki
Wyrzucę razem API, jeśli ktoś tego potrzebuje.
Wyniki: 27.11.2018
27 bots, 729 games.
name | avg. score/round
----------------|-------------------
PatternFinder | 3.152
DirichletDice2 | 3.019
EvaluaterBot | 2.971
Ensemble | 2.800
DirichletDice | 2.763
Shifting | 2.737
FastGrudger | 2.632
Nash2 | 2.574
HistoricAverage | 2.552
LastOptimalBot | 2.532
Number6 | 2.531
HandshakeBot | 2.458
OldTitForTat | 2.411
WeightedAverage | 2.403
TitForTat | 2.328
AllD | 2.272
Tetragram | 2.256
Nash | 2.193
Jade | 2.186
Useless | 2.140
RandomBot | 2.018
CopyCat | 1.902
TatForTit | 1.891
NeverCOOP | 1.710
AllC | 1.565
AllN | 1.446
Kevin | 1.322
king-of-the-hill
python
SIGSTACKFAULT
źródło
źródło
while len(botlist) > 1:
zebotlist.remove(lowest_scoring_bot)
w dolnej części pętli, masz turnieju eliminacji z interesujących wyników.Odpowiedzi:
EvaluaterBot
Wygrywa ze wszystkimi poprzednio przesłanymi botami, z wyjątkiem (być może) losowego bota (ale może mieć przewagę, ponieważ wybiera D w losowaniu, a D powinien być optymalny) i gra przeciwko sobie.
źródło
NashEquilibrium
Ten bot wziął udział w zajęciach z teorii gier na studiach, ale był leniwy i nie poszedł na zajęcia, na których omawiał iterowane gry. Gra więc tylko w jedną grę mieszaną równowagą Nasha. Okazuje się, że 1/5 2/5 2/5 to mieszany NE dla wypłat.
Stałe nadużywanie równowagi Nasha
Ten bot odebrał lekcję od dwóch leniwych braci. Problem jego leniwego brata polegał na tym, że nie korzystał z ustalonych strategii. Ta wersja sprawdza, czy przeciwnik jest stałym graczem lub titfortat i gra odpowiednio, w przeciwnym razie gra normalną równowagę nasha.
Jedynym minusem jest to, że gra średnio o 2,2 punktu na turę.
źródło
class NashEquilibrium: def round(self, _): a = random.random() for k, v in [(0.2, "C"), (0.6, "N"), (1, "D")]: if a <= k: return v
TatForTit
Ten bot naprzemiennie wybiera DNDN, a TitForTat zmienia CDCD, uzyskując średni zysk netto w wysokości 3 punktów na rundę, jeśli poprawnie odczytałem macierz wypłat. Myślę, że może to być optymalne w stosunku do TitForTat. Oczywiście można poprawić wykrywanie przeciwnika nieobjętego TFT i przyjmowanie innych strategii, ale ja po prostu dążyłem do oryginalnej nagrody.
źródło
PatternFinder
Ten bot szuka poprzednich wystąpień ostatniego stanu gry, aby zobaczyć, jak przeciwnik zareagował na te zdarzenia, preferując dłuższe mecze według wzorca i nowsze mecze, a następnie odtwarza ruch, który „pokona” przewidywany ruch przeciwnika. Jest dużo miejsca na to, aby był mądrzejszy ze wszystkimi śledzonymi danymi, ale zabrakło mi czasu na pracę nad tym.
źródło
Jadeit
Zaczyna się optymistycznie, ale staje się coraz bardziej zgorzkniały, gdy przeciwnik odmawia współpracy. Wiele magicznych stałych, które prawdopodobnie można by poprawić, ale prawdopodobnie nie będzie to wystarczająco dobre, aby uzasadnić czas.
źródło
Ensemble
To uruchamia zestaw powiązanych modeli. Poszczególne modele uwzględniają różne ilości historii i mają opcję albo wyboru ruchu, który zoptymalizuje oczekiwaną różnicę wypłat, albo losowego wyboru ruchu proporcjonalnego do oczekiwanej różnicy wypłat.
Każdy członek zespołu głosuje następnie na preferowany ruch. Otrzymują liczbę głosów równą temu, ile więcej wygrywają niż przeciwnik (co oznacza, że okropne modele otrzymają głosy negatywne). Którykolwiek ruch wygrywa, głosowanie jest następnie wybierane.
(Prawdopodobnie powinni podzielić swoje głosy między ruchy proporcjonalnie do tego, na ile faworyzują każdy, ale teraz nie dbam o to wystarczająco dużo).
Pokonuje wszystko, co do tej pory opublikowano, z wyjątkiem EvaluaterBot i PatternFinder. (Jeden na jednego, pokonuje EvaluaterBot i przegrywa z PatternFinder).
Framework testowy
W przypadku, gdy ktokolwiek uzna to za przydatne, oto struktura testowa do wyszukiwania pojedynczych pojedynków. Python2. Po prostu umieść wszystkich przeciwników, których jesteś zainteresowany, w opponents.py i zmień odniesienia do Ensemble na własne.
źródło
OldTitForTat
Gracz ze starej szkoły jest zbyt leniwy, aby aktualizować nowe zasady.
źródło
NeverCOOP
Jeśli przeciwny bot ma wady lub jest neutralny, wybierz defekt. W przeciwnym razie, jeśli jest to pierwsza tura lub przeciwny bot współpracuje, wybierz neutralny. Nie jestem pewien, jak dobrze to zadziała ...
źródło
if(last):
w bocie Grudger, wykrywając, czy była poprzednia runda.None in "ND"
błędy.if last and last in "ND":
było to zbyt skomplikowane?LastOptimalBot
Zakłada, że przeciwny bot zawsze będzie ponownie wykonywał ten sam ruch i wybiera ten, który ma najlepszą wypłatę przeciwko niemu.
Średnie:
źródło
return last
.return last
, LOB poszedłby 18-9 w ciągu 6 rund zamiast 13-10 w ciągu 5 rund, które obecnie otrzymuje. Myślę, że jest w porządku - nie martw się o optymalizację przykładowych botów.return last
byłby lepszy T4T do tego wyzwania, myślęif(last): return last; else: return "C"
jest gorzej.CopyCat
Kopiuje ostatni ruch przeciwnika.
Nie spodziewam się, że będzie dobrze, ale nikt jeszcze nie wdrożył tego klasycznego.
źródło
Ulepszone kości Dirichleta
To ulepszona wersja kości Dirichlet. Zamiast brać oczekiwany rozkład wielomianowy z rozkładu Dirichleta, losuje rozkład wielomianowy losowo z rozkładu Dirichleta. Następnie zamiast rysować z wielomianu i dawać optymalną odpowiedź na to, daje optymalną oczekiwaną odpowiedź na dany wielomian za pomocą punktów. Tak więc losowość została zasadniczo przesunięta z losowania wielomianowego na losowanie Dirichleta. Ponadto priory są teraz bardziej płaskie, aby zachęcić do eksploracji.
Jest „ulepszony”, ponieważ teraz uwzględnia system punktowy, podając najlepszą oczekiwaną wartość względem prawdopodobieństw, przy jednoczesnym zachowaniu jego losowości poprzez losowanie samych prawdopodobieństw. Wcześniej próbowałem po prostu uzyskać najlepszą oczekiwaną wypłatę z oczekiwanych prawdopodobieństw, ale zrobiło to źle, ponieważ utknęło i nie zbadałem wystarczająco dużo, aby zaktualizować swoje kości. Było to również bardziej przewidywalne i możliwe do wykorzystania.
Oryginalne zgłoszenie:
Kości Dirichleta
Zasadniczo zakładam, że odpowiedź przeciwnika na mój ostatni wynik jest zmienną wielomianową (kostki ważone), po jednej dla każdego z moich wyników, więc istnieją kości dla „C”, jeden dla „N” i jeden dla „D” . Więc jeśli mój ostatni rzut był na przykład „N”, to rzucam „N-kostkami”, aby zgadnąć, jaka byłaby ich odpowiedź na moje „N”. Zaczynam od przeornika Dirichleta, który zakłada, że mój przeciwnik jest w pewnym sensie „inteligentny” (bardziej prawdopodobne, że zagra w tę z najlepszą wypłatą w stosunku do mojego ostatniego rzutu, najmniej prawdopodobne, że zagra w tę z najgorszą wypłatą). Generuję „oczekiwany” rozkład wielomianowy z odpowiedniego Dirichleta wcześniej (jest to oczekiwana wartość rozkładu prawdopodobieństwa na podstawie ich masy kości). Rzucam ważonymi kostkami mojego ostatniego wyniku,
Zaczynając od trzeciej rundy, wykonuję Bayesowską aktualizację odpowiedniego Dirichleta przed ostatnią odpowiedzią mojego przeciwnika na rzecz, w którą grałem dwie rundy temu. Próbuję iteracyjnie nauczyć się ich ważenia kości.
Mogłem też po prostu wybrać odpowiedź z najlepszym „oczekiwanym” wynikiem po wygenerowaniu kości, zamiast po prostu rzucać kostką i reagować na wynik. Chciałem jednak zachować losowość, aby mój bot był mniej wrażliwy na tych, którzy próbują przewidzieć wzór.
źródło
Kevin
Wybiera najgorszy wybór. Najgorszy zrobiony bot.
Nieprzydatny
Patrzy na dwa ostatnie ruchy wykonane przez przeciwnika i wybiera najbardziej niewykonane, inaczej wybiera coś losowego. Jest prawdopodobnie lepszy sposób na zrobienie tego.
źródło
Średnia historyczna
Spogląda na historię i znajduje działanie, które byłoby średnio najlepsze. Zaczyna współpracować.
źródło
Średnia ważona
Zachowanie przeciwnika jest modelowane jako trójkąt prostokątny z narożnikami dla CND odpowiednio 0,0 0,1 1,0. Każdy ruch przeciwnika przesuwa punkt w obrębie tego trójkąta w kierunku tego rogu, a my gramy, aby pokonać ruch wskazany przez punkt (przy czym C otrzymuje odpowiednio mały kawałek trójkąta). Teoretycznie chciałem mieć dłuższą pamięć z większą wagą do poprzednich ruchów, ale w praktyce obecne meta faworyzuje boty, które zmieniają się szybko, więc przekształca się to w przybliżenie LastOptimalBot przeciwko większości wrogów. Delegowanie dla potomności; może ktoś będzie inspirowany.
źródło
Tetragram
Postaraj się znaleźć wzór w ruchach przeciwnika, zakładając, że obserwują również nasz ostatni ruch.
źródło
Uścisk dłoni
Rozpoznaje, kiedy gra przeciwko sobie, a następnie współpracuje. W przeciwnym razie naśladuje LastOptimalBot, który wydaje się najlepszą strategią jednowierszową. Działa gorzej niż LastOptimalBot, w ilości odwrotnie proporcjonalnej do liczby rund. Oczywiście lepiej by było, gdyby było więcej kopii w terenie * kaszel ** mrugnięcie *.
źródło
ShiftingOptimalBot
Ten bot używa algorytmu LastOptimalBot, dopóki wygrywa. Jeśli jednak inny bot zacznie to przewidywać, zacznie grać w ruch, który wykonał przeciwnik jako ostatni (czyli ruch, który pokonuje ruch, który pokonałby LastOptimalBot). Cyklicznie przechodzi przez proste transpozycje tych algorytmów, o ile nadal traci (lub gdy się nudzi rysując dużo).
Szczerze mówiąc, jestem zaskoczony, że LastOptimalBot siedzi na 5. miejscu, pisząc to. Jestem całkiem pewien, że zrobi to lepiej, zakładając, że poprawnie napisałem ten python.
źródło
HandshakePatternMatch
Dlaczego wzór pasuje do ciebie? Uścisk dłoni i współpraca.
źródło
import PatternFinder
oszukuje w moich książkach.Mocno zakodowane
Po prostu odtwarza zakodowaną sekwencję ruchów zoptymalizowaną pod kątem pokonania niektórych najlepszych deterministycznych botów.
źródło