def test_create_game(self):
        card_set1 = []
        card_set2 = []
        test_env = self

        for cardIndex in range(0, 30):
            card_set1.append(card_lookup("Stonetusk Boar"))
            card_set2.append(card_lookup("Novice Engineer"))

        deck1 = Deck(card_set1, Malfurion())
        deck2 = Deck(card_set2, Jaina())
        checked_cards = []

        class MockAgent1:
            def do_card_check(self, cards):
                test_env.assertEqual(len(cards), 3)
                checked_cards.append(list(cards))
                return [False, True, True]

            def set_game(self, game):
                pass

        class MockAgent2:
            def do_card_check(self, cards):
                test_env.assertEqual(len(cards), 4)
                checked_cards.append(list(cards))
                return [False, True, True, False]

            def set_game(self, game):
                pass

        agent1 = mock.Mock(spec=MockAgent1(), wraps=MockAgent1())
        agent2 = mock.Mock(spec=MockAgent2(), wraps=MockAgent2())
        game = Game([deck1, deck2], [agent1, agent2])
        game.pre_game()

        self.assertEqual(agent1.method_calls[0][0], "do_card_check",
                         "Agent not asked to select cards")
        self.assertEqual(agent2.method_calls[0][0], "do_card_check",
                         "Agent not asked to select cards")

        self.assertTrue(game.players[0].deck == deck1,
                        "Deck not assigned to player")
        self.assertTrue(game.players[1].deck == deck2,
                        "Deck not assigned to player")

        self.assertTrue(game.players[0].agent == agent1,
                        "Agent not stored in the hearthbreaker")
        self.assertTrue(game.players[1].agent == agent2,
                        "Agent not stored in the hearthbreaker")

        self.assertListEqual(checked_cards[0][1:], game.players[0].hand[1:],
                             "Cards not retained after request")
        self.assertListEqual(checked_cards[1][1:2], game.players[1].hand[1:2],
                             "Cards not retained after request")
示例#2
0
    def test_play_with_one_card(self):
        file = open("AllSets.enUS.json", "r", encoding="UTF-8")
        card_dict = json.load(file)
        for card_set in [
                'Classic', "Basic", "Curse of Naxxramas", "Goblins vs Gnomes",
                "Blackrock Mountain"
        ]:

            for card_info in card_dict[card_set]:
                if 'collectible' in card_info and card_info[
                        'collectible'] and card_info["type"] != "Hero":
                    try:
                        card = card_lookup(card_info["name"])
                    except KeyError:
                        continue
                    game = generate_game_for(type(card), StonetuskBoar,
                                             PlayAndAttackAgent,
                                             DoNothingAgent)
                    try:
                        while not game.game_ended:
                            game.play_single_turn()
                    except Exception as e:
                        print(card)
                        raise e
            file.close()
示例#3
0
    def get_starting_hands(self):
        starting_hands1 = tuple(
            itertools.combinations(self.game.players[0].deck.cards, 5))
        starting_hands2 = tuple(
            itertools.combinations(self.game.players[1].deck.cards, 5))

        startinghands1 = []
        startinghands2 = []
        for i in range(len(starting_hands1)):
            startinghands1.append(starting_hands1[i])
        for i in range(len(starting_hands2)):
            startinghands2.append(starting_hands2[i])

        for i in range(len(startinghands2)):
            coin = engine.card_lookup("The Coin")
            coin.player = self.game.players[1]
            t = list(startinghands2[i])
            t.append(coin)
            startinghands2[i] = tuple(t)

        starting_hands = []
        for i in range(len(startinghands1)):
            for j in range(len(startinghands2)):
                starting_hands.append((startinghands1[i], startinghands2[j]))
        return starting_hands
    def test_first_turn(self):
        card_set1 = []
        card_set2 = []

        for cardIndex in range(0, 30):
            card_set1.append(card_lookup("Stonetusk Boar"))
            card_set2.append(card_lookup("Novice Engineer"))

        deck1 = Deck(card_set1, Malfurion())
        deck2 = Deck(card_set2, Jaina())

        agent1 = mock.Mock(spec=DoNothingAgent(), wraps=DoNothingAgent())
        agent2 = mock.Mock(spec=DoNothingAgent(), wraps=DoNothingAgent())
        game = Game([deck1, deck2], [agent1, agent2])

        game.start()
示例#5
0
 def can_add(card):
     rarity = card_lookup(card).rarity
     num = cards_in_deck.setdefault(card, 0)
     if rarity == CARD_RARITY.LEGENDARY:
         return num < 1
     else:
         return num < 2
示例#6
0
 def use(self, player, game):
     from hearthbreaker.engine import card_lookup
     super().use(player, game)
     if len(player.graveyard) > 0 and len(player.minions) < 7:
         card_name = game.random_choice(player.graveyard)
         card = card_lookup(card_name)
         card.summon(player, game, len(player.minions))
示例#7
0
def can_add(card, deck):
    rarity = card_lookup(card).rarity
    num = deck.count(card)
    if rarity == CARD_RARITY.LEGENDARY:
        return num < 1
    else:
        return num < 2
示例#8
0
    def read_json(self, file):
        """
        Read a replay in the complete json format.  This format is compatible with the netplay format, and is
        also designed to be more future proof.  For more info, see the
        `replay format <https://github.com/danielyule/hearthbreaker/blob/master/replay_format.md>`_

        :param file: Either a string or an IO object.  If a string, then it is assumed to be a filename describing
                     where a replay file is found.  If an IO object, then the IO object should be opened for
                     reading.
        :type file: :class:`str` or :class:`io.TextIOBase`
        """
        from jsonschema import validate
        was_filename = False
        if 'read' not in dir(file):
            was_filename = True
            file = open(file, 'r')

        jd = json.load(file)
        validate(jd, self.schema)
        self.decks = []
        for deck in jd['header']['decks']:
            deck_size = len(deck['cards'])
            cards = [card_lookup(deck['cards'][index % deck_size]) for index in range(0, 30)]
            self.decks.append(
                Deck(cards, hero_from_name(deck['hero'])))

        self.random = jd['header']['random']
        self.keeps = jd['header']['keep']
        if len(self.keeps) == 0:
            self.keeps = [[0, 1, 2], [0, 1, 2, 3]]
        self._moves = [Move.from_json(**js) for js in jd['moves']]
        if was_filename:
            file.close()
