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")
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, )
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()
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
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.")
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
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())
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
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
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
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
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())
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)])
def setUp(self): self.ace = Card('Ace', 11) self.card = Card('1', 1)
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)]
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))
def draw_black_card(self): return Card(Colors.black, random.randint(self.card_min, self.card_max))
def card(): return Card()