class Board: def __init__(self, exit_on_game_over=False): self.actions = ActionFactory(self) self.deck1 = [] self.deck2 = [] self.players = [] self.sides = [[], []] self.active_player = 0 self.exit_on_game_over = exit_on_game_over self.winner = None def initialize_game(self): initializer = DeckInitializer() self.deck1 = initializer.make_std_deck() self.deck2 = initializer.make_std_deck() p1_starts = self._player1_starts() self.active_player = 0 if p1_starts else 1 self.players = [ Player(id=1, deck=self.deck1, hand=Hand(self.deck1), starts=p1_starts), Player(id=2, deck=self.deck2, hand=Hand(self.deck2), starts=not p1_starts) ] self.sides = [[initializer.create_hero('jaina')], [initializer.create_hero('jaina')]] def _player1_starts(self): return random() < 0.5 def play_minion(self, index): self.execute_action(self.actions.play_minion(index)) def cast_spell(self, card_idx, target_idx, safe=False): self.execute_action(self.actions.cast_spell(card_idx, target_idx, safe)) def end_turn(self, safe=False): self.execute_action(self.actions.end_turn(safe)) def active_draw_card(self, card_idx): self.execute_action(self.actions.draw(card_idx)) def attack(self, atk_idx, def_idx, safe=False): self.execute_action(self.actions.attack(atk_idx, def_idx, safe)) def execute_action(self, action): action.execute() def change_active_player(self): self.active_player = self.get_other_idx() def get_active_hand(self): return self.get_active_player().hand def get_other_hand(self): return self.get_other_player().hand def get_active_deck(self): return self.get_active_player().deck def get_other_deck(self): return self.get_other_player().deck def get_active_idx(self): return self.active_player def get_other_idx(self): return 1 if self.active_player == 0 else 0 def get_active_side(self): return self.sides[self.get_active_idx()] def get_other_side(self): return self.sides[self.get_other_idx()] def get_active_player(self): return self.players[self.get_active_idx()] def get_other_player(self): return self.players[self.get_other_idx()] def game_loop(self): pass def game_over(self, active): self.winner = active+1 if self.exit_on_game_over: print(str(self)) print('Player #{} won!'.format(active+1)) sys.exit(self.winner) def is_game_over(self): return self.winner is not None def __str__(self): board_str = '' for player in self.players: board_str += str(player) + '\n' i = 1 board_str += '\n\n' for side in self.sides: board_str += 'SIDE OF PLAYER #{}:\n'.format(i) i += 1 for card in side: board_str += '{}\n'.format(card) return board_str
class Analyzer: def __init__(self, board): self.board = board self.actions = ActionFactory(board) self.reviewer = BoardReviewer(board) def generate_actions(self): if self.board.is_game_over(): return [] all_actions = [] all_actions.extend(self.generate_playing_minions()) all_actions.extend(self.generate_attacks()) all_actions.extend(self.generate_casting_spells()) all_actions.extend(self.generate_ending_turn()) # all_actions.extend(self.generate_card_draw()) return all_actions def grade_board(self): return self.reviewer.grade_board() def generate_playing_minions(self): player = self.board.get_active_player() active_side = self.board.get_active_side() actions = [] for idx, card in enumerate(player.hand.cards): if card.cost <= player.mana: if card.type == 'minion': if len(active_side) < 7: actions.append(self.actions.play_minion(idx)) return actions def generate_ending_turn(self): return [self.actions.end_turn()] def generate_attacks(self): active_side = self.board.get_active_side() other_side = self.board.get_other_side() actions = [] for idx, minion in enumerate(active_side): # Skip the hero if idx == 0: continue if minion.can_attack: taunts = [c for c in other_side if c.taunt] for enemyidx, enemy in enumerate(other_side): if taunts: if enemy.taunt: actions.append(self.actions.attack(idx, enemyidx)) else: actions.append(self.actions.attack(idx, enemyidx)) return actions def generate_casting_spells(self): active_player = self.board.get_active_player() other_side = self.board.get_other_side() actions = [] for cardidx, card in enumerate(active_player.hand.cards): if card.type != 'spell': continue if card.cost > active_player.mana: continue for enemyidx, _ in enumerate(other_side): actions.append(self.actions.cast_spell(cardidx, enemyidx)) return actions def generate_card_draw(self): deck = self.board.get_active_deck() card_scores = [self.reviewer.grade_card(c) for c in deck.cards] max_score_idx = card_scores.index(max(card_scores)) return [self.actions.draw(max_score_idx)]