示例#9
0
 def from_json(name=None,
               conditions=[],
               source="collection",
               source_list=None,
               make_copy=False,
               minion=None):
     from hearthbreaker.engine import card_lookup
     query = CardQuery.__new__(CardQuery)
     query.name = name
     query.conditions = []
     for condition in conditions:
         query.conditions.append(Condition.from_json(**condition))
     else:
         query.condition = None
     query.source = CARD_SOURCE.from_str(source)
     if source_list:
         query.source_list = [card_lookup(item) for item in source_list]
     else:
         query.source_list = None
     query.make_copy = make_copy
     if minion:
         query.minion = Selector.from_json(**minion)
     else:
         query.minion = None
     return query
示例#10
0
    def read_json(self, file):
        """
        Read a replay in the complete json format.  This format is compatible with the netplay format, and is
        also designed to be more future proof.  For more info, see the
        `replay format <https://github.com/danielyule/hearthbreaker/blob/master/replay_format.md>`_

        :param file: Either a string or an IO object.  If a string, then it is assumed to be a filename describing
                     where a replay file is found.  If an IO object, then the IO object should be opened for
                     reading.
        :type file: :class:`str` or :class:`io.TextIOBase`
        """
        from jsonschema import validate
        was_filename = False
        if 'read' not in dir(file):
            was_filename = True
            file = open(file, 'r')

        jd = json.load(file)
        validate(jd, self.schema)
        self.decks = []
        for deck in jd['header']['decks']:
            deck_size = len(deck['cards'])
            cards = [
                card_lookup(deck['cards'][index % deck_size])
                for index in range(0, 30)
            ]
            self.decks.append(Deck(cards, hero_from_name(deck['hero'])))

        self.random = jd['header']['random']
        self.keeps = jd['header']['keep']
        if len(self.keeps) == 0:
            self.keeps = [[0, 1, 2], [0, 1, 2, 3]]
        self._moves = [Move.from_json(**js) for js in jd['moves']]
        if was_filename:
            file.close()
示例#11
0
    def test_first_turn(self):
        card_set1 = []
        card_set2 = []

        for cardIndex in range(0, 30):
            card_set1.append(card_lookup("Stonetusk Boar"))
            card_set2.append(card_lookup("Novice Engineer"))

        deck1 = Deck(card_set1, Malfurion())
        deck2 = Deck(card_set2, Jaina())

        agent1 = mock.Mock(spec=DoNothingAgent(), wraps=DoNothingAgent())
        agent2 = mock.Mock(spec=DoNothingAgent(), wraps=DoNothingAgent())
        game = Game([deck1, deck2], [agent1, agent2])

        game.start()
示例#12
0
 def use(self, player, game):
     from hearthbreaker.engine import card_lookup
     super().use(player, game)
     if len(player.graveyard) > 0 and len(player.minions) < 7:
         card_name = game.random_choice(player.graveyard)
         card = card_lookup(card_name)
         card.summon(player, game, len(player.minions))
    def test_create_game(self):
        card_set1 = []
        card_set2 = []
        test_env = self

        for cardIndex in range(0, 30):
            card_set1.append(card_lookup("Stonetusk Boar"))
            card_set2.append(card_lookup("Novice Engineer"))

        deck1 = Deck(card_set1, Malfurion())
        deck2 = Deck(card_set2, Jaina())
        checked_cards = []

        class MockAgent1:
            def do_card_check(self, cards):
                test_env.assertEqual(len(cards), 3)
                checked_cards.append(list(cards))
                return [False, True, True]

            def set_game(self, game):
                pass

        class MockAgent2:
            def do_card_check(self, cards):
                test_env.assertEqual(len(cards), 4)
                checked_cards.append(list(cards))
                return [False, True, True, False]

            def set_game(self, game):
                pass

        agent1 = mock.Mock(spec=MockAgent1(), wraps=MockAgent1())
        agent2 = mock.Mock(spec=MockAgent2(), wraps=MockAgent2())
        game = Game([deck1, deck2], [agent1, agent2])
        game.pre_game()

        self.assertEqual(agent1.method_calls[0][0], "do_card_check", "Agent not asked to select cards")
        self.assertEqual(agent2.method_calls[0][0], "do_card_check", "Agent not asked to select cards")

        self.assertTrue(game.players[0].deck == deck1, "Deck not assigned to player")
        self.assertTrue(game.players[1].deck == deck2, "Deck not assigned to player")

        self.assertTrue(game.players[0].agent == agent1, "Agent not stored in the hearthbreaker")
        self.assertTrue(game.players[1].agent == agent2, "Agent not stored in the hearthbreaker")

        self.assertListEqual(checked_cards[0][1:], game.players[0].hand[1:], "Cards not retained after request")
        self.assertListEqual(checked_cards[1][1:2], game.players[1].hand[1:2], "Cards not retained after request")
示例#14
0
 def from_json(card, actions, selector, condition=None):
     from hearthbreaker.engine import card_lookup
     actions = [Action.from_json(**action) for action in actions]
     selector = Selector.from_json(**selector)
     if condition:
         condition = Condition.from_json(**condition)
     card = card_lookup(card)
     return Choice(card, actions, selector, condition)
