ITPW
Wojna deklarowana - treść zadania

Wojna deklarowana

Opis gry

W tym roku na ITPW będziemy zmagać się z wojną deklarowaną. Jest to gra karciana, połączenie ogólnie znanych gier: wojny i pokera.

Każdy z graczy posiada stos zakrytych kart (nie widzi ich on, ani tym bardziej inni). W zwykłej wojnie każdy z graczy odkrywa po prostu pierwszą kartę i właściciel najwyższej karty zbiera pozostałe. U nas dodatkowo występuje etap licytacji. Najpierw każdy z graczy podgląda swoją pierwszą kartę i wkłada ją do puli. Później gracze licytują, podobnie jak w pokerze, być może dokładając kolejne karty do puli. Po zakończeniu licytacji następuje odsłonięcie i porównanie podglądanych wcześniej pierwszych kart i właściciel najwyższej karty zbiera całą pulę. Tą procedurę powtarza się wielokrotnie. Celem gry jest zebranie wszystkich kart.

Licytacja

Podczas licytacji można zrobić jedną z trzech rzeczy:

  • Spasować - Nie dokładamy żadnej karty, rezygnujemy z dalszej licytacji, a także z ewentualnego zwycięstwa w tej rundzie. Gracz, który spasuje nie pokazuje na koniec swojej pierwszej karty i nie uczestniczy w porównaniu kart.
  • Sprawdzić - Wyrównujemy liczbę kart w naszej puli do największej puli wśród innych graczy. Inaczej mówiąc dokładamy karty, aż będziemy mieli wyłożone tyle kart, ile najwięcej wyłożył któryś z pozostałych graczy. W szczególności może to oznaczać, że nic nie trzeba dokładać.
  • Podniesienie o N (gdzie N wynosi 1 lub 2 lub 3) - Dokładamy tyle kart, ile przy sprawdzaniu, oraz dodatkowo N kart.

Gracze licytują po kolei. Zaczyna gracz losowo wybrany. Licytacja kończy się, w jednym z trzech przypadków:

  • wszyscy gracze oprócz jednego spasowali,
  • żaden z graczy jeszcze nie podniósł, a kolejka doszła do gracza, który jako pierwszy sprawdził,
  • kolejka doszła do gracza, który jako ostatni podniósł.

Podsumowując: Istotna jest największa liczba kart włożona przez któregoś z graczy do puli. Tylko gracze, którzy włożą taką liczbę kart uczestniczą na koniec w porównaniu pierwszej karty i mogą zgarnąć pulę. Zatem podnosząc ustalamy tą największą liczbę kart na pewnym poziomie - pozostali gracze muszą włożyć po tyle samo lub zrezygnować z wygranej. Zasady kończenia licytacji mówią, że gdy już tylko jeden gracz chce podnosić, a inni nie, to może on podnieść tylko raz.

Jest jeszcze dodatkowa zasada: jeśli komuś w czasie licytacji zabraknie kart, to mimo wszystko może sprawdzać. Dokłada wtedy tylko tyle kart, ile ma. Na koniec ma takie same prawo do zabrania puli, jak pozostali. (Gdyby nie było tej zasady, gracze mający więcej kart mogliby za bardzo wykorzystywać swoją przewagę.)

Wojna

Podczas porównywania kart może się okazać, że największą kartę posiada więcej niż jeden gracz. Występuje wtedy tak zwana "wojna". Wówczas gracze, którzy mają tą największą kartę, dokładają jeszcze dwie karty, z których pierwszą podglądają i na jej podstawie dokonane zostanie rozstrzygnięcie. Następnie (tylko oni) licytują jeszcze raz. Na koniec odkrywa się i porównuje dodatkowo podglądnięte karty. Kto teraz ma największą zbiera wszystko: karty z pierwszej i drugiej licytacji. Oczywiście "wojna" może się powtórzyć.

Szczegóły

W grze będzie brało udział zawsze czterech graczy. W aplecie umożliwiono, jedynie do celów testowych, rozgrywkę mniejszej liczby graczy.

Zebrane karty lądują na końcu stosu zwycięzcy, w losowej kolejności. Kart używanych do licytacji nikt nie widzi. Każdy zna jedynie swoją podglądniętą kartę i odkryte karty osób, które do końca nie spasowały.

Jeśli ktoś w czasie "wojny" ma tylko jedną kartę, to jeszcze może grać. Dokłada wówczas tylko tą jedyną kartę, jako podglądaną, a następnie uznajemy, że sprawdza. Ale gdy nie ma już nawet tej pierwszej, to przegrywa.

Nawet gdy gracz włożył już wszystkie karty do puli, to jest ciągle proszony w swojej kolejce o podanie ruchu (może spasować lub sprawdzić).

