Example #1
0
    def write_json(self, file):
        """
        Write 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 should be written.  If an IO object, then the IO object should be opened for
                     writing.
        :type file: :class:`str` or :class:`io.TextIOBase`
        """
        was_filename = False
        if 'write' not in dir(file):
            was_filename = True
            writer = open(file, 'w')
        else:
            writer = file

        header_cards = [{"cards": [card.name for card in self.__shorten_deck(deck.cards)],
                         "class": CHARACTER_CLASS.to_str(deck.character_class)} for deck in self.decks]

        header = {
            'decks': header_cards,
            'keep': self.keeps,
            'random': self.random,
        }
        json.dump({'header': header, 'moves': self._moves}, writer, default=lambda o: o.__to_json__(), indent=2,
                  sort_keys=True)
        if was_filename:
            writer.close()
Example #2
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`
        """
        was_filename = False
        if 'read' not in dir(file):
            was_filename = True
            file = open(file, 'r')

        jd = json.load(file)
        self.decks = []
        for deck in jd['header']['decks']:
            deck_size = len(deck['cards'])
            cards = [hearthbreaker.game_objects.card_lookup(deck['cards'][index % deck_size]) for index in range(0, 30)]
            self.decks.append(
                hearthbreaker.game_objects.Deck(cards, CHARACTER_CLASS.from_str(deck['class'])))

        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()
Example #3
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`
        """
        was_filename = False
        if 'read' not in dir(file):
            was_filename = True
            file = open(file, 'r')

        jd = json.load(file)
        self.decks = []
        for deck in jd['header']['decks']:
            deck_size = len(deck['cards'])
            cards = [hearthbreaker.game_objects.card_lookup(deck['cards'][index % deck_size]) for index in range(0, 30)]
            self.decks.append(
                hearthbreaker.game_objects.Deck(cards, CHARACTER_CLASS.from_str(deck['class'])))

        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()
Example #4
0
    def write_json(self, file):
        """
        Write 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 should be written.  If an IO object, then the IO object should be opened for
                     writing.
        :type file: :class:`str` or :class:`io.TextIOBase`
        """
        was_filename = False
        if 'write' not in dir(file):
            was_filename = True
            writer = open(file, 'w')
        else:
            writer = file

        header_cards = [{"cards": [card.name for card in self.__shorten_deck(deck.cards)],
                         "class": CHARACTER_CLASS.to_str(deck.character_class)} for deck in self.decks]

        header = {
            'decks': header_cards,
            'keep': self.keeps,
            'random': self.random,
        }
        json.dump({'header': header, 'moves': self._moves}, writer, default=lambda o: o.__to_json__(), indent=2,
                  sort_keys=True)
        if was_filename:
            writer.close()
Example #5
0
    def draw_hero(self, hero, window, x, y):
        color = curses.color_pair(0)
        if self.targets:
            if hero is self.selected_target:
                color = curses.color_pair(4)
            elif hero in self.targets:
                color = curses.color_pair(3)
        if hero.weapon is not None:
            weapon_power = "({0}) ({1})".format(hero.weapon.base_attack,
                                                hero.weapon.durability)
            window.addstr(y, x, "{0:^20}".format(hero.weapon.card))
            window.addstr(y + 1, x, "{0:^20}".format(weapon_power))

        hero_power = "({0}) ({1}+{4}) -- {2}/{3}".format(
            hero.calculate_attack(), hero.health, hero.player.mana,
            hero.player.max_mana, hero.armor)
        window.addstr(
            y, x + 20,
            "{0:^20}".format(CHARACTER_CLASS.to_str(hero.character_class)),
            color)
        window.addstr(y + 1, x + 20, "{0:^20}".format(hero_power), color)

        window.addstr(y, x + 40, "{0:^20}".format("Hero Power"))
        if hero.power.can_use():
            window.addstr(y + 1, x + 40, "{0:^20}".format("*"))
    def test_all_cards(self):
        fake_game = generate_game_for(StonetuskBoar, StonetuskBoar, DoNothingBot, DoNothingBot)
        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*")
        file = open("cards.csv", "r")
        reader = csv.DictReader(file)
        for row in reader:
            if row['Implemented?'] == "yes":
                card = card_lookup(row["Name"])
                self.assertEqual(int(row["Cost"]), card.mana, row["Name"])
                self.assertEqual(CHARACTER_CLASS.from_str(row["Class"]), card.character_class, row["Name"])
                self.assertEqual(CARD_RARITY.from_str(row["Rarity"]), card.rarity,
                                 "Expected card '{0}' to have rarity {1}".format(row["Name"], row["Rarity"]))
                if row["Type"] == "Minion":
                    minion = card.create_minion(fake_game.current_player)
                    minion.player = fake_game.current_player
                    minion.game = fake_game
                    for effect in split_re.split(row["Text"]):
                        if effect == "Taunt":
                            self.assertTrue(minion.taunt, "Expected {:s} to have taunt".format(row["Name"]))
                        elif effect == "Divine Shield":
                            self.assertTrue(minion.divine_shield,
                                            "Expected {:s} to have divine shield".format(row["Name"]))
                        elif effect == "Stealth":
                            self.assertTrue(minion.stealth, "Expected {:s} to have stealth".format(row["Name"]))
                        elif effect == "Windfury":
                            self.assertTrue(minion.windfury, "Expected {:s} to have windfury".format(row["Name"]))
                        elif effect == "Charge":
                            self.assertTrue(minion.charge, "Expected {:s} to have charge".format(row["Name"]))
                        elif battlecry_re.match(effect):
                            self.assertTrue(minion.battlecry is not None, "Expected {:s} to have a battlecry".format
                                            (row["Name"]))
                        elif deathrattle_re.match(effect):
                            self.assertTrue(minion.deathrattle is not None, "Expected {:s} to have a deathrattle".format
                                            (row["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(row["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.spell_damage,
                                             ("Expected {:s} to have spell damage of" +
                                             " {:s}, but had {:d}").format(row["Name"],
                                                                           spell_damage_re.match(effect).group(1),
                                             minion.spell_damage))
                    minion.silence()
                    self.assertEqual(int(row["Attack"]), minion.calculate_attack(), row["Name"])
                    self.assertEqual(int(row["Health"]), minion.health, row["Name"])
                    self.assertEqual(MINION_TYPE.from_str(row["Race"]), card.minion_type, row["Name"])
                elif row["Type"] == "Weapon":
                    weapon = card.create_weapon(fake_game.current_player)
                    self.assertEqual(int(row["Attack"]), weapon.base_attack, row["Name"])
                    self.assertEqual(int(row["Health"]), weapon.durability, row["Name"])

        file.close()
Example #7
0
        def __init_weapon__(self):
            init_dict = {
                'name': card_def['name'],
                'mana': card_def['mana'],
                'rarity': CARD_RARITY.from_str(card_def['rarity'])
            }
            if 'character_class' in card_def:
                init_dict['character_class'] = CHARACTER_CLASS.from_str(
                    card_def['character_class'])

            if 'battlecry' in card_def:
                init_dict['battlecry'] = Battlecry.from_json(
                    **card_def['battlecry'])

            if 'combo' in card_def:
                init_dict['combo'] = Battlecry.from_json(**card_def['combo'])

            if 'overload' in card_def:
                init_dict['overload'] = card_def['overload']

            if 'buffs' in card_def:
                init_dict['buffs'] = [
                    Buff.from_json(**buff) for buff in card_def['buffs']
                ]
            if 'auras' in card_def:
                init_dict['auras'] = [
                    Aura.from_json(**aura) for aura in card_def['auras']
                ]
            if 'effects' in card_def:
                init_dict['effects'] = [
                    Effect.from_json(**effect)
                    for effect in card_def['effects']
                ]

            WeaponCard.__init__(self, **init_dict)
        def __init__(self):
            init_dict = {
                'name': card_def['name'],
                'mana': card_def['mana'],
                'rarity': CARD_RARITY.from_str(card_def['rarity'])
            }
            if 'character_class' in card_def:
                init_dict['character_class'] = CHARACTER_CLASS.from_str(
                    card_def['character_class'])

            if 'minion_type' in card_def:
                init_dict['minion_type'] = MINION_TYPE.from_str(
                    card_def['minion_type'])

            if 'battlecry' in card_def:
                init_dict['battlecry'] = Battlecry.from_json(
                    **card_def['battlecry'])

            if 'choices' in card_def:
                init_dict['choices'] = [
                    Choice.from_json(**choice)
                    for choice in card_def['choices']
                ]

            if 'combo' in card_def:
                init_dict['combo'] = Battlecry.from_json(**card_def['combo'])

            if 'overload' in card_def:
                init_dict['overload'] = card_def['overload']

            MinionCard.__init__(self, **init_dict)
        def __init__(self):
            init_dict = {
                'name': card_def['name'],
                'mana': card_def['mana'],
                'rarity': CARD_RARITY.from_str(card_def['rarity'])
            }
            if 'character_class' in card_def:
                init_dict['character_class'] = CHARACTER_CLASS.from_str(card_def['character_class'])

            if 'minion_type' in card_def:
                init_dict['minion_type'] = MINION_TYPE.from_str(card_def['minion_type'])

            if 'battlecry' in card_def:
                init_dict['battlecry'] = Battlecry.from_json(**card_def['battlecry'])

            if 'choices' in card_def:
                init_dict['choices'] = [Choice.from_json(**choice) for choice in card_def['choices']]

            if 'combo' in card_def:
                init_dict['combo'] = Battlecry.from_json(**card_def['combo'])

            if 'overload' in card_def:
                init_dict['overload'] = card_def['overload']

            MinionCard.__init__(self, **init_dict)
        def __init_weapon__(self):
            init_dict = {
                'name': card_def['name'],
                'mana': card_def['mana'],
                'rarity': CARD_RARITY.from_str(card_def['rarity'])
            }
            if 'character_class' in card_def:
                init_dict['character_class'] = CHARACTER_CLASS.from_str(card_def['character_class'])

            if 'battlecry' in card_def:
                init_dict['battlecry'] = Battlecry.from_json(**card_def['battlecry'])

            if 'combo' in card_def:
                init_dict['combo'] = Battlecry.from_json(**card_def['combo'])

            if 'overload' in card_def:
                init_dict['overload'] = card_def['overload']

            if 'buffs' in card_def:
                init_dict['buffs'] = [Buff.from_json(**buff) for buff in card_def['buffs']]
            if 'auras' in card_def:
                init_dict['auras'] = [Aura.from_json(**aura) for aura in card_def['auras']]
            if 'effects' in card_def:
                init_dict['effects'] = [Effect.from_json(**effect) for effect in card_def['effects']]

            WeaponCard.__init__(self, **init_dict)
        def __init__(self):
            init_dict = {
                'name': card_def['name'],
                'mana': card_def['mana'],
                'rarity': CARD_RARITY.from_str(card_def['rarity'])
            }
            if 'character_class' in card_def:
                init_dict['character_class'] = CHARACTER_CLASS.from_str(card_def['character_class'])

            if 'minion_type' in card_def:
                init_dict['minion_type'] = MINION_TYPE.from_str(card_def['minion_type'])

            if 'battlecry' in card_def:
                init_dict['battlecry'] = tuple(Battlecry.from_json(**battlecry) for battlecry in card_def['battlecry'])

            if 'choices' in card_def:
                init_dict['choices'] = [Choice.from_json(**choice) for choice in card_def['choices']]

            if 'combo' in card_def:
                init_dict['combo'] = Battlecry.from_json(**card_def['combo'])

            if 'overload' in card_def:
                init_dict['overload'] = card_def['overload']

            if 'buffs' in card_def:
                init_dict['buffs'] = [Buff.from_json(**buff) for buff in card_def['buffs']]
            if 'auras' in card_def:
                init_dict['auras'] = [Aura.from_json(**aura) for aura in card_def['auras']]
            if 'effects' in card_def:
                init_dict['effects'] = [Effect.from_json(**effect) for effect in card_def['effects']]

            MinionCard.__init__(self, **init_dict)
Example #12
0
        def __init__(self):
            init_dict = {
                'name': card_def['name'],
                'mana': card_def['mana'],
                'rarity': CARD_RARITY.from_str(card_def['rarity'])
            }
            if 'character_class' in card_def:
                init_dict['character_class'] = CHARACTER_CLASS.from_str(
                    card_def['character_class'])

            if 'minion_type' in card_def:
                init_dict['minion_type'] = MINION_TYPE.from_str(
                    card_def['minion_type'])

            if 'battlecry' in card_def:
                init_dict['battlecry'] = tuple(
                    Battlecry.from_json(**battlecry)
                    for battlecry in card_def['battlecry'])

            if 'choices' in card_def:
                init_dict['choices'] = [
                    Choice.from_json(**choice)
                    for choice in card_def['choices']
                ]

            if 'combo' in card_def:
                init_dict['combo'] = Battlecry.from_json(**card_def['combo'])

            if 'overload' in card_def:
                init_dict['overload'] = card_def['overload']

            if 'buffs' in card_def:
                init_dict['buffs'] = [
                    Buff.from_json(**buff) for buff in card_def['buffs']
                ]
            if 'auras' in card_def:
                init_dict['auras'] = [
                    Aura.from_json(**aura) for aura in card_def['auras']
                ]
            if 'effects' in card_def:
                init_dict['effects'] = [
                    Effect.from_json(**effect)
                    for effect in card_def['effects']
                ]

            MinionCard.__init__(self, **init_dict)
        def __init_weapon__(self):
            init_dict = {
                'name': card_def['name'],
                'mana': card_def['mana'],
                'rarity': CARD_RARITY.from_str(card_def['rarity'])
            }
            if 'character_class' in card_def:
                init_dict['character_class'] = CHARACTER_CLASS.from_str(card_def['character_class'])

            if 'battlecry' in card_def:
                init_dict['battlecry'] = Battlecry.from_json(**card_def['battlecry'])

            if 'combo' in card_def:
                init_dict['combo'] = Battlecry.from_json(**card_def['combo'])

            if 'overload' in card_def:
                init_dict['overload'] = card_def['overload']

            WeaponCard.__init__(self, **init_dict)
Example #14
0
    def draw_hero(self, player, window, x, y):
        color = curses.color_pair(0)
        if self.targets:
            if player.hero is self.selected_target:
                color = curses.color_pair(4)
            elif player.hero in self.targets:
                color = curses.color_pair(3)
        if player.weapon is not None:
            weapon_power = "({0}) ({1})".format(player.weapon.base_attack, player.weapon.durability)
            window.addstr(y, x, "{0:^20}".format(player.weapon.card.name))
            window.addstr(y + 1, x, "{0:^20}".format(weapon_power))

        hero_power = "({0}) ({1}+{4}) -- {2}/{3}".format(player.hero.calculate_attack(), player.hero.health,
                                                         player.mana, player.max_mana, player.hero.armor)
        window.addstr(y, x + 20, "{0:^20}".format(CHARACTER_CLASS.to_str(player.hero.character_class)), color)
        window.addstr(y + 1, x + 20, "{0:^20}".format(hero_power), color)

        window.addstr(y, x + 40, "{0:^20}".format("Hero Power"))
        if player.hero.power.can_use():
            window.addstr(y + 1, x + 40, "{0:^20}".format("*"))
Example #15
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))
Example #16
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))
Example #17
0
    def test_all_cards(self):
        fake_game = generate_game_for(StonetuskBoar, StonetuskBoar,
                                      DoNothingBot, DoNothingBot)
        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*")
        file = open("cards.csv", "r")
        reader = csv.DictReader(file)
        implemented_count = 0
        total_count = 0
        for row in reader:
            total_count += 1
            if row['Implemented?'] == "yes":
                implemented_count += 1
                card = card_lookup(row["Name"])
                self.assertEqual(int(row["Cost"]), card.mana, row["Name"])
                self.assertEqual(CHARACTER_CLASS.from_str(row["Class"]),
                                 card.character_class, row["Name"])
                self.assertEqual(
                    CARD_RARITY.from_str(row["Rarity"]), card.rarity,
                    "Expected card '{0}' to have rarity {1}".format(
                        row["Name"], row["Rarity"]))
                if row["Type"] == "Minion":
                    minion = card.create_minion(fake_game.current_player)
                    minion.player = fake_game.current_player
                    for effect in split_re.split(row["Text"]):
                        if effect == "Taunt":
                            self.assertTrue(
                                minion.taunt,
                                "Expected {:s} to have taunt".format(
                                    row["Name"]))
                        elif effect == "Divine Shield":
                            self.assertTrue(
                                minion.divine_shield,
                                "Expected {:s} to have divine shield".format(
                                    row["Name"]))
                        elif effect == "Stealth":
                            self.assertTrue(
                                minion.stealth,
                                "Expected {:s} to have stealth".format(
                                    row["Name"]))
                        elif effect == "Windfury":
                            self.assertTrue(
                                minion.windfury,
                                "Expected {:s} to have windfury".format(
                                    row["Name"]))
                        elif effect == "Charge":
                            self.assertTrue(
                                minion.charge,
                                "Expected {:s} to have charge".format(
                                    row["Name"]))
                        elif battlecry_re.match(effect):
                            self.assertTrue(
                                minion.battlecry is not None,
                                "Expected {:s} to have a battlecry".format(
                                    row["Name"]))
                        elif deathrattle_re.match(effect):
                            self.assertTrue(
                                minion.deathrattle is not None,
                                "Expected {:s} to have a deathrattle".format(
                                    row["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(
                                     row["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.spell_damage,
                                ("Expected {:s} to have spell damage of" +
                                 " {:s}, but had {:d}").format(
                                     row["Name"],
                                     spell_damage_re.match(effect).group(1),
                                     minion.spell_damage))
                    minion.silence()
                    self.assertEqual(int(row["Attack"]),
                                     minion.calculate_attack(), row["Name"])
                    self.assertEqual(int(row["Health"]), minion.health,
                                     row["Name"])
                    self.assertEqual(MINION_TYPE.from_str(row["Race"]),
                                     card.minion_type, row["Name"])
                elif row["Type"] == "Weapon":
                    weapon = card.create_weapon(fake_game.current_player)
                    self.assertEqual(int(row["Attack"]), weapon.base_attack,
                                     row["Name"])
                    self.assertEqual(int(row["Health"]), weapon.durability,
                                     row["Name"])

        file.close()
        print("Implemented {0} cards, with {1} cards left".format(
            implemented_count, total_count - implemented_count))