Gra w karty “makao”

Gra zaczyna się od rozdania każdemu graczowi pięciu kart. Wygrywa ten, kto pierwszy się ich wszystkich pozbędzie, wyrzucając na stół jedną (lub kilka) pasujących wg koloru bądź wartości. Oczywiście jest też wiele okoliczności, w których graczowi przybywa kart. Np po zagraniu karty 2 lub 3 następny gracz musi dobrać z talii odpowiednio dwie lub trzy karty. No chyba, że sam ma kartę 2 lub 3 i może odbić atak; wtedy następny z kolei gracz bierze 4 lub 6 kart.

Po przeczytaniu reguł gry na Wikipedii możesz dojść do wniosku, że potrzebne będą następujące klasy:

  • Card - reprezentującą pojedynczą niefunkcyjne kartę do gry, posiadająca kolor i wartość; każda karta umie zwrócić właściwy dla niej efekt - obiekt klasy Effect, który dla klasy bazowej Card będzie pusty

  • Effect, która zawiera informację o efekcie zagrania danej karty: liczbę kart do wzięcia (np trzy dla trójki), kierunek gry (król pik bije do tyłu!) bądź postój. Ważną metodą klasy Effect jest combine(e: Effect) która dodaje e do self, sumując nałożone kary.

  • klasy odpowiadające kartom funkcyjnym : dwójkom, trójkom, czwórkom, piątkom, waletom itd, które będą dziedziczyć po Card; różnią się zwracanym efektem oraz metodą can_follow(c: Card)

  • Deck - reprezentujaca talię kart

  • Player - reprezentującą gracza

  • Strategy - definiująca zachowanie gracza; zaimplementowana w niej metoda best_move(crds: List[Card], e: Effect, top: Card) przyjmuje listę kart gracza, aktualny efekt gry oraz kartę na stole i zwraca kartę (karty) które ma zagrać gracz. Podstawowe klasy potomne to RandomStrategy i Human

class inheritance diagram

Rozgrywka (sekcja __main__ programu) powinna przebiegać mniej więcej następująco:

currently_plays = 0
players = []                # create players here
talia = Deck.generate()     # create a standard deck of 52 cards
used_cards = Deck([])       # table is an empty deck
after_makao = False
used_cards.append(talia.give(1))
e = Effect()                # start from an empty effect
while not after_makao:
    top_card = used_cards.show_top()
    # Player plays by returning a list of cards, that may be empty ....
    played_cards = players[currently_plays].play(top_card, e)
    # .... and puts cards on a table
    used_cards.extend(played_cards)
    for crd in played_cards:
        e.combine(crd.effect)
    currently_plays = (currently_plays+e.whos_next ) % len(players)


used_cards.extend(played_cards)
# if talia.cards_left ...