示例#15
0
 def from_json(card, actions, selector, condition=None):
     from hearthbreaker.engine import card_lookup
     actions = [Action.from_json(**action) for action in actions]
     selector = Selector.from_json(**selector)
     if condition:
         condition = Condition.from_json(**condition)
     card = card_lookup(card)
     return Choice(card, actions, selector, condition)
示例#16
0
 def __from_json__(wd, player):
     from hearthbreaker.engine import card_lookup
     weapon_card = card_lookup(wd['name'])
     weapon = weapon_card.create_weapon(player)
     weapon.base_attack = wd['attack']
     weapon.durability = wd['durability']
     weapon.card = weapon_card
     GameObject.__from_json__(weapon, **wd)
     return weapon
示例#17
0
 def __from_json__(wd, player):
     from hearthbreaker.engine import card_lookup
     weapon_card = card_lookup(wd['name'])
     weapon = weapon_card.create_weapon(player)
     weapon.base_attack = wd['attack']
     weapon.durability = wd['durability']
     weapon.card = weapon_card
     GameObject.__from_json__(weapon, **wd)
     return weapon
示例#18
0
    def get_card(self, player, owner):
        from hearthbreaker.engine import card_lookup, get_cards
        if self.name:
            return card_lookup(self.name)

        if self.source == CARD_SOURCE.COLLECTION:
            card_list = get_cards()
        elif self.source == CARD_SOURCE.MY_DECK:
            card_list = filter(lambda c: not c.drawn, player.deck.cards)
        elif self.source == CARD_SOURCE.MY_HAND:
            card_list = player.hand
        elif self.source == CARD_SOURCE.OPPONENT_DECK:
            card_list = filter(lambda c: not c.drawn, player.opponent.deck.cards)
        elif self.source == CARD_SOURCE.OPPONENT_HAND:
            card_list = player.opponent.hand
        elif self.source == CARD_SOURCE.LIST:
            card_list = self.source_list
        elif self.source == CARD_SOURCE.LAST_CARD:
            return type(player.game.last_card)()
        elif self.source == CARD_SOURCE.MINION:
            return self.minion.get_targets(owner, owner)[0].card
        else:
            card_list = []
        # TODO Throw an exception in any other case?

        def check_condition(condition):
            return lambda c: condition.evaluate(player, c)

        for condition in self.conditions:
            card_list = filter(check_condition(condition), card_list)

        card_list = [card for card in card_list]
        card_len = len(card_list)
        if card_len == 1:
            chosen_card = card_list[0]
        elif card_len == 0:
            return None
        else:
            chosen_card = player.game.random_choice(card_list)

        if self.source == CARD_SOURCE.COLLECTION or self.source == CARD_SOURCE.LIST or self.make_copy:
            return chosen_card
        elif self.source == CARD_SOURCE.MY_DECK:
            chosen_card.drawn = True
            player.deck.left -= 1
            return chosen_card
        elif self.source == CARD_SOURCE.OPPONENT_DECK:
            chosen_card.drawn = True
            player.opponent.deck.left -= 1
            return chosen_card
        elif self.source == CARD_SOURCE.MY_HAND:
            player.hand.remove(chosen_card)
            return chosen_card
        elif self.source == CARD_SOURCE.OPPONENT_HAND:
            player.opponent.hand.remove(chosen_card)
            return chosen_card
示例#19
0
def deck_valid(deck):
    counter = collections.defaultdict(lambda: 0)
    for card in deck.deck:
        card_ob = card_lookup(card)
        rarity = card_ob.rarity
        if card_ob.character_class != 0 and card_ob.character_class != deck.hero:
            return False
        counter[card] += 1
        if rarity == CARD_RARITY.LEGENDARY:
            if not counter[card] == 1:
                return False
        else:
            if not counter[card] <= 2:
                return False
    return True
    def test_play_with_one_card(self):
        file = open("AllSets.enUS.json", "r", encoding="UTF-8")
        card_dict = json.load(file)
        for card_set in ['Expert', "Basic", "Curse of Naxxramas", "Goblins vs Gnomes"]:

            for card_info in card_dict[card_set]:
                if 'collectible' in card_info and card_info['collectible'] and card_info["type"] != "Hero":
                    try:
                        card = card_lookup(card_info["name"])
                    except KeyError:
                        continue
                    game = generate_game_for(type(card), StonetuskBoar, PlayAndAttackAgent, DoNothingAgent)

                    while not game.game_ended:
                        game.play_single_turn()
            file.close()
示例#21
0
def load_deck(filename):
    cards = []

    with open(filename, "r") as deck_file:
        contents = deck_file.read()
        items = contents.splitlines()
        for line in items[0:]:
            parts = line.split(" ", 1)
            count = int(parts[0])
            for i in range(0, count):
                card = card_lookup(parts[1])
                cards.append(card)

    if len(cards) > 20:
        pass

    return cards
示例#22
0
 def __from_json__(md, player, game):
     from hearthbreaker.engine import card_lookup
     minion = Minion(md['attack'], md['max_health'])
     GameObject.__from_json__(minion, **md)
     minion.health = md['max_health'] - md['damage']
     minion.exhausted = md['exhausted']
     minion.attacks_performed = not md['attacks_performed']
     minion.born = md['sequence_id']
     if 'enrage' in md:
         minion.enrage = [Aura.from_json(**enrage) for enrage in md['enrage']]
     minion.deathrattle = []
     for rattle in md['deathrattles']:
         minion.deathrattle.append(Deathrattle.from_json(**rattle))
     minion.card = card_lookup(md["name"])
     minion.game = game
     minion.player = player
     return minion
