Beispiel #1
0
def main():
    print("Running main.py")
    d = Deck()
    hole_cards = d.draw(2)
    # board = d.draw(5)
    board = [
        Card.from_int(1),
        Card.from_int(2),
        Card.from_int(15),
        Card.from_int(28),
        Card.from_int(5)
    ]
    print(utils.best_hand(hole_cards[0], hole_cards[1], board))
    print("Finished main.py")
Beispiel #2
0
def fetch_card_data(card_name, card_count):
    """
    Use scryfall API to convert card name to Card object

    Args:
        card_name (str): name of card
        card_count (int): number of card_names included in deck
    Returns:
        (Card): containing relevant attributes fetched from scryfall
    """
    card_obj = sc.cards.Named(fuzzy=card_name)

    mana_cost = card_obj.mana_cost()
    cmc = int(card_obj.cmc())
    color_identity = (card_obj.color_identity(), )
    card_type = (card_obj.type_line(), )
    text = card_obj.oracle_text()
    im_url = card_obj.image_uris()["normal"]

    return Card(
        card_name,
        int(card_count),
        mana_cost,
        cmc,
        color_identity,
        card_type,
        text,
        im_url,
    )
Beispiel #3
0
def main() -> None:
    """Main session flow"""
    logging.debug("Main flow invoked")
    global settings, feature1, feature2, feature3, feature4, win, lose, deck, features_total
    result = None
    print("\n" + settings.intro)
    input("\n\n\nPress ENTER to start!")
    while len(deck.cards) > 0:
        card = Card(deck)
        # Check if win or lose conditions are met
        result = condition_check()
        if result == "lose" or result == "win":
            logging.info(f"Session result confirmed: {result}")
            break
        # Loop below re-executes if input was different from "l" or "r"
        while True:
            status()  # Prints current status screen
            print(card.cta + "\n")
            print(f"Left: {card.l_text}")
            print(f"Right: {card.r_text}")
            choice = input("\nChoose your destiny! [l/r]:\n")
            if choice.lower() == 'l':
                logging.debug("Left option chosen")
                for idx, feature in enumerate(features_total):
                    feature.value += card.l_impact[idx]
                    logging.info(f"Applied {card.l_impact[idx]} to {feature.value}")
                break
            elif choice.lower() == 'r':
                logging.debug("Right option chosen")
                for idx, feature in enumerate(features_total):
                    feature.value += card.r_impact[idx]
                    logging.info(f"Applied {card.r_impact[idx]} to {feature.value}")
                break
        clear()

    # End of session
    if result == 'win':
        logging.info("Win conditions achieved")
        print("\nYOU WON!\n")
        print(win.text)
    elif result == 'lose':
        logging.info("Lose conditions achieved")
        print("\nYOU LOST!\n")
        print(lose.text)
    else:
        logging.error("Unexpected end of session: %(module)s %(lineno)d")
        print("UNEXPECTED END OF SESSION")
    input("\n\nPress ENTER to exit...")

    # Clean up
    logging.debug("Cleaning all values up...")
    for _ in [settings, feature1, feature2, feature3, feature4, win, lose, deck]:
        _ = None
    features_total = []
    clear()
Beispiel #4
0
def initiate_carddeck():
    ''''initiate the 12 cards of the carddeck.'''
    cards = []
    for difficulty_level in range(3):
        y = 100 + difficulty_level * (PADDING_V + RECTHEIGHT_CARDDECK
                                      )  # determining the y coordinate
        for __ in range(4):  #instance the 4 card
            x = START_X_CARDS + __ * (PADDING_H + RECTWIDTH_CARDDECK
                                      )  # determining the x coordinate
            c = Card(difficulty_level, x, y, RECTWIDTH_CARDDECK,
                     RECTHEIGHT_CARDDECK, LETTER_FONT)
            cards.append(c)
    return cards
Beispiel #5
0
 def loaddeck(self):
     filepath = "deck.txt"
     with open(filepath, "r") as file:
         line = file.readline()
         while line:
             row = line.split(",")
             if row[0] == "Card":
                 self.deck.append(Card(row[1], row[2]))
             elif row[0] == "Gem":
                 if len(row) == 6:
                     self.deck.append(
                         Gem(row[1], row[2], row[3], bool(row[4]),
                             [int(row[5])]))
                 elif len(row) == 7:
                     values = [int(row[5]), int(row[6])]
                     self.deck.append(
                         Gem(row[1], row[2], row[3], bool(row[4]), values))
             line = file.readline()
         for player in self.players:
             self.deck.pop()
     self.shuffledeck(7)
     self.deck.insert(0, Card("fire in the hole", "action"))
     print("Deck loaded.")
