From d78f25d530582d06b6835ffb05a9ca23d3324390 Mon Sep 17 00:00:00 2001 From: jonas H Date: Sun, 23 Aug 2026 13:42:39 +0200 Subject: [PATCH] add bot in myrummy --- myrummy/READEME.txt | 10 ++++- myrummy/game.py | 95 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 96 insertions(+), 9 deletions(-) diff --git a/myrummy/READEME.txt b/myrummy/READEME.txt index 50fd9f1..4e82db1 100644 --- a/myrummy/READEME.txt +++ b/myrummy/READEME.txt @@ -3,10 +3,18 @@ MYRUMMY CLI Start: python main.py -Beim Start werden zwei Einstellungen abgefragt: +Beim Start werden Einstellungen abgefragt: + - Wie viele menschliche Spieler (1-4) + - Wie viele Bots (menschliche + Bots insgesamt max. 4): + - Bei 1 menschlichem Spieler ist mindestens 1 Bot Pflicht + - Bei 2-4 Spielern sind Bots optional (0 für keine) - 13-1-Umlauf: Folgen dürfen über 13 hinweg weiterlaufen (z.B. 12,13,1) - Erstmeldung 30: Für die erste Meldung werden 30 Punkte gebraucht +Bots spielen automatisch: Sie legen, was sie können (Sätze und Folgen, +beachten die 30-Punkte-Regel) und ziehen sonst eine Karte. Die Handkarten +eines Bots werden nie angezeigt. + Nach jedem beendeten Zug erscheint ein Übergabe-Bildschirm, damit der nächste Spieler die Karten des Vorgängers nicht sieht. diff --git a/myrummy/game.py b/myrummy/game.py index 1ec3aa3..0b70e1f 100644 --- a/myrummy/game.py +++ b/myrummy/game.py @@ -9,9 +9,19 @@ def yes_no(q, default=None): 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): + def __init__(self,name,bot=False): self.name=name + self.bot=bot self.hand=[] self.opened=False @@ -19,9 +29,14 @@ 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('Spieler 1'),Player('Spieler 2')] + 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) @@ -110,7 +125,7 @@ class Game: if not self.deck: raise ValueError('Stapel leer.') card=self.deck.pop(); self.p.hand.append(card); self.p.hand=sort_hand(self.p.hand) print(f'\n {self.p.name} zieht {card.text()} und beendet damit den Zug.') - self.turn=1-self.turn; self.drew=False; self.melded=False; self.history=[] + self.turn=(self.turn+1)%len(self.players); self.drew=False; self.melded=False; self.history=[] self.handover=True def finish(self): @@ -131,7 +146,7 @@ class Game: if not self.p.hand: print(f'\n{self.p.name} gewinnt!') return True - self.turn=1-self.turn; self.drew=False; self.melded=False; self.history=[] + self.turn=(self.turn+1)%len(self.players); self.drew=False; self.melded=False; self.history=[] self.handover=True return False @@ -160,13 +175,77 @@ class Game: input('\nENTER...') return False + def find_meld(self, hand): + # Satz: gleicher Wert, unterschiedliche Farben, 3-4 Karten + by_val={} + for c in hand: + if not c.joker: by_val.setdefault(c.value, []).append(c) + for val in sorted(by_val): + by_col={} + for c in by_val[val]: by_col.setdefault(c.color, []).append(c) + if len(by_col)>=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 + print(f'\n {p.name} ist am Zug:') + 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 + for m in melded: + print(' legt: '+' '.join(c.plain() for c in m)) + 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: + card=self.deck.pop(); p.hand.append(card); p.hand=sort_hand(p.hand) + print(f' kann nicht legen und zieht {card.plain()}.') + else: + print(' Stapel leer - Zug wird beendet.') + self.turn=(self.turn+1)%len(self.players); self.drew=False; self.melded=False; self.history=[] + self.handover=True + input('\n ENTER...') + return False + def run(self): while True: - self.show() - if self.command(input('\n> ')): return + 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() - print(f'\n Zug beendet. Bitte gib den Computer an {self.p.name} weiter,') - print(' damit der andere Spieler deine Karten nicht sehen kann.') + 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...')