Skip to content

Instantly share code, notes, and snippets.

@hejmsdz
Last active July 1, 2017 11:01
Show Gist options
  • Save hejmsdz/e51c161c28c7c2b1996c504a75cd99af to your computer and use it in GitHub Desktop.
Save hejmsdz/e51c161c28c7c2b1996c504a75cd99af to your computer and use it in GitHub Desktop.
Gra w makao
#!/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)
#!/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 = []
print
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
print
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
print
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