# CopyBot This bot is basically an updated version of `TleilaxuBot`. It keeps its own copies of all bots, and asks the current leader for advice. If the leader is unable to answer, it defaults to throwing the die 5 times. It achieves a win rate of about 16% using this strategy. class CopyBot(Bot): _bot_copies = {} _avoid = set(['TleilaxuBot', 'CopyBot']) def __init__(self, *args): super().__init__(*args) if not self._bot_copies: for f_info in inspect.stack(): try: all_bots = f_info.frame.f_locals["bots"] break except KeyError: pass finally: del f_info for bot_class in all_bots: name = bot_class.__name__ if name != __class__.__name__: self._bot_copies[name] = bot_class(-1, self.end_score) for bot in self._bot_copies.values(): bot.index = self.index self.find_bots() def find_bots(self): for f_info in inspect.stack(): try: self.bots = f_info.frame.f_locals["game_bots"] self.bot_names = [bot.__class__.__name__ for bot in self.bots] break except KeyError: pass finally: del f_info def update_state(self, current_throws): self.bot_names = [bot.__class__.__name__ for bot in self.bots] self.current_throws = current_throws for i, bot_name in enumerate(self.bot_names): if i != self.index: self._bot_copies[bot_name].update_state(current_throws) def make_throw(self, scores, last_round): self.bot_names = [bot.__class__.__name__ for bot in self.bots] other_scores = [ (s, i) for i, s in enumerate(scores) if self.bot_names[i] not in self._avoid ] ind = [i for s, i in other_scores if s == max(other_scores)[0]][0] throws = 0 try: winner_bot = self._bot_copies[self.bot_names[ind]] for answer in winner_bot.make_throw(scores, last_round): throws += 1 yield answer winner_bot.update_state(self.current_throws) except Exception: while throws < 5: yield True throws += 1 yield False