Exemple #1
0
    def __from_json__(cls, pd, game, agent):
        deck = Deck.__from__to_json__(pd["deck"],
                                      hero_from_name(pd["hero"]["name"]))
        player = Player("whatever", deck, agent, game)
        hero = Hero.__from_json__(pd["hero"], player)
        player.hero = hero
        hero.player = player
        if hero.weapon:
            hero.weapon.player = player
        player.mana = pd["mana"]
        player.max_mana = pd["max_mana"]
        player.name = pd['name']
        player.hand = []
        for card_def in pd['hand']:
            card = card_lookup(card_def['name'])
            card.__from_json__(card, **card_def)
            card.attach(card, player)
            player.hand.append(card)
        player.graveyard = set()
        for card_name in pd["graveyard"]:
            player.graveyard.add(card_name)

        player.secrets = []
        for secret_name in pd["secrets"]:
            secret = card_lookup(secret_name)
            secret.player = player
            player.secrets.append(secret)
        i = 0
        player.minions = []
        for md in pd["minions"]:
            minion = Minion.__from_json__(md, player, game)
            minion.index = i
            player.minions.append(minion)
            i += 1
        return player
Exemple #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`
        """
        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()
Exemple #3
0
    def __from_json__(cls, pd, game, agent):
        deck = Deck.__from__to_json__(pd["deck"], hero_from_name(pd["hero"]["name"]))
        player = Player("whatever", deck, agent, game)
        hero = Hero.__from_json__(pd["hero"], player)
        player.hero = hero
        hero.player = player
        if pd["weapon"]:
            player.weapon = Weapon.__from_json__(pd["weapon"], player)
            player.weapon.player = player
        player.mana = pd["mana"]
        player.max_mana = pd["max_mana"]
        player.upcoming_overload = pd["upcoming_overload"]
        player.current_overload = pd["current_overload"]
        player.name = pd["name"]
        player.hand = []
        for card_def in pd["hand"]:
            card = card_lookup(card_def["name"])
            card.__from_json__(card, **card_def)
            card.attach(card, player)
            player.hand.append(card)
        player.graveyard = pd["graveyard"]

        player.secrets = []
        for secret_name in pd["secrets"]:
            secret = card_lookup(secret_name)
            secret.player = player
            player.secrets.append(secret)
        i = 0
        player.minions = []
        for md in pd["minions"]:
            minion = Minion.__from_json__(md, player, game)
            minion.index = i
            player.minions.append(minion)
            i += 1
        return player
Exemple #4
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()
Exemple #5
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]]
Exemple #6
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]]