Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 I assigned this variable but it thinks I didn't
Index -> Programming, Python -> Python Help
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
OREO Speedwagon




PostPosted: Thu Jan 06, 2011 8:59 am   Post subject: I assigned this variable but it thinks I didn't

My project is a text-based version of a simplified Magic card game for two players. To accomodate the multiplayer functionality, I have to have variables "redirect" to other ones (nowManaField could either == manaField, or manaField2, depending on what player is 'now'). This is working fine for most of the program, but when I try to 'play mana' (move the first card called 'Mana' from nowHand(and therefore hand) to the end nowManaField (which is manaField)), it claims nowManaField was never assigned a value, even when I rearrange the code.

Here is a selected version of my code...
Python:

running = True

#Define Functions
def playMana(): #put mana into play
    if nowManaPlayed != False:
        print('You have already played mana this turn.')
    else:
        x = 0
        for i in nowHand:
            if nowHand[x] == 'Mana':
                nowManaField.append(nowHand[x])
                del nowHand[x]
                print('You have played Mana.')
                break
            x += 1
            nowManaPlayed = True

#Dictionaries
hand = []
hand2 = []
deck = ['Ghost', 'Witchcraft', 'Mana', 'Soldier', 'Mana', 'Golem', 'Snake', 'Witchcraft', 'Mana', 'Mana']
deck2 = ['Mermaid', 'Seadragon', 'Tidal Wave', 'Mana', 'Mana', 'Mermaid', 'Spirit of Hurricane', 'Tidal Wave', 'Mana', 'Mana']
manaField = []
manaField2 = []

#Set up game
manaPlayed = False
manaPlayed2 = False
hand[0:7] = deck[0:7]
hand2[0:7] = deck2[0:7]
del deck[0:7]
del deck2[0:7]

#Set up for Player One
nowHand = hand
nowManaField = manaField
nowManaPlayed = manaPlayed

#Run loop

while running == True:
    command = input('Command? ')
##a bunch of ifs are here...##
    elif command == 'play mana':
         playMana()


Even when I rearrange all the blocks, I still get this error:
Quote:
Traceback (most recent call last):
File "H:\PYTHON\Magic_try2.py", line 186, in <module>
playMana()
File "H:\PYTHON\Magic_try2.py", line 34, in playMana
if nowManaPlayed != False:
UnboundLocalError: local variable 'nowManaPlayed' referenced before assignment


How do I clear this?
Sponsor
Sponsor
Sponsor
sponsor
rdrake




PostPosted: Thu Jan 06, 2011 9:46 am   Post subject: Re: I assigned this variable but it thinks I didn't

You're doing sick things. It's trying to warn you.

Essentially you're trying to assign a value to a global variable inside a method. Python thinks you're trying to assign to a local variable that doesn't exist anywhere. You must add the global keyword to make sure it knows what you're doing.

Consult this resource for more details.
OREO Speedwagon




PostPosted: Mon Jan 10, 2011 8:58 am   Post subject: RE:I assigned this variable but it thinks I didn\'t

Thanks rdrake, I applied 'global' liberally and it seems to work now... although I'm a little unclear as to why the global and local distinction even exists. =/

And why is what I'm doing "sick", as you put it?
DemonWasp




PostPosted: Mon Jan 10, 2011 10:44 am   Post subject: RE:I assigned this variable but it thinks I didn\'t

Globals are dangerous, bad programming practice. If you use a global in a method (A), you cannot use it in any method that either calls A, or is called by A. The method is then a leaky abstraction, because the method is "leaking" information about the state of the method. If you use a local in method (A), you can use the same symbol elsewhere without any "collisions".

The most common symptom of this bad practice is variables mysteriously changing value when you least expect it.

