def num_trumps_beating(hand, board): # finding the best card in hand first max_hand_power = 0 top_card = hand[0] for c in hand: if not c.istrump: continue if call.card_power(c) > max_hand_power: max_hand_power = call.card_power(c) top_card = c if top_card.name == 'null' or top_card.suit == 'null': print(top_card) print() for c in hand: print(c, call.card_power(c)) exit(10) # find all the trump cards that have been played played_powers = set() for c in board.all_cards_played: played_powers.add(call.card_power(c)) trump_powers = [35, 31, 30, 25, 20, 15, 12] n_possible_ahead = sum([p > max_hand_power for p in trump_powers]) n_played_ahead = sum([p > max_hand_power for p in played_powers]) return (top_card, n_possible_ahead - n_played_ahead)
def highest_remaining_trump(board, pos): hand = board.pos_hand_dict[pos] ntrump = sum([c.istrump for c in hand]) if ntrump == 0: return (None, False) # finding the best card in hand first max_hand_power = 0 top_card = hand[0] for c in hand: if not c.istrump: continue if call.card_power(c) > max_hand_power: max_hand_power = call.card_power(c) top_card = c # find all the trump cards that have been played played_powers = { call.card_power(c) for c in board.all_cards_played if c.istrump } # go in descending order to see if the card has (1) been played or (2) is in hand trump_powers = [35, 31, 30, 25, 20, 15, 12] for p in trump_powers: if p in played_powers: continue else: if p == max_hand_power: return (top_card, True) else: return (None, False) return (None, False)
def current_winner(pos, board): # the leader is winning, and it's up to everyone else to beat them winning_pos = board.leader_pos winning_card = board.cards_played[0] if board.cards_played[0].suit == 'null': board.cards_played[0] = b.card('nine', 'clubs') board.cards_played[0].set_trump(board.trump_suit) # print('you had to fix something') # look at the rest of the cards for i in range(1, len(board.cards_played)): c = board.cards_played[i] # a card that (isn't trump) and (isn't the same suit as the winning card) can win if not c.istrump and c.suit != winning_card.suit: continue # get this card's position p = all_pos[(all_pos.index(board.leader_pos) + i) % 4] # compare the power of the two cards, knowing now that # the two cards are actually comparable (both of the same suit, # or the non-winning card trumps the winning card) cpower = call.card_power(c) wpower = call.card_power(winning_card) if cpower > wpower: winning_card = c winning_pos = p return (winning_card, winning_pos)
def key_cards(pos, board, legal_hand): # get the lowest card lowest = call.find_weakest_card(legal_hand, board.trump_suit) # see if you even have the right suits to beat the winning card winning_card, winning_pos = current_winner(pos, board) if not has_winnable_suit(legal_hand, winning_card): return (False, None, lowest, None) # get the highest card and the lowest winning card highest, lowest_winning = highest_and_lowest_winning( legal_hand, winning_card) can_win = call.card_power(highest) > call.card_power(winning_card) return (can_win, highest, lowest, lowest_winning)
def pick_lead_card(board, pos): hand = board.pos_hand_dict[pos] tnum = tricknum(hand) # always play the right on 3 c, have = right_on_3(hand) if have: return(c) # next, play an offsuit ace if you have it c, have = offsuit_ace(hand, board) if have: return(c) # next, if the person on your left called it and you can lead a suit # that has already been led, do it c, have = caller_awkward_spot(hand, board) if have: return(c) # next, play off your partner's jack, if they called it c, have = partners_jack(hand, pos, board.caller_pos) if have: return(c) # next, play an offsuit king if you have it c, have = offsuit_king(hand, board) if have: return(c) # next, play the top trump card if you have it c, have = highest_remaining_trump(hand, board) if have: return(c) # next, if your partner called it and you've taken 2 so far, lead trump to let them have it c, have = carry_the_team(hand, board) if have: return(c) # next, play your highest card ntrump = sum([c.istrump for c in hand]) ncards = 6-tnum frac_trump = ntrump/ncards if frac_trump >= 0.75: # only lead trump if you have 3/4 or 4/5, not 3/5 or 2/4 or 2/3 trumps = [c for c in hand if c.istrump] power = [call.card_power(c) for c in trumps] idx = power.index(min(power)) return(trumps[idx]) non_trumps = [c for c in hand if (not c.istrump and c.suit != 'null')] power = [call.card_power(c) for c in non_trumps] idx = power.index(max(power)) return(non_trumps[idx])
def nth_highest_remaining_trump(hand, board, n=1): played_trump_powers = {call.card_power(c) for c in board.all_cards_played if c.istrump} trump_powers = [35, 31, 30, 25, 20, 15, 12] # need to time this to see which is faster # The Problem: Want to compare the played powers with the possible powers of trump cards # Want to find the nth power that has not been played so far # Want to transform that into a card, then return that card # Method 1: # Look at all the powers, then turn the power into a card by making use of call's power_trump dictionary # I would need to loop through the power_trump dictionary to find the right name # As I'm writing this out, I can see that Method 1 is just clearly the best, so I won't even write out Method 2. for p in trump_powers: if p in played_trump_powers: n -= 1 if n == 0: for key in call.power_trump: if call.power_trump[key] == p: if key == 'right': c = b.card('jack', board.trump_suit, istrump = True, isright = True) elif key == 'left': c = b.card('jack', board.trump_suit, istrump = True, isleft = True) else: c = b.card(key, board.trump_suit, istrump = True) return(c, c in hand) c = b.card('nine', board.trump_suit, istrump = True) return(c, False)
def proper_winning_card(hand, winning_card, trump_suit): # from the beginning, we know that these are only cards which are legal under following suit, so there can # never be a mix of trump and follow-suit cards in this hand # there can still be a mix of trump and non-trump cards, though if winning_card.istrump: winning_suit = trump_suit else: winning_suit = winning_card.suit # check if you can even possibly win (if you have any trump or any of the led suit) hand_power = [] can_beat = False for c in hand: if c.istrump: can_beat = True break if c.suit == winning_suit: can_beat = True break if not can_beat: return (call.find_weakest_card(hand, trump_suit)) # by this point, we know that there is at least one card of the right suit to beat the winning card # find the power of each card in your hand for c in hand: if c.istrump or (c.suit == winning_card.suit and not c.isleft): hand_power.append(call.card_power(c)) else: hand_power.append(-1) # find the power of the winning card win_power = call.card_power(winning_card) # these cards are either all trump or none trump better_cards = [ hand[i] for i in range(len(hand)) if hand_power[i] > win_power ] if len(better_cards) == 0: return (call.find_weakest_card(hand, trump_suit)) hand_power = [call.card_power(c) for c in better_cards] if better_cards[ 0].istrump: # means they are all trump -- play the lowest trump that wins idx = hand_power.index(min(hand_power)) return (better_cards[idx]) else: # means none are trump -- play the highest card that wins idx = hand_power.index(max(hand_power)) return (better_cards[idx])
def highest_card(board, pos): hand = board.pos_hand_dict[pos] non_trumps = [c for c in hand if (not c.istrump and c.suit != 'null')] power = [call.card_power(c) for c in non_trumps] idx = power.index(max(power)) return (non_trumps[idx], True)
def highest_and_lowest_winning(hand, winning_card): hand_power = get_hand_power(hand, winning_card) max_idx = hand_power.index(max(hand_power)) highest = hand[max_idx] # find the power of the winning card win_power = call.card_power(winning_card) # these cards are either all trump or none trump # can't have a mix, or else you would have to follow suit better_cards = [ hand[i] for i in range(len(hand)) if hand_power[i] > win_power ] if len(better_cards) == 0: return (highest, None) hand_power = [call.card_power(c) for c in better_cards] min_idx = hand_power.index(min(hand_power)) lowest_winning = better_cards[min_idx] return (highest, lowest_winning)
def get_hand_power(hand, winning_card): hand_power = [] # by this point, we know that there is at least one card of the right suit to beat the winning card # find the power of each card in your hand for c in hand: if c.istrump or (c.suit == winning_card.suit and not c.isleft): hand_power.append(call.card_power(c)) else: hand_power.append(-1) return (hand_power)
def lead_trump(board, pos): hand = board.pos_hand_dict[pos] tnum = 1 + sum([c.name == 'null' for c in hand]) ntrump = sum([c.istrump for c in hand]) ncards = 6 - tnum frac_trump = ntrump / ncards if frac_trump < 0.75: return (None, False) trumps = [c for c in hand if c.istrump] power = [call.card_power(c) for c in trumps] idx = power.index(min(power)) return (trumps[idx], True)
def carry_the_team(hand, board): # only works if the partner of the caller is leading if board.leader_pos != b.partner(board.caller_pos): return(None, False) # only after the partner has taken 2 tricks (though maybe just one is fine?) if board.winners.count(board.leader_pos) < 2: return(None, False) # gotta lead trump if sum([c.istrump for c in hand]) == 0: return(None, False) trump_hand = [c for c in hand if c.istrump] powers = [call.card_power(c) for c in trump_hand] idx = powers.index(min(powers)) return(trump_hand[idx], True)
def lead_alone(board, pos): hand = board.pos_hand_dict[pos] # see if you've got the top trump card if sum([c.istrump for c in hand]) > 0: top_card, n_ahead = num_trumps_beating(hand, board) if n_ahead == 0: return (top_card) # if you've got an offsuit ace, lead it next for c in hand: if c.name == 'ace': if not c.istrump: return (c) # next, just play your best card powers = [call.card_power(c) for c in hand] idx = powers.index(max(powers)) return (hand[idx])
def top_card(board, pos): hand = board.pos_hand_dict[pos] powers = [call.card_power(c) for c in hand] idx = powers.index(max(powers)) return (hand[idx], True)
import basicprogs as b import numpy as np import time import call n = int(1e5) c = b.card('nine', 'hearts') c1 = b.card('nine', 'hearts') c2 = b.card('jack', 'clubs') cn = b.card('null', 'null') # this is 5x longer than the other way # uses numpy arrays to allow null cards to have -99 value t1 = time.time() for i in range(n): powers = np.array([call.card_power(c) for c in hand]) testcard = np.array(hand)[powers == min(abs(powers))][0] t2 = time.time() print('Took %.2f seconds using abs method' % (t2 - t1)) # this is the better way # creates a sub_hand that specifically ignores null cards t3 = time.time() for i in range(n): sub_hand = [c for c in hand if c.suit != 'null'] powers = [call.card_power(c) for c in sub_hand] idx = powers.index(min(powers)) testcard = sub_hand[idx] t4 = time.time() print('Took %.2f seconds using sub_hand method' % (t4 - t3))