Last active
July 1, 2017 11:01
-
-
Save hejmsdz/e51c161c28c7c2b1996c504a75cd99af to your computer and use it in GitHub Desktop.
Gra w makao
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
#-*- coding: utf-8 -*- | |
""" | |
Gra w makao | |
Mikołaj Rozwadowski, 2014 | |
Zasady: | |
- karty dokładamy tak, żeby zgadzały się kolorem lub figurą | |
- jeśli na ręce nie ma pasujących kart, bierzemy jedną z talii | |
- karty o tych samych figurach można kłaść w jednym ruchu | |
- dwójka i trójka każą wziąć z talii tyleż kart (można przebijać dalej) | |
- czwórka każe zaczekać kolejkę (również można przebijać dalej) | |
- walet żąda figur (obowiązuje całą kolejkę) | |
- as zmienia kolor (obowiązuje tylko następnego gracza) | |
Sterowanie: | |
- aby położyć kartę, podaj jej indeks liczony od zera | |
- aby położyć kilka kart za jednym razem, podaj indeksy oddzielone spacją (uważaj na kolejność!) | |
- aby spasować (wziąć kartę), wciśnij enter, nic nie wpisując | |
- jeśli wpiszesz błędne polecenie, dostaniesz dodatkową kartę | |
- po rzuceniu waleta wpisz A, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, aby zażądać | |
- po rzuceniu asa wpisz trefl, karo, kier, pik, aby zmienić | |
Uwagi: | |
- gra była testowane na Pythonie 2.7.5 pod Linuksem | |
""" | |
from makao import * | |
import time | |
import sys | |
print "Makao" | |
try: | |
p = int(raw_input("Podaj liczbę graczy: ")) | |
if p<=0: | |
raise ValueError | |
print "Pozostaw imię gracza puste, aby dodać bota" | |
players = [raw_input("Imię gracza: ") for i in range(p)] | |
except ValueError: | |
log_message("Musisz podać liczbę większą od 0\n(większą od 1, jeśli nie chcesz grać sam ze sobą)", 2) | |
sys.exit() | |
try: | |
deal = int(raw_input("Po ile kart rozdać? (domyślnie 5) ")) | |
if deal<=0: | |
raise ValueError | |
except ValueError: | |
deal = 5 | |
game = Game(players) | |
while game.turn(): | |
time.sleep(1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
#-*- coding: utf-8 -*- | |
import random | |
import collections | |
import sys | |
import os | |
def log_message(msg, level=0): | |
colors = ["\033[92m", "\033[93m", "\033[91m", "\033[94m"] | |
print colors[level]+msg+"\033[0m" | |
def plural(n, form1, form2, form5): | |
if n==1: | |
return form1 | |
elif 2<=(n%10)<=4 and n/10!=1: | |
return "%u %s"%(n, form2) | |
else: | |
return "%u %s"%(n, form5) | |
def chance(prob): | |
return random.random()<prob | |
class Card: | |
suit_names = ["trefl", "karo", "kier", "pik"] | |
rank_names = [None, "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"] | |
def __init__(self, rank, suit): | |
self.rank = rank | |
self.suit = suit | |
def __repr__(self): | |
return self.rank_names[self.rank]+" "+self.suit_names[self.suit] | |
def __lt__(self, other): | |
return self.rank<other.rank and self.suit<other.suit | |
# czy to karta funkcyjna? | |
def is_special(self): | |
return self.rank in [1, 2, 3, 4, 11] | |
# czy daną kartę można położyć na aktualną? | |
def match(self, other, match_rank=False): | |
if match_rank: | |
return self.rank == other.rank | |
else: | |
return self.rank == other.rank or self.suit == other.suit | |
# zachowanie kart funkcyjnych | |
def on_laid(self, game, param=None): | |
# as - zmiana koloru | |
if self.rank==1: | |
change = raw_input("Na co zmieniasz? ") if param is None else param | |
if not change: | |
return | |
try: | |
i = Card.suit_names.index(change) | |
except: | |
log_message("Nie ma takiego koloru!", 2) | |
return | |
if param: | |
log_message("... i zmienia na "+change) | |
def f(card, player, mock=False): | |
if card is None: | |
return False | |
if card.suit==i or card.rank==1: | |
return 2 | |
else: | |
return False | |
game.restriction.create(f, 1, "Możesz położyć tylko "+change+" lub asa") | |
return | |
# 2, 3 - weź tyle kart | |
if self.rank==2 or self.rank==3: | |
game.cards_pending += self.rank | |
def f(card, player, mock=False): | |
if card is None or (card.rank!=2 and card.rank!=3): | |
if not mock: | |
player.take_card(game.cards_pending) | |
game.cards_pending = 0 | |
return -1 | |
else: | |
return False | |
else: | |
return True | |
game.restriction.create(f, 1, "Możesz położyć tylko 2 lub 3") | |
log_message(plural(game.cards_pending, "karta!", "karty!", "kart!"), 3) | |
return | |
# 4 - postój | |
if self.rank==4: | |
game.stops_pending += 1 | |
def f(card, player, mock=False): | |
if card is None or card.rank!=4: | |
if not mock: | |
player.stop += game.stops_pending | |
game.stops_pending = 0 | |
log_message(player.name+" czeka "+plural(player.stop, "kolejkę", "kolejki", "kolejek"), 3) | |
return -1 | |
else: | |
return False | |
else: | |
return True | |
game.restriction.create(f, 1, "Możesz położyć tylko 4") | |
log_message("Postój "+plural(game.stops_pending, "kolejkę", "kolejki", "kolejek"), 3) | |
return | |
# walet - żądanie | |
if self.rank==11: | |
demand = raw_input("Czego żądasz? ") if param is None else param | |
if not demand: | |
return | |
try: | |
i = Card.rank_names.index(demand) | |
except: | |
log_message("Nie ma takiej karty!", 2) | |
return | |
if param: | |
log_message("... i żąda "+demand) | |
def f(card, player, mock=False): | |
if card is None: | |
return False | |
if card.rank==i or card.rank==11: | |
return 2 | |
else: | |
return False | |
game.restriction.create(f, len(game.players), "Możesz położyć tylko "+demand+" lub waleta") | |
return | |
class Player: | |
def __init__(self, game, name): | |
self.name = name | |
self.game = game | |
self.cards = [] | |
self.stop = 0 | |
# wypisanie wszystkich kart na ręce | |
def __repr__(self): | |
return "\n".join(["%2u: %s"%(i,card) for i,card in enumerate(self.cards)]) | |
# wzięcie kart(y) z talii na rękę | |
def take_card(self, n=1): | |
log_message(self.name+" bierze "+plural(n, "kartę", "karty", "kart"), 3) | |
try: | |
for i in range(n): | |
self.cards.append(self.game.deck.pop()) | |
except IndexError: | |
log_message("Brak kart w talii na stole!", 2) | |
sys.exit() | |
# pas | |
def pass_turn(self): | |
if self.game.restriction(None, self)!=-1: | |
self.take_card() | |
# położenie kart na stół | |
def lay_card(self, indices): | |
multi = False | |
for i in indices: | |
if type(i)==tuple: | |
(i, param) = i | |
else: | |
param = None | |
try: | |
card = self.cards[i] | |
except IndexError: | |
log_message("Numer karty spoza zakresu!", 2) | |
self.pass_turn() | |
break | |
restr = self.game.restriction(card, self) | |
if restr == -1: | |
return | |
elif (not self.game.current.match(card, multi) or restr == False) and restr!=2: | |
log_message("Nie możesz położyć tej karty!", 2) | |
self.pass_turn() | |
break | |
multi = True | |
self.game.deck.insert(random.randrange(len(self.game.deck)+1), self.game.current) | |
self.game.current = card | |
log_message("%s kładzie %s"%(self.name, card)) | |
self.game.current.on_laid(self.game, param) | |
# zaznacz kartę do usunięcia | |
# nie usuwaj od razu, bo poprzestawiają się indeksy | |
self.cards[i] = None | |
self.cards = filter(None, self.cards) | |
def turn(self): | |
self.cards.sort(key=lambda x: (x.rank,x.suit)) | |
print self | |
self.game.restriction.info() | |
cmd = raw_input(":") | |
if cmd: | |
try: | |
lay = [int(i) for i in cmd.split(" ")] | |
except ValueError: | |
log_message("Zły format wejścia!", 2) | |
self.pass_turn() | |
return | |
self.lay_card(lay) | |
else: | |
self.pass_turn() | |
class Bot(Player): | |
counter = 0 | |
def __init__(self, game, name=None): | |
if name: | |
self.name = name | |
else: | |
self.name = "Komputer #%u"%Bot.counter | |
Bot.counter+= 1 | |
self.game = game | |
self.cards = [] | |
self.stop = 0 | |
def turn(self): | |
# bo tak | |
if chance(0.05): | |
self.pass_turn() | |
return | |
layable = [] | |
ranks = set() | |
for i,card in enumerate(self.cards): | |
restr = self.game.restriction(card, self, True) | |
match = self.game.current.match(card) | |
if (restr==True and match==True) or restr==2: | |
layable.append(i) | |
ranks.add(card.rank) | |
if len(layable): | |
# być może można rzucić kilka kart na raz | |
c = collections.Counter(card.rank for card in self.cards if card.rank in ranks) | |
[[rank, n]] = c.most_common(1) | |
lay = [] | |
for i,card in enumerate(self.cards): | |
if card.rank!=rank: | |
continue | |
restr = self.game.restriction(card, self, True) | |
match = self.game.current.match(card) | |
# walet | |
if card.rank==11: | |
dc = collections.Counter(card.rank for card in self.cards if not card.is_special()) | |
if len(dc)>0: | |
[[demand, n]] = dc.most_common(1) | |
elif chance(0.5): | |
demand = str(random.randint(5,10)) | |
else: | |
demand = "" | |
i = (i, Card.rank_names[demand]) | |
# as | |
elif card.rank==1: | |
cc = collections.Counter(card.suit for card in self.cards) | |
[[change, n]] = cc.most_common(1) | |
i = (i, Card.suit_names[change]) | |
if (restr==True and match==True) or restr==2: | |
lay.insert(0, i) | |
elif chance(0.6): | |
lay.append(i) | |
self.lay_card(lay) | |
else: | |
self.pass_turn() | |
# klasa do chwilowego ograniczania zbioru możliwych do rzucenia kart | |
class Restriction: | |
active = False | |
def create(self, function, turns, information): | |
self.active = True | |
# funkcja otrzymuje kartę do sprawdzenia (może być None) i gracza, który ją położył | |
# zwraca: | |
# * True, jeśli można położyć kartę, o ile pasuje kolorem/figurą | |
# * False, jeśli nie można położyć karty i gracz powinien wziąć nową kartę ze stołu | |
# * -1, jeśli nie można położyć karty, ale funkcja sama wyegzekwuje konsekwencje | |
# * 2, jeśli można położyć kartę bez względu na wszystko inne | |
self.function = function | |
self.turns = turns | |
self.information = information | |
def disable(self): | |
self.active = False | |
def turn(self): | |
if self.active: | |
if self.turns==0: | |
self.disable() | |
else: | |
self.turns -= 1 | |
def info(self): | |
if self.active: | |
log_message(self.information, 3) | |
def __call__(self, card, player, mock=False): | |
if self.active: | |
return self.function(card, player, mock) | |
else: | |
return True | |
class Game: | |
# rozpoczęcie partii | |
def __init__(self, players, deal=5): | |
# przygotowanie talii | |
self.deck = [Card(rank, suit) for rank in range(1, 14) for suit in range(4)] | |
random.shuffle(self.deck) | |
# przygotowanie graczy | |
self.players = [(Player if p else Bot)(self, p) for p in players] | |
# rozdanie kart | |
for player in self.players: | |
player.take_card(deal) | |
# pierwsza niefunkcyjna karta na stół | |
self.current = self.deck.pop(next(i for i,card in enumerate(self.deck) if not card.is_special())) | |
# kolejka | |
self.turn_id = 0 | |
self.cards_pending = 0 | |
self.stops_pending = 0 | |
self.restriction = Restriction() | |
self.winners = [] | |
def turn(self): | |
os.system("clear") | |
player = self.current_player() | |
if player.stop>0: | |
log_message(player.name+" czeka jeszcze "+plural(player.stop, "kolejkę", "kolejki", "kolejek")) | |
player.stop -= 1 | |
self.next_turn() | |
return True | |
self.restriction.turn() | |
print "Aktualna karta:", self.current | |
print player.name | |
player.turn() | |
if len(player.cards)==1: | |
log_message("Makao!", 1) | |
elif len(player.cards)==0: | |
log_message("Po makale!", 2) | |
self.winners.append(player.name) | |
del self.players[self.turn_id] | |
if len(self.players) <= 1: | |
print "Koniec gry!" | |
for i,p in enumerate(self.winners): | |
print "%2u. %s"%(i+1, p) | |
return False | |
self.next_turn() | |
return True | |
# przesunięcie kolejki | |
def next_turn(self): | |
self.turn_id+=1 | |
self.turn_id%=len(self.players) | |
# czyja jest teraz kolej? | |
def current_player(self): | |
return self.players[self.turn_id] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment