From 0af318459029c4f80bcca32d427393d623b15492 Mon Sep 17 00:00:00 2001 From: Jarvis Date: Sat, 21 Feb 2026 09:46:29 +0000 Subject: [PATCH] Add random trading (~10% chance per turn, 50/50 accept/reject) --- monop_players.py | 105 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 96 insertions(+), 9 deletions(-) diff --git a/monop_players.py b/monop_players.py index c767340..8feaaec 100644 --- a/monop_players.py +++ b/monop_players.py @@ -65,6 +65,10 @@ class PlayerBot: self._prompt_answered = False # Seen "goes first" yet self._first_player_announced = False + # Trading state + self.in_trade = False + self.trade_props_offered = 0 + self.turns_played = 0 def log(self, msg): print(f"[{self.nick}] {msg}", flush=True) @@ -219,8 +223,17 @@ class PlayerBot: self.jail_turns = 0 if self.is_my_turn(): - self.say_delayed("roll") - self.rolled_this_turn = True + self.turns_played += 1 + # ~10% chance to initiate a trade (after turn 5, not in debt) + if (self.turns_played > 5 and not self.in_debt + and random.random() < 0.10): + self.in_trade = True + self.trade_props_offered = 0 + self.log("Initiating a trade!") + self.say_delayed("trade") + else: + self.say_delayed("roll") + self.rolled_this_turn = True return # ============================================================ @@ -331,13 +344,7 @@ class PlayerBot: self.say_delayed("yes") return - # Trade confirmation: "{name}, is the trade ok?" - m = re.match(r'^(.+?), is the trade ok\?$', msg) - if m: - name = m.group(1) - if name.lower() == self.nick.lower(): - self.say_delayed("yes") - return + # (Trade confirmation handled in TRADING section below) # Resign confirmation if msg == "Do you really want to resign?": @@ -428,6 +435,7 @@ class PlayerBot: # COMMAND PROMPT # ============================================================ if msg == "-- Command:": + self.in_trade = False # trade ended (accepted, rejected, or cancelled) if self.is_my_turn(): if self.in_debt: self.say_delayed("mortgage") @@ -495,6 +503,85 @@ class PlayerBot: if m: return + # ============================================================ + # TRADING + # ============================================================ + + # "There ain't no-one around to trade WITH!!" + if msg.startswith("There ain't no-one"): + self.in_trade = False + if self.is_my_turn(): + self.say_delayed("roll") + self.rolled_this_turn = True + return + + # "player {name} ({N}):" — trade property listing phase + m = re.match(r'^player (.+?) \((\d+)\):$', msg) + if m and self.in_trade: + # This announces whose properties are being listed + self.trade_props_offered = 0 + return + + # "Which property do you wish to trade?" — pick a property or done + if msg == "Which property do you wish to trade?": + if self.in_trade: + if self.trade_props_offered == 0 and random.random() < 0.5: + # Offer one property then done + self.trade_props_offered = 1 + self.say_delayed("?") # get the list + else: + self.say_delayed("done") + return + + # "You have $X. How much are you trading?" — offer some cash + m = re.match(r'^You have \$(\d+)\.\s+How much are you trading\?', msg) + if m: + if self.in_trade: + cash = int(m.group(1)) + # Offer 0-25% of cash randomly + offer = random.randint(0, max(1, cash // 4)) + self.say_delayed(str(offer)) + return + + # "You have N get-out-of-jail-free cards. How many are you trading?" + m = re.match(r'^You have (\d+) get-out-of-jail-free card', msg) + if m: + if self.in_trade: + self.say_delayed("0") + return + + # "You've already allocated that." + if msg == "You've already allocated that.": + if self.in_trade: + self.say_delayed("done") + return + + # "{name}, is the trade ok?" — 50/50 accept or reject + m = re.match(r'^(.+?), is the trade ok\?$', msg) + if m: + name = m.group(1) + if name.lower() == self.nick.lower(): + if random.random() < 0.5: + self.log("Accepting trade!") + self.say_delayed("yes") + else: + self.log("Rejecting trade!") + self.say_delayed("no") + return + + # "Trade is done!" — trade completed + if msg == "Trade is done!": + self.in_trade = False + # Now we need to roll + if self.is_my_turn() and not self.rolled_this_turn: + self.say_delayed("roll") + self.rolled_this_turn = True + return + + # Trade summary lines (just informational) + if msg.startswith("Player ") and msg.endswith("gives:"): + return + # ============================================================ # EVERYTHING ELSE — ignore silently # ============================================================