示例#23
0
	def load_deck(self, filename):
		cards = []
		character_class = CHARACTER_CLASS.MAGE

		with open(filename, "r") as deck_file:
			contents = deck_file.read()
			items = contents.splitlines()
			for line in items[0:]:
				parts = line.split(" ", 1)
				count = int(parts[0])
				for i in range(0, count):
					card = card_lookup(parts[1])
					if card.character_class != CHARACTER_CLASS.ALL:
						character_class = card.character_class
					cards.append(card)

		if len(cards) > 30:
			pass
		return Deck(cards, hero_for_class(character_class))
示例#24
0
 def __from_json__(md, player, game):
     from hearthbreaker.engine import card_lookup
     minion = Minion(md['attack'], md['max_health'])
     GameObject.__from_json__(minion, **md)
     minion.health = md['max_health'] - md['damage']
     minion.exhausted = md['exhausted']
     minion.attacks_performed = not md['attacks_performed']
     minion.born = md['sequence_id']
     if 'enrage' in md:
         minion.enrage = [
             Aura.from_json(**enrage) for enrage in md['enrage']
         ]
     minion.deathrattle = []
     for rattle in md['deathrattles']:
         minion.deathrattle.append(Deathrattle.from_json(**rattle))
     minion.card = card_lookup(md["name"])
     minion.game = game
     minion.player = player
     return minion
示例#25
0
 def from_json(name=None, conditions=[], source="collection", source_list=None, make_copy=False, minion=None):
     from hearthbreaker.engine import card_lookup
     query = CardQuery.__new__(CardQuery)
     query.name = name
     query.conditions = []
     for condition in conditions:
         query.conditions.append(Condition.from_json(**condition))
     else:
         query.condition = None
     query.source = CARD_SOURCE.from_str(source)
     if source_list:
         query.source_list = [card_lookup(item) for item in source_list]
     else:
         query.source_list = None
     query.make_copy = make_copy
     if minion:
         query.minion = Selector.from_json(**minion)
     else:
         query.minion = None
     return query
示例#26
0
def load_deck(filename):
    cards = []
    character_class = CHARACTER_CLASS.MAGE

    with open(filename, "r") as deck_file:
        contents = deck_file.read()
        items = contents.splitlines()
        for line in items[0:]:
            parts = line.split(" ", 1)
            count = int(parts[0])
            for i in range(0, count):
                card = card_lookup(parts[1])
                if card.character_class != CHARACTER_CLASS.ALL:
                    character_class = card.character_class
                cards.append(card)

    if len(cards) > 30:
        pass

    return Deck(cards, hero_for_class(character_class))
示例#27
0
 def __from_json__(cards):
     from hearthbreaker.engine import card_lookup
     return CardList([card_lookup(card) for card in cards])
示例#28
0
 def __from_json__(cards):
     from hearthbreaker.engine import card_lookup
     return CardList([card_lookup(card) for card in cards])
