tags:

views:

91

answers:

2

Hi,

I'm creating a game, and am quite new to Python generally.

I created a function 'descriptionGenerator()' which generates a description for characters and objects either randomly or using variables passed to it.

It seemed to be working, but every now and then it wouldn't work correctly. So i placed it in a loop, and it never seems to be able to complete the loop without one of the iterations having this problem.

The code is as follows:

#+------------------------------------------+
#| Name: bitsandpieces.py       |
#| A module for the 'Europa I' game         |
#|  created for the Game Making Competition |
#|                                  |
#| Date Created/Modified:                   |
#|          3/4/10 | 3/4/10                 |
#+------------------------------------------+

# Import the required modules
    # Import system modules:
import time
import random
    # Import 3rd party modules:

    # Import game modules:
# Define the 'descriptionGenerator()' function
def descriptionGenerator(descriptionVariables):
    descriptionVariableSize = len(descriptionVariables)
    if descriptionVariables[0] == 'char':
        # If there is only one variable ('char'), create a random description
        if descriptionVariableSize == 1:
            # Define choices for descriptionVariables to be generated from
            gender_choices = ['male', 'female']
            hair_choices = ['black', 'red', 'blonde', 'grey', 'brown', 'blue']
            hair_choices2 = ['long', 'short', 'cropped', 'curly']
            size_choices = ['tubby', 'thin', 'fat', 'almost twig-like']
            demeanour_choices = ['glowering', 'bright', 'smiling', 'sombre', 'intelligent']
            impression_choices = ['likeable', 'unlikeable', 'dangerous', 'annoying', 'afraid']
            # Define description variables
            gender = random.choice(gender_choices)
            height = str(float('0.' + str(random.randint(1, 9))) + float(random.randint(1, 2)))
            if float(height) > 1.8:
                height_string = 'tall'
                if float(height) > 2:
                    height_string = 'very tall'
            elif float(height) < 1.8 and float(height) > 1.5:
                height_string = 'average'
            elif float(height) < 1.5:
                height_string = 'short'
                if float(height) < 1.3:
                    height_string = 'very short'
            hair = random.choice(hair_choices2) + ' ' + random.choice(hair_choices)
            size = random.choice(size_choices)
            demeanour = random.choice(demeanour_choices)
            impression = random.choice(impression_choices)
            # Collect description variables in list 'randomDescriptionVariables'
            randomDescriptionVariables = ['char', gender, height, height_string, hair, size, demeanour, impression]
            # Generate description using the 'descriptionGenerator' function
            descriptionGenerator(randomDescriptionVariables)
        # Generate the description of a character using the variables passed to the function
        elif descriptionVariableSize == 8:
            if descriptionVariables[1] == 'male':
                if descriptionVariables[7] != 'afraid':
                    print """A %s man, about %s m tall. He has %s hair and is %s. He is %s and you get the impression that he is %s.""" %(descriptionVariables[3], descriptionVariables[2], descriptionVariables[4], descriptionVariables[5], descriptionVariables[6], descriptionVariables[7])
                elif descriptionVariables[7] == 'afraid':
                    print """A %s man, about %s m tall. He has %s hair and is %s. He is %s.\nYou feel that you should be %s of him.""" %(descriptionVariables[3], descriptionVariables[2], descriptionVariables[4], descriptionVariables[5], descriptionVariables[6], descriptionVariables[7])
            elif descriptionVariables[1] == 'female':
                if descriptionVariables[7] != 'afraid':
                    print """A %s woman, about %s m tall. She has %s hair and is %s. She is %s and you get the impression that she is %s.""" %(descriptionVariables[3], descriptionVariables[2], descriptionVariables[4], descriptionVariables[5], descriptionVariables[6], descriptionVariables[7])
                elif descriptionVariables[7] == 'afraid':
                    print """A %s woman, about %s m tall. She has %s hair and is %s. She is %s.\nYou feel that you should be %s of her.""" %(descriptionVariables[3], descriptionVariables[2], descriptionVariables[4], descriptionVariables[5], descriptionVariables[6], descriptionVariables[7])
        else:
            pass
    elif descriptionVariables[0] == 'obj':
        # Insert code here 2 deal with object stuff
        pass

print
print
myDescriptionVariables = ['char']
i = 0
while i < 30:
    print
    print
    print
    descriptionGenerator(myDescriptionVariables)
    i = i + 1
time.sleep(10)

When it fails to properly execute it says this:

Traceback (most recent call last):
  File "/Users/Jasper/Development/Programming/MyProjects/Game Making Challenge/Europa I/Code/Code 2.0/bitsandpieces.py", line 79, in <module>
    descriptionGenerator(myDescriptionVariables)
  File "/Users/Jasper/Development/Programming/MyProjects/Game Making Challenge/Europa I/Code/Code 2.0/bitsandpieces.py", line 50, in descriptionGenerator
    randomDescriptionVariables = ['char', gender, height, height_string, hair, size, demeanour, impression]
