Tle przyszłych
W 2017 roku ty i twój przeciwnik zmierzą się w futurystycznej bitwie na broń, w której tylko jeden może przetrwać. Czy masz wystarczające doświadczenie, aby pokonać przeciwnika? Nadszedł czas, aby szlifować umiejętności posługiwania się bronią w swoim ulubionym języku programowania i walczyć z wszelkimi przeciwnościami!
Wyniki turnieju
Ten turniej zakończył na UTC rano lutym 2 nd , 2017. Dzięki naszym zawodników, mieliśmy ekscytujący turniej futurystyczny!
MontePlayer jest ostatecznym zwycięzcą po bliskich bitwach z CBetaPlayer i StudiousPlayer. Trzech najlepszych pojedynków Guen wykonało pamiątkową fotografię:
MontePlayer - by TheNumberOne
+------------+
CBetaPlayer | | - by George V. Williams
+------------+ # 1 | StudiousPlayer - by H Walters
| +----------------+
| # 2 # 3 |
+------------------------------------------+
The Futurustic Gun Duel @ PPCG.SE 2017
Gratulacje dla zwycięzców! Szczegółowa tabela wyników znajduje się na końcu tego postu.
Ogólne wskazówki
- Odwiedź oficjalne repozytorium kodu źródłowego używanego w tym turnieju.
- Wpisy w C ++: odziedzicz
Player
klasę. - Pozycje inne niż C ++: wybierz jeden interfejs w sekcji Interfejs dla zgłoszeń innych niż C ++ .
- Obecnie dozwolone języki inne niż C ++: Python 3, Java.
Pojedynek
- Każdy gracz zaczyna od rozładowanego pistoletu, który może załadować nieskończoną ilość amunicji.
- W każdej turze gracze jednocześnie wybiorą jedną z następujących akcji:
0
- Załaduj 1 amunicję do pistoletu.1
- Wystrzel kulę w przeciwnika; kosztuje 1 załadowaną amunicję.2
- Wystrzel promień plazmy na przeciwnika; kosztuje 2 załadowanej amunicji.-
- Broń przychodzącą kulę za pomocą metalowej osłony.=
- Broń przychodzącą wiązkę plazmy za pomocą deflektora termicznego.
- Jeśli obaj gracze przetrwać po 100 th kolei obaj wydechowego do śmierci, co przekłada się remisem .
Gracz przegrywa pojedynek z bronią, jeśli on
- Czy nie używać metalową osłonę bronić przychodzące kulę.
- Czy NIE UŻYWAĆ deflektora termiczną bronić plazmy przychodzące.
- Wystrzel z pistoletu bez załadowania wystarczającej ilości amunicji, w której jego działo wybuchnie i zabije właściciela.
Ostrzeżenia
Zgodnie z instrukcją dla futurystycznych właścicieli broni :
- Metalowa osłona NIE MOŻE bronić przed nadchodzącą wiązką plazmy. Podobnie deflektor termiczny NIE MOŻE bronić przed nadlatującym pociskiem.
- Promień plazmy obezwładnia pocisk (ponieważ ten pierwszy wymaga więcej załadowanej amunicji). Dlatego jeśli gracz strzela wiązką plazmy w przeciwnika, który strzela kulą w tej samej turze, przeciwnik zostaje zabity.
- Jeśli obaj gracze wystrzelą do siebie pocisk w tej samej turze, pociski zostaną anulowane i obaj gracze przeżyją. Podobnie, jeśli obaj gracze wystrzelą na siebie wiązkę plazmy w tej samej turze, obaj gracze przeżyją.
Warto również zauważyć, że:
- NIE będziesz znać akcji przeciwnika po kolei, dopóki się nie skończy.
- Odbijanie wiązek plazmowych i pociski osłaniające NIE zaszkodzą przeciwnikowi.
Dlatego w każdej turze jest 25 prawidłowych kombinacji akcji:
+-------------+---------------------------------------------+
| Outcome | P L A Y E R B |
| Table +--------+-----------------+------------------+
| for Players | Load | Bullet Plasma | Metal Thermal |
+---+---------+--------+--------+--------+--------+---------+
| P | Load | | B wins | B wins | | |
| L +---------+--------+--------+--------+--------+---------+
| A | Bullet | A wins | | B wins | | A wins |
| Y | +--------+--------+--------+--------+---------+
| E | Plasma | A wins | A wins | | A wins | |
| R +---------+--------+--------+--------+--------+---------+
| | Metal | | | B wins | | |
| | +--------+--------+--------+--------+---------+
| A | Thermal | | B wins | | | |
+---+---------+--------+--------+---------------------------+
Note: Blank cells indicate that both players survive to the next turn.
Przykładowy pojedynek
Oto pojedynek, który kiedyś miałem z przyjacielem. Wtedy nie wiedzieliśmy wiele o programowaniu, więc używaliśmy gestów rąk i sygnalizowaliśmy prędkość dwóch obrotów na sekundę. Od lewej do prawej nasze działania były z kolei:
Me: 001-000-1201101001----2
Friend: 00-10-=1-==--0100-1---1
Zgodnie z powyższymi zasadami przegrałem. Czy rozumiesz dlaczego? To dlatego, że wystrzeliłem ostatnią wiązkę plazmy, gdy miałem tylko 1 załadowaną amunicję, co spowodowało wybuch mojej broni.
Odtwarzacz C ++
Ty , jako cywilizowanego futurystycznym programista, nie będzie bezpośrednio obsługiwać broń. Zamiast tego piszesz kod, Player
który walczy z innymi ”. Publicznie dziedzicząc klasę c ++ w projekcie GitHub, możesz zacząć pisać miejską legendę.
Player.hpp can be found in Tournament\Player.hpp
An example of a derived class can be found in Tournament\CustomPlayer.hpp
Co musisz lub możesz zrobić
- Musisz odziedziczyć
Player
klasę w drodze publicznego dziedziczenia i ogłosić klasę jako ostateczną. - Musisz zastąpić
Player::fight
, która zwraca wartość poprawną zaPlayer::Action
każdym razem, gdy zostanie wywołana. - Opcjonalnie możesz przesłonić
Player::perceive
iPlayer::declared
kontrolować działania przeciwnika i śledzić swoje zwycięstwa. - Opcjonalnie użyj prywatnych elementów statycznych i metod w klasie pochodnej, aby wykonać bardziej złożone obliczenia.
- Opcjonalnie użyj innych standardowych bibliotek C ++.
Czego NIE wolno robić
- NIE wolno używać żadnej bezpośredniej metody rozpoznawania przeciwnika poza podanym identyfikatorem przeciwnika, który jest tasowany na początku każdego turnieju. Możesz zgadywać, kto jest graczem podczas gry w turnieju.
- NIE wolno zastępować żadnych metod w
Player
klasie, które nie są zadeklarowane jako wirtualne. - NIE wolno deklarować ani inicjować niczego w zakresie globalnym.
- Od debiutu (teraz zdyskwalifikowanego)
BlackHatPlayer
gracze NIE mogą podglądać ani modyfikować stanu przeciwnika.
Przykładowy pojedynek
Proces pojedynku z bronią odbywa się za pomocą GunDuel
klasy. Przykład walki można znaleźć Source.cpp
w sekcji Inicjowanie pojedynku .
Mamy pokazać GunClubPlayer
, HumanPlayer
a GunDuel
klasa, które można znaleźć w Tournament\
katalogu repozytorium.
W każdym pojedynku GunClubPlayer
załaduje pocisk; odpal to; wypłukać i powtórzyć. Podczas każdej tury HumanPlayer
poprosi cię o akcję przeciwko przeciwnikowi. Twoje kontrole klawiaturowe są znaki 0
, 1
, 2
, -
i =
. W systemie Windows można użyć HumanPlayer
do debugowania zgłoszenia.
Rozpoczęcie pojedynku
W ten sposób możesz debugować odtwarzacz za pomocą konsoli.
// Source.cpp
// An example duel between a HumanPlayer and GunClubPlayer.
#include "HumanPlayer.hpp"
#include "GunClubPlayer.hpp"
#include "GunDuel.hpp"
int main()
{
// Total number of turns per duel.
size_t duelLength = 100;
// Player identifier 1: HumanPlayer.
HumanPlayer human(2);
// Player identifier 2: GunClubPlayer.
GunClubPlayer gunClub(1);
// Prepares a duel.
GunDuel duel(human, gunClub, duelLength);
// Start a duel.
duel.fight();
}
Przykładowe gry
Minimalna liczba tur, które musisz pokonać, GunClubPlayer
to 3. Oto powtórka z gry 0-1
przeciwko GunClubPlayer
. Liczba w nawiasie to liczba załadowanej amunicji dla każdego gracza po zakończeniu tury.
:: Turn 0
You [0/12/-=] >> [0] load ammo (1 ammo)
Opponent selects [0] load ammo (1 ammo)
:: Turn 1
You [0/12/-=] >> [-] defend using metal shield (1 ammo)
Opponent selects [1] fire a bullet (0 ammo)
:: Turn 2
You [0/12/-=] >> [1] fire a bullet (0 ammo)
Opponent selects [0] load ammo (1 ammo)
:: You won after 3 turns!
:: Replay
YOU 0-1
FOE 010
Press any key to continue . . .
Najszybszym sposobem na pokonanie GunClubPlayer
bez wykonywania nieprawidłowych ruchów jest sekwencja 0=
, ponieważ pocisk strzela prosto przez deflektor termiczny. Powtórka jest
:: Turn 0
You [0/12/-=] >> [0] load ammo (1 ammo)
Opponent selects [0] load ammo (1 ammo)
:: Turn 1
You [0/12/-=] >> [=] defend using thermal deflector (1 ammo)
Opponent selects [1] fire a bullet (0 ammo)
:: You lost after 2 turns!
:: Replay
YOU 0=
FOE 01
Press any key to continue . . .
Turniej
Turniej odbywa się w formacie „Last Player Standing”. W turnieju wszystkie ważne zgłoszenia (w tym GunClubPlayer
) są umieszczane w puli. Każde zgłoszenie ma przydzielony losowy, ale niepowtarzalny identyfikator, który pozostanie taki sam podczas całego turnieju. Podczas każdej rundy:
- Każde zgłoszenie rozpoczyna się od 0 punktów i rozegra 100 pojedynków z każdym innym zgłoszeniem.
- Każdy zwycięski pojedynek da 1 punkt; losowanie i przegrywanie daje 0 punktów.
- Pod koniec rundy zgłoszenia z minimalną liczbą punktów opuszczają turniej. W przypadku remisu, gracz z najmniejszą ilością punktów zdobytych od początku turnieju odejdzie.
- Jeśli pozostanie więcej niż jeden gracz, rozpocznie się następna runda.
- Punkty NIE przenoszą się do następnej rundy.
Zgłoszenie
Prześlesz jednego gracza na odpowiedź. Możesz przesłać wiele plików do odtwarzacza, o ile NIE kolidują one z innymi przesyłkami. Aby utrzymać płynność, proszę:
- Nazwij główny plik nagłówka jako
<Custom>Player.hpp
, - Nazwij swoje inne pliki jako
<Custom>Player*.*
, np.MyLittlePlayer.txt
Jeśli nazwa klasy toMyLittlePlayer
, lubEmoPlayerHates.cpp
jeśli nazwa klasy toEmoPlayer
. - Jeśli twoje imię
Shooter
lub podobne słowa pasują do kontekstu tego turnieju, nie musisz dodawaćPlayer
na końcu. Jeśli uważasz, że nazwa zgłoszenia działa lepiej bez przyrostkaPlayer
, nie musisz go dodawaćPlayer
. - Upewnij się, że kod można skompilować i połączyć w systemie Windows.
Możesz skomentować, poprosić o wyjaśnienia lub znaleźć luki. Mam nadzieję, że spodoba ci się ten futurystyczny pojedynek z bronią i życzę szczęśliwego nowego roku!
Wyjaśnienie
- Możesz mieć losowe zachowanie.
- Dozwolone są nieprawidłowe działania (strzelanie, gdy załadowana amunicja nie wystarcza).
- Jeśli gracz dokona nieprawidłowego wejścia, jego pistolet natychmiast wybuchnie.
- Możesz studiować odpowiedzi.
- Możesz wyraźnie rejestrować zachowanie przeciwnika w każdym turnieju.
- W każdej rundzie rozegrasz 100 pojedynków z każdym przeciwnikiem; kolejność 100 pojedynków jest jednak losowa - nie masz gwarancji stoczenia 100 pojedynczych przeciwników z rzędu.
Dodatkowe zasoby
@flawr przetłumaczył dostarczone źródło C ++ na Javę jako odniesienie, jeśli chcesz przesłać wpisy C ++.
Interfejs dla zgłoszeń innych niż C ++
Obecnie akceptowane: Python 3, Java.
Postępuj zgodnie z jedną z poniższych specyfikacji:
Specyfikacja interfejsu 1: kod wyjścia
Twoje zgłoszenie będzie uruchamiane raz na turę.
Expected Command Line Argument Format:
<opponent-id> <turn> <status> <ammo> <ammo-opponent> <history> <history-opponent>
Expected Return Code: The ASCII value of a valid action character.
'0' = 48, '1' = 49, '2' = 50, '-' = 45, '=' = 61
<opponent-id> is an integer in [0, N), where N is size of tournament.
<turn> is 0-based.
If duel is in progress, <status> is 3.
If duel is draw / won / lost, <status> is 0 / 1 / 2.
<history> and <history-opponent> are strings of actions, e.g. 002 0-=
If turn is 0, <history> and <history-opponent> are not provided.
You can ignore arguments you don't particularly need.
Możesz przetestować swoje zgłoszenie PythonPlayer\
i JavaPlayer\
katalogi.
Specyfikacja interfejsu 2: stdin / stdout
(Podziękowania dla H Waltersa)
Twoje zgłoszenie będzie realizowane raz na turniej.
Istnieje stały wymóg dla wszystkich zgłoszeń dotyczących wykonywania operacji we / wy, ponieważ zarówno stdin, jak i stdout są podłączone do sterownika turnieju. Naruszenie tego może doprowadzić do impasu. Wszystkie wpisy MUSZĄ być zgodne z tym DOKŁADNYM algorytmem (w pseudokodzie):
LOOP FOREVER
READ LINE INTO L
IF (LEFT(L,1) == 'I')
INITIALIZE ROUND
// i.e., set your/opponent ammo to 0, if tracking them
// Note: The entire line at this point is a unique id per opponent;
// optionally track this as well.
CONTINUE LOOP
ELSE IF (LEFT(L,1) == 'F')
WRITELN F // where F is your move
ELSE IF (LEFT(L,1) == 'P')
PROCESS MID(L,2,1) // optionally perceive your opponent's action.
END IF
CONTINUE LOOP
QUIT
Tutaj F jest jednym z 0
, 1
, 2
, -
, lub =
za load / bullet / plasma / metal / thermal
. PROCES oznacza opcjonalną reakcję na to, co zrobił twój przeciwnik (w tym śledzenie amunicji przeciwnika, jeśli to robisz). Zauważ, że akcja przeciwnika jest również jedną z „0”, „1”, „2”, „-” lub „=” i występuje w drugim znaku.
Ostateczna tablica wyników
08:02 AM Tuesday, February 2, 2017 Coordinated Universal Time (UTC)
| Player | Language | Points | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
|:------------------ |:---------- | ------:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:|
| MontePlayer | C++ | 11413 | 1415 | 1326 | 1247 | 1106 | 1049 | 942 | 845 | 754 | 685 | 555 | 482 | 381 | 287 | 163 | 115 | 61 |
| CBetaPlayer | C++ | 7014 | 855 | 755 | 706 | 683 | 611 | 593 | 513 | 470 | 414 | 371 | 309 | 251 | 192 | 143 | 109 | 39 |
| StudiousPlayer | C++ | 10014 | 1324 | 1233 | 1125 | 1015 | 907 | 843 | 763 | 635 | 555 | 478 | 403 | 300 | 201 | 156 | 76 |
| FatedPlayer | C++ | 6222 | 745 | 683 | 621 | 655 | 605 | 508 | 494 | 456 | 395 | 317 | 241 | 197 | 167 | 138 |
| HanSoloPlayer | C++ | 5524 | 748 | 668 | 584 | 523 | 490 | 477 | 455 | 403 | 335 | 293 | 209 | 186 | 153 |
| SurvivorPlayer | C++ | 5384 | 769 | 790 | 667 | 574 | 465 | 402 | 354 | 338 | 294 | 290 | 256 | 185 |
| SpecificPlayer | C++ | 5316 | 845 | 752 | 669 | 559 | 488 | 427 | 387 | 386 | 340 | 263 | 200 |
| DeceptivePlayer | C++ | 4187 | 559 | 445 | 464 | 474 | 462 | 442 | 438 | 369 | 301 | 233 |
| NotSoPatientPlayer | C++ | 5105 | 931 | 832 | 742 | 626 | 515 | 469 | 352 | 357 | 281 |
| BarricadePlayer | C++ | 4171 | 661 | 677 | 614 | 567 | 527 | 415 | 378 | 332 |
| BotRobotPlayer | C++ | 3381 | 607 | 510 | 523 | 499 | 496 | 425 | 321 |
| SadisticShooter | C++ | 3826 | 905 | 780 | 686 | 590 | 475 | 390 |
| TurtlePlayer | C++ | 3047 | 754 | 722 | 608 | 539 | 424 |
| CamtoPlayer | C++ | 2308 | 725 | 641 | 537 | 405 |
| OpportunistPlayer | C++ | 1173 | 426 | 420 | 327 |
| GunClubPlayer | C++ | 888 | 500 | 388 |
| PlasmaPlayer | C++ | 399 | 399 |
Turniej potrwa do 1 lutego 2017 r., Chyba że zaznaczono inaczej.
Player
implementację, która wywołuje inny proces obliczania bieżącej tury. Dzięki temu ludzie będą mogli uczestniczyć w dowolnym języku, którym z przyjemnością posługujesz się na swoim komputerze.
Player::fight
” / „możesz odziedziczyć Player::perceive
” ... w obu przypadkach termin zastępuje , a nie dziedziczy .
GunDuel.hpp
, oba validA
i validB
użyjactionA