# 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