Example #1
0
 def __init__(self):
     super(TinderWall, self).__init__('Tinder Wall', is_permanent=True)
     tinder_wall_play_action = Action('Tinder Wall',
                                      'Play',
                                      requirements=[
                                          CardInHand(self.name),
                                          ManaInPool(ColorDict({'Green':
                                                                1}))
                                      ],
                                      consequences=[
                                          MoveCard(self.name, 'Hand',
                                                   'Battlefield'),
                                          ReduceMana(ColorDict({'Green':
                                                                1})),
                                          AddStorm()
                                      ])
     tinder_wall_mana_action = Action('Tinder Wall',
                                      'Sacrifice',
                                      requirements=[CardInPlay(self.name)],
                                      consequences=[
                                          MoveCard(self.name, 'Battlefield',
                                                   'Graveyard'),
                                          AddMana(ColorDict({'Red': 2}))
                                      ])
     self.add_action(tinder_wall_play_action)
     self.add_action(tinder_wall_mana_action)
Example #2
0
 def reset_game(self, draw_opening_hand=True, test=False):
     for card, maindeck, sideboard in self.cards:
         self.deck[card.name] = maindeck
         if sideboard > 0:
             self.sideboard[card.name] = sideboard
         self.hand[card.name] = 0
         self.exile[card.name] = 0
         if card.is_permanent:
             self.battlefield[card.name] = 0
         self.graveyard[card.name] = 0
         if card.is_tappable:
             self.tapped[card.name] = 0
     self.mana_pool = ColorDict()
     self.goblins = 0
     self.storm_count = 0
     self.opp_life_total = 20
     self.taiga_bottom = False
     self.turn = 1
     self.lost = False
     self.won = False
     if draw_opening_hand:
         self.draw_opening_hand()
     if test:
         self.add_mana(ColorDict({'Red': 2}))
         self.increase_card_count('Goblin Charbelcher', 'Battlefield')
         self.increase_card_count('Taiga', 'Battlefield')
         #self.increase_card_count('Seething Song', 'Hand')
         self.reduce_card_count('Goblin Charbelcher', 'Deck')
         self.reduce_card_count('Taiga', 'Deck')
Example #3
0
 def __init__(self):
     super(ChromeMox, self).__init__('Chrome Mox',
                                     is_tappable=True,
                                     is_permanent=True)
     for card_for_chrome_mox in CARDS_FOR_CHROME_MOX:
         chrome_mox_play = Action('Chrome Mox',
                                  'Play',
                                  requirements=[
                                      CardInHand(self.name),
                                      CardInHand(card_for_chrome_mox)
                                  ],
                                  consequences=[
                                      MoveCard(self.name, 'Hand',
                                               'Battlefield'),
                                      MoveCard(card_for_chrome_mox, 'Hand',
                                               'Exile'),
                                      AddStorm()
                                  ])
         self.add_action(chrome_mox_play)
     chrome_mox_activate = Action('Chrome Mox',
                                  'Activate',
                                  requirements=[CardUntapped(self.name)],
                                  consequences=[Tap(self.name)])
     self.add_mana_action(chrome_mox_activate,
                          adding=[ColorDict({c: 1}) for c in COLORS])
Example #4
0
 def __init__(self):
     super(RiteOfFlame, self).__init__('Rite of Flame')
     rite_of_flame_action = Action('Rite of Flame',
                                   'Play',
                                   requirements=[
                                       CardInHand(self.name),
                                       ManaInPool(ColorDict({'Red': 1}))
                                   ],
                                   consequences=[
                                       MoveCard(self.name, 'Hand',
                                                'Graveyard'),
                                       ReduceMana(ColorDict({'Red': 1})),
                                       AddStorm(),
                                       AddRiteMana()
                                   ])
     self.add_action(rite_of_flame_action)
Example #5
0
 def __init__(self):
     super(SeethingSong, self).__init__('Seething Song')
     seething_song_action = Action('Seething Song',
                                   'Play',
                                   requirements=[CardInHand(self.name)],
                                   consequences=[
                                       AddMana(ColorDict({'Red': 5})),
                                       MoveCard(self.name, 'Hand',
                                                'Graveyard'),
                                       AddStorm()
                                   ])
     self.add_mana_action(seething_song_action,
                          paying=color_combinations(
                              ColorDict({
                                  'Red': 1,
                                  'Colorless': 2
                              })))