Gdy ma nastąpić "wojna", a już tylko jeden gracz spośród "walczących" (tych, którzy mieli najwyższą kartę) ma niezerową liczbę kart, to nie dochodzi do "wojny". Gracz ten zbiera pulę, a pozostali przegrywają. Jeśli natomiast wszyscy spośród potencjalnych uczestników "wojny" nie mają już kart, to włożone karty zostają podczas kolejnej licytacji (jest to już zwykła licytacja, a nie wojna - licytują wszyscy, a każdy początkowo wkłada tylko jedną kartę).

Do zwycięstwa liczy się kolejność odpadania z gry. Bierzemy tu pod uwagę tylko numer licytacji, w której gracz odpadł (nieważne, kiedy dokładnie oddał ostatnią kartę). Należy zwrócić uwagę, że w przypadku "wojny" mamy osobne licytacje przed nią i po niej. Jeśli gracz odpada w ten sposób, że ma uczestniczyć w "wojnie", ale nie ma już ani jednej karty, to jego odpadnięcie wlicza się jeszcze do licytacji przed "wojną". Kolejno odpadający gracze uzyskują: 0, 12, 24, 48 punkty. W przypadku remisu pomiędzy pewnymi graczami (odpadnięcia w tej samej licytacji), uzyskują oni średnią arytmetyczną z punktów za uzyskane przez siebie pozycje.

Aby nie doszło do nieskończonej rozgrywki, gra może zostać przerwana. Przerwanie gry nastąpi pomiędzy pełnymi licytacjami (jednak może to być w trakcie "wojny", licytacje przed i po "wojnie" liczymy osobno). Pierwsze 200 licytacji odbędzie się na pewno. Przed każdą kolejną licytacją gra może zakończyć się z prawdopodobieństwem 1/200.

Podczas jednego uruchomienia programu może zostać rozegranych więcej niż jedno rozdanie z tymi samymi przeciwnikami. Ma to dać więcej czasu na dostosowanie się do przeciwników. Dlatego też, nawet gdy gracz przegra, otrzymuje informacje o ruchach innych zawodników. Prawdopodobnie podczas turnieju głównego będzie to czterdzieści rozdań podczas jednego uruchomienia (w turnieju próbnym mniej).

Protokół

Protokół bazowany jest na protokole GTP.

Arbiter i gracz

Protokół jest przeznaczony dla dwóch stron: gracza oraz arbitra (lub apletu). Pod pojęciem "gracz" rozumiemy program grający stworzony przez zawodnika, grający w grę. "Aplet" jest to interfejs użytkownika umożliwiający wyświetlanie przebiegu gry i testowanie programów. Istnieje również twór zwany "arbitrem", robiący zasadniczo to samo co aplet, jednak nie mający interfejsu graficznego. Poniżej będziemy używać tylko słowa "arbiter", mając na myśli także aplet.

W przypadku wielu programów grających, arbiter komunikuje się z każdym z nich osobno.

Komunikacja jest tekstowa, za pomocą standardowych kanałów wejścia i wyjścia.

Komunikacja jest synchroniczna i powtarza schemat: arbiter wysyła komendę; gracz wysyła odpowiedź.

Składnia

Składnia każdej z komend może być inna, ale zawsze kończy się znakiem nowej linii.

Puste linie wysyłane przez arbitra powinny być ignorowane.

Odpowiedź gracza zawsze zaczyna się znakiem '=' lub '?' po czym następuje właściwa odpowiedź oraz kończy się dwoma znakami nowej linii (czyli pustą linią).

W przypadku nieobsługiwanej komendy lub wykrycia innego błędu gracz powinien zacząć odpowiedź od '?', po czym wypisać opis błędu i zakończyć odpowiedź dwoma znakami nowej linii.

Komendy

Kolor niebieski oznacza linie wysyłane przez arbitra do gracza, a kolor zielony oznacza odpowiedź gracza.
Parametry podawane są w nawiasach trójkątnych.

Komendy ogólne (niezwiązane z konkretną grą)

Ogólne komendy uniwersalne dla protokołu GTP.

help
=
<komenda_1>
<komenda_2>
...
<komenda_n>
 
Zwraca listę komend obsługiwanych przez protokół. Stosuje się też równoważną komendę 'list_commands'.

name
= <nazwa_programu>
 
Wypisuje nazwę programu. Nazwa ta wyświetla się w aplecie. Podczas turnieju nie ma znaczenia.

quit
=
 
Kończy działanie programu. Program i tak zostanie zabity, ale można na koniec wypisać jakieś statystyki z działania programu, które zostaną zapisane do pliku log.

your_number <n>
=
 
Standardowo komenda będzie wykonywana na początku gry z numerem gracza. Graczy numerujemy od 1.

Komendy do wojny deklarowanej

setdeck <n> <v_1> ... <v_n>
=
 
Ustawia talię kart. <v_1> ... <v_n> są liczbami całkowitymi. Standardowo komenda będzie wykonywana na początku gry z argumentami dla dwóch talii, czyli <n>=104, a lista liczba będzie składała się z ośmiu kopii liczb od 1 do 13. Informuje jednocześnie, że rozpoczyna się nowe rozdanie.