示例#29
0
    def test_all_cards(self):
        fake_game = generate_game_for(StonetuskBoar, StonetuskBoar,
                                      DoNothingAgent, DoNothingAgent)
        overload_re = re.compile("Overload: \\((\\d)\\)")
        spell_damage_re = re.compile("Spell Damage \\+(\\d)")
        battlecry_re = re.compile("Battlecry: .*")
        deathrattle_re = re.compile("Deathrattle: .*")
        split_re = re.compile("\\s*\\.\\s*")
        bold_tag_re = re.compile("</?b>")
        file = open("AllSets.enUS.json", "r", encoding="UTF-8")
        card_dict = json.load(file)
        not_implemented = []
        total_cards = 0
        for card_set in [
                'Expert', "Basic", "Curse of Naxxramas", "Goblins vs Gnomes",
                "Reward", "Promotion"
        ]:
            for card_info in card_dict[card_set]:
                if card_info["type"] in [
                        'Minion', 'Spell', 'Weapon', 'Secret'
                ]:
                    total_cards += 1
                    try:
                        card = card_lookup(id_mappings[card_info["id"]])
                    except KeyError:
                        not_implemented.append("{}: ({})".format(
                            card_info["name"], card_info['id']))
                        continue
                    if "cost" in card_info:
                        self.assertEqual(
                            int(card_info["cost"]), card.mana,
                            "Expected {} to have cost {}.  Got {}".format(
                                card_info["name"], card_info["cost"],
                                card.mana))
                    if "playerClass" in card_info:
                        self.assertEqual(
                            CHARACTER_CLASS.from_str(card_info["playerClass"]),
                            card.character_class,
                            "Expected {} to have class {}.  Got {}".format(
                                card_info["name"], card_info["playerClass"],
                                CHARACTER_CLASS.to_str(card.character_class)))
                    else:
                        self.assertEqual(
                            CHARACTER_CLASS.ALL, card.character_class,
                            "Expected {} to have no class.  Got {}".format(
                                card_info["name"],
                                CHARACTER_CLASS.to_str(card.character_class)))
                    if "rarity" in card_info:
                        self.assertEqual(
                            CARD_RARITY.from_str(card_info["rarity"]),
                            card.rarity,
                            "Expected card {} to have rarity {}.  Got {}".
                            format(card_info["name"], card_info["rarity"],
                                   CARD_RARITY.to_str(card.rarity)))
                    if "collectible" in card_info:
                        if card_info['collectible']:
                            self.assertTrue(
                                card.collectible,
                                "Expected card {} to be collectible".format(
                                    card_info['name']))
                        else:
                            self.assertFalse(
                                card.collectible,
                                "Expected card {} not to be collectible".
                                format(card_info['name']))
                    if card_info["type"] == "Minion":
                        minion = card.create_minion(fake_game.current_player)
                        minion.player = fake_game.current_player
                        minion.game = fake_game
                        minion.card = card
                        minion.add_to_board(0)
                        if "text" in card_info:
                            for effect in split_re.split(
                                    re.sub(bold_tag_re, "",
                                           card_info["text"])):
                                if effect == "Taunt":
                                    self.assertTrue(
                                        minion.taunt,
                                        "Expected {:s} to have taunt".format(
                                            card_info["name"]))
                                elif effect == "Divine Shield":
                                    self.assertTrue(
                                        minion.divine_shield,
                                        "Expected {:s} to have divine shield".
                                        format(card_info["name"]))
                                elif effect == "Stealth":
                                    self.assertTrue(
                                        minion.stealth,
                                        "Expected {:s} to have stealth".format(
                                            card_info["name"]))
                                elif effect == "Windfury":
                                    self.assertTrue(
                                        minion.windfury(),
                                        "Expected {:s} to have windfury".
                                        format(card_info["name"]))
                                elif effect == "Charge":
                                    self.assertTrue(
                                        minion.charge(),
                                        "Expected {:s} to have charge".format(
                                            card_info["name"]))
                                elif battlecry_re.match(effect):
                                    self.assertTrue(
                                        card.battlecry is not None,
                                        "Expected {:s} to have a battlecry".
                                        format(card_info["name"]))
                                elif deathrattle_re.match(effect):
                                    self.assertTrue(
                                        minion.deathrattle is not None,
                                        "Expected {:s} to have a deathrattle".
                                        format(card_info["name"]))
                                elif overload_re.match(effect) is not None:
                                    self.assertEqual(
                                        int(
                                            overload_re.match(effect).group(
                                                1)), card.overload,
                                        ("Expected {:s} to have overload of" +
                                         " {:s}, but had {:d}").format(
                                             card_info["name"],
                                             overload_re.match(effect).group(
                                                 1), card.overload))
                                elif spell_damage_re.match(effect) is not None:
                                    self.assertEqual(
                                        int(
                                            spell_damage_re.match(
                                                effect).group(1)),
                                        minion.player.spell_damage,
                                        ("Expected {:s} to have spell damage of"
                                         + " {}, but had {}").format(
                                             card_info["name"],
                                             spell_damage_re.match(
                                                 effect).group(1),
                                             minion.player.spell_damage))
                        minion.silence()
                        self.assertEqual(
                            int(card_info["attack"]),
                            minion.calculate_attack(),
                            "Expected {} to have attack of {}.  Got {}".format(
                                card_info["name"], card_info["attack"],
                                minion.calculate_attack()))
                        self.assertEqual(
                            int(card_info["health"]), minion.health,
                            "Expected {} to have health of {}.  Got {}".format(
                                card_info["name"], card_info["health"],
                                minion.health))
                        if "race" in card_info:
                            self.assertEqual(
                                MINION_TYPE.from_str(card_info["race"]),
                                card.minion_type,
                                "Expected {} to have race {}.  Got {}".format(
                                    card_info["name"], card_info["race"],
                                    MINION_TYPE.to_str(card.minion_type)))
                        else:
                            self.assertEqual(
                                MINION_TYPE.NONE, card.minion_type,
                                "Expected {} to have no race.  Got {}".format(
                                    card_info["name"],
                                    MINION_TYPE.to_str(card.minion_type)))
                    elif card_info["type"] == "Weapon":
                        weapon = card.create_weapon(fake_game.current_player)
                        self.assertEqual(
                            int(card_info["attack"]), weapon.base_attack,
                            "Expected {} to have attack of {}.  Got {}".format(
                                card_info["name"], card_info["attack"],
                                weapon.base_attack))
                        self.assertEqual(
                            int(card_info["durability"]), weapon.durability,
                            "Expected {} to have durability of {}.  Got {}".
                            format(card_info["name"], card_info["durability"],
                                   weapon.durability))

        file.close()
        if len(not_implemented) > 0:
            print("{} of {} cards implemented".format(
                total_cards - len(not_implemented), total_cards))
            print("Cards not implemented:")
            for card in not_implemented:
                print("  - {}".format(card))
示例#30
0
    def read(self, file):
        """
        Read a replay in the compact format.  This format is a series of directives, and isn't as flexible
        or well structured as the json format (in :meth:write_json).  For more info, see the
        `replay format <https://github.com/danielyule/hearthbreaker/blob/master/replay_format.md>`_

        :param file: Either a string or an IO object.  If a string, then it is assumed to be a filename describing
                     where a replay file is to be found.  If an IO object, then the IO object should be opened for
                     reading.
        :type file: :class:`str` or :class:`io.TextIOBase`
        """
        was_filename = False
        if 'read' not in dir(file):
            was_filename = True
            file = open(file, 'r')
        line_pattern = re.compile("\s*(\w*)\s*\(([^)]*)\)\s*(;.*)?$")
        for line in file:
            (move, args) = line_pattern.match(line).group(1, 2)
            args = [arg.strip() for arg in args.split(",")]
            if move == 'play':
                card = args[0]
                if len(args) > 1:
                    target = args[1]
                else:
                    target = None
                self._moves.append(
                    PlayMove(hearthbreaker.proxies.ProxyCard(card),
                             target=target))

            elif move == 'summon':
                card = args[0]

                index = int(args[1])

                if len(args) > 2:
                    target = args[2]
                else:
                    target = None

                self._moves.append(
                    PlayMove(hearthbreaker.proxies.ProxyCard(card), index,
                             target))
            elif move == 'attack':
                self._moves.append(AttackMove(args[0], args[1]))
            elif move == 'power':
                if len(args) > 0 and args[0] != '':
                    self._moves.append(PowerMove(args[0]))
                else:
                    self._moves.append(PowerMove())
            elif move == 'end':
                self._moves.append(TurnEndMove())
            elif move == 'start':
                self._moves.append(TurnStartMove())
            elif move == 'random':
                if len(self._moves) == 0:
                    if len(args[0]) > 0:
                        for num in args:
                            self.random.append(int(num))

                else:
                    for num in args:
                        if num.isdigit():
                            self._moves[-1].random_numbers.append(int(num))
                        else:
                            self._moves[-1].random_numbers.append(
                                hearthbreaker.proxies.ProxyCharacter(num))

            elif move == 'deck':
                if len(self.decks) > 1:
                    raise Exception("Maximum of two decks per file")
                deck_size = len(args) - 1
                cards = [
                    card_lookup(args[1 + index % deck_size])
                    for index in range(0, 30)
                ]
                self.decks.append(Deck(cards, hero_from_name(args[0])))

            elif move == 'keep':
                if len(self.keeps) > 1:
                    raise Exception("Maximum of two keep directives per file")
                self.keeps.append([int(a) for a in args])

            elif move == 'concede':
                self._moves.append(ConcedeMove())
        if was_filename:
            file.close()
        if len(self.keeps) is 0:
            self.keeps = [[0, 1, 2], [0, 1, 2, 3]]