Variables should, in general, be in the tightest scope possible. "Scope" means "places where you can refer to that variable". Consider a loop-counter, usually i. That loop counter should only be visible to code within the loop -- and not to methods invoked within that loop, just the code that is directly there. The biggest problem is if that counter is a global, meaning it can be accessed anywhere in the system, for any reason -- this is a huge problem, because one loop will happily stomp all over another's exit condition...pointers will get misplaced, data will get trashed, and buffers will overflow. Bad things will happen.

Generally, you want to use objects to encapsulate "data" with "behaviour". You might want, for example, a class called Deck that describes what a player has in their deck.
OREO Speedwagon




PostPosted: Fri Jan 14, 2011 9:26 am   Post subject: RE:I assigned this variable but it thinks I didn\'t

so, if they're dangerous... should I just revert back to my old code, in which instead of calling functions after testing 'input', just have the code right there? I only changed to functions because I found it easier to read.
DemonWasp




PostPosted: Fri Jan 14, 2011 12:21 pm   Post subject: RE:I assigned this variable but it thinks I didn\'t

No, you should be using functions. However, the functions should reference local variables wherever possible, not global variables. Methods and functions should operate on their parameters (and, if they're members of a class, the contents of that instance of the class).

I don't know Python very well, so forgive syntax errors. Consider (rough, but should give you the idea):
Python:

def playMana ( manaPlayed, hand, manaField ): #put mana into play
    if manaPlayed != False:
        print ( 'You have already played mana this turn.' )
        return True
    else:
        x = 0
        for i in hand:
            if hand[x] == 'Mana':
                manaField.append ( nowHand[x] )
                del nowHand[x]
                print('You have played Mana.')
                break
            x += 1
            return True
        return False  # fell through the for-loop, so no mana in hand


Then you can just call it with one of the following:

Python:

playMana ( manaPlayed, hand, manaField )   # Player 1
playMana ( manaPlayed2, hand2, manaField2 )    # Player 2
OREO Speedwagon




PostPosted: Mon Jan 17, 2011 10:18 am   Post subject: RE:I assigned this variable but it thinks I didn\'t

OK, thanks, that seems to work Smile

One thing though - are booleans supposed to act weird in this situation?

Python:

def playMana(manaPlayed, hand, manaField): #put mana into play
    if manaPlayed == True:
        print('You have already played mana this turn.')
    else:
        x = 0
        for i in hand:
            if hand[x] == 'Mana':
                manaField.append(hand[x])
                del hand[x]
                print('You have played Mana.')
                manaPlayed = True
                break
            x += 1

I removed the return commands, since with them, no mana was getting moved, ever.
My problem is that manaPlayed, which is used to track whether or not the player has played mana that turn (1 mana per turn), is either not being flipped to 'True' after playing, it's getting re-written somewhere in the code (I've stepped through it and it isn't), or I've somehow got two different copies of manaPlayed and it's checking the wrong one.
Should I make manaPlayed a global? 3:
DemonWasp




PostPosted: Mon Jan 17, 2011 1:27 pm   Post subject: RE:I assigned this variable but it thinks I didn\'t

Sorry, I should have specified: when the function returns something, you're supposed to use that return value. In this case, we're returning a new value of manaPlayed. You would use this like so:

code:

manaPlayed = playMana ( manaPlayed, hand, manaField )   # Player 1
manaPlayed2 = playMana ( manaPlayed2, hand2, manaField2 )    # Player 2


This code could be a lot more idiomatic if each player was represented by a Player object (class), with member method playMana(). In that case, playMana() would take no arguments and return no values - it would operate on the class' member variables, which would include manaPlayed, hand, and manaField.
Sponsor
Sponsor
Sponsor
sponsor
OREO Speedwagon




PostPosted: Tue Jan 18, 2011 8:23 am   Post subject: RE:I assigned this variable but it thinks I didn\'t

Welp, looks like I'm gonna have to learn classes XD

Thanks so much for your help!!
Display posts from previous:   
   Index -> Programming, Python -> Python Help
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 9 Posts ]
Jump to:   


Style:  
Search: