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()
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()
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))
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))
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())
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)
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]]