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")
    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()
Beispiel #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`
        """
        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()
Beispiel #4
0
def do_stuff():
    _count = 0

    def play_game():
        nonlocal _count
        _count += 1
        new_game = game.copy()
        try:
            winner = new_game.start()
            print("Winner: ", winner)
            print("turns passed : ", new_game._turns_passed)

            print("# " * 27, " GAME OVER ", " #" * 27)
            print(new_game.players[0],
                  "has",
                  new_game.players[0].hero.health,
                  "life points,\t",
                  end='')
            print(new_game.players[1], "has", new_game.players[1].hero.health,
                  "life points")
            print(winner, 'won the game (', winner.agent, ')')
            print("# " * 61, "\n")
            print("AVG tree depth per nr of turns", global_depth)
            print("AVG percent of explored children", global_nodesvisited)

        except Exception as e:
            # print(json.dumps(new_game.__to_json__(), default=lambda o: o.__to_json__(), indent=1))
            # print(new_game._all_cards_played)
            raise e

        del new_game

        if _count % 1000 == 0:
            print("---- game #{} ----".format(_count))

    cards = load_deck("mage3.hsdeck")
    deck1 = Deck(cards, Jaina())
    deck2 = Deck(cards, Malfurion())
    game = Game([deck1, deck2], [MCTSAgent(30), RandomAgent()])
    # game = Game([deck1, deck2], [AggressiveAgent(), RandomAgent()])

    # game = Game([deck1, deck2], [ControllingAgent(), RandomAgent()])
    # game = Game([deck1, deck2], [TalkativeAgent(), RandomAgent()])
    # game = Game([deck1, deck2], [RandomAgent(), RandomAgent()])

    print(timeit.timeit(play_game, 'gc.enable()', number=1))
Beispiel #5
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))
Beispiel #6
0
 def test_deck_shortening(self):
     deck1 = Deck([
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         RagnarosTheFirelord(),
         GoldshireFootman(),
         GoldshireFootman()
     ], Malfurion())
     deck2 = StackedDeck([StonetuskBoar()], CHARACTER_CLASS.HUNTER)
     game = Game([deck1, deck2], [RandomAgent(), RandomAgent()])
     replay = record(game)
     game.start()
     replay.write(StringIO())
Beispiel #7
0
    def test_RandomAgent(self):
        deck1 = Deck([
            GoldshireFootman(),
            GoldshireFootman(),
            MurlocRaider(),
            MurlocRaider(),
            BloodfenRaptor(),
            BloodfenRaptor(),
            FrostwolfGrunt(),
            FrostwolfGrunt(),
            RiverCrocolisk(),
            RiverCrocolisk(),
            IronfurGrizzly(),
            IronfurGrizzly(),
            MagmaRager(),
            MagmaRager(),
            SilverbackPatriarch(),
            SilverbackPatriarch(),
            ChillwindYeti(),
            ChillwindYeti(),
            KeeperOfTheGrove(),
            KeeperOfTheGrove(),
            SenjinShieldmasta(),
            SenjinShieldmasta(),
            BootyBayBodyguard(),
            BootyBayBodyguard(),
            FenCreeper(),
            FenCreeper(),
            BoulderfistOgre(),
            BoulderfistOgre(),
            WarGolem(),
            WarGolem(),
        ], Malfurion())

        deck2 = Deck([
            Shieldbearer(),
            Shieldbearer(),
            FlameImp(),
            FlameImp(),
            YoungPriestess(),
            YoungPriestess(),
            DarkIronDwarf(),
            DarkIronDwarf(),
            DireWolfAlpha(),
            DireWolfAlpha(),
            Voidwalker(),
            Voidwalker(),
            HarvestGolem(),
            HarvestGolem(),
            KnifeJuggler(),
            KnifeJuggler(),
            ShatteredSunCleric(),
            ShatteredSunCleric(),
            ArgentSquire(),
            ArgentSquire(),
            Doomguard(),
            Doomguard(),
            Soulfire(),
            Soulfire(),
            DefenderOfArgus(),
            DefenderOfArgus(),
            AbusiveSergeant(),
            AbusiveSergeant(),
            NerubianEgg(),
            NerubianEgg(),
        ], Guldan())

        game = Game([deck1, deck2], [RandomAgent(), RandomAgent()])
        game.pre_game()
        game.current_player = game.players[1]

        game.play_single_turn()

        self.assertEqual(0, len(game.current_player.minions))

        game.play_single_turn()
        self.assertEqual(2, len(game.current_player.minions))
        self.assertEqual(3, game.current_player.minions[1].health)
        self.assertEqual("Young Priestess",
                         game.current_player.minions[0].card.name)

        game.play_single_turn()
        self.assertEqual(1, len(game.current_player.minions))
        self.assertEqual("Frostwolf Grunt",
                         game.current_player.minions[0].card.name)

        game.play_single_turn()
        self.assertEqual(0, len(game.other_player.minions))
        self.assertEqual(28, game.other_player.hero.health)
        self.assertEqual(3, len(game.current_player.minions))
        self.assertEqual("Dire Wolf Alpha",
                         game.current_player.minions[2].card.name)

        for turn in range(0, 13):
            game.play_single_turn()
            self.assertFalse(game.game_ended)

        game.play_single_turn()

        self.assertEqual(0, game.current_player.hero.health)
        self.assertEqual(21, game.other_player.hero.health)

        self.assertTrue(game.game_ended)
Beispiel #8
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]]