setstate <P> <n> <G_1> ... <G_n>
=
 
Powiadamia o aktualnej dystrybucji kart między pulą i graczami. <P> oznacza liczbę kart w puli, tj. liczbę kart, które są dostępne do wygrania. <n> jest liczbą graczy, a <G_1> ... <G_n> liczbą kart każdego z graczy (0 oznacza, że gracz już odpadł lub bezpośrednio przed obecną turą licytacji włożył do puli swoje ostatnie karty). Komendę tą arbiter będzie wysyłać graczowi przed każdą rundą licytacji.

topcard <gracz> <karta>
=
 
Podaje kartę jaka jest użyta w licytacji przez gracza <gracz>. <gracz> jest numerkiem gracza, a <karta> jest liczbą całkowitą.

play <gracz> <ruch>
=
 
Wykonuje zagranie <ruch> gracza <gracz>. <ruch> może mieć trzy formy:
  • pass - oznacza, że gracz pasuje,
  • check - sprawdzenie, czyli gracz wkłada do puli tylko tyle ile włożył ostatni nie pasujący gracz lub 0 jeśli nie było takiego; w przypadku, gdy gracz nie posiada wystarczającej liczby kart, to oznacza to, że wkłada wszystkie swoje karty (all-in),
  • raise <k> - włożenie do puli tyle co włożył ostatni gracz plus <k>, gdzie <k> wynosi 1, 2 lub 3.

genmove <gracz>
= <ruch>
 
Generuje <ruch> dla gracza <gracz>. Komenda to nie powoduje wykonania ruchu. Do gracza zostaje wysłana odpowiednia komenda 'play' w celu wykonania ruchu. Taka składnia pozwala w aplecie używać ręcznie komendy 'genmove' do hintów.

undo
=
 
Cofa ostatni ruch. Nie wysyłana ani przez arbitra, ani przez aplet. Może być pomocna przy ręcznym testowaniu.

Zarządzanie czasem

time_settings <T> <M> <t> <m>
=
 
Podaj informacje o stosowanych limitach czasowych. Na pierwsze <M> ruchów silnik dostaje <T> milisekund. Na każde kolejne <m> ruchów silnik będzie dostawał dodatkowo <t> milisekund. Przez ruch rozumie się tu pojedyncze wywołanie komendy 'genmove'. Czas ten musi starczyć także na wykonanie komend innych niż 'genmove' (w szczególności, jeśli gracz przegrał i nie otrzymuje dość dużo razy żadnych 'genmove' - musi się wtedy trochę spieszyć).

time_left <t> <m>
=
 
Podaje graczowi informacje o pozostałym mu czasie: na najbliższe <m> ruchów dostępne jest <t> milisekund.

Komunikacja arbiter <-----> gracz

Schemat komunikacji pomiędzy arbitrem a graczami jest następujący:

your_number
tyle razy, ile ma być rozgrywek rób:
    //pojedyncze rozdanie
    setdeck
    time_settings
    dopóki nie koniec rozdania:
        // pojedyncza licytacja
        setstate
        topcard dla danego gracza, tylko jeśli nie odpadł
        dopóki nie koniec licytacji rób (dla graczy, którzy nie odpadli):
            time_left
            genmove
            play wysyłane do wszystkich graczy (w tym do niego też)
        topcard na temat wszystkich graczy, którzy dotrwali do końca licytacji
quit // a potem i tak zaraz jest ubijany :-)

Program nie ma obowiązku implementować wszystkich poleceń. Minimalny gracz wystarczy, że zaimplementuje polecenia 'setdeck' (jedynie jako "zerowanie" rozgrywki), 'topcard', 'play' i 'genmove'. Oczywiście jeśli z góry założy, jaka jest talia i ilu graczy.

Jeżeli uczestnik będzie chciał dopuścić inne talie lub liczbę graczy (np. do testów), to powinien zaimplementować także 'setdeck' i 'setstate'. Zauważmy, że uczestnik może tak naprawdę grać z licytacji na licytację nie interesując się poprzednimi implementując 'setstate'.

Do obsługi czasu wystarczy zaimplementować 'time_left'. Możliwe, że warto też obsługiwać 'time_settings'.

Rozgrywki

Podczas turnieju losowe czwórki graczy będą grały ze sobą, przy czym zapewnione zostanie, aby każdy grał z każdym tą samą liczbę razy (tzn. każda para graczy wystąpi tyle samo razy). Zsumowane liczby punktów z każdej partii (liczonych jak opisano powyżej) tworzą końcowy ranking. Czas na zawodnika (na komputerach klasy zbliżonej do Pentium4 3 GHz) będzie wynosił około pół minuty na pierwsze 1000 ruchów, później w miarę proporcjonalnie będzie dodawany. Możliwe jest, że w rozgrywkach wystąpią także pewne programy dostarczone przez organizatorów.
ITPW, KNI TEAM