Example #6
0
 def __init__(self):
     super(Manamorphose, self).__init__('Manamorphose')
     manamorphose_action = Action('Manamorphose',
                                  'Play',
                                  requirements=[CardInHand(self.name)],
                                  consequences=[
                                      MoveCard(self.name, 'Hand',
                                               'Graveyard'),
                                      DrawCard(),
                                      AddStorm()
                                  ])
     self.add_mana_action(
         manamorphose_action,
         paying=color_combinations(ColorDict({
             'Red': 1,
             'Colorless': 1
         })),
         adding=fill_up_remaining_colors(2, COLORS, ColorDict(), []))
Example #7
0
def color_combinations(mana_cost):
    """

    :param mana_cost:
    :return: list of ColorDicts, representing the possbile mana combinations
    """
    always = ColorDict(mana_cost)
    colorless_remaining = mana_cost['Colorless']
    del always['Colorless']
    options = fill_up_remaining_colors(colorless_remaining, COLORS, always, [])
    return options
Example #8
0
 def __init__(self):
     super(SimianSpiritGuide, self).__init__('Simian Spirit Guide')
     simian_spirit_guide_action = Action(
         'Simian Spirit Guide',
         'Exile',
         requirements=[CardInHand(self.name)],
         consequences=[
             AddMana(ColorDict({'Red': 1})),
             MoveCard(self.name, 'Hand', 'Exile')
         ])
     self.add_action(simian_spirit_guide_action)
Example #9
0
    def __init__(self):
        super(ElvishSpiritGuide, self).__init__('Elvish Spirit Guide')
        elvish_spirit_guide_action = Action(
            'Elvish Spirit Guide',
            'Exile',
            requirements=[CardInHand(self.name)],
            consequences=[
                AddMana(ColorDict({'Green': 1})),
                MoveCard(self.name, 'Hand', 'Exile')
            ])

        self.add_action(elvish_spirit_guide_action)
Example #10
0
    def __init__(self):
        self.deck = {}
        self.hand = {}
        self.exile = {}
        self.sideboard = {}
        self.battlefield = {}
        self.graveyard = {}
        self.tapped = {}

        self.mana_pool = ColorDict()
        self.goblins = 0
        self.storm_count = 0
        self.opp_life_total = 20
        self.taiga_bottom = False
        self.turn = 1
        self.lost = False
        self.won = False

        self.actions_set = False
        self.actions = []

        self.cards = []
Example #11
0
 def __init__(self):
     super(ReforgeTheSoul, self).__init__('Reforge the Soul')
     reforge_the_soul_action = Action(
         'Reforge the Soul',
         'Play',
         requirements=[CardInHand(self.name)],
         consequences=[DiscardHand(),
                       DrawCard(7), AddStorm()])
     self.add_mana_action(reforge_the_soul_action,
                          paying=color_combinations(
                              ColorDict({
                                  'Red': 2,
                                  'Colorless': 3
                              })))
Example #12
0
 def __init__(self):
     super(GoblinCharbelcher, self).__init__('Goblin Charbelcher',
                                             is_tappable=True,
                                             is_permanent=True)
     charbelcher_play = Action('Goblin Charbelcher',
                               'Play',
                               requirements=[CardInHand(self.name)],
                               consequences=[
                                   MoveCard(self.name, 'Hand',
                                            'Battlefield'),
                                   AddStorm()
                               ])
     charbelcher_activate = Action(
         'Goblin Charbelcher',
         'Activate',
         requirements=[CardInPlay(self.name),
                       CardUntapped(self.name)],
         consequences=[Tap(self.name), Belch()])
     self.add_mana_action(charbelcher_play,
                          paying=color_combinations(
                              ColorDict({'Colorless': 4})))
     self.add_mana_action(charbelcher_activate,
                          paying=color_combinations(
                              ColorDict({'Colorless': 3})))
Example #13
0
 def __init__(self):
     super(EmptyTheWarrens, self).__init__('Empty the Warrens')
     empty_the_warrens_action = Action('Empty the Warrens',
                                       'Play',
                                       requirements=[CardInHand(self.name)],
                                       consequences=[
                                           AddStorm(),
                                           AddGoblins(),
                                           MoveCard(self.name, 'Hand',
                                                    'Graveyard')
                                       ])
     self.add_mana_action(empty_the_warrens_action,
                          paying=color_combinations(
                              ColorDict({
                                  'Red': 1,
                                  'Colorless': 3
                              })))
