76 lines
2.3 KiB
Python
76 lines
2.3 KiB
Python
from dataclasses import dataclass
|
|
|
|
RESET='\033[0m'
|
|
COLORS={'r':'\033[31m','y':'\033[33m','g':'\033[32m','b':'\033[34m'}
|
|
COLOR_ORDER={'r':0,'y':1,'g':2,'b':3}
|
|
|
|
@dataclass(frozen=True)
|
|
class Card:
|
|
color: str|None
|
|
value: int|None
|
|
joker: bool=False
|
|
uid: int=0
|
|
|
|
def text(self):
|
|
if self.joker:
|
|
return f'{COLORS["r"]}J{RESET}'
|
|
return f'{COLORS[self.color]}{self.value}{RESET}'
|
|
|
|
def plain(self):
|
|
return 'J' if self.joker else f'{self.color}{self.value}'
|
|
|
|
|
|
def deck():
|
|
cards=[]
|
|
uid=0
|
|
for _ in range(2):
|
|
for c in COLORS:
|
|
for n in range(1,14):
|
|
cards.append(Card(c,n,False,uid)); uid+=1
|
|
for _ in range(2):
|
|
cards.append(Card(None,None,True,uid)); uid+=1
|
|
return cards
|
|
|
|
|
|
def points(card):
|
|
return 30 if card.joker else card.value
|
|
|
|
|
|
def valid_group(cards):
|
|
if not 3 <= len(cards) <= 4: return False
|
|
normal=[c for c in cards if not c.joker]
|
|
jok=len(cards)-len(normal)
|
|
if not normal: return False
|
|
return len({c.value for c in normal})==1 and len({c.color for c in normal})==len(normal) and len(normal)+jok>=3
|
|
|
|
|
|
def valid_run(cards, wrap=False):
|
|
if not 3 <= len(cards) <= 13: return False
|
|
normal=sorted((c for c in cards if not c.joker), key=lambda x:x.value)
|
|
jok=len(cards)-len(normal)
|
|
if not normal or len({c.color for c in normal}) != 1: return False
|
|
if len({c.value for c in normal}) != len(normal): return False
|
|
if not wrap:
|
|
gaps=sum(b.value-a.value-1 for a,b in zip(normal,normal[1:]))
|
|
return gaps <= jok and normal[-1].value-normal[0].value+1+jok <= 13
|
|
# 13-1-Umlauf: Werte liegen auf einem Kreis 1..13, die Folge ist ein
|
|
# zusammenhängender Bogen. Alle Lücken außer der größten müssen durch
|
|
# Joker gefüllt werden.
|
|
gaps=[b.value-a.value-1 for a,b in zip(normal,normal[1:])]
|
|
gaps.append(normal[0].value+13-normal[-1].value-1)
|
|
return 13-len(normal)-jok <= max(gaps)
|
|
|
|
|
|
def valid(cards, wrap=False):
|
|
return valid_group(cards) or valid_run(cards, wrap)
|
|
|
|
|
|
def kind(cards, wrap=False):
|
|
if valid_run(cards, wrap): return 'Folge'
|
|
if valid_group(cards): return 'Satz'
|
|
return 'UNGÜLTIG'
|
|
|
|
|
|
def sort_hand(cards):
|
|
return sorted(cards,key=lambda c:(c.joker, COLOR_ORDER.get(c.color,99), c.value or 99))
|