Beispiel #6
0
def longest_run(player):
    """Get longest natural run to determine hold and discard logic."""
    # initialise collectors
    unique_cards = ([], [])
    card_vals = ([], [])
    longest = [[], []]
    max_length = [0, 0]

    # separate card into colours
    for card in player.hand:
        if not card.value == 25:
            if card.value not in card_vals[card.colour]:
                unique_cards[card.colour].append(card.name)
                card_vals[card.colour].append(card.value)

    # iterate through all combinations
    curr_colour = -1
    for colour in unique_cards:
        curr_colour += 1
        elements = len(colour)
        # generate slice positions
        for i in range(2, elements + 1):
            for j in range(0, i):
                # do slice and determine length of run
                temp = colour[j:i]
                check_val = [Card(card).value for card in temp]
                length = Group(temp).check_run(check_val)
                # hold longest run length
                if length > max_length[curr_colour]:
                    max_length[curr_colour] = length
                    longest[curr_colour] = temp

    # determine if max length is equal, else hold both coloured runs
    if max_length[0] == max_length[1]:
        l_colour = (0, 1)
    elif max_length[0] > max_length[1]:
        l_colour = (0, )
    else:
        l_colour = (1, )

    return max_length, longest, l_colour
Beispiel #7
0
class TestCardFunctions(unittest.TestCase):
    def setUp(self):
        self.ace = Card('Ace', 11)
        self.card = Card('1', 1)

    def test_card_has_value(self):
        card_value = self.card.get_card_value()
        self.assertEqual(1, card_value)

    def test_set_card_value(self):
        self.card.set_card_value(2)
        self.assertEqual(2, self.card.get_card_value())

    def test_get_card_name(self):
        card_name = self.ace.get_card_name()
        self.assertEqual('Ace', card_name)

    def test_card_is_ace(self):
        self.assertTrue(self.ace.is_ace())
        self.assertFalse(self.card.is_ace())
Beispiel #8
0
def gen_discard(phase, player, table, counts):
    """Generate discards given hand and table status."""
    # initialise collectors
    discard = []
    natural = []
    wild = []
    mval = []
    hval = []
    suit = []
    hold_4s = []

    # get current conditions for values and suits
    exwild = [card.name for card in player.hand if not card.value == 25]
    # value conditions
    v = counts['values']
    max_val = max(v.values())
    try:
        min_val = min(v.values())
    except ValueError:
        min_val = None
    for value, count in v.items():
        if count == min_val:
            mval.append(value)
        elif count == max_val:
            hval.append(value)
    # suit conditions
    try:
        min_suit = min(counts['suits'].values())
    except ValueError:
        min_suit = None
    for value, count in counts['suits'].items():
        if count == min_suit:
            suit.append(value)

    # do not discard valid plays to next player
    player_phase = table.status[player.pid].phase
    if player.pid + 1 == 4:
        next_player_phase = table.status[0].phase
    else:
        next_player_phase = table.status[player.pid + 1].phase
    if (player_phase is None and next_player_phase is not None):
        test_4s = []
        val_4s = []
        gen_4s(player.hand, table, test_4s)
        check_4s(table, test_4s, val_4s)
        hold_4s = [play[1][0] for play in val_4s]

    # get current draw probabilities and additional hold logic
    prob = prob_count(player, table)
    hold = gen_hold(phase, player, table, counts)
    for card in player.hand:
        if card.value == 25:
            wild.append(card)
        else:
            natural.append(card)

    # discard largest value for phase played
    if phase is None:
        for card in natural:
            discard.append(card.name)
        temp = [Card(i) for i in discard]
        temp.sort(key=attrgetter('value'), reverse=True)
        discard = [card.name for card in temp]
        return discard

    if phase == 1 or phase == 3:
        for card in natural:
            # discard lowest (non)multiple
            if card.value in mval:
                discard.append(card.name)
            # discard overdrawn card (essentially 0 probability)
            elif ((prob[2][card.value] <= 0 and card.value not in hval)
                  or card.value not in hval):
                discard.append(card.name)

    elif phase == 2:
        for card in natural:
            # discard smallest suit
            if card.suit in suit:
                discard.append(card.name)
        # sort by highest value
        temp = [Card(i) for i in discard]
        temp.sort(key=attrgetter('value'), reverse=True)
        discard = [card.name for card in temp]
        # for same length suits, hold more probable
        sorting = [(prob[1][Card(i).suit], Card(i)) for i in discard]
        sorting.sort(key=lambda x: x[0])
        discard = [card[1].name for card in sorting]

    elif phase == 4:
        # discard duplicates
        for card in natural:
            if v[card.value] > 1:
                discard.append(card.name)
        # sort by highest value
        temp = [Card(i) for i in discard]
        temp.sort(key=attrgetter('value'), reverse=True)
        discard = [card.name for card in temp]

    elif phase == 5:
        # utilised hold logic for discard
        for card in natural:
            if card.name not in hold:
                if card.value not in hval:
                    discard.append(card.name)
        if not len(discard):
            for card in natural:
                if card.value in hval:
                    discard.append(card.name)

    # sort by highest value, then by probability (hold more probable)
    if phase == 1 or phase == 3 or phase == 5:
        temp = [Card(i) for i in discard]
        temp.sort(key=attrgetter('value'), reverse=True)
        discard = [card.name for card in temp]
        sorting = [(prob[2][Card(i).value], Card(i)) for i in discard]
        sorting.sort(key=lambda x: x[0])
        discard = [card[1].name for card in sorting]

    # clear cards not caught by basic logic
    for card in hold:
        if card in discard:
            discard.remove(card)
    for card in hold_4s:
        if card in discard:
            discard.remove(card)
    if not len(discard):
        discard.append(exwild[-1])

    return discard