Example #14
0
 def __init__(self):
     super(DesperateRitual, self).__init__('Desperate Ritual')
     desperate_ritual_action = Action('Desperate Ritual',
                                      'Play',
                                      requirements=[CardInHand(self.name)],
                                      consequences=[
                                          AddMana({'Red': 3}),
                                          AddStorm(),
                                          MoveCard(self.name, 'Hand',
                                                   'Graveyard')
                                      ])
     self.add_mana_action(desperate_ritual_action,
                          paying=color_combinations(
                              ColorDict({
                                  'Red': 1,
                                  'Colorless': 1
                              })))
Example #15
0
 def __init__(self):
     super(Taiga, self).__init__('Taiga',
                                 is_tappable=True,
                                 is_permanent=True)
     taiga_action_play = Action(
         'Taiga',
         'Play',
         requirements=[CardInHand(self.name)],
         consequences=[MoveCard(self.name, 'Hand', 'Battlefield')])
     taiga_action_tap = Action('Taiga',
                               'Tap',
                               requirements=[CardUntapped(self.name)],
                               consequences=[Tap(self.name)])
     self.add_action(taiga_action_play)
     self.add_mana_action(taiga_action_tap,
                          adding=fill_up_remaining_colors(
                              1, ['Red', 'Green'], ColorDict(), []))
Example #16
0
 def __init__(self):
     super(LotusPetal, self).__init__('Lotus Petal', is_permanent=True)
     lotus_petal_play = Action('Lotus Petal',
                               'Play',
                               requirements=[CardInHand(self.name)],
                               consequences=[
                                   MoveCard(self.name, 'Hand',
                                            'Battlefield'),
                                   AddStorm()
                               ])
     lotus_petal_activate = Action(
         'Lotus Petal',
         'Sacrifice',
         requirements=[CardInPlay(self.name)],
         consequences=[MoveCard(self.name, 'Battlefield', 'Graveyard')])
     self.add_action(lotus_petal_play)
     self.add_mana_action(lotus_petal_activate,
                          adding=[ColorDict({c: 1}) for c in COLORS])
Example #17
0
 def __init__(self):
     super(BurningWish, self).__init__('Burning Wish')
     for card_for_burning_wish in CARDS_FOR_BURNING_WISH:
         burning_wish_wish = Action(
             'Burning Wish',
             'Play ' + card_for_burning_wish,
             requirements=[
                 CardInHand(self.name),
                 CardInSideboard(card_for_burning_wish)
             ],
             consequences=[
                 MoveCard(self.name, 'Hand', 'Exile'),
                 MoveCard(card_for_burning_wish, 'Sideboard', 'Hand'),
                 AddStorm()
             ])
         self.add_mana_action(burning_wish_wish,
                              paying=color_combinations(
                                  ColorDict({
                                      'Red': 1,
                                      'Colorless': 1
                                  })))
Example #18
0
 def __init__(self):
     super(LionsEyeDiamond, self).__init__('Lions Eye Diamond',
                                           is_permanent=True)
     lions_eye_diamond_play = Action('Lions Eye Diamond',
                                     'Play',
                                     requirements=[CardInHand(self.name)],
                                     consequences=[
                                         MoveCard(self.name, 'Hand',
                                                  'Battlefield'),
                                         AddStorm()
                                     ])
     lions_eye_diamond_activate = Action(
         'Lions Eye Diamond',
         'Sacrifice',
         requirements=[CardInPlay(self.name)],
         consequences=[
             DiscardHand(),
             MoveCard(self.name, 'Battlefield', 'Graveyard')
         ])
     self.add_action(lions_eye_diamond_play)
     self.add_mana_action(lions_eye_diamond_activate,
                          adding=[ColorDict({c: 3}) for c in COLORS])
