def PresetGame(pp, testNr=1): from fireplace import cards cards.db.initialize() for test in range(testNr): class1 = pp.class1 class2 = pp.class2 Dummy1 = DummyAgent("Dummy1", DummyAgent.DummyAI, myClass=class1) Dummy2 = DummyAgent("Dummy2", DummyAgent.DummyAI, myClass=class2) deck1 = random_draft(Dummy1.myClass, []) #random deck wrt its class deck2 = random_draft(Dummy2.myClass, []) #random deck wrt its class player1 = Player(Dummy1.name, deck1, Dummy1.myClass.default_hero) player2 = Player(Dummy2.name, deck2, Dummy2.myClass.default_hero) game = Game(players=(player1, player2)) # Configurations player1._start_hand_size = 3 ## this line must be before 'start()' player2._start_hand_size = 3 ## player1.max_mana = 9 ## this line must be before 'start()' player2.max_mana = 9 ## game.start() player1.hero.max_health = 30 ## this line must be below 'start()' player2.hero.max_health = 30 ## cards_to_mulligan = [] player1.choice.choose(*cards_to_mulligan) player2.choice.choose(*cards_to_mulligan) player1._targetedaction_log = [] player2._targetedaction_log = [] pp(game.current_player).execute(test) pass
def main(): deck1 = randomDraft(hero=fireplace.heroes.MAGE) deck2 = randomDraft(hero=fireplace.heroes.WARRIOR) player1 = Player(name="Player1") player1.prepareDeck(deck1, fireplace.heroes.MAGE) player2 = Player(name="Player2") player2.prepareDeck(deck2, fireplace.heroes.WARRIOR) game = Game(players=(player1, player2)) game.start() while True: heropower = game.currentPlayer.hero.power # always play the hero power, just for kicks if heropower.isPlayable(): if heropower.hasTarget(): heropower.play(target=random.choice(heropower.targets)) else: heropower.play() # iterate over our hand and play whatever is playable for card in game.currentPlayer.hand: if card.isPlayable(): if card.hasTarget(): card.play(target=random.choice(card.targets)) else: card.play() else: print("Not playing", card) # Randomly attack with whatever can attack for character in game.currentPlayer.characters: if character.canAttack(): character.attack(random.choice(character.targets)) game.endTurn()
def main(): deck1 = random_draft(hero=MAGE) deck2 = random_draft(hero=WARRIOR) player1 = Player(name="Player1") player1.prepare_deck(deck1, MAGE) player2 = Player(name="Player2") player2.prepare_deck(deck2, WARRIOR) game = Game(players=(player1, player2)) game.start() while True: heropower = game.current_player.hero.power # always play the hero power, just for kicks if heropower.is_playable(): if heropower.has_target(): heropower.play(target=random.choice(heropower.targets)) else: heropower.play() # iterate over our hand and play whatever is playable for card in game.current_player.hand: if card.is_playable(): if card.has_target(): card.play(target=random.choice(card.targets)) else: card.play() else: print("Not playing", card) # Randomly attack with whatever can attack for character in game.current_player.characters: if character.can_attack(): character.attack(random.choice(character.targets)) game.end_turn()
def getInitGame(self): """ Returns: startBoard: a representation of the board (ideally this is the form that will be the input to your neural network) """ if self.isolate: self.isolateSet() cards.db.initialize() if self.is_basic: #create quick simple game with open('notbasic.data', 'rb') as f: extra_set = pickle.load(f) p1 = 6 #priest p2 = 7 #rogue deck1 = random_draft(CardClass(p1), exclude=extra_set) deck2 = random_draft(CardClass(p2), exclude=extra_set) else: p1 = random.randint(1, 9) p2 = random.randint(1, 9) deck1 = random_draft(CardClass(p1)) deck2 = random_draft(CardClass(p2)) self.players[0] = Player("Player1", deck1, CardClass(p1).default_hero) self.players[1] = Player("Player2", deck2, CardClass(p2).default_hero) game = Game(players=self.players) game.start() # Skip mulligan for now for player in game.players: cards_to_mulligan = random.sample(player.choice.cards, 0) player.choice.choose(*cards_to_mulligan) game.player_to_start = game.current_player self.game = game return game
def setup_game(): """ initializes a game between two players Returns: game: A game entity representing the start of the game after the mulligan phase """ #choose classes (priest, rogue, shaman, warlock) p1 = random.randint(6, 9) p2 = random.randint(6, 9) #initialize players and randomly draft decks #pdb.set_trace() deck1 = random_draft(CardClass(p1)) deck2 = random_draft(CardClass(p2)) player1 = Player("Player1", deck1, CardClass(p1).default_hero) player2 = Player("Player2", deck2, CardClass(p2).default_hero) #begin the game game = Game(players=(player1, player2)) game.start() #Skip mulligan for now for player in game.players: cards_to_mulligan = random.sample(player.choice.cards, 0) player.choice.choose(*cards_to_mulligan) return game
def initGame(self): cards.db.initialize() if self.is_basic: #create quick simple game with open('notbasic.data', 'rb') as f: extra_set = pickle.load(f) p1 = 6 #priest p2 = 7 #rogue deck1 = random_draft(CardClass(p1), exclude=extra_set) deck2 = random_draft(CardClass(p2), exclude=extra_set) else: p1 = random.randint(1, 9) p2 = random.randint(1, 9) deck1 = random_draft(CardClass(p1)) deck2 = random_draft(CardClass(p2)) Board.players[0] = Player("Player1", deck1, CardClass(p1).default_hero) Board.players[1] = Player("Player2", deck2, CardClass(p2).default_hero) game = Game(players=self.players) game.start() # Skip mulligan for now for player in game.players: cards_to_mulligan = random.sample(player.choice.cards, 0) player.choice.choose(*cards_to_mulligan) # self.start_player = game.current_player game.player_to_start = game.current_player Board.game = game return game
def play_full_game(): deck1 = random_draft(hero=MAGE) deck2 = random_draft(hero=WARRIOR) player1 = Player("Player1", deck1, MAGE) player2 = Player("Player2", deck2, WARRIOR) game = Game(players=(player1, player2)) game.start() for player in game.players: # print("Can mulligan %r" % (player.choice.cards)) mull_count = random.randint(0, len(player.choice.cards)) cards_to_mulligan = random.sample(player.choice.cards, mull_count) player.choice.choose(*cards_to_mulligan) try: while True: player = game.current_player heropower = player.hero.power if heropower.is_usable() and random.random() < 0.1: if heropower.has_target(): heropower.use(target=random.choice(heropower.targets)) else: heropower.use() continue # iterate over our hand and play whatever is playable for card in player.hand: if card.is_playable() and random.random() < 0.5: target = None if card.choose_cards: card = random.choice(card.choose_cards) if card.has_target(): target = random.choice(card.targets) # print("Playing %r on %r" % (card, target)) card.play(target=target) if player.choice: choice = random.choice(player.choice.cards) # print("Choosing card %r" % (choice)) player.choice.choose(choice) continue # Randomly attack with whatever can attack for character in player.characters: if character.can_attack(): character.attack(random.choice(character.targets)) continue game.end_turn() except GameOver: return game # print("Game completed normally in " + str(game.turn) + " turns.") return game
def getInitGame(self): """ Returns: startBoard: a representation of the board (ideally this is the form that will be the input to your neural network) """ if self.isolate: self.isolateSet() cards.db.initialize() if self.is_basic: #create quick simple game # with open('notbasic.data', 'rb') as f: # extra_set = pickle.load(f) extra_set = cards.filter(card_set=[ CardSet.EXPERT1, CardSet.HOF, CardSet.NAXX, CardSet.GVG, CardSet.BRM, CardSet.TGT, CardSet.LOE, CardSet.OG, CardSet. KARA, CardSet.GANGS, CardSet.UNGORO, CardSet.ICECROWN, CardSet. LOOTAPALOOZA, CardSet.GILNEAS, CardSet.BOOMSDAY, CardSet.TROLL ]) # LOOTAPALOOZA = Kobolds and Catacombs # GILNEAS = Witchwood # TROLL = Rasthakan's Rumble # p1 = 6 #priest p1 = 7 #rogue p2 = 7 #rogue # p1 = 4 # mage # p2 = 4 # mage # deck1 = random_draft(CardClass(p1), exclude=extra_set) # deck2 = random_draft(CardClass(p2), exclude=extra_set) deck1 = self.roguebasic_draft( ) # use same shuffled rogue AI basic decks for now deck2 = self.roguebasic_draft() else: p1 = random.randint(1, 9) p2 = random.randint(1, 9) deck1 = random_draft(CardClass(p1)) deck2 = random_draft(CardClass(p2)) self.players[0] = Player("Player1", deck1, CardClass(p1).default_hero) self.players[1] = Player("Player2", deck2, CardClass(p2).default_hero) game = Game(players=self.players) game.start() # Skip mulligan for now (only mulligan expensive cards) for player in game.players: # if player.name == 'Player1': # cards_to_mulligan = [c for c in player.choice.cards if c.cost > 3] # else: cards_to_mulligan = random.sample(player.choice.cards, 0) player.choice.choose(*cards_to_mulligan) # track played card list self.players[0].playedcards = [] self.players[1].playedcards = [] #game.player_to_start = game.current_player # obsolete? self.game = game return game
def play_full_game(): deck1 = random_draft(hero=MAGE) deck2 = random_draft(hero=WARRIOR) player1 = Player(name="Player1") player1.prepare_deck(deck1, MAGE) player2 = Player(name="Player2") player2.prepare_deck(deck2, WARRIOR) game = Game(players=(player1, player2)) game.start() for player in game.players: print("Can mulligan %r" % (player.choice.cards)) mull_count = random.randint(0, len(player.choice.cards)) cards_to_mulligan = random.sample(player.choice.cards, mull_count) player.choice.choose(*cards_to_mulligan) while True: player = game.current_player heropower = player.hero.power if heropower.is_usable() and percent_chance(10): if heropower.has_target(): heropower.use(target=random.choice(heropower.targets)) else: heropower.use() continue # iterate over our hand and play whatever is playable for card in player.hand: if card.is_playable() and percent_chance(50): target = None if card.choose_cards: card = random.choice(card.choose_cards) if card.has_target(): target = random.choice(card.targets) print("Playing %r on %r" % (card, target)) card.play(target=target) continue # Randomly attack with whatever can attack for character in player.characters: if character.can_attack(): character.attack(random.choice(character.targets)) continue if player.choice: choice = random.choice(player.choice.cards) print("Choosing card %r" % (choice)) player.choice.choose(choice) continue game.end_turn()
def collect_game_data(self): win_num = 0 game_data = [] start_time = time.time() for game_round in range(self.model_config.round_num): # initialize game deck1 = [ c[1] for c in self.game_config.card_config.cards_list[1:] * 4 ] player1 = HearthStoneGod('Player1', deck1, CardClass.MAGE.default_hero, self.game_config, game_model=self.player1_model, mode=self.player1_mode, device=self.device) deck2 = [ c[1] for c in self.game_config.card_config.cards_list[1:] * 4 ] player2 = HearthStoneGod('Player2', deck2, CardClass.MAGE.default_hero, self.game_config, game_model=self.player2_model, mode=self.player2_mode, device=self.device) game = Game(players=[player1, player2]) game.start() # play game # mulligan player1.mulligan(skip=True) player2.mulligan(skip=True) try: while True: player = game.current_player player.play_turn(game) except GameOver: if player2.hero.dead: win_num += 1 game_data.append((player1.replay, player1.hero.health)) else: game_data.append((player1.replay, -player2.hero.health)) end_time = time.time() win_rate = win_num / self.model_config.round_num return game_data, win_rate
def test_full_game(): global __last_turn__ __last_turn__ = [None, None, None] try: json = [] deck1 = get_face_hunter_deck() deck2 = random_draft(hero=WARRIOR) player1 = Player("Player1", deck1, HUNTER) player2 = Player("Player2", deck2, WARRIOR) game = Game(players=(player1, player2)) game.start() play_full_game(json, game, player1, player2) except GameOver: #LAST TURN if (__last_turn__[1] != None): hashmap = get_hash_map(game, player1, player2, __last_turn__[2], __last_turn__[0].entity_id, __last_turn__[0].entity_id, __last_turn__[1].entity_id, __last_turn__[0]) json.append(hashmap) else: hashmap = get_hash_map(game, player1, player2, __last_turn__[2], __last_turn__[0].entity_id, __last_turn__[0].entity_id, None, __last_turn__[0]) json.append(hashmap) #RESULT if (game.current_player.hero.health < 1): hashmap = get_hash_map(game, player1, player2, 21, game.current_player.hero.entity_id, None, None, None) json.append(hashmap) else: hashmap = get_hash_map(game, player1, player2, 20, game.current_player.hero.entity_id, None, None, None) json.append(hashmap) f = open(REPLAY_JSON_PATH, 'w') write_line_to_file(f, json.__str__()) my_datetime = datetime.now() path_to_zip = "C:\\Users\\Lubko\\OneDrive\\Documents\\matfyz\\bakalarka\\Hearthstone-Deck-Tracker-master\\Hearthstone Deck Tracker\\obj\\Debug\\Replay\\Replays\\" + my_datetime.strftime( "%d_%B_%Y__%H_%M.hdtreplay") my_zip_file = zipfile.ZipFile(path_to_zip, mode='w') my_zip_file.write(REPLAY_JSON_PATH) f.close() my_zip_file.close()
def setup_game() -> (Game, (Agent, Agent)): agent1 = MonteCarloAgent(CardClass.WARRIOR) agent2 = GameStateAgent(CardClass.PALADIN) print(agent1.player, " vs ", agent2.player) game = Game(players=(agent1.player, agent2.player)) agent1.game = game agent2.game = game game.start() return game, (agent1, agent2)
class Room(): def __init__(self): self.id = -1 self.players = [] self.game = None def add_player(self, player): if len(self.players) >= 2: raise RoomFull self.players.append(player) if len(self.players) == 2: self.game = Game(players=self.players) self.game.start()
def play_game(hero1, hero2): deck1 = decks[hero1] player1 = Player(name="Player1") player1.prepare_deck(deck1, hero1) deck2 = decks[hero2] player2 = Player(name="Player2") player2.prepare_deck(deck2, hero2) game = Game(players=(player1, player2)) game.start() player1.choice.choose(*[]) player2.choice.choose(*[]) while game.state != State.COMPLETE: try: heropower = game.current_player.hero.power if heropower.is_usable(): if heropower.has_target(): heropower.use(target=random.choice(heropower.targets)) else: heropower.use() for card in game.current_player.hand: if card.is_playable(): target = None if card.choose_cards: card = random.choice(card.choose_cards) if card.has_target(): target = random.choice(card.targets) card.play(target=target) for character in game.current_player.characters: if character.can_attack(): character.attack(random.choice(character.targets)) game.end_turn() except GameOver: pass if player1.playstate == PlayState.TIED: return None if player1.playstate == PlayState.WON: return player1 return player2
def setup_basic_game(): p1 = 6 #priest p2 = 7 #rogue deck1 = random_draft(CardClass(p1)) deck2 = random_draft(CardClass(p2)) player1 = Player("Player1", deck1, CardClass(p1).default_hero) player2 = Player("Player2", deck2, CardClass(p2).default_hero) game = Game(players=(player1, player2)) game.start() #Skip mulligan for player in game.players: cards_to_mulligan = random.sample(player.choice.cards, 0) player.choice.choose(*cards_to_mulligan) return game
def play_full_game(hero1, deck1, hero2, deck2): log.info('{} vs {}'.format(hero1, hero2)) player1 = Player("Player1", deck1, hero1) player2 = Player("Player2", deck2, hero2) game = Game(players=(player1, player2)) game.start() # Random mulligan for now for player in game.players: if player.choice: player.choice.choose() print(repr(game)) return begin_time = datetime.datetime.utcnow() N = 1000 for i in range(N): game2 = copy.deepcopy(game) end_time = datetime.datetime.utcnow() print((end_time - begin_time)) return try: while True: state = GameState(game) #if state.winner() != None: #print("Winner: " + str(state.winner())) #break mcts = MonteCarlo(state, 1) play = mcts.get_play() log.info("GOT A MOVE!!!! %r", play) break fireplace.logging.log.setLevel(logging.DEBUG) play.play(game) fireplace.logging.log.setLevel(logging.WARN) except GameOver: state = GameState(game) if state.winner() != None: log.info("Winner: " + str(state.winner()))
def main(): deck1 = random_draft(hero=MAGE) deck2 = random_draft(hero=WARRIOR) player1 = Player(name="Player1") player1.prepare_deck(deck1, MAGE) player2 = Player(name="Player2") player2.prepare_deck(deck2, WARRIOR) game = Game(players=(player1, player2)) game.start() for player in game.players: print("Can mulligan %r" % (player.choice.cards)) mull_count = random.randint(0, len(player.choice.cards)) cards_to_mulligan = random.sample(player.choice.cards, mull_count) player.choice.choose(*cards_to_mulligan) while True: heropower = game.current_player.hero.power # always play the hero power, just for kicks if heropower.is_usable(): if heropower.has_target(): heropower.use(target=random.choice(heropower.targets)) else: heropower.use() # iterate over our hand and play whatever is playable for card in game.current_player.hand: if card.is_playable(): target = None if card.choose_cards: card = random.choice(card.choose_cards) if card.has_target(): target = random.choice(card.targets) print("Playing %r on %r" % (card, target)) card.play(target=target) else: print("Not playing", card) # Randomly attack with whatever can attack for character in game.current_player.characters: if character.can_attack(): character.attack(random.choice(character.targets)) game.end_turn()
def main(): deck1 = random_draft(hero=MAGE) deck2 = random_draft(hero=WARRIOR) player1 = Player(name="Player1") player1.prepare_deck(deck1, MAGE) player2 = Player(name="Player2") player2.prepare_deck(deck2, WARRIOR) game = Game(players=(player1, player2)) game.start() for player in game.players: print("Can mulligan %r" % (player.choice.cards)) mull_count = random.randint(0, len(player.choice.cards)) cards_to_mulligan = random.sample(player.choice.cards, mull_count) player.choice.choose(*cards_to_mulligan) while True: heropower = game.current_player.hero.power # always play the hero power, just for kicks if heropower.is_usable(): if heropower.has_target(): heropower.use(target=random.choice(heropower.targets)) else: heropower.use() # iterate over our hand and play whatever is playable for card in game.current_player.hand: if card.is_playable(): target = None choice = None if card.has_target(): target = random.choice(card.targets) if card.data.choose_cards: choice = random.choice(card.data.choose_cards) card.play(target=target, choose=choice) else: print("Not playing", card) # Randomly attack with whatever can attack for character in game.current_player.characters: if character.can_attack(): character.attack(random.choice(character.targets)) game.end_turn()
def play_game(hero1, hero2): open(log_file, 'w').close() deck1 = random_draft(hero=hero1) deck1[0] = "EX1_160a" player1 = Player(name="Player1") player1.prepare_deck(deck1, hero1) deck2 = random_draft(hero=hero2) deck2[0] = "EX1_160a" player2 = Player(name="Player2") player2.prepare_deck(deck2, hero2) game = Game(players=(player1, player2)) game.start() player1.choice.choose(*[]) player2.choice.choose(*[]) while game.state != State.COMPLETE: try: heropower = game.current_player.hero.power if heropower.is_usable(): if heropower.has_target(): heropower.use(target=random.choice(heropower.targets)) else: heropower.use() for card in game.current_player.hand: if card.is_playable(): target = None if card.choose_cards: card = random.choice(card.choose_cards) if card.has_target(): target = random.choice(card.targets) card.play(target=target) for character in game.current_player.characters: if character.can_attack(): character.attack(random.choice(character.targets)) game.end_turn() except GameOver: pass
def setup_game(): from fireplace.game import Game from fireplace.player import Player fireplace.cards.filter(name="Garrosh") player1 = Player("OddWarrior", warrior_deck, CardClass.WARRIOR.default_hero) player2 = Player("MurlocPaladin", paladin_deck, CardClass.PALADIN.default_hero) game = Game(players=(player1, player2)) game.start() for player in game.players: mull_count = 0 cards_to_mulligan = [] player.choice.choose(*cards_to_mulligan) game.begin_turn(player) return game
def initGame(self): self.init_envi() if self.is_basic: #create quick simple game p1 = 6 #priest p2 = 7 #rogue else: p1 = random.randint(1, 9) p2 = random.randint(1, 9) deck1 = random_draft(CardClass(p1)) deck2 = random_draft(CardClass(p2)) self.players[0] = Player("Player1", deck1, CardClass(p1).default_hero) self.players[1] = Player("Player2", deck2, CardClass(p2).default_hero) game = Game(players=self.players) game.start() #Skip mulligan for now for player in self.game.players: cards_to_mulligan = random.sample(player.choice.cards, 0) player.choice.choose(*cards_to_mulligan) return game
def setup_game(deck, player_name, opponents_deck): from fireplace.game import Game from fireplace.player import Player #Some cards from these decks aren't implemented which means that they won't have an effect, #if they are a minion then it will have it's stats but not the battlecry effect, spell will just do nothing #either implement it or talk about it deck1 = deck deck2 = opponents_deck #global so it can carry over to other functions global name name = player_name #It seems that player classes influence the deck win rate, Hunters win more than Warlocks due to the dumb AI player1 = Player(name, deck1, CardClass.WARRIOR.default_hero) player2 = Player("Oppenent", deck2, CardClass.MAGE.default_hero) game = Game(players=(player1, player2)) game.start() return game
def test_full_game(): global __last_turn__ __last_turn__ = [None,None,None] try: json = [] deck1 = get_face_hunter_deck() deck2 = random_draft(hero=WARRIOR) player1 = Player("Player1", deck1, HUNTER) player2 = Player("Player2", deck2, WARRIOR) game = Game(players=(player1, player2)) game.start() play_full_game(json, game, player1, player2) except GameOver: #LAST TURN if (__last_turn__[1] != None): hashmap = get_hash_map(game, player1, player2, __last_turn__[2], __last_turn__[0].entity_id,__last_turn__[0].entity_id, __last_turn__[1].entity_id, __last_turn__[0]) json.append(hashmap) else: hashmap = get_hash_map(game, player1, player2, __last_turn__[2], __last_turn__[0].entity_id,__last_turn__[0].entity_id, None, __last_turn__[0]) json.append(hashmap) #RESULT if (game.current_player.hero.health < 1): hashmap = get_hash_map(game, player1, player2, 21, game.current_player.hero.entity_id, None, None, None) json.append(hashmap) else: hashmap = get_hash_map(game, player1, player2, 20, game.current_player.hero.entity_id, None, None, None) json.append(hashmap) f = open(REPLAY_JSON_PATH, 'w') write_line_to_file(f,json.__str__()) my_datetime = datetime.now() path_to_zip = "C:\\Users\\Lubko\\OneDrive\\Documents\\matfyz\\bakalarka\\Hearthstone-Deck-Tracker-master\\Hearthstone Deck Tracker\\obj\\Debug\\Replay\\Replays\\" + my_datetime.strftime("%d_%B_%Y__%H_%M.hdtreplay") my_zip_file = zipfile.ZipFile(path_to_zip, mode='w') my_zip_file.write(REPLAY_JSON_PATH) f.close() my_zip_file.close()
def setup_game() -> ".game.Game": from fireplace.game import Game from simulator.player import Player # card_indices = [27, 48, 68, 159, 169, 180, 307, 386, 546, 588] # randomly chosen 10 integers from [1,698] # card_indices = [random.randrange(1, 25) for i in range(10)] deck1 = shuffled_const_draft([]) # choose cards for Player1 deck2 = shuffled_const_draft([]) # choose cards for Player2 printer.print_deck_content("Player1", deck1) printer.print_deck_content("Player2", deck2) player1 = Player("Player1", deck1, CardClass.MAGE.default_hero) player2 = Player("Player2", deck2, CardClass.HUNTER.default_hero) game = Game(players=(player1, player2)) game.start() player1.hero.set_current_health(20) player2.hero.set_current_health(20) return game
class HearthState: """ A state of the game, i.e. the game board. """ def __init__(self): self.playerJustMoved = 2 # At the root pretend the player just moved is p2 - p1 has the first move random.seed(1857) # The idea of adjacent cards it to ignore minion placement if none of these cards can be found, since it doesn't # matter. #adjacent_cards = ["Dire Wolf Alpha", "Ancient Mage", "Defender of Argus", "Sunfury Protector", # "Flametongue Totem", "Explosive Shot", "Cone of Cold", "Betrayal", "Void Terror", # "Unstable Portal", "Wee Spellstopper", "Piloted Shredder", "Piloted Sky Golem", # "Recombobulator", "Foe Reaper 4000", "Nefarian"] #self.adjacent_cards = adjacent_cards self.player1 = None self.hero1 = MAGE self.deck1 = [] self.player2 = None self.hero2 = None self.deck2 = [] self.game = None # Simple Arcane Missiles lethal test #self.deck1 = ["EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", # "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", # "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", # "EX1_277", "EX1_277", "EX1_277"] #self.hero1 = MAGE #self.player1 = Player("one", self.deck1, self.hero1) #self.deck2 = ["EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", # "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", # "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", # "EX1_277", "EX1_277", "EX1_277"] #self.hero2 = MAGE #self.player2 = Player("two", self.deck2, self.hero2) #self.game = Game(players=(self.player1, self.player2)) #self.game.start() #for player in self.game.players: # if player.choice: # player.choice.choose() #self.game.players[0].hero.hit(24) #self.game.players[1].hero.hit(24) def Clone(self): """ Create a deep clone of this game state. """ st = HearthState() st.playerJustMoved = self.playerJustMoved st.player1 = self.player1 st.hero1 = self.hero1 st.deck1 = copy.copy(self.deck1) st.player2 = self.player2 st.hero2 = self.hero2 st.deck2 = copy.copy(self.deck2) #st.game = copy.copy(self.game) st.game = copy.deepcopy(self.game) return st def DoMove(self, move): """ Update a state by carrying out the given move. """ if self.game is not None: assert self.game.current_player.playstate == PlayState.PLAYING if self.game.current_player is not None: if self.game.current_player.name == "one": self.playerJustMoved = 1 else: self.playerJustMoved = 2 try: if move[0] == MOVE.PRE_GAME: self.player1 = Player("one", self.deck1, self.hero1) self.player2 = Player("two", self.deck2, self.hero2) self.game = Game(players=(self.player1, self.player2)) self.game.start() # TODO: Mulligan for player in self.game.players: if player.choice: player.choice.choose() elif move[0] == MOVE.PICK_CLASS: self.hero2 = move[1] elif move[0] == MOVE.PICK_CARD: if len(self.deck1) < 30: self.deck1.append(move[1].id) else: self.deck2.append(move[1].id) elif move[0] == MOVE.MULLIGAN: self.game.current_player.choice.choose(*move[1]) elif move[0] == MOVE.END_TURN: self.game.end_turn() elif move[0] == MOVE.HERO_POWER: heropower = self.game.current_player.hero.power if move[3] is None: heropower.use() else: heropower.use(target=heropower.targets[move[3]]) elif move[0] == MOVE.PLAY_CARD: card = self.game.current_player.hand[move[2]] if move[3] is None: card.play() else: card.play(target=card.targets[move[3]]) elif move[0] == MOVE.MINION_ATTACK: minion = self.game.current_player.field[move[2]] minion.attack(minion.targets[move[3]]) elif move[0] == MOVE.HERO_ATTACK: hero = self.game.current_player.hero hero.attack(hero.targets[move[3]]) elif move[0] == MOVE.CHOICE: self.game.current_player.choice.choose(move[1]) else: raise NameError("DoMove ran into unclassified card", move) except: return def GetMoves(self): """ Get all possible moves from this state. """ if self.game is not None: if self.game.current_player.playstate != PlayState.PLAYING: return [] valid_moves = [] # Move format is [enum, card, index of card in hand, target index] if self.game is None and len(self.deck1) == 30 and len(self.deck2) == 30: valid_moves.append([MOVE.PRE_GAME]) elif self.game is None and len(self.deck1) == 30 and self.hero2 is None: valid_moves.append([MOVE.PICK_CLASS, DRUID]) valid_moves.append([MOVE.PICK_CLASS, HUNTER]) valid_moves.append([MOVE.PICK_CLASS, MAGE]) valid_moves.append([MOVE.PICK_CLASS, PALADIN]) valid_moves.append([MOVE.PICK_CLASS, PRIEST]) valid_moves.append([MOVE.PICK_CLASS, ROGUE]) valid_moves.append([MOVE.PICK_CLASS, SHAMAN]) valid_moves.append([MOVE.PICK_CLASS, WARLOCK]) valid_moves.append([MOVE.PICK_CLASS, WARRIOR]) elif self.game is None and len(self.deck1) < 30 or len(self.deck2) < 30: collection = [] exclude = [] if len(self.deck1) < 30: hero = cards.db[self.hero1] deck = self.deck1 else: hero = cards.db[self.hero2] deck = self.deck2 for card in cards.db.keys(): if card in exclude: continue cls = cards.db[card] if not cls.collectible: continue if cls.type == CardType.HERO: # Heroes are collectible... continue if cls.card_class and cls.card_class != hero.card_class: continue collection.append(cls) for card in collection: if card.rarity == Rarity.LEGENDARY and card.id in deck: continue elif deck.count(card.id) < Deck.MAX_UNIQUE_CARDS: valid_moves.append([MOVE.PICK_CARD, card]) elif self.game.current_player.choice is not None: for card in self.game.current_player.choice.cards: valid_moves.append([MOVE.CHOICE, card]) else: # Play card for card in self.game.current_player.hand: dupe = False for i in range(len(valid_moves)): if valid_moves[i][1].id == card.id: dupe = True break if not dupe: if card.is_playable(): if card.has_target(): for t in range(len(card.targets)): valid_moves.append([MOVE.PLAY_CARD, card, self.game.current_player.hand.index(card), t]) else: valid_moves.append([MOVE.PLAY_CARD, card, self.game.current_player.hand.index(card), None]) # Hero Power heropower = self.game.current_player.hero.power if heropower.is_usable(): if heropower.has_target(): for t in range(len(heropower.targets)): valid_moves.append([MOVE.HERO_POWER, None, None, t]) else: valid_moves.append([MOVE.HERO_POWER, None, None, None]) # Minion Attack for minion in self.game.current_player.field: if minion.can_attack(): for t in range(len(minion.targets)): valid_moves.append([MOVE.MINION_ATTACK, minion, self.game.current_player.field.index(minion), t]) # Hero Attack hero = self.game.current_player.hero if hero.can_attack(): for t in range(len(hero.targets)): valid_moves.append([MOVE.HERO_ATTACK, hero, None, t]) valid_moves.append([MOVE.END_TURN]) return valid_moves def GetResult(self, playerjm): """ Get the game result from the viewpoint of playerjm. """ if self.game.players[0].hero.health <= 0 and self.game.players[1].hero.health <= 0: return 0.1 elif self.game.players[playerjm - 1].hero.health <= 0: # loss return 0 elif self.game.players[2 - playerjm].hero.health <= 0: # win return pow(0.99, self.game.turn) else: # Should not be possible to get here unless we terminate the game early. return 0.1 def __repr__(self): try: s = "Turn: " + str(self.game.turn) s += "\n[" + str(self.game.players[0].hero.health) + " hp ~ " + str(len(self.game.players[0].hand)) + " in hand ~ " + str(self.game.players[0].tempMana) + "/" + str(self.game.players[0].maxMana) + " mana] " #s += "\n[" + str(self.game.players[0].hero.health) + " hp ~ " + str(len(self.game.players[0].hand)) + " in hand ~ " + str(self.game.players[0].deck.left) + "/" + str(len(self.game.players[0].deck.cards)) + " in deck ~ " + str(self.game.players[0].mana) + "/" + str(self.game.players[0].max_mana) + " mana] " for minion in self.game.players[0].field: s += str(minion.atk) + "/" + str(minion.health) + ":" s += "\n[" + str(self.game.players[1].hero.health) + " hp ~ " + str(len(self.game.players[1].hand)) + " in hand ~ " + str(self.game.players[1].tempMana) + "/" + str(self.game.players[1].maxMana) + " mana] " #s += "\n[" + str(self.game.players[1].hero.health) + " hp ~ " + str(len(self.game.players[1].hand)) + " in hand ~ " + str(self.game.players[1].deck.left) + "/" + str(len(self.game.players[1].deck.cards)) + " in deck ~ " + str(self.game.players[1].mana) + "/" + str(self.game.players[1].max_mana) + " mana] " for minion in self.game.players[1].field: s += str(minion.atk) + "/" + str(minion.health) + ":" s += "\n" + "Current Player: " + str(self.game.currentPlayer) return s except: s = "Deck 1: " + ", ".join(self.deck1) s += "\nDeck 2: " + ", ".join(self.deck2) return s
class Board(): """ This class interacts with Game.py to initialize the game, return states, and return actions """ def __init__(self): self.num_actions = 23 self.players = ['player1', 'player2'] self.is_basic = True def initEnvi(self): cards.db.initialize() def initGame(self): self.initEnvi() if self.is_basic: #create quick simple game p1 = 6 #priest p2 = 7 #rogue else: p1 = random.randint(1, 9) p2 = random.randint(1, 9) deck1 = random_draft(CardClass(p1)) deck2 = random_draft(CardClass(p2)) self.players[0] = Player("Player1", deck1, CardClass(p1).default_hero) self.players[1] = Player("Player2", deck2, CardClass(p2).default_hero) self.game = Game(players=self.players) self.game.start() #Skip mulligan for now for player in self.game.players: cards_to_mulligan = random.sample(player.choice.cards, 0) player.choice.choose(*cards_to_mulligan) self.start_player = game.current_player return self.game def getGame(self): return self.game def getValidMoves(self, game, player): actions = np.zeros((21, 9)) #If the player is being given a choice, return only valid choices if game.player.choice: for card in game.player.choice.cards: actions[20, card] = 1 #actions.append(("choose", card, None)) else: # add cards in hand for index, card in enumerate(game.player.hand): if card.is_playable(): if card.requires_target(): for target in card.targets: actions[index, target] = 1 else: actions[index, 8] = 1 # add targets available to minions that can attack for position, minion in enumerate(game.player.field): if minion.can_attack(): for index, target in enumerate(minion.attack_targets): actions[position + 10, target] = 1 # add hero power and targets if applicable if game.player.hero.power.is_usable(): if game.player.hero.power.requires_target(): for index, target in enumerate( game.player.hero.power.targets): actions[17, index] = 1 else: actions[17, 8] = 1 # add hero attacking if applicable if game.player.hero.can_attack(): for index, target in enumerate( game.player.hero.attack_targets): actions[18, target] = 1 # add end turn actions[19] = 1 return actions def performAction(self, game, a, player): """ utilty to convert an action tuple into an action input Args: a, a tuple representing index of action player, current player game, game object (either actual game or copy) """ try: if 0 <= a[0] <= 9: if a[1] == 0: game.player.hand[a[0]].play(a[1]) else: game.player.hand[a[0]].play() elif 10 <= a[0] <= 16: player.field[a[0]].attack(a[1]) elif a[0] == 17: if a[1] == 0: game.player.hero.power.use([a[1]]) else: game.player.hero.power.use() elif a[0] == 18: game.player.hero.attack(a[1]) elif a[0] == 19: game.end_turn() elif a[0] == 20: game.player.choice.choose(a[1]) else: raise UnhandledAction except UnhandledAction: print("Attempted to take an inappropriate action!\n") print(a) except GameOver: raise def getState(self, game, player): """ Args: game, the current game object player, the player from whose perspective to analyze the state return: a numpy array features extracted from the supplied game. """ s = np.zeros(263, dtype=np.int32) p1 = game.player p2 = game.player.opponent #0-9 player1 class, we subtract 1 here because the classes are from 1 to 10 s[p1.hero.card_class - 1] = 1 #10-19 player2 class s[10 + p2.hero.card_class - 1] = 1 i = 20 # 20-21: current health of current player, then opponent s[i] = p1.hero.health s[i + 1] = p2.hero.health # 22: hero power usable y/n s[i + 2] = p1.hero.power.is_usable() * 1 # 23-24: # of mana crystals for you opponent s[i + 3] = p1.max_mana s[i + 4] = p2.max_mana # 25: # of crystals still avalible s[i + 5] = p1.mana #26-31: weapon equipped y/n, pow., dur. for you, then opponent s[i + 6] = 0 if p1.weapon is None else 1 s[i + 7] = 0 if p1.weapon is None else p1.weapon.damage s[i + 8] = 0 if p1.weapon is None else p1.weapon.durability s[i + 9] = 0 if p2.weapon is None else 1 s[i + 10] = 0 if p2.weapon is None else p2.weapon.damage s[i + 11] = 0 if p2.weapon is None else p2.weapon.durability # 32: number of cards in opponents hand s[i + 12] = len(p2.hand) #in play minions i = 33 #33-102, your monsters on the field p1_minions = len(p1.field) for j in range(0, 7): if j < p1_minions: # filled y/n, pow, tough, current health, can attack s[i] = 1 s[i + 1] = p1.field[j].atk s[i + 2] = p1.field[j].max_health s[i + 3] = p1.field[j].health s[i + 4] = p1.field[j].can_attack() * 1 # deathrattle, div shield, taunt, stealth y/n s[i + 5] = p1.field[j].has_deathrattle * 1 s[i + 6] = p1.field[j].divine_shield * 1 s[i + 7] = p1.field[j].taunt * 1 s[i + 8] = p1.field[j].stealthed * 1 s[i + 9] = p1.field[j].silenced * 1 i += 10 #103-172, enemy monsters on the field p2_minions = len(p2.field) for j in range(0, 7): if j < p2_minions: # filled y/n, pow, tough, current health, can attack s[i] = 1 s[i + 1] = p2.field[j].atk s[i + 2] = p2.field[j].max_health s[i + 3] = p2.field[j].health s[i + 4] = p2.field[j].can_attack() * 1 # deathrattle, div shield, taunt, stealth y/n s[i + 5] = p2.field[j].has_deathrattle * 1 s[i + 6] = p2.field[j].divine_shield * 1 s[i + 7] = p2.field[j].taunt * 1 s[i + 8] = p2.field[j].stealthed * 1 s[i + 9] = p2.field[j].silenced * 1 i += 10 #in hand #173-262, your cards in hand p1_hand = len(p1.hand) for j in range(0, 10): if j < p1_hand: #card y/n s[i] = 1 # minion y/n, attk, hp, battlecry, div shield, deathrattle, taunt s[i + 1] = 1 if p1.hand[j].type == 4 else 0 s[i + 2] = p1.hand[j].atk if s[i + 1] == 1 else 0 s[i + 2] = p1.hand[j].health if s[i + 1] == 1 else 0 s[i + 3] = p1.hand[j].divine_shield * 1 if s[i + 1] == 1 else 0 s[i + 4] = p1.hand[j].has_deathrattle * 1 if s[i + 1] == 1 else 0 s[i + 5] = p1.hand[j].taunt * 1 if s[i + 1] == 1 else 0 # weapon y/n, spell y/n, cost s[i + 6] = 1 if p1.hand[j].type == 7 else 0 s[i + 7] = 1 if p1.hand[j].type == 5 else 0 s[i + 8] = p1.hand[j].cost i += 9 return s
def find_card_pair(onlyresult=1): card_class = CardClass.MAGE #カードクラスを設定することは必須 allCards = get_all_cards(card_class, costMax=2) vanillas = get_all_vanillas(allCards) nonVanillas = get_all_non_vanillas(allCards) spells = get_all_spells(allCards) #良いカードペアを漠然と探す旅に出る2枚は呪文カードしばり for matchNumber in range(10): count1 = 0 count2 = 0 #ヒーローパワーを消す、というのもよいかも。 nonvanillaName1 = random.choice(nonVanillas) nonvanilla1 = nonvanillaName1.id nonvanillaName2 = random.choice(spells) #この呪文によって、まえのカードが活かされるかどうか nonvanilla2 = nonvanillaName2.id print(" specific cards : %r%r" % (nonvanillaName1, nonvanillaName2)) for repeat in range(25): if onlyresult == 0: print(" GAME %d" % repeat, end=" -> ") #set decks and players deck1 = [] position = random.randint(1, 7) for i in range(position): deck1.append((random.choice(vanillas)).id) deck1.append(nonvanilla1) deck1.append(nonvanilla2) for i in range(8 - position): #デッキは10枚 deck1.append(random.choice(vanillas).id) player1 = Player("Player1", deck1, card_class.default_hero) deck2 = copy.deepcopy(deck1) random.shuffle(deck2) player2 = Player("Player2", deck2, card_class.default_hero) #set a game game = Game(players=(player1, player2)) game.start() for player in game.players: #print("Can mulligan %r" % (player.choice.cards)) mull_count = random.randint(0, len(player.choice.cards)) cards_to_mulligan = random.sample(player.choice.cards, mull_count) player.choice.choose(*cards_to_mulligan) game.player1.hero.max_health = 10 game.player2.hero.max_health = 10 turnNumber = 0 if onlyresult == 0: print("Turn ", end=':') while True: turnNumber += 1 if onlyresult == 0: print(turnNumber, end=":") #StandardRandom(game)#ここはもう少し賢くする weight = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] weight[0] = weight[1] = 5 weight[26] = 10 weight[2] = weight[3] = weight[6] = weight[7] = 5 weight[10] = weight[11] = weight[12] = weight[13] = 5 StandardStep1(game, debugLog=False) if game.state != State.COMPLETE: try: game.end_turn() except GameOver: #まれにおこる pass if game.state == State.COMPLETE: if game.current_player.playstate == PlayState.WON: winner = game.current_player.name break elif game.current_player.playstate == PlayState.LOST: winner = game.current_player.opponent.name break else: winner = "DRAW" break if onlyresult == 0: print("%s won." % winner) if winner == "Player1": if onlyresult == 1: print("O", end=".") count1 += 1 elif winner == "Player2": if onlyresult == 1: print("X", end=".") count2 += 1 print("(%d : %d)" % (count1, count2), end=" ") #25戦で10点差があれば有意な差あり if count1 - count2 >= 10: print("Significant") else: print("") pass
def investigate_card_pair(onlyresult=0): card_class = CardClass.HUNTER allCards = get_all_cards(card_class) vanillas = get_all_vanillas(allCards) nonVanillas = get_all_non_vanillas(allCards) count1 = 0 count2 = 0 #ヒーローパワーを消す、というのもよいかも。 #良いカードペアを漠然と探す旅に出る? nonvanilla1 = 'EX1_045' #random.choice(nonVanillas).id#自分で指定してもよい nonvanilla2 = 'EX1_332' #random.choice(nonVanillas).id# #古代の番人:EX1_045:攻撃できない。 #沈黙:EX1_332:ミニオン1体を沈黙させる print(" specific cards : %r%r" % (nonvanilla1, nonvanilla2)) for repeat in range(50): print(" GAME %d" % repeat, end=" -> ") #set decks and players deck1 = [] position = random.randint(1, 7) for i in range(position): deck1.append((random.choice(vanillas)).id) deck1.append(nonvanilla1) deck1.append(nonvanilla2) for i in range(8 - position): #デッキは10枚 deck1.append(random.choice(vanillas).id) player1 = Player("AAAA", deck1, card_class.default_hero) deck2 = copy.deepcopy(deck1) random.shuffle(deck2) player2 = Player("BBBB", deck2, card_class.default_hero) #set a game game = Game(players=(player1, player2)) game.start() for player in game.players: #print("Can mulligan %r" % (player.choice.cards)) mull_count = random.randint(0, len(player.choice.cards)) cards_to_mulligan = random.sample(player.choice.cards, mull_count) player.choice.choose(*cards_to_mulligan) game.player1.hero.max_health = 10 # ヒーローのHPは10 game.player2.hero.max_health = 10 turnNumber = 0 print("Turn ", end=':') while True: turnNumber += 1 print(turnNumber, end=":") weight = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] weight[0] = weight[1] = 5 weight[26] = 10 weight[2] = weight[3] = weight[6] = weight[7] = 5 weight[10] = weight[11] = weight[12] = weight[13] = 5 StandardStep1(game, debugLog=False) #StandardRandom(game,debugLog=True) #ここはもう少し賢い人にやってほしい if game.state != State.COMPLETE: try: game.end_turn() except GameOver: #まれにおこる pass else: if game.current_player.playstate == PlayState.WON: winner = game.current_player.name break elif game.current_player.playstate == PlayState.LOST: winner = game.current_player.opponent.name break else: winner = "DRAW" break print("%s won." % winner) if winner == "AAAA": count1 += 1 elif winner == "BBBB": count2 += 1 print("%d : %d" % (count1, count2))
def play_one_game(P1: Agent, P2: Agent, deck1=[], deck2=[], debugLog=True, HEROHPOPTION=30, P1MAXMANA=1, P2MAXMANA=1, P1HAND=3, P2HAND=3): """ エージェント同士で1回対戦する。 実験的に、ヒーローの体力、初期マナ数、初期ハンド枚数をコントロールできます。 play one game by P1 and P2 """ from fireplace.utils import random_draft from fireplace.player import Player import random exclude = [] # you may exclude some cards to construct a deck log.info("New game settings") if len(deck1) == 0: deck1 = random_draft(P1.myClass, exclude) #random deck wrt its class if len(deck2) == 0: deck2 = random_draft(P2.myClass, exclude) #random deck wrt its class player1 = Player(P1.name, deck1, P1.myClass.default_hero) player2 = Player(P2.name, deck2, P2.myClass.default_hero) player1.choiceStrategy = P1.choiceStrategy player2.choiceStrategy = P2.choiceStrategy game = Game(players=(player1, player2)) # Configurations player1._start_hand_size = P1HAND ## this line must be before 'start()' player2._start_hand_size = P2HAND ## player1.max_mana = int( P1MAXMANA) - 1 ## this line must be before 'start()' player2.max_mana = int(P2MAXMANA) - 1 game.start() player1.hero.max_health = int( HEROHPOPTION) ## this line must be below 'start()' player2.hero.max_health = int(HEROHPOPTION) ## #mulligan exchange # Any agent are allowed to give an algorithm to do mulligan exchange. for player in game.players: if player.name == P1.name: if P1.mulliganStrategy == None: mull_count = random.randint(0, len(player.choice.cards)) cards_to_mulligan = random.sample(player.choice.cards, mull_count) else: cards_to_mulligan = P1.mulliganStrategy( P1, player.choice.cards) elif player.name == P2.name: if P2.mulliganStrategy == None: mull_count = random.randint(0, len(player.choice.cards)) cards_to_mulligan = random.sample(player.choice.cards, mull_count) else: cards_to_mulligan = P2.mulliganStrategy( P2, player.choice.cards) player.choice.choose(*cards_to_mulligan) # includes begin_turn() #mulligan exchange end log.info("New game start") while True: #game main loop player = game.current_player start_time = time.time() if player.name == P1.name: #please make each Agent.func has arguments 'self, game, option, gameLog, debugLog' P1.func(P1, game, option=P1.option, gameLog=game.get_log(), debugLog=debugLog) elif player.name == P2.name: #please make each Agent.func has arguments 'self, game, option, gameLog, debugLog' P2.func(P2, game, option=P2.option, gameLog=game.get_log(), debugLog=debugLog) else: Original_random(game) #random player by fireplace #turn end procedure from here if player.choice != None: player.choice = None #somotimes it comes here if game.state != State.COMPLETE: try: game.end_turn() if debugLog: print(">>>>%s>>>>turn change %d[sec]>>>>%s" % (player, time.time() - start_time, player.opponent), end=' ') print("%d : %d" % (player1.hero.health + player1.hero.armor, player2.hero.health + player2.hero.armor)) if game.current_player.choice != None: postAction(game.current_player) except GameOver: #it rarely occurs gameover = 0 #ゲーム終了フラグが立っていたらゲーム終了処理を行う #if game was over if game.state == State.COMPLETE: if debugLog: print(">>>>>>>>>>game end >>>>>>>>" % (), end=' ') print("%d : %d" % (player1.hero.health, player2.hero.health)) if game.current_player.playstate == PlayState.WON: return game.current_player.name if game.current_player.playstate == PlayState.LOST: return game.current_player.opponent.name return 'DRAW' #Maybe impossible to come here.
class Board(object): def __init__(self, is_basic=True): self.state = np.zeros(263, dtype=np.int32) self.players = ['player1', 'player2'] self.is_basic = is_basic # self.game = Game() def init_envi(self): """ Initializes the environment. All basic initialization goes here. """ cards.db.initialize() self.last_move = -1 def init_game(self): """ initializes a game between two players Returns: game: A game entity representing the start of the game after the mulligan phase """ if self.is_basic: #create quick simple game p1 = 6 #priest p2 = 7 #rogue deck1 = random_draft(CardClass(p1)) deck2 = random_draft(CardClass(p2)) self.players[0] = Player("Player1", deck1, CardClass(p1).default_hero) self.players[1] = Player("Player2", deck2, CardClass(p2).default_hero) self.game = Game(players=self.players) self.game.start() #Skip mulligan for player in self.game.players: cards_to_mulligan = random.sample(player.choice.cards, 0) player.choice.choose(*cards_to_mulligan) return self.game else: p1 = random.randint(1, 9) p2 = random.randint(1, 9) #initialize players and randomly draft decks #pdb.set_trace() deck1 = random_draft(CardClass(p1)) deck2 = random_draft(CardClass(p2)) self.players[0] = Player("Player1", deck1, CardClass(p1).default_hero) self.players[1] = Player("Player2", deck2, CardClass(p2).default_hero) #begin the game self.game = Game(players=self.players) self.game.start() #Skip mulligan for now for player in self.game.players: cards_to_mulligan = random.sample(player.choice.cards, 0) player.choice.choose(*cards_to_mulligan) return self.game def get_actions(self, player): """ generate a list of tuples representing all valid actions format: (actiontype, index, target) card.requires_target!! """ actions = [] #If the player is being given a choice, return only valid choices if player.choice: for card in player.choice.cards: actions.append(("choose", card, None)) else: # add cards in hand for index, card in enumerate(player.hand): if card.is_playable(): # summonable minions (note some require a target on play) if card.type == 4: if card.requires_target(): for target in card.targets: actions.append(("summon", index, target)) else: actions.append(("summon", index, None, None)) # playable spells and weapons elif card.requires_target(): for target in card.targets: actions.append(("spell", index, target)) else: actions.append(("spell", index, None)) # add targets avalible to minions that can attack for position, minion in enumerate(player.field): if minion.can_attack(): for target in minion.attack_targets: actions.append(("attack", position, target)) # add hero power and targets if applicable if player.hero.power.is_usable(): if player.hero.power.requires_target(): for target in player.hero.power.targets: actions.append(("hero_power", None, target)) else: actions.append(("hero_power", None, None)) # add hero attacking if applicable if player.hero.can_attack(): for target in player.hero.attack_targets: actions.append(("hero_attack", None, target)) # add end turn actions.append(("end_turn", None, None)) self.actions = actions return actions def get_actionsize(self): self.action_size = len(self.actions) return self.action_size def perform_action(self, a, player, game): """ utilty to convert an action tuple into an action input Args: a, a tuple representing (action, index, target) """ try: if a[0] == "summon": if a[2] is None: player.hand[a[1]].play() else: player.hand[a[1]].play(a[2]) elif a[0] == "spell": if a[2] is None: player.hand[a[1]].play() else: player.hand[a[1]].play(a[2]) elif a[0] == "attack": player.field[a[1]].attack(a[2]) elif a[0] == "hero_power": if a[2] is None: player.hero.power.use() else: player.hero.power.use(a[2]) elif a[0] == "hero_attack": player.hero.attack(a[2]) elif a[0] == "end_turn": game.end_turn() elif a[0] == "choose": #print("Player choosing card %r, " % a[1]) player.choice.choose(a[1]) else: raise UnhandledAction except UnhandledAction: print("Attempted to take an inappropriate action!\n") print(a) except GameOver: raise def get_state(self): """ Args: game, the current game object player, the player from whose perspective to analyze the state return: a numpy array features extracted from the supplied game. """ s = np.zeros(263, dtype=np.int32) c = np.zeros(263, dtype=np.int32) for player in self.players: p1 = player p2 = player.opponent #0-9 player1 class, we subtract 1 here because the classes are from 1 to 10 s[p1.hero.card_class - 1] = 1 #10-19 player2 class s[10 + p2.hero.card_class - 1] = 1 i = 20 # 20-21: current health of current player, then opponent s[i] = p1.hero.health s[i + 1] = p2.hero.health # 22: hero power usable y/n s[i + 2] = p1.hero.power.is_usable() * 1 # 23-24: # of mana crystals for you opponent s[i + 3] = p1.max_mana s[i + 4] = p2.max_mana # 25: # of crystals still avalible s[i + 5] = p1.mana #26-31: weapon equipped y/n, pow., dur. for you, then opponent s[i + 6] = 0 if p1.weapon is None else 1 s[i + 7] = 0 if p1.weapon is None else p1.weapon.damage s[i + 8] = 0 if p1.weapon is None else p1.weapon.durability s[i + 9] = 0 if p2.weapon is None else 1 s[i + 10] = 0 if p2.weapon is None else p2.weapon.damage s[i + 11] = 0 if p2.weapon is None else p2.weapon.durability # 32: number of cards in opponents hand s[i + 12] = len(p2.hand) #in play minions i = 33 #33-102, your monsters on the field p1_minions = len(p1.field) for j in range(0, 7): if j < p1_minions: # filled y/n, pow, tough, current health, can attack s[i] = 1 s[i + 1] = p1.field[j].atk s[i + 2] = p1.field[j].max_health s[i + 3] = p1.field[j].health s[i + 4] = p1.field[j].can_attack() * 1 # deathrattle, div shield, taunt, stealth y/n s[i + 5] = p1.field[j].has_deathrattle * 1 s[i + 6] = p1.field[j].divine_shield * 1 s[i + 7] = p1.field[j].taunt * 1 s[i + 8] = p1.field[j].stealthed * 1 s[i + 9] = p1.field[j].silenced * 1 i += 10 #103-172, enemy monsters on the field p2_minions = len(p2.field) for j in range(0, 7): if j < p2_minions: # filled y/n, pow, tough, current health, can attack s[i] = 1 s[i + 1] = p2.field[j].atk s[i + 2] = p2.field[j].max_health s[i + 3] = p2.field[j].health s[i + 4] = p2.field[j].can_attack() * 1 # deathrattle, div shield, taunt, stealth y/n s[i + 5] = p2.field[j].has_deathrattle * 1 s[i + 6] = p2.field[j].divine_shield * 1 s[i + 7] = p2.field[j].taunt * 1 s[i + 8] = p2.field[j].stealthed * 1 s[i + 9] = p2.field[j].silenced * 1 i += 10 #in hand #173-262, your cards in hand p1_hand = len(p1.hand) for j in range(0, 10): if j < p1_hand: #card y/n s[i] = 1 # minion y/n, attk, hp, battlecry, div shield, deathrattle, taunt s[i + 1] = 1 if p1.hand[j].type == 4 else 0 s[i + 2] = p1.hand[j].atk if s[i + 1] == 1 else 0 s[i + 2] = p1.hand[j].health if s[i + 1] == 1 else 0 s[i + 3] = p1.hand[j].divine_shield * 1 if s[i + 1] == 1 else 0 s[i + 4] = p1.hand[j].has_deathrattle * 1 if s[i + 1] == 1 else 0 s[i + 5] = p1.hand[j].taunt * 1 if s[i + 1] == 1 else 0 # weapon y/n, spell y/n, cost s[i + 6] = 1 if p1.hand[j].type == 7 else 0 s[i + 7] = 1 if p1.hand[j].type == 5 else 0 s[i + 8] = p1.hand[j].cost i += 9 if player == self.players[0]: c = s continue else: self.state = np.append(c, s) return self.state # self.state = s # return self.state def get_state_data(self): state = [] self.get_actions() pass def check_winner(self): for player in self.players: if player.playstate == PlayState.WON: return True, player if player.playstate == PlayState.TIED: return True, -1 return False, -1
player1 = HearthStoneGod('Player1', deck1, CardClass.MAGE.default_hero, game_config, mode='manual') deck2 = [c[1] for c in game_config.card_config.cards_list[1:] * 4] player2 = HearthStoneGod('Player2', deck2, CardClass.MAGE.default_hero, game_config, game_model=game_model, mode='model_play') game = Game(players=(player1, player2)) game.start() player1.mulligan(skip=True) player2.mulligan(skip=True) try: while True: player = game.current_player player.play_turn(game) except GameOver: if game.player2.hero.dead: print('You Win!') else: print('You Lose!')
class Test: def __init__(self): self.player1 = None self.hero1 = None self.deck1 = [] self.player2 = None self.hero2 = None self.deck2 = [] self.game = None def start(self): self.hero1 = CardClass.HUNTER.default_hero self.hero2 = CardClass.HUNTER.default_hero self.deck1 = list(hunter_simple_deck) self.deck2 = list(hunter_simple_deck) self.player1 = Player(PLAYER_1_NAME, self.deck1, self.hero1) self.player2 = Player(PLAYER_2_NAME, self.deck2, self.hero2) self.game = Game(players=(self.player1, self.player2)) self.game.start() self.skipMulligan() def skipMulligan(self): self.player1.choice.choose() self.player2.choice.choose() def possibleNextAtkLight(self, used=[]): result = [] player = self.game.current_player for x in range(0, len(player.characters)): if x not in used: character = player.characters[x] if character.can_attack(): result.append((character, Actions.ATTACK)) return result def possibleNextAtk(self): result = [] player = self.game.current_player for character in player.characters: if character.can_attack(): result.append((character, Actions.ATTACK)) return result def simulatePossibleAtksLight(self, cards_atk=[], gstate=None, cards_used=[]): if gstate == None: gstate = GameState(self.game) result = [] list_of_next_atks = self.possibleNextAtkLight(cards_used) for (character, type_of_action) in list_of_next_atks: p = self.game.current_player opp = p.opponent for target in character.targets: temp_state = GameState(self.game) temp_state.copy(gstate) #target_dict = {'card': target, 'atk': target.atk, 'health': target.health, 'opponent': True if target.controller.first_player != p.first_player else False} value = temp_state.minionAtk(character, target) if value: result.append((cards_atk + [(character, target)], temp_state)) result.extend(self.simulatePossibleAtksLight(cards_atk + [(character, target)], temp_state, cards_used + [p.characters.index(character)])) return result def simulatePossibleAtks(self, cards_atk=[]): result = [] list_of_next_atks = self.possibleNextAtk() for i in range(0, len(list_of_next_atks)): p = self.game.current_player opp = p.opponent index_of_char = p.characters.index(list_of_next_atks[i][0]) list_of_targets = list_of_next_atks[i][0].targets for j in range(0, len(list_of_targets)): copy_test = Test() copy_test.game = copy.deepcopy(self.game) target = list_of_targets[j] target_dict = {'card': target, 'atk': target.atk, 'health': target.health, 'opponent': True if target.controller.first_player != p.first_player else False} if target_dict['opponent'] == True: index_of_target = opp.characters.index(target) copy_test.game.current_player.characters[index_of_char].attack(target=copy_test.game.current_player.opponent.characters[index_of_target]) else: index_of_target = p.characters.index(target) copy_test.game.current_player.characters[index_of_char].attack(target=copy_test.game.current_player.characters[index_of_target]) player = copy_test.game.current_player opponent = player.opponent result.append((cards_atk + [(p.characters[index_of_char], target_dict)], GameState(player.hero.health, player.mana, player.characters, opponent.hero.health, opponent.characters))) result.extend(copy_test.simulatePossibleAtks(cards_atk + [(p.characters[index_of_char], target_dict)])) return result def possibleNextActionLight(self, used=[]): result = [] player = self.game.current_player for x in range(0, len(player.hand)): if x not in used: card = player.hand[x] if card.is_playable(): result.append((x, Actions.PLAY)) if player.hero.power.is_usable() and player.hero.power not in used: result.append((player.hero.power, Actions.POWER)) return result def possibleNextAction(self): result = [] player = self.game.current_player for card in player.hand: if card.is_playable(): result.append((card, Actions.PLAY)) if player.hero.power.is_usable(): result.append((player.hero.power, Actions.POWER)) return result def simulatePossibleActionsLight(self, cards_played=[], gstate=None, cards_used=[]): if gstate == None: gstate = GameState(self.game) current_mana = self.game.current_player.mana result = [] list_of_possible_actions = self.possibleNextActionLight(cards_used) for (card_index, type_of_action) in list_of_possible_actions: if (type_of_action == Actions.PLAY): card = self.game.current_player.hand[card_index] if isinstance(card, fireplace.card.Minion): temp_state = GameState(self.game) temp_state.copy(gstate) temp_state.addMinion(card) self.game.current_player.__dict__['_max_mana'] = self.game.current_player.__dict__['_max_mana'] - card.cost result.append((cards_played + [card], temp_state)) result.extend(self.simulatePossibleActionsLight(cards_played + [card], temp_state, cards_used + [card_index])) self.game.current_player.__dict__['_max_mana'] = current_mana if isinstance(card, fireplace.card.Spell): if len(card.targets) > 0: for target in card.targets: temp_state = GameState(self.game) temp_state.copy(gstate) if card.id == 'GAME_005': #THE COIN self.game.current_player.__dict__['_max_mana'] = self.game.current_player.__dict__['_max_mana'] + 1 temp_state.mana = self.game.current_player.mana result.append((cards_played + [card], temp_state)) result.extend(self.simulatePossibleActionsLight(cards_played + [card], temp_state, cards_used + [card_index])) self.game.current_player.__dict__['_max_mana'] = current_mana else: self.game.current_player.__dict__['_max_mana'] = self.game.current_player.__dict__['_max_mana'] - card.cost temp_state.mana = self.game.current_player.mana #target_dict = {'card': target, 'atk': target.atk, 'health': target.health, 'opponent': True if target.controller.first_player != self.game.current_player.first_player else False} temp_state.playSpell(card, target) temp_state.updateState() result.append((cards_played + [(card, target)], temp_state)) result.extend(self.simulatePossibleActionsLight(cards_played + [(card, target)], temp_state, cards_used + [card_index])) self.game.current_player.__dict__['_max_mana'] = current_mana if (type_of_action == Actions.POWER): temp_state = GameState(self.game) temp_state.copy(gstate) if self.game.current_player.hero.power.id == 'DS1h_292': temp_state.enemy_herohealth = temp_state.enemy_herohealth - 2 self.game.current_player.__dict__['_max_mana'] = self.game.current_player.__dict__['_max_mana'] - self.game.current_player.hero.power.cost temp_state.mana = self.game.current_player.mana result.append((cards_played + [card_index], temp_state)) result.extend(self.simulatePossibleActionsLight(cards_played + [card_index], temp_state, cards_used + [card_index])) self.game.current_player.__dict__['_max_mana'] = self.game.current_player.__dict__['_max_mana'] + self.game.current_player.hero.power.cost self.game.current_player.__dict__['_max_mana'] = current_mana return result def simulatePossibleActions(self, cards_played=[]): result = [] list_of_next_actions = self.possibleNextAction() for i in range(0, len(list_of_next_actions)): p = self.game.current_player opp = p.opponent card = list_of_next_actions[i][0] type_of_action = list_of_next_actions[i][1] target_flag = False if type_of_action == Actions.PLAY: index_of_card = p.hand.index(list_of_next_actions[i][0]) target_flag = False if len(card.targets) > 0: target_flag = True list_of_targets = card.targets for j in range(0, len(list_of_targets)): copy_test = Test() copy_test.game = copy.deepcopy(self.game) target = list_of_targets[j] target_dict = {'card': target, 'atk': target.atk, 'health': target.health, 'opponent': True if target.controller.first_player != p.first_player else False} if target_dict['opponent'] == True: index_of_target = opp.characters.index(target) copy_test.game.current_player.hand[index_of_card].play(target=copy_test.game.current_player.opponent.characters[index_of_target]) else: index_of_target = p.characters.index(target) copy_test.game.current_player.hand[index_of_card].play(target=copy_test.game.current_player.characters[index_of_target]) player = copy_test.game.current_player opponent = player.opponent result.append((cards_played + [(card, target_dict)], GameState(player.hero.health, player.mana, player.characters, opponent.hero.health, opponent.characters))) result.extend(copy_test.simulatePossibleAtks(cards_played + [(card, target_dict)])) else: copy_test = Test() copy_test.game = copy.deepcopy(self.game) temp_list_of_next_actions = copy_test.possibleNextAction() temp_list_of_next_actions[i][0].play() elif type_of_action == Actions.POWER: copy_test = Test() copy_test.game = copy.deepcopy(self.game) copy_test.game.current_player.hero.power.use() if not target_flag: player = copy_test.game.current_player opponent = player.opponent result.append((cards_played + [card], GameState(player.hero.health, player.mana, player.characters, opponent.hero.health, opponent.characters))) result.extend(copy_test.simulatePossibleActions(cards_played + [card])) return result '''
def test_full_game(ai_1_id, deck_1_id, ai_2_id, deck_2_id, clear_results): global __last_turn__ global player1 global player2 global my_json global neural_net global table player1 = get_instance_by_name(ai_1_id, deck_1_id) player2 = get_instance_by_name(ai_2_id, deck_2_id) __last_turn__ = [None, None, None] attributes = get_attributes() my_datetime = datetime.now() game_id = player1.get_id() + "-" + deck_1_id + "-" + player2.get_id( ) + "-" + deck_2_id + "-" + my_datetime.strftime("%Y_%m_%d") + "-" + str( attributes["NumGame"]).zfill(7) try: path_to_dir = os.path.dirname( os.getcwd()) + "\\game_results\\" + game_id + "\\" if not os.path.exists(path_to_dir): os.makedirs(path_to_dir) my_json = [] path_to_csv = path_to_dir + game_id + ".csv" csv_file = open(path_to_csv, "w") fieldnames = get_field_names() csv_writer = csv.DictWriter(csv_file, fieldnames=fieldnames) csv_writer.writeheader() # path_to_deck1 = path_to_dir + type(player1).__name__ + "_" + my_datetime.strftime("%d_%B_%Y__%H_%M.hsdeck.txt") # deck1_file = open(path_to_deck1,"w") # log_deck(deck1_file, player1) # path_to_deck2 = path_to_dir + type(player2).__name__ + "_" + my_datetime.strftime("%d_%B_%Y__%H_%M.hsdeck.txt") # deck2_file = open(path_to_deck2,"w") # log_deck(deck2_file, player2) game = Game(players=(player1, player2)) game.start() play_full_game(my_json, game, csv_writer) except GameOver: win_reward = 0 # if (player1.__class__ is Q_learner_super_makro or player1.__class__ is Q_learner_super_makro_alt): # if (player1.hero.health > 0): # reward = win_reward # else: # reward = 0 # player1.update_neural_network(player1.previous_state, player1.previous_q_value, player1.get_state(), player1.previous_action, reward) # net = player1.neural_network # # path = os.path.join(os.path.dirname(os.getcwd()), 'network.xml') # # NetworkWriter.writeToFile(net, path) # neural_net = net # # if (player2.__class__ is Q_learner_super_makro or player2.__class__ is Q_learner_super_makro_alt): # if (player2.hero.health > 0): # reward = win_reward # else: # reward = 0 # player2.update_neural_network(player2.previous_state, player2.previous_q_value, player2.get_state(), player2.previous_action, reward) # net = player2.neural_network # # path = os.path.join(os.path.dirname(os.getcwd()), 'network.xml') # # NetworkWriter.writeToFile(net, path) # neural_net = net if (player1.__class__ is Q_learner_table or player1.__class__ is Q_learner_table_08 or player1.__class__ is Q_learner_table_win): if (player1.hero.health > 0): reward = 0 else: reward = 0 player1.update_table(player1.previous_state, player1.get_state(), player1.previous_action, reward) table = player1.table if (player2.__class__ is Q_learner_table or player2.__class__ is Q_learner_table_08 or player2.__class__ is Q_learner_table_win): if (player2.hero.health > 0): reward = 0 else: reward = 0 player2.update_table(player2.previous_state, player2.get_state(), player2.previous_action, reward) table = player2.table #LAST TURN if (__last_turn__[1] != None): hashmap = get_hash_map(game, player1, player2, __last_turn__[2], __last_turn__[0].entity_id, __last_turn__[0], __last_turn__[1], __last_turn__[0]) my_json.append(hashmap) else: hashmap = get_hash_map(game, player1, player2, __last_turn__[2], __last_turn__[0].entity_id, __last_turn__[0], None, __last_turn__[0]) my_json.append(hashmap) #RESULT if (game.current_player.hero.health < 1): hashmap = get_hash_map(game, player1, player2, 21, game.current_player.hero.entity_id, None, None, None) my_json.append(hashmap) else: hashmap = get_hash_map(game, player1, player2, 20, game.current_player.hero.entity_id, None, None, None) my_json.append(hashmap) f = open(REPLAY_JSON_PATH, 'w') write_line_to_file(f, my_json.__str__()) path_to_replay = path_to_dir + game_id + ".hdtreplay" my_zip_file = zipfile.ZipFile(path_to_replay, mode='w') my_zip_file.write(REPLAY_JSON_PATH) if (clear_results): csv_result_file = open(path_to_result, "w") csv_writer = csv.DictWriter(csv_result_file, fieldnames=get_field_names_of_result()) csv_writer.writeheader() else: csv_result_file = open(path_to_result, "a") csv_writer = csv.DictWriter(csv_result_file, fieldnames=get_field_names_of_result()) csv_writer.writerow(get_result_of_game(game)) csv_result_file.close() f.close() my_zip_file.close() set_attributes(attributes) except: print("UNEXPECTED ERROR:", sys.exc_info())
def play_one_game(P1: Agent, P2: Agent, deck1=[], deck2=[], HeroHPOption=30, debugLog=True): from fireplace.utils import random_draft from fireplace.player import Player import random #バグが確認されているものを当面除外する exclude = ['CFM_672', 'CFM_621', 'CFM_095', 'LOE_076', 'BT_490'] # 'LOE_076' : Sir Finley Mrrgglton # 'BT_490' : 魔力喰い、ターゲットの扱いにエラーがあるので除外。 if len(deck1) == 0: deck1 = random_draft(P1.myClass, exclude) #ランダムなデッキ if len(deck2) == 0: deck2 = random_draft(P2.myClass, exclude) #ランダムなデッキ player1 = Player(P1.name, deck1, P1.myClass.default_hero) player2 = Player(P2.name, deck2, P2.myClass.default_hero) game = Game(players=(player1, player2)) game.start() for player in game.players: #print("Can mulligan %r" % (player.choice.cards)) mull_count = random.randint(0, len(player.choice.cards)) cards_to_mulligan = random.sample(player.choice.cards, mull_count) player.choice.choose(*cards_to_mulligan) if HeroHPOption != 30: game.player1.hero.max_health = HeroHPOption game.player2.hero.max_health = HeroHPOption while True: from agent_Standard import StandardRandom, HumanInput, Original_random from agent_Maya import Maya_MCTS player = game.current_player #print("%r starts their turn."%player.name); if player.name == "Maya": Maya_MCTS(game) #マヤ氏の作品 elif player.name == "Standard": StandardRandom( game, debugLog=debugLog) #公式のランダムより、もう少しキチンとしたランダムプレーエージェント elif player.name == "Human": HumanInput(game) #人がプレーするときはこれ elif player.name == P1.name: P1.func(game, option=P1.option, debugLog=debugLog) #P1.funcには引数option, debugLogを作ってください elif player.name == P2.name: P2.func(game, option=P2.option, debugLog=debugLog) #P2.funcには引数option, debugLogを作ってください else: Original_random(game) #公式のランダム if player.choice != None: player.choice = None #論理的にはおこらないが、ときどきおこる if game.state != State.COMPLETE: try: game.end_turn() except GameOver: #まれにおこる gameover = 0 if game.state == State.COMPLETE: #ゲーム終了フラグが立っていたら if game.current_player.playstate == PlayState.WON: return game.current_player.name if game.current_player.playstate == PlayState.LOST: return game.current_player.opponent.name return 'DRAW'
def test_full_game(ai_1_id, deck_1_id, ai_2_id, deck_2_id, clear_results): global __last_turn__ global player1 global player2 global my_json global neural_net player1 = get_instance_by_name(ai_1_id, deck_1_id) player2 = get_instance_by_name(ai_2_id, deck_2_id) __last_turn__ = [None,None,None] attributes = get_attributes() my_datetime = datetime.now() game_id = player1.get_id() + "-" + deck_1_id + "-" +player2.get_id() + "-" + deck_2_id + "-" + my_datetime.strftime("%Y_%m_%d") + "-" + str(attributes["NumGame"]).zfill(7) try: path_to_dir = os.path.dirname(os.getcwd()) + "\\game_results\\" + game_id + "\\" if not os.path.exists(path_to_dir): os.makedirs(path_to_dir) my_json = [] path_to_csv = path_to_dir + game_id + ".csv" csv_file = open(path_to_csv,"w") fieldnames = get_field_names() csv_writer = csv.DictWriter(csv_file, fieldnames=fieldnames) csv_writer.writeheader() # path_to_deck1 = path_to_dir + type(player1).__name__ + "_" + my_datetime.strftime("%d_%B_%Y__%H_%M.hsdeck.txt") # deck1_file = open(path_to_deck1,"w") # log_deck(deck1_file, player1) # path_to_deck2 = path_to_dir + type(player2).__name__ + "_" + my_datetime.strftime("%d_%B_%Y__%H_%M.hsdeck.txt") # deck2_file = open(path_to_deck2,"w") # log_deck(deck2_file, player2) game = Game(players=(player1, player2)) game.start() play_full_game(my_json, game, csv_writer) except GameOver: win_reward = 0 if (player1.__class__ is Q_learner): if (player1.hero.health > 0): reward = win_reward else: reward = 0 player1.update_neural_network(player1.previous_state, player1.previous_q_value, player1.get_state(), player1.previous_action, reward) net = player1.neural_network # path = os.path.join(os.path.dirname(os.getcwd()), 'network.xml') # NetworkWriter.writeToFile(net, path) neural_net = net if (player2.__class__ is Q_learner): if (player2.hero.health > 0): reward = win_reward else: reward = 0 player2.update_neural_network(player2.previous_state, player2.previous_q_value, player2.get_state(), player2.previous_action, reward) net = player2.neural_network # path = os.path.join(os.path.dirname(os.getcwd()), 'network.xml') # NetworkWriter.writeToFile(net, path) neural_net = net #LAST TURN if (__last_turn__[1] != None): hashmap = get_hash_map(game, player1, player2, __last_turn__[2], __last_turn__[0].entity_id,__last_turn__[0], __last_turn__[1], __last_turn__[0]) my_json.append(hashmap) else: hashmap = get_hash_map(game, player1, player2, __last_turn__[2], __last_turn__[0].entity_id,__last_turn__[0], None, __last_turn__[0]) my_json.append(hashmap) #RESULT if (game.current_player.hero.health < 1): hashmap = get_hash_map(game, player1, player2, 21, game.current_player.hero.entity_id, None, None, None) my_json.append(hashmap) else: hashmap = get_hash_map(game, player1, player2, 20, game.current_player.hero.entity_id, None, None, None) my_json.append(hashmap) f = open(REPLAY_JSON_PATH, 'w') write_line_to_file(f,my_json.__str__()) path_to_replay = path_to_dir + game_id + ".hdtreplay" my_zip_file = zipfile.ZipFile(path_to_replay, mode='w') my_zip_file.write(REPLAY_JSON_PATH) if (clear_results): csv_result_file = open(path_to_result,"w") csv_writer = csv.DictWriter(csv_result_file, fieldnames=get_field_names_of_result()) csv_writer.writeheader() else: csv_result_file = open(path_to_result,"a") csv_writer = csv.DictWriter(csv_result_file, fieldnames=get_field_names_of_result()) csv_writer.writerow(get_result_of_game(game)) csv_result_file.close() f.close() my_zip_file.close() set_attributes(attributes) except: print ("UNEXPECTED ERROR:", sys.exc_info())
class HearthState: """ A state of the game, i.e. the game board. """ def __init__(self): self.playerJustMoved = 2 # At the root pretend the player just moved is p2 - p1 has the first move random.seed(1857) # The idea of adjacent cards it to ignore minion placement if none of these cards can be found, since it doesn't # matter. #adjacent_cards = ["Dire Wolf Alpha", "Ancient Mage", "Defender of Argus", "Sunfury Protector", # "Flametongue Totem", "Explosive Shot", "Cone of Cold", "Betrayal", "Void Terror", # "Unstable Portal", "Wee Spellstopper", "Piloted Shredder", "Piloted Sky Golem", # "Recombobulator", "Foe Reaper 4000", "Nefarian"] #self.adjacent_cards = adjacent_cards self.player1 = None self.hero1 = MAGE self.deck1 = [] self.player2 = None self.hero2 = None self.deck2 = [] self.game = None # Simple Arcane Missiles lethal test #self.deck1 = ["EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", # "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", # "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", # "EX1_277", "EX1_277", "EX1_277"] #self.hero1 = MAGE #self.player1 = Player("one", self.deck1, self.hero1) #self.deck2 = ["EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", # "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", # "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", "EX1_277", # "EX1_277", "EX1_277", "EX1_277"] #self.hero2 = MAGE #self.player2 = Player("two", self.deck2, self.hero2) #self.game = Game(players=(self.player1, self.player2)) #self.game.start() #for player in self.game.players: # if player.choice: # player.choice.choose() #self.game.players[0].hero.hit(24) #self.game.players[1].hero.hit(24) def Clone(self): """ Create a deep clone of this game state. """ st = HearthState() st.playerJustMoved = self.playerJustMoved st.player1 = self.player1 st.hero1 = self.hero1 st.deck1 = copy.copy(self.deck1) st.player2 = self.player2 st.hero2 = self.hero2 st.deck2 = copy.copy(self.deck2) #st.game = copy.copy(self.game) st.game = copy.deepcopy(self.game) return st def DoMove(self, move): """ Update a state by carrying out the given move. """ if self.game is not None: assert self.game.current_player.playstate == PlayState.PLAYING if self.game.current_player is not None: if self.game.current_player.name == "one": self.playerJustMoved = 1 else: self.playerJustMoved = 2 try: if move[0] == MOVE.PRE_GAME: self.player1 = Player("one", self.deck1, self.hero1) self.player2 = Player("two", self.deck2, self.hero2) self.game = Game(players=(self.player1, self.player2)) self.game.start() # TODO: Mulligan for player in self.game.players: if player.choice: player.choice.choose() elif move[0] == MOVE.PICK_CLASS: self.hero2 = move[1] elif move[0] == MOVE.PICK_CARD: if len(self.deck1) < 30: self.deck1.append(move[1].id) else: self.deck2.append(move[1].id) elif move[0] == MOVE.MULLIGAN: self.game.current_player.choice.choose(*move[1]) elif move[0] == MOVE.END_TURN: self.game.end_turn() elif move[0] == MOVE.HERO_POWER: heropower = self.game.current_player.hero.power if move[3] is None: heropower.use() else: heropower.use(target=heropower.targets[move[3]]) elif move[0] == MOVE.PLAY_CARD: card = self.game.current_player.hand[move[2]] if move[3] is None: card.play() else: card.play(target=card.targets[move[3]]) elif move[0] == MOVE.MINION_ATTACK: minion = self.game.current_player.field[move[2]] minion.attack(minion.targets[move[3]]) elif move[0] == MOVE.HERO_ATTACK: hero = self.game.current_player.hero hero.attack(hero.targets[move[3]]) elif move[0] == MOVE.CHOICE: self.game.current_player.choice.choose(move[1]) else: raise NameError("DoMove ran into unclassified card", move) except: return def GetMoves(self): """ Get all possible moves from this state. """ if self.game is not None: if self.game.current_player.playstate != PlayState.PLAYING: return [] valid_moves = [ ] # Move format is [enum, card, index of card in hand, target index] if self.game is None and len(self.deck1) == 30 and len( self.deck2) == 30: valid_moves.append([MOVE.PRE_GAME]) elif self.game is None and len( self.deck1) == 30 and self.hero2 is None: valid_moves.append([MOVE.PICK_CLASS, DRUID]) valid_moves.append([MOVE.PICK_CLASS, HUNTER]) valid_moves.append([MOVE.PICK_CLASS, MAGE]) valid_moves.append([MOVE.PICK_CLASS, PALADIN]) valid_moves.append([MOVE.PICK_CLASS, PRIEST]) valid_moves.append([MOVE.PICK_CLASS, ROGUE]) valid_moves.append([MOVE.PICK_CLASS, SHAMAN]) valid_moves.append([MOVE.PICK_CLASS, WARLOCK]) valid_moves.append([MOVE.PICK_CLASS, WARRIOR]) elif self.game is None and len(self.deck1) < 30 or len( self.deck2) < 30: collection = [] exclude = [] if len(self.deck1) < 30: hero = cards.db[self.hero1] deck = self.deck1 else: hero = cards.db[self.hero2] deck = self.deck2 for card in cards.db.keys(): if card in exclude: continue cls = cards.db[card] if not cls.collectible: continue if cls.type == CardType.HERO: # Heroes are collectible... continue if cls.card_class and cls.card_class != hero.card_class: continue collection.append(cls) for card in collection: if card.rarity == Rarity.LEGENDARY and card.id in deck: continue elif deck.count(card.id) < Deck.MAX_UNIQUE_CARDS: valid_moves.append([MOVE.PICK_CARD, card]) elif self.game.current_player.choice is not None: for card in self.game.current_player.choice.cards: valid_moves.append([MOVE.CHOICE, card]) else: # Play card for card in self.game.current_player.hand: dupe = False for i in range(len(valid_moves)): if valid_moves[i][1].id == card.id: dupe = True break if not dupe: if card.is_playable(): if card.has_target(): for t in range(len(card.targets)): valid_moves.append([ MOVE.PLAY_CARD, card, self.game.current_player.hand.index(card), t ]) else: valid_moves.append([ MOVE.PLAY_CARD, card, self.game.current_player.hand.index(card), None ]) # Hero Power heropower = self.game.current_player.hero.power if heropower.is_usable(): if heropower.has_target(): for t in range(len(heropower.targets)): valid_moves.append([MOVE.HERO_POWER, None, None, t]) else: valid_moves.append([MOVE.HERO_POWER, None, None, None]) # Minion Attack for minion in self.game.current_player.field: if minion.can_attack(): for t in range(len(minion.targets)): valid_moves.append([ MOVE.MINION_ATTACK, minion, self.game.current_player.field.index(minion), t ]) # Hero Attack hero = self.game.current_player.hero if hero.can_attack(): for t in range(len(hero.targets)): valid_moves.append([MOVE.HERO_ATTACK, hero, None, t]) valid_moves.append([MOVE.END_TURN]) return valid_moves def GetResult(self, playerjm): """ Get the game result from the viewpoint of playerjm. """ if self.game.players[0].hero.health <= 0 and self.game.players[ 1].hero.health <= 0: return 0.1 elif self.game.players[playerjm - 1].hero.health <= 0: # loss return 0 elif self.game.players[2 - playerjm].hero.health <= 0: # win return pow(0.99, self.game.turn) else: # Should not be possible to get here unless we terminate the game early. return 0.1 def __repr__(self): try: s = "Turn: " + str(self.game.turn) s += "\n[" + str( self.game.players[0].hero.health) + " hp ~ " + str( len(self.game.players[0].hand)) + " in hand ~ " + str( self.game.players[0].tempMana) + "/" + str( self.game.players[0].maxMana) + " mana] " #s += "\n[" + str(self.game.players[0].hero.health) + " hp ~ " + str(len(self.game.players[0].hand)) + " in hand ~ " + str(self.game.players[0].deck.left) + "/" + str(len(self.game.players[0].deck.cards)) + " in deck ~ " + str(self.game.players[0].mana) + "/" + str(self.game.players[0].max_mana) + " mana] " for minion in self.game.players[0].field: s += str(minion.atk) + "/" + str(minion.health) + ":" s += "\n[" + str( self.game.players[1].hero.health) + " hp ~ " + str( len(self.game.players[1].hand)) + " in hand ~ " + str( self.game.players[1].tempMana) + "/" + str( self.game.players[1].maxMana) + " mana] " #s += "\n[" + str(self.game.players[1].hero.health) + " hp ~ " + str(len(self.game.players[1].hand)) + " in hand ~ " + str(self.game.players[1].deck.left) + "/" + str(len(self.game.players[1].deck.cards)) + " in deck ~ " + str(self.game.players[1].mana) + "/" + str(self.game.players[1].max_mana) + " mana] " for minion in self.game.players[1].field: s += str(minion.atk) + "/" + str(minion.health) + ":" s += "\n" + "Current Player: " + str(self.game.currentPlayer) return s except: s = "Deck 1: " + ", ".join(self.deck1) s += "\nDeck 2: " + ", ".join(self.deck2) return s
def load_game(): data = json.load(open("N://HSTracker//board_state-hunter.json")) assert "player" in data assert "opponent" in data player_name = data["player"]["name"] opponent_name = data["opponent"]["name"] player_class = get_class(data["player"]["playerClass"]) opponent_class = get_class(data["opponent"]["playerClass"]) player_deck = random_draft(player_class) opponent_deck = random_draft(opponent_class) # Keep just enough cards for mulligan while len(player_deck) > 4: player_deck.pop() while len(opponent_deck) > 4: opponent_deck.pop() player_controller_id = data["player"]["entity"]["Tags"]["CONTROLLER"] opponent_controller_id = data["opponent"]["entity"]["Tags"]["CONTROLLER"] player_player = Player(player_name, player_deck, player_class.default_hero) opponent_player = Player(opponent_name, opponent_deck, opponent_class.default_hero) game = None if player_controller_id == 1 and opponent_controller_id == 2: game = Game(players=(player_player, opponent_player)) elif player_controller_id == 2 and opponent_controller_id == 1: game = Game(players=(opponent_player, player_player)) game.start() # Don't redraw mulligan cards for player in game.players: if player.choice: player.choice.choose() assert "cardsInHand" in data["opponent"] cards_in_opponent_hand = data["opponent"]["cardsInHand"] game.players[player_controller_id - 1].discard_hand() game.players[opponent_controller_id - 1].discard_hand() # fill the hand of the opponent with the card which doesn't do anything on draw / reveal for i in range(0, cards_in_opponent_hand): game.players[opponent_controller_id - 1].give("OG_335") # Shifting Shade assert "entity" in data["player"] assert "Tags" in data["player"]["entity"] process_tags(game.players[player_controller_id - 1], data["player"]["entity"]["Tags"]) assert "entity" in data["opponent"] assert "Tags" in data["opponent"]["entity"] process_tags(game.players[opponent_controller_id - 1], data["opponent"]["entity"]["Tags"]) cards_to_recheck = list() for entity in data["hand"]: assert "Tags" in entity assert "CONTROLLER" in entity["Tags"] controller = entity["Tags"]["CONTROLLER"] assert controller == player_controller_id assert "CardId" in entity cur_card_id = entity["CardId"] cur_card = game.players[controller - 1].give(cur_card_id) set_card_tags(cur_card, entity["Tags"], game) add_to_tags_verify_list(cards_to_recheck, cur_card, entity["Tags"]) # first summon heroes and their powers for entity in data["board"]: assert "Tags" in entity and "CONTROLLER" in entity["Tags"] cur_controller_id = entity["Tags"]["CONTROLLER"] assert cur_controller_id == 1 or cur_controller_id == 2 cur_controller = game.players[cur_controller_id - 1] assert "HasCardId" in entity and entity["HasCardId"] is True and "CardId" in entity cur_card_id = entity["CardId"] temp_card = Card(cur_card_id) if isinstance(temp_card, Hero) or isinstance(temp_card, HeroPower) or isinstance(temp_card, Weapon): cur_card = cur_controller.summon(cur_card_id) add_to_tags_verify_list(cards_to_recheck, cur_card, entity["Tags"]) set_card_tags(cur_card, entity["Tags"], game) for entity in data["board"]: assert "Tags" in entity and "CONTROLLER" in entity["Tags"] cur_controller_id = entity["Tags"]["CONTROLLER"] assert cur_controller_id == 1 or cur_controller_id == 2 cur_controller = game.players[cur_controller_id - 1] assert "HasCardId" in entity and entity["HasCardId"] is True and "CardId" in entity cur_card_id = entity["CardId"] temp_card = Card(cur_card_id) if isinstance(temp_card, Enchantment): if cur_card_id != 'EX1_059e' and cur_card_id != 'OG_281e': # don't apply "Experiments!" (health swap) buff # don't apply "Fanatic Devotion" buff (must be C'thun's increased stats) if not ("ATTACHED" in entity["Tags"]): # sometimes enchantments stay in play while not being attached to anything continue attached_id = entity["Tags"]["ATTACHED"] buff_attached_to = get_game_entity_by_id(game, attached_id) assert not (buff_attached_to is None) cur_card = my_add_buff(buff_attached_to, temp_card) set_card_tags(cur_card, entity["Tags"], game) elif not (isinstance(temp_card, Hero) or isinstance(temp_card, HeroPower)): cur_card = my_summon(game, cur_controller, temp_card) add_to_tags_verify_list(cards_to_recheck, cur_card, entity["Tags"]) set_card_tags(cur_card, entity["Tags"], game) for t in cards_to_recheck: set_card_tags(t[0], t[1], game) ensure_tags_are_same(t[0], t[1]) for player in game.players: sorted_cards = dict() for card in player.field: if isinstance(card, Weapon): continue zone_position = card._summon_index assert not zone_position in sorted_cards sorted_cards[zone_position] = card player.field = CardList() for pos in sorted(sorted_cards.keys()): assert pos == len(player.field) player.field.append(sorted_cards[pos]) game.current_player = game.players[player_controller_id - 1] for player in game.players: player.cards_played_this_turn = 0 player.minions_played_this_turn = 0 player.minions_killed_this_turn = 0 return game
from fireplace.exceptions import GameOver from fireplace.entity import Entity from fireplace.game import Game from fireplace.player import Player from fireplace.utils import random_draft from hearthstone.enums import PlayState cards.db.initialize() fireplace.logging.log.setLevel(logging.WARN) deck1 = random_draft(SHAMAN) deck2 = random_draft(PALADIN) player1 = Player("Player1", deck1, SHAMAN) player2 = Player("Player2", deck2, PALADIN) game = Game(players=(player1, player2)) game.start() for player in game.players: if player.choice: player.choice.choose() begin_time = datetime.datetime.utcnow() N = 100 for i in range(N): game2 = copy.deepcopy(game) end_time = datetime.datetime.utcnow() print((end_time - begin_time) / N)