Beispiel #9
0
def gen_viable(phase, player, table, counts):
    """Generate viable cards given hand and table status."""
    v = counts['values']
    discard = table.discard
    viable = []
    if discard is None:
        return

    # get discard, try placing on phases
    if phase is None:
        card = [discard]
        logical_plays = []
        valid_plays = []
        gen_4s(card, table, logical_plays)
        check_4s(table, logical_plays, valid_plays)
        # draw from discard if valid play 4
        if len(valid_plays):
            viable.append(discard.name)
            logical_plays.clear()
            valid_plays.clear()
        return viable

    # draw card if at least 2, at most 5 of the same value
    if phase == 1 or phase == 3:
        if 2 <= counts['values'][discard.value] <= 5:
            viable.append(discard.name)

    # draw card if at least 4 of the same suit
    elif phase == 2:
        if counts['suits'][discard.suit] >= 4:
            viable.append(discard.name)

    # draw card if neighbour to held card value and not repeat
    elif phase == 4:
        pos = discard.value
        if v[max((pos - 1), 2)] == 0 or v[min((pos + 1), 13)] == 0:
            if v[pos] == 0:
                viable.append(discard.name)

    # draw card if at least 2 of the same value
    # or neighbour to held card value
    elif phase == 5:
        pos = discard.value
        longest = longest_run(player)
        values = (dd(int), dd(int))
        hval = []
        max_val = max(v.values())
        for value, count in v.items():
            if count == max_val:
                hval.append(value)
        # count by colour
        for card in player.hand:
            if not card.value == 25:
                if not card.colour:
                    values[0][card.value] += 1
                else:
                    values[1][card.value] += 1
        if discard.value in hval and 2 <= v[discard.value] <= 5:
            viable.append(discard.name)

        # both colours same run length
        if len(longest[2]) == 2:
            pass
        # black longest run
        elif not longest[2][0]:
            terminals = (Card(longest[1][0][0]), Card(longest[1][0][-1]))
            if not discard.colour:
                if (discard.value + 1 == terminals[0].value
                        or discard.value - 1 == terminals[1].value):
                    viable.append(discard.name)
        # red longest run
        else:
            terminals = (Card(longest[1][1][0]), Card(longest[1][1][-1]))
            if discard.colour:
                if (discard.value + 1 == terminals[0].value
                        or discard.value - 1 == terminals[1].value):
                    viable.append(discard.name)

        # catch values at edge of values, or middle (joining) card
        pos = discard.value
        col = discard.colour
        start = max((pos - 1), 2)
        end = min((pos + 1), 13)
        if discard.value == 2 or discard.value == 13:
            if values[col][start] > 0 or values[col][end] > 0:
                viable.append(discard.name)
        elif values[col][start] > 0 and values[col][end] > 0:
            viable.append(discard.name)

    return viable
