import copy, random from cards import * def yes_no(q, default=None): while True: a=input(q+' (j/n): ').strip().lower() if a in ('j','ja','y','yes'): return True if a in ('n','nein','no'): return False if not a and default is not None: return default print(' Bitte j oder n eingeben.') def number(q, lo, hi): while True: a=input(q+f' ({lo}-{hi}): ').strip() try: n=int(a) except ValueError: print(f' Bitte eine Zahl von {lo} bis {hi} eingeben.'); continue if lo<=n<=hi: return n print(f' Bitte eine Zahl von {lo} bis {hi} eingeben.') class Player: def __init__(self,name,bot=False): self.name=name self.bot=bot self.hand=[] self.opened=False class Game: def __init__(self): print('EINSTELLUNGEN') print(' ~~~~~~~~~~~~') n=number(' Wie viele menschliche Spieler', 1, 4) if 4-n>0: b=number(' Wie viele Bots' + (' (mindestens 1)' if n==1 else ' (0 für keine)'), 1 if n==1 else 0, 4-n) else: b=0 self.wrap=yes_no(' 13-1-Umlauf erlauben (z.B. 12,13,1)') self.min30=yes_no(' Braucht die Erstmeldung 30 Punkte') self.players=[Player(f'Spieler {i+1}') for i in range(n)]+[Player(f'Bot {i+1}', bot=True) for i in range(b)] self.turn=0 self.table=[] self.deck=deck(); random.shuffle(self.deck) self.history=[] self.drew=False self.melded=False self.handover=False for p in self.players: p.hand=sort_hand([self.deck.pop() for _ in range(14)]) @property def p(self): return self.players[self.turn] def save(self): self.history.append(copy.deepcopy((self.players,self.table,self.deck,self.drew,self.melded))) def undo(self): if not self.history: print('Nichts zum Rückgängigmachen.'); return self.players,self.table,self.deck,self.drew,self.melded=self.history.pop() def clear(self): print('\033[2J\033[H',end='') def show(self): self.clear() print('╔════════════════════════════════════════════════════╗') print('║ MYRUMMY ║') print('╚════════════════════════════════════════════════════╝') print(f' Am Zug: {self.p.name} Karten im Stapel: {len(self.deck)}') print(f' Regeln: 13-1-Umlauf: {"ja" if self.wrap else "nein"} Erstmeldung 30: {"ja" if self.min30 else "nein"}') print(f' Erstmeldung: {"ja" if self.p.opened else "nein"}') print('\nTISCH') if not self.table: print(' (leer)') for i,g in enumerate(self.table,1): print(f' {i:>2}: ' + ' '.join(f'{j}:{c.text()}' for j,c in enumerate(g,1)) + f' [{kind(g, self.wrap)}]') print('\nHAND') lines=[]; key=None for i,c in enumerate(self.p.hand,1): k='J' if c.joker else c.color if k!=key: lines.append([]); key=k lines[-1].append(f'{i}:{c.text()}') for l in lines: print(' '+ ' '.join(l)) print('\nBEFEHLE') print(' m H G Handkarte H -> Gruppe G') print(' m H new Handkarte H -> neue Gruppe') print(' t G C Tischkarte C aus Gruppe G -> Hand') print(' n leere neue Gruppe') print(' a G1 G2 Gruppen verbinden') print(' s G POS Gruppe nach POS teilen') print(' d ziehen (beendet den Zug)') print(' u undo') print(' sort Hand sortieren') print(' finish Zug prüfen/beenden') print(' q beenden') def idx(self,x,maxi): n=int(x) if not 1<=n<=maxi: raise ValueError('Nummer außerhalb des gültigen Bereichs.') return n-1 def move_hand(self,h,g): hi=self.idx(h,len(self.p.hand)); self.save() card=self.p.hand.pop(hi) if g.lower()=='new': self.table.append([card]) else: self.table[self.idx(g,len(self.table))].append(card) self.melded=True def move_table(self,g,c): gi=self.idx(g,len(self.table)); ci=self.idx(c,len(self.table[gi])); self.save() self.p.hand.append(self.table[gi].pop(ci)) if not self.table[gi]: self.table.pop(gi) self.p.hand=sort_hand(self.p.hand) def merge(self,a,b): ai=self.idx(a,len(self.table)); bi=self.idx(b,len(self.table)) if ai==bi: raise ValueError('Gleiche Gruppe.') self.save(); self.table[ai]+=self.table[bi]; self.table.pop(bi) def split(self,g,pos): gi=self.idx(g,len(self.table)); pos=int(pos) if not 1<=pos=3: return [by_col[col][0] for col in sorted(by_col)[:4]] # Folge: gleiche Farbe, aufeinanderfolgend, 3+ Karten by_col={} for c in hand: if not c.joker: by_col.setdefault(c.color, []).append(c) for col in by_col: vals=sorted({c.value for c in by_col[col]}) i=0 while i=3: return [next(c for c in by_col[col] if c.value==v) for v in vals[i:j+1]] i=j+1 return None def bot_turn(self): p=self.p melded=[] while True: m=self.find_meld(p.hand) if not m: break for c in m: p.hand.remove(c) melded.append(m) total=sum(points(c) for m in melded for c in m) if melded and (p.opened or not self.min30 or total>=30): for m in melded: self.table.append(m) if not p.opened: p.opened=True if not p.hand: print(f'\n {p.name} gewinnt!') return True else: for m in melded: for c in m: p.hand.append(c) p.hand=sort_hand(p.hand) if self.deck: p.hand.append(self.deck.pop()); p.hand=sort_hand(p.hand) self.turn=(self.turn+1)%len(self.players); self.drew=False; self.melded=False; self.history=[] self.handover=True return False def run(self): while True: if self.p.bot: if self.bot_turn(): return else: self.show() if self.command(input('\n> ')): return if self.handover: self.handover=False self.clear() if self.p.bot: print(f'\n Zug beendet. {self.p.name} ist jetzt am Zug,') print(' seine Karten bleiben verborgen.') else: print(f'\n Zug beendet. Bitte gib den Computer an {self.p.name} weiter,') print(' damit der andere Spieler deine Karten nicht sehen kann.') input(' ENTER drücken, wenn du bereit bist...')