示例#31
0
 def get_card(self, target, player, owner):
     from hearthbreaker.engine import card_lookup
     return card_lookup(self.card)
示例#32
0
    def read(self, file):
        """
        Read a replay in the compact format.  This format is a series of directives, and isn't as flexible
        or well structured as the json format (in :meth:write_json).  For more info, see the
        `replay format <https://github.com/danielyule/hearthbreaker/blob/master/replay_format.md>`_

        :param file: Either a string or an IO object.  If a string, then it is assumed to be a filename describing
                     where a replay file is to be found.  If an IO object, then the IO object should be opened for
                     reading.
        :type file: :class:`str` or :class:`io.TextIOBase`
        """
        was_filename = False
        if 'read' not in dir(file):
            was_filename = True
            file = open(file, 'r')
        line_pattern = re.compile("\s*(\w*)\s*\(([^)]*)\)\s*(;.*)?$")
        for line in file:
            (move, args) = line_pattern.match(line).group(1, 2)
            args = [arg.strip() for arg in args.split(",")]
            if move == 'play':
                card = args[0]
                if len(args) > 1:
                    target = args[1]
                else:
                    target = None
                self._moves.append(PlayMove(hearthbreaker.proxies.ProxyCard(card), target=target))

            elif move == 'summon':
                card = args[0]

                index = int(args[1])

                if len(args) > 2:
                    target = args[2]
                else:
                    target = None

                self._moves.append(PlayMove(hearthbreaker.proxies.ProxyCard(card), index, target))
            elif move == 'attack':
                self._moves.append(AttackMove(args[0], args[1]))
            elif move == 'power':
                if len(args) > 0 and args[0] != '':
                    self._moves.append(PowerMove(args[0]))
                else:
                    self._moves.append(PowerMove())
            elif move == 'end':
                self._moves.append(TurnEndMove())
            elif move == 'start':
                self._moves.append(TurnStartMove())
            elif move == 'random':
                if len(self._moves) == 0:
                    if len(args[0]) > 0:
                        for num in args:
                            self.random.append(int(num))

                else:
                    for num in args:
                        if num.isdigit():
                            self._moves[-1].random_numbers.append(int(num))
                        else:
                            self._moves[-1].random_numbers.append(hearthbreaker.proxies.ProxyCharacter(num))

            elif move == 'deck':
                if len(self.decks) > 1:
                    raise Exception("Maximum of two decks per file")
                deck_size = len(args) - 1
                cards = [card_lookup(args[1 + index % deck_size]) for index in range(0, 30)]
                self.decks.append(
                    Deck(cards, hero_from_name(args[0])))

            elif move == 'keep':
                if len(self.keeps) > 1:
                    raise Exception("Maximum of two keep directives per file")
                self.keeps.append([int(a) for a in args])

            elif move == 'concede':
                self._moves.append(ConcedeMove())
        if was_filename:
            file.close()
        if len(self.keeps) is 0:
            self.keeps = [[0, 1, 2], [0, 1, 2, 3]]
示例#33
0
 def get_card(self, target, player, owner):
     from hearthbreaker.engine import card_lookup
     return card_lookup(self.card)
示例#34
0
    def get_card(self, player, owner):
        from hearthbreaker.engine import card_lookup, get_cards
        if self.name:
            return card_lookup(self.name)

        if self.source == CARD_SOURCE.COLLECTION:
            card_list = get_cards()
        elif self.source == CARD_SOURCE.MY_DECK:
            card_list = filter(lambda c: not c.drawn, player.deck.cards)
        elif self.source == CARD_SOURCE.MY_HAND:
            card_list = player.hand
        elif self.source == CARD_SOURCE.OPPONENT_DECK:
            card_list = filter(lambda c: not c.drawn,
                               player.opponent.deck.cards)
        elif self.source == CARD_SOURCE.OPPONENT_HAND:
            card_list = player.opponent.hand
        elif self.source == CARD_SOURCE.LIST:
            card_list = self.source_list
        elif self.source == CARD_SOURCE.LAST_CARD:
            return type(player.game.last_card)()
        elif self.source == CARD_SOURCE.LAST_DRAWN:
            chosen_card = player.hand[-1]
            player.hand.remove(chosen_card)
            chosen_card.unattach()
            return chosen_card
        elif self.source == CARD_SOURCE.MINION:
            card_list = [
                minion.card
                for minion in self.minion.get_targets(owner, owner)
            ]
        elif self.source == CARD_SOURCE.MY_SECRETS:
            card_list = [secret.card for secret in player.secrets]
        elif self.source == CARD_SOURCE.ENEMY_SECRETS:
            card_list = [secret for secret in player.opponent.secrets]
        else:
            card_list = []
        # TODO Throw an exception in any other case?

        def check_condition(condition):
            return lambda c: condition.evaluate(player, c)

        for condition in self.conditions:
            card_list = filter(check_condition(condition), card_list)

        card_list = [card for card in card_list]
        card_len = len(card_list)
        if card_len == 1:
            chosen_card = card_list[0]
        elif card_len == 0:
            return None
        else:
            chosen_card = player.game.random_choice(card_list)

        if self.source == CARD_SOURCE.COLLECTION or self.source == CARD_SOURCE.LIST or self.make_copy:
            return chosen_card
        elif self.source == CARD_SOURCE.MY_DECK:
            chosen_card.drawn = True
            player.deck.left -= 1
            return chosen_card
        elif self.source == CARD_SOURCE.OPPONENT_DECK:
            chosen_card.drawn = True
            player.opponent.deck.left -= 1
            return chosen_card
        elif self.source == CARD_SOURCE.MY_HAND:
            player.hand.remove(chosen_card)
            chosen_card.unattach()
            return chosen_card
        elif self.source == CARD_SOURCE.OPPONENT_HAND:
            player.opponent.hand.remove(chosen_card)
            chosen_card.unattach()
            return chosen_card
        elif self.source == CARD_SOURCE.MY_SECRETS:
            if player is player.game.other_player:
                chosen_card.deactivate(player)
            player.secrets.remove(chosen_card)
            return chosen_card
        elif self.source == CARD_SOURCE.ENEMY_SECRETS:
            if player.opponent is player.game.other_player:
                chosen_card.deactivate(player.opponent)
            player.opponent.secrets.remove(chosen_card)
            return chosen_card
