Dostępne wyniki końcowe
Wprowadzenie
Po mojej poprzedniej KOTH z ciężkimi motywami ( wojna fantasy , światowa pandemia ...) wróciłem z nową, lekką grą. Tym razem walczysz w sytuacji przypominającej grę planszową. Stos do góry nogami jest umieszczony na środku naprawdę dużego stołu, a ty jesteś zdeterminowany, aby zdobyć część łupu!
Słownik
Monety : Tokeny, które można odwrócić lub odpiąć.
Unflipped : Monety umieszczone na stole z wartością skierowaną w dół. Jest to domyślny stan monet.
Odwrócone : Monety umieszczone na stole z wartością skierowaną w górę.
Lokalny : odnosi się do stosu monet.
Globalny : odnosi się do stosu monet w centrum.
Zasada
Na początku gry każdy gracz zaczyna od 0 punktów i 0 monet (przerzuconych lub odpiętych). Gra jest turowa. Podczas swojej tury gracze mogą wykonać do 3 akcji wchodzących w interakcję ze stosem monet na środku stołu, własnym stosem monet lub z innymi graczami.
Kolejność gry określa się losowo na początku gry. Kolejność graczy na liście argumentów reprezentuje kolejność zakrętów i na tej liście przebiega od lewej do prawej. „Dalej” i „Poprzedni” odnoszą się odpowiednio do „po prawej stronie na tej liście” i „po lewej stronie na tej liście” z pętlą, jeśli jesteś ostatnią ze stron.
Gra trwa 50 rund lub dopóki na środku tury gracza nie ma 0 monet (oznacza to, że ukończysz 3 akcje, nawet jeśli stos jest pusty po pierwszej akcji, i możesz odłożyć monety, aby pozwolić gra będzie kontynuowana). Początkową liczbę globalnych monet określa się losowo za pomocą tego wzoru:
(2 ^ nb_players) + (nb_players * 10) - random(1 + (nb_players ^ 2))`
Każda akcja da ci punkty (lub sprawi, że stracisz trochę), a pod koniec gry każda posiadana moneta zostanie dodana do twoich punktów ( -1 za odpięcie, +2 za przerzucenie ). Gracz z najwyższym wynikiem wygrywa.
Kontroler udostępnia dane wejściowe za pomocą argumentów poleceń, a program musi wysyłać dane wyjściowe za pomocą standardowego wyjścia.
Składnia
Wkład
Za każdym razem, gdy wywoływany jest twój program, będzie on otrzymywał argumenty w następującym formacie:
Round;YourPlayerId;Coins;PlayerId_Points_Flipped_Unflipped;PlayerId_Points_Flipped_Unflipped;...
Rundy są indeksowane 1.
Przykładowe dane wejściowe
6;2;52;1_20_3_12;0_-2_0_1;2_12_1_0
Tutaj widzisz, że jest to szósta runda i jesteś graczem 2. Na środkowym stosie znajdują się 52 monety. Masz 12 punktów, 1 monetę odrzuconą i 0 monetę nieodpinaną. Punkty mogą być ujemne.
Wydajność
Musisz wydać trzy znaki (bez spacji, bez separatora), z których każdy odpowiada jednej akcji, którą wykonasz w tej turze. Kolejność znaków określa kolejność akcji. Możesz wygenerować te same działania wiele razy. Jeśli nie ma wystarczającej ilości monet, aby ukończyć akcję, wykorzysta maksymalną liczbę dostępnych monet i zlicza punkty tylko za użyte monety.
N
: Nic nie
1
rób: Weź 1 monetę ze środkowego stosu [Efekty: +1 miejscowy odpięty / -1 punkt / -1 globalny odpięty]
2
: Weź 2 monety ze środkowego stosu [Efekty: +2 lokalny odpięty / -2 punkty / -2 globalny odpięty]
3
: Weź 3 monety ze środkowego stosu [Efekty: +3 lokalne odpięte / -3 punkty / -3 globalny odpięty]
A
: Odłóż 1 monetę ze swojego stosu [Efekty: -1 lokalne rozpięte / +1 punkt / +1 globalny odpięty]
B
: Odłóż 2 monety ze stosu [Efekty: -2 lokalne odpięty / +2 punkty / +2 globalny odpięty]
C
: Odłóż 3 monety ze swojego stosu [Efekty: -3 lokalny odpięty / +3 punkty / +3 global unclipped]
X
: Usuń 1 monetę ze stosu[Efekty: -1 lokalny odpięty / 0 punkt]
Y
: Usuń 2 monety ze stosu [Efekty: -2 lokalny odpięty / 0 punkt]
Z
: Usuń 3 monety ze stosu [Efekty: -3 lokalny odpięty / 0 punkt]
R
: Obróć monety do poprzedniego gracza [Efekty: -1 punkt za otrzymane odczepienie, +2 punkty za otrzymane odrzucenie / dotyczy wszystkich graczy]
T
: Obracanie monet do następnego gracza [Efekty: -1 punkt za otrzymane odrzucenie / otrzymane / dotyczy wszyscy gracze]
F
: Odwróć 1 monetę [Efekty: -1 odepnij lokalnie / +1 odrzuć lokalnie / +2 punkt]
U
: Odepnij 1 monetę [Efekty: +1 odepnij lokalnie / -1 odrzuć lokalnie / -2 punkt]
Przykładowe dane wyjściowe
2FF
: Bierze dwie monety i rzuca dwie monety, zdobywając punkty -2 + 2 + 2 = 2 points
Jeśli dane wyjściowe są niepoprawne, kontroler przyjmie NNN
.
Kontroler
Kontroler można znaleźć na GitHub . Zawiera także dwa sampleboty napisane w Javie. Aby go uruchomić, sprawdź projekt i otwórz go w swoim Java IDE. Punkt wejścia w main
metodzie klasy Game
. Wymagana Java 8.
Aby dodać boty, najpierw potrzebujesz skompilowanej wersji dla Javy (pliki .class) lub źródeł tłumaczonych języków. Umieść je w folderze głównym projektu. Następnie utwórz nową klasę Java w players
pakiecie (możesz wziąć przykład z już istniejących botów). Ta klasa musi zostać zaimplementowana, Player
aby zastąpić metodę String getCmd()
. Zwrócony ciąg to polecenie powłoki do uruchamiania botów. Można na przykład wykonać pracę bota Ruby z tym poleceniem: return "C:\Ruby\bin\ruby.exe MyBot.rb";
. Na koniec dodaj bota do tablicy graczy na szczycie Game
klasy.
Zasady
- Boty nie powinny być pisane w celu pokonania lub wspierania określonych innych botów.
- Zapis do plików jest dozwolony. Napisz do „twojasubmissionname.txt”, folder zostanie opróżniony przed rozpoczęciem gry. Inne zasoby zewnętrzne są niedozwolone.
- Twoje zgłoszenie ma 1 sekundę na odpowiedź.
- Podaj polecenia, aby skompilować i uruchomić swoje zgłoszenia.
Obsługiwane języki
Spróbuję wesprzeć każdy język, ale musi on być dostępny online za darmo. Podaj instrukcje instalacji, jeśli nie używasz języka „głównego nurtu”.
W tej chwili mogę uruchomić: Java 6-7-8, PHP, Ruby, Perl, Python 2-3, Lua, R, node.js, Haskell, Kotlin, C ++ 11.
Ostateczne rezultaty
Oto wyniki 100 gier (punkty są sumowane):
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
Indywidualne wyniki gier są dostępne tutaj: http://pasted.co/63f1e924 (z monetami początkowymi i liczbą rund na grę).
Nagrodę w wysokości 50 reputacji otrzymuje zwycięzca: Bird In The Hand autorstwa Martina Büttnera .
Dziękujemy wszystkim za udział, do zobaczenia KOTH ~
źródło
Odpowiedzi:
Bird in the Hand, Ruby
Jeśli żadne z nas nie ma błędu w swoich programach, główny algorytm tego jest prawdopodobnie bardzo podobny do Oracle Mathiasa. Opierając się na założeniu, że przed końcową rundą nie wiemy, z jakimi monetami się skończy, oceniamy bieżący zestaw ruchów wyłącznie na podstawie punktów otrzymanych natychmiast, całkowicie ignorując, jakie monety skończymy z. Ponieważ istnieje tylko 14 3 = 2744 możliwych zestawów ruchów, możemy łatwo symulować je wszystkie, aby dowiedzieć się, ile punktów przyniosą.
Jeśli jednak zestaw ruchów kończy grę (albo dlatego, że zmniejsza globalną pulę do zera, albo dlatego, że jest to runda 50, a my jesteśmy ostatnią, która się porusza), to bierze również pod uwagę monety posiadane na końcu zestaw ruchów, aby określić wartość zestawu ruchów. Najpierw zastanawiałem się nad zakończeniem gry, gdy tylko jest to możliwe, ale spowodowałoby to okropny ruch,
333
gdy w puli pozostało tylko 9 monet.Jeśli istnieje wiele zestawów ruchów dających ten sam wynik, wybieramy losowy. (Mógłbym to zmienić w celu odchylenia na korzyść zestawów ruchów kończących grę).
źródło
Oracle, Python 3
Aktualizacja: zmieniono kolejność różnych prób sprzyjania niskiemu stosowi monet zamiast rotacji.
Próbuje każdej możliwej mocy wyjściowej i zachowaj tę, która daje maksymalną liczbę punktów w tej turze.
źródło
deepcopy
złożoności przestrzeni (a więc czasu [ ]) poprzez utrzymanie tylko odpowiednich sąsiadów. Nie jestem jednak pewien, jak to wpłynie na sytuację.filter_neighbors
i zmodyfikowałem go,invalid_move
aby uwzględnić wyjaśnienia w pytaniu. Nie mogę jednak odtworzyć błędu:$ 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'
printTTR
Chciwy Rotacja, Ruby
Jest to dość podobne do podejścia ArtOfCode, z tą różnicą, że sprawdza, z którego sąsiada możemy uzyskać więcej punktów, i wybiera
C
zamiast tego,F
czy po obrocie otrzymamy 3 lub więcej monet.Po napisaniu tego, jestem prawie pewien, że lepszym podejściem byłoby po prostu łapczywe wybieranie najlepszego ze wszystkich ruchów za każdym razem, poprzedzając obrót, biorąc w miarę możliwości (zamiast trzymać się ustalonego „odpiąć, obrócić, pozbyć się” „odpiętego” wzoru).
Nie bierze to również pod uwagę ukrytych punktów reprezentowanych przez monety rzeczywiście posiadane (w oparciu o założenie, że gra będzie trwać tyle rund, że prawdopodobnie i tak nie zatrzymam moich monet).
źródło
Flipper, Python 2
Flipper zbiera monety i próbuje odwrócić odpięty do odwróconego. Flipper nie jest sprytnym graczem, ale stara się być pozytywną siłą w grze.
Flipper potrzebuje tylko
python flipper.py <arg>
do uruchomienia.źródło
SimpleBot, Python 3
SimpleBot jest, cóż, prosty. Opracował jedną strategię i będzie się jej trzymał.
Biegać:
gdzie zawartość
main.py
pliku to:źródło
Balance, Lua
Balance spróbuje utrzymać równowagę w swoim tokenie, minimalizując stratę na wypadek, gdyby ktoś użył
R
iT
przeciwko niemu. Uważa, że ten styl życia jest prawdziwy i powinien zostać narzucony każdemu, kto nie zachowuje równowagi między rzutami / monetami, więc wszyscy bliscy zostaną ukarani, gdy tylko może stracić punkty.Potrzebuje następującego polecenia do uruchomienia:
Gdzie plik balance.lua zawiera następujący fragment kodu:
źródło
Woźny, Python 3
Próbuje wyczyścić bałagan, jaki robią inni gracze przy pomocy tych wszystkich monet i odłożyć je z powrotem do puli.
Próbuje oddać wszystkie swoje odblokowane monety, jeśli ma kilka zablokowanych monet, to je odblokuje, a jeśli pozbyje się wszystkich swoich monet, zdobędzie kogoś innego.
źródło
Crook, R.
Biegać:
Rscript Crook.R
Zasadniczo wymienia monety z sąsiadami tylko wtedy, gdy ich wymiana jest nierówna na jego korzyść. Jeśli żadna korzystna wymiana nie jest możliwa, to wymienia monety ze stosem globalnym w sposób, który utrzymuje nienaruszony stosunek, ale generuje pewne punkty.
Edycja: Dodałem trochę głębi do tego bota, zmuszając go do sprawdzania kolejnych i poprzednich stosów 2 i 3 graczy zamiast tylko następnego i sprawdzania, czy ogólnie rzecz biorąc, warto obracać tyle razy.
Druga edycja: Zgodnie z pomysłem @ MartinBüttner, bot wykonuje teraz „RT” lub „TR”, jeśli byłoby to dla niego bardziej korzystne niż dla jego sąsiadów (gdybym nie zepsuł się przy wdrażaniu :)).
źródło
RTR
, aby uzyskać wynik z jego monet dwukrotnie.Jim, Ruby
na podstawie Chciwej rotacji Martina Büttnera .
obraca się w jedną lub drugą stronę, w zależności od tego, co da mu najwięcej punktów w porównaniu z najlepszym innym graczem. Potem odwraca się, by uzyskać szybką gotówkę.
źródło
TraderBot
Ten bot próbuje się obracać, ilekroć zajmuje najwięcej punktów w tej akcji. Jeśli nie może się obracać, próbuje pozbyć się odblokowanych monet lub podjąć kilka dodatkowych, aby je zmienić w następujących czynnościach.
import java.util.List;
TraderBot klasy publicznej {
Aby uruchomić: po prostu dodaj go do tego samego folderu, co domyślne boty, a następnie utwórz następującą klasę
Następnie dodaj tę klasę do
Player[] players
tablicy.źródło
Kołodziej
Wheeler obliczył najlepszy możliwy ruch podczas obracania monet.
źródło
Saboteur, Python 2
Losowość oznacza, że prawdopodobnie nie będzie zbyt dobrze sabotażować, ale później myślę, że będę musiał poczekać do końca (ile pozostało tur / monet), a NASTĘPNIE obrócić, po obejrzeniu pobliskich graczy, z których można ukraść ... właściwie tylko jeden obrót wydaje się naprawdę słaby, biorąc pod uwagę, że inni ludzie również mogą używać rotacji. Nie sądzę, żeby to działało bardzo dobrze ...
źródło
SecondBest, Python 3
Ten program przejdzie wszystkie możliwe 3 kombinacje ruchów i wybierze drugą najlepszą.
Ponieważ jeśli masz idealny ruch, prawdopodobnie jest to pułapka.
Edycja: usunięto komentarz z komentarzem
Edycja: kod drukował losowy legalny ruch. Powinien teraz zwracać drugi najlepszy wynik.
źródło
Devil's Bot
Chociaż jego produkcja jest tylko o połowę mniejsza od liczby diabła, wyniki powinny być dość katastrofalne. Biorąc 9 monet w każdej turze, ostatecznie wyczerpuje stos monet. Ponieważ ten bot nigdy nie rzuca żadnymi monetami, jest bardzo zły dla każdego, kto siedzi obok niego, gdy występuje obrót (-9 punktów za każdą turę wykonaną przez tego bota).
Dowództwo:
python3 devil.py
Mam nadzieję, że później zrobię kilka prawdziwych botów.
źródło
Remember Me, Python 3
Ten program zawiera znaczną ilość wbudowanych danych z testu przeciwko stałemu botowi SecondBest.
to powinno nauczyć o tym, co porusza są najlepsze do wykorzystania, ale nie wykorzystane doświadczenia innych graczy.
Edycja: usunięto niepotrzebne obliczenia punktowe
Edycja: niepomocowany wkład gracza
źródło