Beispiel #10
0
def prob_count(player, table):
    """Get probability of card occurrence."""
    # get current game status and history
    history = table.history
    played = table.status
    # define collector dictionaries and variables
    deck = 63
    player_hands = {0: 10, 1: 10, 2: 10, 3: 10}
    prob_col = {0: 48, 1: 48}
    suits = ('C', 'D', 'H', 'S')
    prob_val = {}
    prob_suit = {}
    for val in range(2, 14):
        prob_val[val] = 8
    prob_val[25] = 8
    for suit in suits:
        prob_suit[suit] = 24

    # iterate through history elements for probability count
    for group in history:
        curr_player = group[0]
        plays = group[1]
        for play in plays:

            if play[0] == 1:
                player_hands[curr_player] += 1
                deck -= 1

            # additional logic for opponent draws (hand comp prediction)
            if play[0] == 2:
                player_hands[curr_player] += 1
                if ((table.phase_status[curr_player] == 1
                     or table.phase_status[curr_player] == 3)
                        and not curr_player == player.pid):
                    picked = Card(play[1])
                    prob_val[picked.value] -= 1
                if table.phase_status[curr_player] == 2:
                    picked = Card(play[1])
                    if not picked.value == 25:
                        prob_suit[picked.suit] -= 1

            if play[0] == 3:
                no_cards = 0
                for group in play[1]:
                    no_cards += len(group)
                player_hands[curr_player] -= no_cards

            if play[0] >= 4:
                player_hands[curr_player] -= 1

            if play[0] == 5:
                discarded = Card(play[1])
                if not discarded.value == 25:
                    prob_col[discarded.colour] -= 1
                    prob_suit[discarded.suit] -= 1
                prob_val[discarded.value] -= 1

    # get number of cards spent
    for phase in played:
        for card in phase.cards:
            if not card.value == 25:
                prob_col[card.colour] -= 1
                prob_suit[card.suit] -= 1
            prob_val[card.value] -= 1
    for card in player.hand:
        if not card.value == 25:
            prob_col[card.colour] -= 1
            prob_suit[card.suit] -= 1
        prob_val[card.value] -= 1

    # simple probability deduction
    cards_left = sum(player_hands.values()) + deck - len(player.hand)
    for k, v in prob_col.items():
        prob_col[k] = v / cards_left
    for k, v in prob_val.items():
        prob_val[k] = v / cards_left
    for k, v in prob_suit.items():
        prob_suit[k] = v / cards_left

    return prob_col, prob_suit, prob_val, player_hands
Beispiel #11
0
    def setUp(self):
        self.blackjack_hand = Hand([Card('7', 7), Card('7', 7), Card('7', 7)])
        self.losing_hand = Hand([Card('1', 1), Card('1', 1), Card('1', 1)])
        self.winning_hand = Hand([Card('7', 7), Card('7', 7), Card('6', 6)])
        self.bust_hand = Hand([Card('7', 7), Card('7', 7), Card('8', 8)])

        self.matching_hand = Hand([Card('7', 7), Card('7', 7)])
        self.non_matching_hand = Hand([Card('7', 7), Card('3', 3)])

        self.ace_hand = Hand([Card('Ace', 11), Card('7', 7)])
        self.non_ace_hand = Hand([Card('4', 4), Card('7', 7)])

        self.low_hand = Hand([Card('4', 4), Card('7', 7)])
        self.high_hand = Hand([Card('9', 9), Card('9', 9)])

        self.player = Player('player')
        self.player2 = Player('player2')
        self.bank = Player('bank')
        self.amount_on_table = 500
Beispiel #12
0
 def test_add_Card_to_hand(self):
     self.card = Card('7', 7)
     self.one_card_hand.add_card_to_hand(self.card)
     self.assertEqual(2, self.one_card_hand.get_amount_of_cards())
Beispiel #13
0
 def setUp(self):
     self.one_card_hand = Hand([Card('7', 7)])
     self.matching_hand = Hand([Card('7', 7), Card('7', 7)])
     self.non_matching_hand = Hand([Card('6', 6), Card('7', 7)])
     self.bust_hand = Hand([Card('7', 7), Card('7', 7), Card('8', 8)])
     self.ace_hand = Hand([Card('Ace', 11), Card('7', 7)])
Beispiel #14
0
 def setUp(self):
     self.ace = Card('Ace', 11)
     self.card = Card('1', 1)
Beispiel #15
0
def generate_regular_deck():
    """ Generates a regular set of 52 cards represented as a list of Card objects """
    
    print("A regular Deck of 52 Cards was created.")
    return [Card(rank, suit) for suit in "chsd" for rank in range(1,13+1)]
Beispiel #16
0
 def draw_card(self):
     if random.random() < 2.0 / 3.0:
         return self.draw_black_card()
     else:
         return Card(Colors.red, random.randint(self.card_min,
                                                self.card_max))
Beispiel #17
0
 def draw_black_card(self):
     return Card(Colors.black, random.randint(self.card_min, self.card_max))
Beispiel #18
0
def card():
    return Card()