<commit_before>import logging
import random
import time
from calendar import timegm
from itertools import chain
from .actions import Attack, BeginTurn, Death, Deaths, EndTurn, EventListener
from .card import Card, THE_COIN
from .entity import Entity
from .enums import CardType, PlayState, Step, Zone
from .managers import GameManager
from .utils import CardList


class GameOver(Exception):
	pass


class BaseGame(Entity):
	type = CardType.GAME
	MAX_MINIONS_ON_FIELD = 7
	Manager = GameManager

	def __init__(self, players):
		self.data = None
		super().__init__()
		self.players = players
		for player in players:
			player.game = self
		self.step = None
		self.next_step = None
		self.turn = 0
		self.current_player = None
		self.auras = []
		self.minions_killed = CardList()
		self.minions_killed_this_turn = CardList()

	def __repr__(self):
		return "<%s %s>" % (self.__class__.__name__, self)

	def __str__(self):
		return "%s vs %s" % (self.players)

	def __iter__(self):
		return self.all_entities.__iter__()

	@property
	def board(self):
		return CardList(chain(self.players[0].field, self.players[1].field))

	@property
	def decks(self):
		return CardList(chain(self.players[0].deck, self.players[1].deck))

	@property
	def hands(self):
		return CardList(chain(self.players[0].hand, self.players[1].hand))

	@property
	def characters(self):
		return CardList(chain(self.players[0].characters, self.players[1].characters))

	@property
	def all_entities(self):
		return CardList(chain(self.entities, self.hands, self.decks))

	@property
	def entities(self):
		return CardList(chain([self], self.players[0].entities, self.players[1].entities))

	@property
	def live_entities(self):
		return CardList(chain(self.players[0].live_entities, self.players[1].live_entities))

	def filter(self, *args, **kwargs):
		return self.all_entities.filter(*args, **kwargs)

	def attack(self, source, target):
		return self.queue_actions(source, [Attack(source, target)])

	def _attack(self):
		"""
		See https://github.com/jleclanche/fireplace/wiki/Combat
		for information on how attacking works
		"""
		attacker = self.proposed_attacker
		defender = self.proposed_defender
		self.proposed_attacker = None
		self.proposed_defender = None
		if attacker.should_exit_combat:
			logging.info("Attack has been interrupted.")
			attacker.should_exit_combat = False
			attacker.attacking = False
			defender.defending = False
			return
		# Save the attacker/defender atk values in case they change during the attack
		# (eg. in case of Enrage)
		def_atk = defender.atk
		attacker.hit(defender, attacker.atk)
		if def_atk:
			defender.hit(attacker, def_atk)
		attacker.attacking = False
		defender.defending = False
		attacker.num_attacks += 1

	def play(self, card):
		"""
		Plays \a card from a Player's hand
		"""
		player = card.controller
		logging.info("%s plays %r", player, card)
		cost = card.cost
		if player.temp_mana:
			# The coin, Innervate etc
			cost -= player.temp_mana
			player.temp_mana = max(0, player.temp_mana - card.cost)
		player.used_mana += cost
		if card.overload:
			logging.info("%s overloads for %i mana", player, card.overload)
			player.overloaded += card.overload
		player.last_card_played = card
		player.summon(card)
		player.combo = True
		player.cards_played_this_turn += 1
		if card.type == CardType.MINION:
			player.minions_played_this_turn += 1

	def card(self, id):
		card = Card(id)
		self.manager.new_entity(card)
		return card

	def check_for_end_game(self):
		"""
		Check if one or more player is currently losing.
		End the game if they are.
		"""
		gameover = False
		for player in self.players:
			if player.playstate == PlayState.LOSING:
				player.playstate = PlayState.LOST
				gameover = True

		if gameover:
			for player in self.players:
				if player.playstate != PlayState.LOST:
					player.playstate = PlayState.WON
			raise GameOver("The game has ended.")

	def process_deaths(self):
		actions = []
		for card in self.live_entities:
			if card.to_be_destroyed and not card.ignore_events:
				actions += self._schedule_death(card)

		self.check_for_end_game()

		if actions:
			self.queue_actions(self, actions)

	def _schedule_death(self, card):
		"""
		Prepare a card for its death. Will run any related Death
		trigger attached to the Game object.
		Returns a list of actions to perform during the death sweep.
		"""
		logging.debug("Scheduling death for %r", card)
		card.ignore_events = True
		if card.type == CardType.MINION:
			self.minions_killed.append(card)
			self.minions_killed_this_turn.append(card)
			card.controller.minions_killed_this_turn += 1
		elif card.type == CardType.HERO:
			card.controller.playstate = PlayState.LOSING

		return [Death(card)]

	def queue_actions(self, source, actions):
		"""<commit_msg>Don't raise GameOver<commit_after>import logging
import random
import time
from calendar import timegm
from itertools import chain
from .actions import Attack, BeginTurn, Death, Deaths, EndTurn, EventListener
from .card import Card, THE_COIN
from .entity import Entity
from .enums import CardType, PlayState, Step, Zone
from .managers import GameManager
from .utils import CardList


class GameOver(Exception):
	pass


class BaseGame(Entity):
	type = CardType.GAME
	MAX_MINIONS_ON_FIELD = 7
	Manager = GameManager

	def __init__(self, players):
		self.data = None
		super().__init__()
		self.players = players
		for player in players:
			player.game = self
		self.step = None
		self.next_step = None
		self.turn = 0
		self.current_player = None
		self.auras = []
		self.minions_killed = CardList()
		self.minions_killed_this_turn = CardList()

	def __repr__(self):
		return "<%s %s>" % (self.__class__.__name__, self)

	def __str__(self):
		return "%s vs %s" % (self.players)

	def __iter__(self):
		return self.all_entities.__iter__()

	@property
	def board(self):
		return CardList(chain(self.players[0].field, self.players[1].field))

	@property
	def decks(self):
		return CardList(chain(self.players[0].deck, self.players[1].deck))

	@property
	def hands(self):
		return CardList(chain(self.players[0].hand, self.players[1].hand))

	@property
	def characters(self):
		return CardList(chain(self.players[0].characters, self.players[1].characters))

	@property
	def all_entities(self):
		return CardList(chain(self.entities, self.hands, self.decks))

	@property
	def entities(self):
		return CardList(chain([self], self.players[0].entities, self.players[1].entities))

	@property
	def live_entities(self):
		return CardList(chain(self.players[0].live_entities, self.players[1].live_entities))

	def filter(self, *args, **kwargs):
		return self.all_entities.filter(*args, **kwargs)

	def attack(self, source, target):
		return self.queue_actions(source, [Attack(source, target)])

	def _attack(self):
		"""
		See https://github.com/jleclanche/fireplace/wiki/Combat
		for information on how attacking works
		"""
		attacker = self.proposed_attacker
		defender = self.proposed_defender
		self.proposed_attacker = None
		self.proposed_defender = None
		if attacker.should_exit_combat:
			logging.info("Attack has been interrupted.")
			attacker.should_exit_combat = False
			attacker.attacking = False
			defender.defending = False
			return
		# Save the attacker/defender atk values in case they change during the attack
		# (eg. in case of Enrage)
		def_atk = defender.atk
		attacker.hit(defender, attacker.atk)
		if def_atk:
			defender.hit(attacker, def_atk)
		attacker.attacking = False
		defender.defending = False
		attacker.num_attacks += 1

	def play(self, card):
		"""
		Plays \a card from a Player's hand
		"""
		player = card.controller
		logging.info("%s plays %r", player, card)
		cost = card.cost
		if player.temp_mana:
			# The coin, Innervate etc
			cost -= player.temp_mana
			player.temp_mana = max(0, player.temp_mana - card.cost)
		player.used_mana += cost
		if card.overload:
			logging.info("%s overloads for %i mana", player, card.overload)
			player.overloaded += card.overload
		player.last_card_played = card
		player.summon(card)
		player.combo = True
		player.cards_played_this_turn += 1
		if card.type == CardType.MINION:
			player.minions_played_this_turn += 1

	def card(self, id):
		card = Card(id)
		self.manager.new_entity(card)
		return card

	def check_for_end_game(self):
		"""
		Check if one or more player is currently losing.
		End the game if they are.
		"""
		gameover = False
		for player in self.players:
			if player.playstate == PlayState.LOSING:
				player.playstate = PlayState.LOST
				gameover = True

		if gameover:
			for player in self.players:
				if player.playstate != PlayState.LOST:
					player.playstate = PlayState.WON
			#raise GameOver("The game has ended.")

	def process_deaths(self):
		actions = []
		for card in self.live_entities:
			if card.to_be_destroyed and not card.ignore_events:
				actions += self._schedule_death(card)

		self.check_for_end_game()

		if actions:
			self.queue_actions(self, actions)

	def _schedule_death(self, card):
		"""
		Prepare a card for its death. Will run any related Death
		trigger attached to the Game object.
		Returns a list of actions to perform during the death sweep.
		"""
		logging.debug("Scheduling death for %r", card)
		card.ignore_events = True
		if card.type == CardType.MINION:
			self.minions_killed.append(card)
			self.minions_killed_this_turn.append(card)
			card.controller.minions_killed_this_turn += 1
		elif card.type == CardType.HERO:
			card.controller.playstate = PlayState.LOSING

		return [Death(card)]

	def queue_actions(self, source, actions):
		"""
{'fraction_non_alphanumeric': 0.10904143993302637, 'fraction_numerical': 0.003976559229803265, 'mean_word_length': 4.185567010309279, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4393853', 'n_tokens_mistral': 3577, 'n_tokens_neox': 3221, 'n_words': 820}