UnboundLocalError: local variable 'height_string' referenced before assignment

Thanks for any help with this

-----EDIT-----

Thanks for the help, fixed that problem, but now there is another one!

I changed this segment of code 2 take the strings as variables, then 'return' them, and then test them:

        elif descriptionVariableSize == 8:
            if descriptionVariables[1] == 'male':
                if descriptionVariables[7] != 'afraid':
                    descriptionOutput = """A %s man, about %s m tall. He has %s hair and is %s. He is %s and you get the impression that he is %s.""" %(descriptionVariables[3], descriptionVariables[2], descriptionVariables[4], descriptionVariables[5], descriptionVariables[6], descriptionVariables[7])
                    return descriptionOutput
                elif descriptionVariables[7] == 'afraid':
                    descriptionOutput = """A %s man, about %s m tall. He has %s hair and is %s. He is %s.\nYou feel that you should be %s of him.""" %(descriptionVariables[3], descriptionVariables[2], descriptionVariables[4], descriptionVariables[5], descriptionVariables[6], descriptionVariables[7])
                    return descriptionOutput
            elif descriptionVariables[1] == 'female':
                if descriptionVariables[7] != 'afraid':
                    descriptionOutput = """A %s woman, about %s m tall. She has %s hair and is %s. She is %s and you get the impression that she is %s.""" %(descriptionVariables[3], descriptionVariables[2], descriptionVariables[4], descriptionVariables[5], descriptionVariables[6], descriptionVariables[7])
                    return descriptionOutput
                elif descriptionVariables[7] == 'afraid':
                    descriptionOutput = """A %s woman, about %s m tall. She has %s hair and is %s. She is %s.\nYou feel that you should be %s of her.""" %(descriptionVariables[3], descriptionVariables[2], descriptionVariables[4], descriptionVariables[5], descriptionVariables[6], descriptionVariables[7])
                    return descriptionOutput
        else:
            print 'Incorrect number of variables contained within \'descriptionVariables\''
    elif descriptionVariables[0] == 'obj':
        # Insert code here 2 deal with object stuff
        pass

myDescriptionVariables = ['char']
myOutput = descriptionGenerator(myDescriptionVariables)
print myOutput

However, when I run this, it gives the following output:

None

What am I doing wrong?

+2  A: 

While you check to see if height is greater than or less than 1.5 or 1.8, you have nothing in place if it is equal to one of those values. Change the comparisons around those points to either >= and <, or to > and <=.

Ignacio Vazquez-Abrams
thanks - didn't see that
Jasper
+3  A: 

You define height_string inside if/else statements:

if float(height) > 1.8:
    height_string = 'tall'
    if float(height) > 2:
        height_string = 'very tall'
elif float(height) < 1.8 and float(height) > 1.5:
    height_string = 'average'
elif float(height) < 1.5:
    height_string = 'short'
    if float(height) < 1.3:
        height_string = 'very short'

However, if height == 1.8 or height == 1.5, all if/elif statements are false, and therefore height_string is never defined. Simply change the second statement to have <= and >= signs instead:

elif float(height) <= 1.8 and float(height) >= 1.5:

In response to your edit:

You call the function with

myOutput = descriptionGenerator(["char"])

Notice that you're passing a list of length one. Therefore, your function sees descriptionVariableSize == 1 and creates the random description.

So far, so good.

But wait! At the end of that if statement, you have an elif:

elif descriptionVariableSize == 8:

Now you do have descriptionVariableSize == 8. However, you used elif - so you just spent all that time creating a random set of descriptions, but you never get to use it, because the first statement was true and this statement is only executed if the first statement was false.

The solution - just change that elif to if. Now, whether you pass in a complete statement or generate one in the function, you'll still reach the second section.

Edit the ... fifth ?

I didn't notice that you call the function again at the end of the random section. Note that you don't return that call - so anything returned is lost to the void. Simply change it to

 return descriptionGenerator(randomDescriptionVariables)

As an added note - your function is getting a bit unwieldy. The problem is that you're doing two completely different things in the function - one is generating a random list of qualities, and another is generating a description from those quallities. It may be better to move the stuff in the first if block into its own function, generateRandomDescription(), or something, that only gets called in that first if block.

Daniel G
but since the second time through, it has been called separately in the random section --> 'descriptionGenerator(randomDescriptionVariables)', doesn't it not matter
Jasper
thanks, will split the function
Jasper
You are correct - I missed that. In that case, though, you aren't `return` ing that value - meaning that whatever you do in that second function is lost. I'll update the answer.
Daniel G
thanks again:)
Jasper
+1 to add emphasis to the added note about 'unwieldy'. Code that is hard to read is also hard to get right.
msw