Search code examples
pythontraceback

Too many values to unpack, error only occurs with high iterations


I am new to python and coding in general. I wrote a program to simulate a dice mechanic. Now I want to calculate the successchance for different scenarios. My function works...sometimes and I´m not able to figure ot why it does not. If the iterations are low it works, if I use higher numbers it fails. I get: ValueError: too many values to unpack (expected 7) in the for loop in simple_check_success_statistic I would be glad for hints.

Thank you for considering.

import random
import math


def roll_dice(sides):
    #get result of dice roll
    return random.randint(1, sides)


def simple_check(skillvalue, targetnumber, temptationdice, luckydice, temptfate):
    # Roll 3D20
    dice_rolls = sorted([roll_dice(20) for _ in range(3)])

    # Check for automatic failure
    if dice_rolls.count(1) >= 2:
        return "Automatic Failure"

    # Roll Temptation Dice and Lucky Dice
    td_rolls = [roll_dice(4) for _ in range(temptationdice)]
    ld_rolls = [roll_dice(4) for _ in range(luckydice)]

    # Check for 4 in TD and LD
    td_4 = 4 in td_rolls
    ld_4 = 4 in ld_rolls

    # Determine the chosen value
    if td_4 and ld_4:
        chosen_value = dice_rolls[1]  # Middle value
    elif td_4:
        chosen_value = dice_rolls[0]  # Lowest value
    elif ld_4 or tf == 1:
        chosen_value = dice_rolls[2]  # Highest value
    else:
        chosen_value = dice_rolls[1]  # Middle value

    # Calculate the Check Result
    cr = skillvalue + chosen_value - 10

    # Calculate Measure of Success
    if cr >= targetnumber:
        marks = math.floor((cr - tn) / 3)
    else:
        marks = 0

    # Determine success or failure
    if cr >= targetnumber:
        return "Success", cr, dice_rolls, td_rolls, ld_rolls, marks, temptfate
    else:
        return "Failure", cr, dice_rolls, td_rolls, ld_rolls, marks, temptfate


def userinput():
    
    #get values for the check
    skillvalue = int(input("Enter Skill Value (0-20): "))
    targetnumber = int(input("Enter Target Number (0-20): "))
    temptationdice = int(input("Enter number of Temptation Dice in pool: "))
    luckydice = int(input("Enter number of Lucky Dice in pool: "))

    while True:
        user_input = input("Tempt fate? (y/n): ").strip().lower()
        if user_input == "y":
            temptfate = True
            break
        elif user_input == "n":
            temptfate = False
            break
        else:
            print("Invalid input. Please enter 'Y' or 'N'.")

    return skillvalue, targetnumber, temptationdice, luckydice, temptfate


def simple_check_success_statistic(iterations, skillvalue, targetnumber, temptationdice, luckydice, temptfate):
    success_array = []

    #get a number of results
    for i in range(iterations):
        result, cr, dice_rolls, td_rolls, ld_rolls, marks, tempted = simple_check(skillvalue, targetnumber, temptationdice, luckydice, temptfate)
        success_array.append(result)

    #determine percentage of successful results
    print(str(success_array.count("Success")/iterations)+"%")


sv, tn, td, ld, tf = userinput()
simple_check_success_statistic(1000, sv, tn, td, ld, tf)

I ran the code through chatgpt (...no comment please ;) ) but it did not spot an error. I looked up arrays and checked the number of variables i return from simple check function. But as i said it sometimes works, othertimes not. I´m a bit lost.


Solution

  • In the "simple_check" function you are expecting it to return 7 different values and then assign those values to variables, but in the:

    # Check for automatic failure
    if dice_rolls.count(1) >= 2:
        return "Automatic Failure"
    

    section you are only returning one value. I fixed this by returning 6 zeroes with what you expected like so:

    # Check for automatic failure
    if dice_rolls.count(1) >= 2:
        return "Automatic Failure", 0, 0, 0, 0, 0, 0
    

    Something you could consider is returning this all as a list and then checking its length with an if statement to determine what to do next. You could say if its length is equal to 7, then we can access all 7 of those indices and there was no issue. If its length is 1, then we got an automatic failure.

    Hope this helps! And if you need anymore clarification please comment and I'll edit my answer.