Example #19
0
class GameState(object):
    def __init__(self):
        self.deck = {}
        self.hand = {}
        self.exile = {}
        self.sideboard = {}
        self.battlefield = {}
        self.graveyard = {}
        self.tapped = {}

        self.mana_pool = ColorDict()
        self.goblins = 0
        self.storm_count = 0
        self.opp_life_total = 20
        self.taiga_bottom = False
        self.turn = 1
        self.lost = False
        self.won = False

        self.actions_set = False
        self.actions = []

        self.cards = []

    def add_card(self, card, maindeck, sideboard):
        self.cards.append((card, maindeck, sideboard))

    def reset_game(self, draw_opening_hand=True, test=False):
        for card, maindeck, sideboard in self.cards:
            self.deck[card.name] = maindeck
            if sideboard > 0:
                self.sideboard[card.name] = sideboard
            self.hand[card.name] = 0
            self.exile[card.name] = 0
            if card.is_permanent:
                self.battlefield[card.name] = 0
            self.graveyard[card.name] = 0
            if card.is_tappable:
                self.tapped[card.name] = 0
        self.mana_pool = ColorDict()
        self.goblins = 0
        self.storm_count = 0
        self.opp_life_total = 20
        self.taiga_bottom = False
        self.turn = 1
        self.lost = False
        self.won = False
        if draw_opening_hand:
            self.draw_opening_hand()
        if test:
            self.add_mana(ColorDict({'Red': 2}))
            self.increase_card_count('Goblin Charbelcher', 'Battlefield')
            self.increase_card_count('Taiga', 'Battlefield')
            #self.increase_card_count('Seething Song', 'Hand')
            self.reduce_card_count('Goblin Charbelcher', 'Deck')
            self.reduce_card_count('Taiga', 'Deck')
            #self.reduce_card_count('Seething Song', 'Deck')

    def possible_actions(self):
        """
        List of binary numbers to represent if that action is available

        :return:
        """
        all_actions = self.all_actions()
        legal_actions = [x.allowed(self) * 1 for x in all_actions]
        return legal_actions, all_actions

    def reward(self):
        if not self.won and not self.lost:
            return None
        if self.won:
            return 60 - self.turn
        return 1

    def all_actions(self):
        if self.actions_set:
            return self.actions
        self.actions = [
            Action('Game',
                   'Pass turn',
                   requirements=[],
                   consequences=[
                       AddTurn(),
                       UntapPermanents(),
                       ResetManaPool(),
                       StormCountZero(),
                       DrawCard(),
                       DealGoblinDamage()
                   ])
        ]
        for card, _, _ in self.cards:
            print(card.name, len(self.actions))
            self.actions.extend(card.actions)
        self.actions_set = True
        return self.actions

    def state_space(self):
        # We should make it so we can just add em all up for the correct representation.
        # The objects should know

        representation_list = []
        for card, _, _ in self.cards:
            representation_list.append(self.deck[card.name] / 4)
        for card, _, _ in self.cards:
            representation_list.append(self.hand[card.name] / 4)
        ## List over only permanents
        for card, _, _ in self.cards:
            representation_list.append(self.battlefield[card.name] / 4)
        for card, _, _ in self.cards:
            representation_list.append(self.graveyard[card.name] / 4)
        for card, _, _ in self.cards:
            if card.name in self.tapped:
                representation_list.append(self.tapped[card.name] / 4)
        for card, _, _ in self.cards:
            if card.name in self.sideboard:
                representation_list.append(self.sideboard[card.name])

        for color in COLORS:
            representation_list.append(self.mana_pool[color] / 2)
        representation_list.append(self.goblins / 10)
        representation_list.append(self.storm_count / 4)
        representation_list.append(self.opp_life_total / 20)
        representation_list.append(self.taiga_bottom * 1)
        representation_list.append(self.turn / 10)
        number_cards_in_deck = sum([self.deck[k] for k in self.deck]) / 53
        representation_list.append(number_cards_in_deck)
        return representation_list

    def untapped(self, card):
        return self.battlefield[card] > self.tapped[card]

    def mana_floating(self, c_dict):
        for k in c_dict:
            if self.mana_pool[k] < c_dict[k]:
                return False
        return True

    def card_in_hand(self, card):
        return self.hand[card] > 0

    def card_in_play(self, card):
        return self.battlefield[card] > 0

    def card_in_sideboard(self, card):
        return self.sideboard[card] > 0

    def card_in_deck(self, card):
        return self.deck[card] > 0

    def storm_count_zero(self):
        self.storm_count = 0

    def goblin_damage(self):
        self.opp_life_total -= self.goblins
        if self.opp_life_total < 1:
            self.won = True

    def damage_opponent(self, damage):
        self.opp_life_total -= damage
        if self.opp_life_total < 1:
            self.won = True

    def untap_permanents(self):
        for card, _, _ in self.cards:
            if card.is_tappable:
                self.tapped[card.name] = 0

    def add_rite_mana(self):
        self.add_mana(ColorDict({'Red': 2 + self.graveyard['Rite of Flame']}))

    def belch(self):
        deck_list = self._list_deck(True, True)
        total_damage = 0
        for card in deck_list:
            if card == 'Taiga':
                total_damage *= 2
                break
            total_damage += 1
        self.damage_opponent(total_damage)
        self.taiga_bottom = True

    def discard_hand(self):
        for card_name in self.hand:
            self.graveyard[card_name] += self.hand[card_name]
            self.hand[card_name] = 0

    def shuffle(self):
        self.taiga_bottom = False

    def draw_cards(self, amount):
        list_deck = self._list_deck()
        if len(list_deck) < amount:
            self.lost = True
        else:
            cards_to_draw = choice(list_deck, amount, False)
            for card_to_draw in cards_to_draw:
                self.deck[card_to_draw] -= 1
                self.hand[card_to_draw] += 1

    def _list_deck(self, include_Taiga=True, shuffle_list=False):
        deck_list = []
        for card_name in self.deck:
            if card_name != 'Taiga' or not self.taiga_bottom:
                deck_list.extend(
                    [card_name for _ in range(self.deck[card_name])])
        if shuffle_list:
            shuffle(deck_list)
        if self.taiga_bottom and include_Taiga and self.deck['Taiga'] > 0:
            deck_list.append('Taiga')
        return deck_list

    def tap_card(self, card):
        self.tapped[card] += 1

    def add_storm(self):
        self.storm_count += 1

    def add_goblins(self):
        self.goblins += 2 * self.storm_count

    def add_mana(self, c_dict):
        self.mana_pool.add_mana(c_dict)

    def reduce_mana(self, c_dict):
        self.mana_pool.subtract_mana(c_dict)

    def reset_mana_pool(self):
        self.mana_pool.subtract_mana(self.mana_pool)

    def increase_card_count(self, card, zone):
        self._zone_dispatcher(zone)[card] += 1

    def reduce_card_count(self, card, zone):
        self._zone_dispatcher(zone)[card] -= 1

    def draw_opening_hand(self):
        self.draw_cards(7)

    def add_turn(self):
        self.turn += 1

    def _zone_dispatcher(self, zone):
        if zone == 'Graveyard':
            return self.graveyard
        if zone == 'Battlefield':
            return self.battlefield
        elif zone == 'Hand':
            return self.hand
        elif zone == 'Exile':
            return self.exile
        elif zone == 'Deck':
            return self.deck
        elif zone == 'Sideboard':
            return self.sideboard
        raise ValueError('Incorrect zone type', zone)

    def __str__(self):
        # It'd be nice to rely on something higher level to represent the game in string form.
        # I find big functions like this hard to manage, but they might not ever really change.

        repr_str = 'GAME STATE: \n'
        #repr_str += '  Cards in hand:      ' + str(sum([self.hand[k] for k in self.hand])) + '\n'
        #repr_str += '  Cards in deck:      ' + str(sum([self.deck[k] for k in self.deck])) + '\n'
        #repr_str += '  Cards in play:      ' + str(sum([self.battlefield[k] for k in self.battlefield])) + '\n'
        #repr_str += '  Cards in graveyard: ' + str(sum([self.graveyard[k] for k in self.graveyard])) + '\n'
        #repr_str += '  Cards in sideboard: ' + str(sum([self.sideboard[k] for k in self.sideboard])) + '\n'

        repr_str += 'Hand: ' + str(sum([self.hand[k]
                                        for k in self.hand])) + ', '
        repr_str += 'Deck: ' + str(sum([self.deck[k]
                                        for k in self.deck])) + ', '
        repr_str += 'Play: ' + str(
            sum([self.battlefield[k] for k in self.battlefield])) + ', '
        repr_str += 'GY: ' + str(
            sum([self.graveyard[k] for k in self.graveyard])) + ', '
        #repr_str += '  Cards in sideboard: ' + str(sum([self.sideboard[k] for k in self.sideboard])) + '\n'

        repr_str += '\nHAND: \n'
        for k in self.hand:
            if self.hand[k] > 0:
                repr_str += k + ': ' + str(self.hand[k]) + ', '
        repr_str += '\nPLAY: \n'
        for k in self.battlefield:
            if self.battlefield[k] > 0:
                repr_str += k + ': ' + str(self.battlefield[k]) + ', '
        repr_str += '\nTAPPED: \n'
        for k in self.tapped:
            if self.tapped[k] > 0:
                repr_str += k + ': ' + str(self.tapped[k]) + ', '

        repr_str += '\nMANA POOL: '
        for c in COLORS:
            repr_str += '  ' + c + ': ' + str(self.mana_pool[c]) + ', '
        repr_str += '\nACTIONS: ' + str(sum(self.possible_actions()[0])) + '\n'
        repr_str += 'GOBLINS: ' + str(self.goblins) + '\n'
        repr_str += 'TURN: ' + str(self.turn) + '\n'
        repr_str += 'OPP LIFETOTAL: ' + str(self.opp_life_total) + '\n'

        return repr_str
Example #20
0
 def add_rite_mana(self):
     self.add_mana(ColorDict({'Red': 2 + self.graveyard['Rite of Flame']}))