Untitled

Includes risky min max
 avatar
unknown
python
5 months ago
10 kB
6
Indexable
import logging
import random
import math
import numpy as np
from CardGame import Card, Deck, Player

logging.basicConfig(filename='group7.log', 
                    level=logging.DEBUG,  # Set to DEBUG to capture all messages
                    filemode='w',  # Clear the log file each time the program runs
                    format='%(message)s',)  # Only the message will be logged

logging.disable(logging.CRITICAL)

# G7 is the best

#Stores guesses by player and round 
player_guesses = {}

SUITS = ["Clubs", "Diamonds", "Hearts", "Spades"]
VALUES = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
NUM_CARDS = len(SUITS) * len(VALUES)
CARD_PROBABILITIES = {num:1/39 for num in range(NUM_CARDS)}
TEAMMATE = {"North": "South", "South": "North", "East": "West", "West": "East"}

# Create a dictionary that maps 0-51 to (value, suit)
NUM_TO_CARD = {
    i: (SUITS[i // 13], VALUES[i % 13])  # i % 13 gives the card value, i // 13 gives the suit
    for i in range(NUM_CARDS)
}

REV_CARD_TO_NUM = {value:key for key, value in NUM_TO_CARD.items()}

MU = 25.5
SIGMA = 100

def gaussian_pdf(x, mu, sigma):
    return (1 / (sigma * math.sqrt(2 * math.pi))) * math.exp(-0.5 * ((x - mu) / sigma) ** 2)


def update_prob_based_on_correct_answers(player,probability_dict, guessed_cards, correct_answers, round):
    """
    Updates the probabilities for the cards in the guessed_cards list.

    Args:
        probability_dict (dict): A dictionary where keys are integers (0-51) representing cards
                                and probabilities.
        guessed_cards (list): A list of card indices representing the guessed cards.
        
    Returns:
        None: The probability_dict is updated in-place.
    """
    #print(f"Number of correct answers {correct_answers}")
    #print(correct_answers)


    perc_correct = correct_answers / len(guessed_cards)  # Factor to boost guessed cards
    perc_wrong =  1 - perc_correct
    var_rounds = round/13
    var_round = var_rounds**2
    #print(f"Perc of correct answers {perc_correct}")
    for card in guessed_cards:
            probability_dict[card] *= perc_correct

    non_guessed_cards = [card for card in probability_dict if card not in guessed_cards]

    for card in non_guessed_cards:
        probability_dict[card] *= perc_wrong

    normalize_probabilities(player)
    print(player.name)
    #print(probability_dict)

def normalize(probability_dict):
    total_prob = sum(probability_dict.values())
    if total_prob > 0:
        for card in probability_dict:
            probability_dict[card] /= total_prob

def playing(player, deck):
   
    turn = len(player.played_cards) + 1
    round = turn
    print(f"The current turn is {turn}")
    if round < 7:
        return risky_min_max(player,deck)
    else:
        flag =  (turn % 2)
        if flag == 0:
            flag = 1
            return max_first(player, deck)
        else:
            flag = 0 
            return min_first(player, deck)


def risky_min_max(player, deck):
    if not player.hand:
        return None

    # Find highets card
    highest_card = -1
    for i, card in enumerate(player.hand):
        card_value = REV_CARD_TO_NUM[(card.suit, card.value)]
        if card_value > highest_card:
            highest_card = card_value
            max_index = i

    #Find lowest card
    lowest_card = 52
    for i, card in enumerate(player.hand):
        card_value = REV_CARD_TO_NUM[(card.suit, card.value)]
        if card_value < lowest_card:
            lowest_card = card_value
            min_index = i

    print(f"Minindex for {player.name} is {lowest_card}")
    print(f"Max index for {player.name} is {highest_card}")
    # If max index is further from 52 than min index from 0
    if (lowest_card < 52 - highest_card):
        print(f"Player using risky minmax {player.name} zeroing above {highest_card}")
        return max_index
    else:
        print(f"Player using risky minmax {player.name} zeroing below {lowest_card}")
        return min_index

def max_first(player, deck):
    """
    Max First strategy.
    
    This strategy always plays the highest-value card in the player's hand.
    
    Parameters:
    player (Player): The current player object.
    deck (Deck): The current deck object.
    
    Returns:
    int or None: The index of the card to be played, or None if no card can be played.
    """
    if not player.hand:
        return None
    
    value_order = deck.values
    max_index = 0 

    highest_card = -1
    for i, card in enumerate(player.hand):
        card_value = REV_CARD_TO_NUM[(card.suit, card.value)]
        if card_value > highest_card:
            highest_card = card_value
            max_index = i
    print(highest_card, NUM_TO_CARD[highest_card])
    return max_index

def min_first(player, deck):
    """
    Min First strategy.
    
    This strategy always plays the lowest-value card in the player's hand.
    
    Parameters:
    player (Player): The current player object.
    deck (Deck): The current deck object.
    
    Returns:
    int or None: The index of the card to be played, or None if no card can be played.
    """
    if not player.hand:
        return None

    lowest_card = 52
    for i, card in enumerate(player.hand):
        card_value = REV_CARD_TO_NUM[(card.suit, card.value)]
        if card_value < lowest_card:
            lowest_card = card_value
            min_index = i
    
    return min_index

def normalize_probabilities(player):
    total = sum(player.card_probabilities.values())
    if total > 0:
        for card in player.card_probabilities:
            player.card_probabilities[card] /= total
    else:
        # This is after all the cards have been played - so no exception
        player.card_probabilities[0] = 1

def zero_probabilities(player, cards):
    print(cards)
    for card in cards:
        suit = card.suit
        val = card.value
        num = REV_CARD_TO_NUM[(suit, val)]
        player.card_probabilities[num] = 0.0
    normalize_probabilities(player)

def zero_below_card(player, card):
    # for each card below the card, set probability to 0
    suit = card.suit
    val = card.value
    num = REV_CARD_TO_NUM[(suit, val)]

    logging.debug(f"The lowest card number is (in number form) {num}")

    for i in range(num):
        player.card_probabilities[i] = 0.0
        logging.debug(f"Setting probability of card {i} to 0")
    normalize_probabilities(player)

def zero_above_card(player, card):
    # for each card above the card, set probability to 0
    suit = card.suit
    val = card.value
    num = REV_CARD_TO_NUM[(suit, val)]

    logging.debug(f"The highest card number is (in number form) {num}")
    
    for i in range(num, 52):
        player.card_probabilities[i] = 0.0
        logging.debug(f"Setting probability of card {i} to 0")
    normalize_probabilities(player)

def choose_cards(player, round, max_probs=False):
    if not max_probs:
        choices = np.random.choice(
            list(player.card_probabilities.keys()),
            13 - round,
            p=list(player.card_probabilities.values()),
            replace=False)
    else:
        choices = sorted(player.card_probabilities.keys(), key=lambda x:player.card_probabilities[x])[-(13 - round):]
    card_choices = [NUM_TO_CARD[card] for card in choices]
    card_choices_obj = [Card(card[0], card[1]) for card in card_choices]
    return card_choices_obj


def guessing(player, cards, round):
    global player_guesses
    if round == 1:
        # global player.card_probabilities
        player.card_probabilities = {num:gaussian_pdf(num, MU, SIGMA) for num in range(NUM_CARDS)}
        zero_probabilities(player, player.hand)
        
    normalize_probabilities(player)
    exposed_cards = [i for j in list(player.exposed_cards.values()) for i in j]
    zero_probabilities(player, exposed_cards)
    zero_probabilities(player, player.played_cards)

    last_exposed_card = player.exposed_cards[TEAMMATE[player.name]][-1]
    last_exposed_card_index = REV_CARD_TO_NUM[(last_exposed_card.suit, last_exposed_card.value)]

    # # if even round, guess the highest card

    if round >= 7: 
        if round % 2 == 0:
            logging.debug(f"Zeroing highest card and above")
            print(f"Player {player.name} zeroing above {last_exposed_card}")
            zero_above_card(player, last_exposed_card)
        else:
            logging.debug(f"Zeroing below card and above")
            print(f"Player {player.name} zeroing below {last_exposed_card}")
            zero_below_card(player, last_exposed_card)

    # we guess min or max based on if the number is closer to 0 or 52
    else:
        if (last_exposed_card_index < 52 - last_exposed_card_index):
            # Assume min card as its closer to 0 index
            zero_below_card(player, last_exposed_card)
        else: 
            zero_above_card(player, last_exposed_card)

    if round > 1: # We have c values 
        correct_answers = player.cVals[-1]
        previous_guesses = player_guesses[player.name].get(round - 1, [])
        print(correct_answers)
        print(len(previous_guesses))
        previous_guess_indices = [REV_CARD_TO_NUM[(card.suit, card.value)] for card in previous_guesses]
        update_prob_based_on_correct_answers(player, player.card_probabilities, previous_guess_indices, correct_answers, round)

        #logging.debug(f"Current Player: {player.name}")
        #logging.debug(f"Current Teammate: {TEAMMATE[player.name]}")
        #logging.debug(f"The player, {player.name}, is examining card: {player.exposed_cards[TEAMMATE[player.name]][-1]}")
        


        #logging.debug(f"Summary of Player: {player.name}")
        #logging.debug(player.card_probabilities)
        # sum of probabilities should be 1
        #logging.debug(f"Total probability: {sum(player.card_probabilities.values())}")
            
    card_choices_obj = choose_cards(player, round, max_probs=True)

    if player.name not in player_guesses:
        player_guesses[player.name] = {}  # Initialize if not present

    player_guesses[player.name][round] = card_choices_obj


    return card_choices_obj
Editor is loading...
Leave a Comment