示例#35
0
    def test_all_cards(self):
        fake_game = generate_game_for(StonetuskBoar, StonetuskBoar, DoNothingAgent, DoNothingAgent)
        overload_re = re.compile("Overload: \\((\\d)\\)")
        spell_damage_re = re.compile("Spell Damage \\+(\\d)")
        battlecry_re = re.compile("Battlecry: .*")
        deathrattle_re = re.compile("Deathrattle: .*")
        split_re = re.compile("\\s*\\.|\n\\s*")
        bold_tag_re = re.compile("</?b>")
        file = open("AllSets.enUS.json", "r", encoding="UTF-8")
        card_dict = json.load(file)
        not_implemented = []
        total_cards = 0
        for card_set in ['Classic', "Basic", "Curse of Naxxramas", "Goblins vs Gnomes", "Blackrock Mountain",
                         "The Grand Tournament", "Reward", "Promotion"]:
            for card_info in card_dict[card_set]:
                if card_info["type"] in ['Minion', 'Spell', 'Weapon', 'Secret']:
                    total_cards += 1
                    try:
                        card = card_lookup(id_mappings[card_info["id"]])
                    except KeyError:
                        if 'collectible' in card_info and card_info['collectible']:
                            not_implemented.append("{}: ({})".format(card_info["name"], card_info['id']))
                        continue
                    if "cost" in card_info:
                        self.assertEqual(int(card_info["cost"]), card.mana,
                                         "Expected {} to have cost {}.  Got {}".format(
                                         card_info["name"], card_info["cost"], card.mana))
                    if "playerClass" in card_info:
                        self.assertEqual(CHARACTER_CLASS.from_str(card_info["playerClass"]), card.character_class,
                                         "Expected {} to have class {}.  Got {}".format(
                                             card_info["name"], card_info["playerClass"],
                                             CHARACTER_CLASS.to_str(card.character_class)))
                    else:
                        self.assertEqual(CHARACTER_CLASS.ALL, card.character_class,
                                         "Expected {} to have no class.  Got {}".format(
                                             card_info["name"], CHARACTER_CLASS.to_str(card.character_class)))
                    if "rarity" in card_info:
                        self.assertEqual(CARD_RARITY.from_str(card_info["rarity"]), card.rarity,
                                         "Expected card {} to have rarity {}.  Got {}".format(
                                             card_info["name"], card_info["rarity"], CARD_RARITY.to_str(card.rarity)))
                    if "collectible" in card_info:
                        if card_info['collectible']:
                            self.assertTrue(card.collectible, "Expected card {} to be collectible".format(
                                card_info['name']))
                        else:
                            self.assertFalse(card.collectible, "Expected card {} not to be collectible".format(
                                card_info['name']))
                    if card_info["type"] == "Minion":
                        minion = card.create_minion(fake_game.current_player)
                        minion.player = fake_game.current_player
                        minion.game = fake_game
                        minion.card = card
                        minion.add_to_board(0)
                        if "text" in card_info:
                            if card_info['name'] == "Argent Horserider":
                                print(split_re.split(re.sub(bold_tag_re, "", card_info["text"])))
                            for effect in split_re.split(re.sub(bold_tag_re, "", card_info["text"])):
                                if effect == "Taunt":
                                    self.assertTrue(minion.taunt,
                                                    "Expected {:s} to have taunt".format(card_info["name"]))
                                elif effect == "Divine Shield":
                                    self.assertTrue(minion.divine_shield,
                                                    "Expected {:s} to have divine shield".format(card_info["name"]))
                                elif effect == "Stealth":
                                    self.assertTrue(minion.stealth,
                                                    "Expected {:s} to have stealth".format(card_info["name"]))
                                elif effect == "Windfury":
                                    self.assertTrue(minion.windfury(),
                                                    "Expected {:s} to have windfury".format(card_info["name"]))
                                elif effect == "Charge":
                                    self.assertTrue(minion.charge(),
                                                    "Expected {:s} to have charge".format(card_info["name"]))
                                elif battlecry_re.match(effect):
                                    self.assertTrue(card.battlecry is not None,
                                                    "Expected {:s} to have a battlecry".format
                                                    (card_info["name"]))
                                elif deathrattle_re.match(effect):
                                    self.assertTrue(minion.deathrattle is not None,
                                                    "Expected {:s} to have a deathrattle".format
                                                    (card_info["name"]))
                                elif overload_re.match(effect) is not None:
                                    self.assertEqual(int(overload_re.match(effect).group(1)), card.overload,
                                                     ("Expected {:s} to have overload of" +
                                                     " {:s}, but had {:d}").format(card_info["name"],
                                                                                   overload_re.match(effect).group(1),
                                                     card.overload))
                                elif spell_damage_re.match(effect) is not None:
                                    self.assertEqual(int(spell_damage_re.match(effect).group(1)),
                                                     minion.player.spell_damage,
                                                     ("Expected {:s} to have spell damage of" +
                                                     " {}, but had {}").format(card_info["name"],
                                                                               spell_damage_re.match(effect).group(1),
                                                     minion.player.spell_damage))
                        minion.silence()
                        self.assertEqual(int(card_info["attack"]), minion.calculate_attack(),
                                         "Expected {} to have attack of {}.  Got {}".format(
                                         card_info["name"], card_info["attack"], minion.calculate_attack()))
                        self.assertEqual(int(card_info["health"]), minion.health,
                                         "Expected {} to have health of {}.  Got {}".format(
                                         card_info["name"], card_info["health"], minion.health))
                        if "race" in card_info:
                            self.assertEqual(MINION_TYPE.from_str(card_info["race"]), card.minion_type,
                                             "Expected {} to have race {}.  Got {}".format(
                                             card_info["name"], card_info["race"],
                                             MINION_TYPE.to_str(card.minion_type)))
                        else:
                            self.assertEqual(MINION_TYPE.NONE, card.minion_type,
                                             "Expected {} to have no race.  Got {}".format(
                                                 card_info["name"], MINION_TYPE.to_str(card.minion_type)))
                    elif card_info["type"] == "Weapon":
                        weapon = card.create_weapon(fake_game.current_player)
                        self.assertEqual(int(card_info["attack"]), weapon.base_attack,
                                         "Expected {} to have attack of {}.  Got {}".format(
                                         card_info["name"], card_info["attack"], weapon.base_attack))
                        self.assertEqual(int(card_info["durability"]), weapon.durability,
                                         "Expected {} to have durability of {}.  Got {}".format(
                                         card_info["name"], card_info["durability"], weapon.durability))

        file.close()
        if len(not_implemented) > 0:
            print("{} of {} cards implemented".format(total_cards - len(not_implemented), total_cards))
            print("Cards not implemented:")
            for card in not_implemented:
                print("  - {}".format(card))
示例#36
0
    def get_card(self, target, player, owner):
        from hearthbreaker.engine import card_lookup, get_cards
        if self.name:
            chosen_card = card_lookup(self.name)
            chosen_card.attach(chosen_card, player)
            return chosen_card

        if self.source == CARD_SOURCE.COLLECTION:
            card_list = get_cards()
        elif self.source == CARD_SOURCE.MY_DECK:
            card_list = filter(lambda c: not c.drawn, player.deck.cards)
        elif self.source == CARD_SOURCE.MY_HAND:
            card_list = player.hand
        elif self.source == CARD_SOURCE.OPPONENT_DECK:
            card_list = filter(lambda c: not c.drawn, player.opponent.deck.cards)
        elif self.source == CARD_SOURCE.OPPONENT_HAND:
            card_list = player.opponent.hand
        elif self.source == CARD_SOURCE.LIST:
            card_list = self.source_list
        elif self.source == CARD_SOURCE.LAST_CARD:
            chosen_card = type(player.game.last_card)()
            chosen_card.attach(chosen_card, player)
            return chosen_card
        elif self.source == CARD_SOURCE.LAST_DRAWN:
            chosen_card = player.hand[-1]
            player.hand.remove(chosen_card)
            chosen_card.unattach()
            return chosen_card
        elif self.source == CARD_SOURCE.MINION:
            chosen_card = self.minion.get_targets(owner, owner)[0].card
            chosen_card.attach(chosen_card, player)
            return chosen_card
        elif self.source == CARD_SOURCE.MY_SECRETS:
            card_list = [secret.card for secret in player.secrets]
        elif self.source == CARD_SOURCE.ENEMY_SECRETS:
            card_list = [secret for secret in player.opponent.secrets]
        else:
            card_list = []
        # TODO Throw an exception in any other case?

        def check_condition(condition):
            return lambda c: condition.evaluate(target, c)

        for condition in self.conditions:
            card_list = filter(check_condition(condition), card_list)

        card_list = [card for card in card_list]
        card_len = len(card_list)
        if card_len == 1:
            chosen_card = card_list[0]
        elif card_len == 0:
            return None
        else:
            chosen_card = player.game.random_choice(card_list)

        chosen_card.attach(chosen_card, player)

        if self.source == CARD_SOURCE.COLLECTION or self.source == CARD_SOURCE.LIST \
                or self.source == CARD_SOURCE.MINION or self.make_copy:
            return chosen_card
        elif self.source == CARD_SOURCE.MY_DECK:
            chosen_card.drawn = True
            player.deck.left -= 1
            return chosen_card
        elif self.source == CARD_SOURCE.OPPONENT_DECK:
            chosen_card.drawn = True
            player.opponent.deck.left -= 1
            return chosen_card
        elif self.source == CARD_SOURCE.MY_HAND:
            player.hand.remove(chosen_card)
            chosen_card.unattach()
            return chosen_card
        elif self.source == CARD_SOURCE.OPPONENT_HAND:
            player.opponent.hand.remove(chosen_card)
            chosen_card.unattach()
            return chosen_card
        elif self.source == CARD_SOURCE.MY_SECRETS:
            if player is player.game.other_player:
                chosen_card.deactivate(player)
            player.secrets.remove(chosen_card)
            return chosen_card
        elif self.source == CARD_SOURCE.ENEMY_SECRETS:
            if player.opponent is player.game.other_player:
                chosen_card.deactivate(player.opponent)
            player.opponent.secrets.remove(chosen_card)
            return chosen_card