Announcement

Collapse
No announcement yet.

Python - Trouble moving variables between functions

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Python - Trouble moving variables between functions

    I thought I was just having a problem with StartingPlot, but looks like it's a more generic problem.

    I have a mod that loads into the game without a problem like this...

    Code:
    def setup(self):
         # find human player
         bComputer = True
         iCount = 0
         tStartPlot = (00, 00)
         while bComputer:
              pPlayer = gc.getPlayer(iCount)
                   if (pPlayer.isHuman()):
                        bComputer = False
                        pHuman = pPlayer
    
                        # get human player starting location
                        tStartPlot = pHuman.getStartingPlot()
    
                        # add additional units to the human player's civ
                        self.makeUnit(iSettler, pHuman, tStartPlot, 1)
                        self.makeUnit(iScout, pHuman, tStartPlot, 1)
                        self.makeUnit(iWarrior, pHuman, tStartPlot, 1)
                   else:
                        iCount = iCount + 1
    			
    
    #################
    ### Utilities ###
    #################
    
    def makeUnit(self, iUnit, pPlayer, tPlot, iNum):
         # display test message
         self.displayTestPopup()
    The problem I run into is whenever I add any statement to def makeunit referring back to the variables listed in the def makeunit line the mod will not load - it stops when it gets to loading the Python modules. For example, if I add

    iX = iNum

    it won't load.

    If I add iX = iUnit

    it won't load.

    If I add iX = tPlot.getX()

    it won't load.

    The test pop-up works fine, so I know that the makeunit function is being accessed, I just can't get any of the variables to work.

    Any ideas on what I'm doing wrong?

    Thanks!
    Last edited by webryder; November 1, 2005, 15:26.

  • #2
    Variables declared in def function(variable) are local to that function. Are you truing to define the body of your function?
    What is it you are trying to do?
    Can you put pre (formatting) tags in your message so we can see the indent of your code? Python without indenting is hard to understand.
    Clash of Civilization team member
    (a civ-like game whose goal is low micromanagement and good AI)
    web site http://clash.apolyton.net/frame/index.shtml and forum here on apolyton)

    Comment


    • #3
      OK - I put in the formatting tags - took me a minute to figure them out.

      I understand that the variable names used in def are local to the function, but if I call the function like this:

      self.makeunit (iSettler)

      and then def the function as

      def makeunit (self, iUnit)

      isn't it supposed to set iUnit = iSettler within makeunit?
      Last edited by webryder; November 1, 2005, 14:17.

      Comment


      • #4
        Re: Python - Trouble moving variables between functions

        Originally posted by webryder
        The problem I run into is whenever I add any statement to def mekunit referring back to the variables listed in the def makeunit line the mod will not load - it stops when it gets to loading the Python modules. For example, if I add

        iX = iNum

        it won't load.
        Does it only happen if you refer to the parameters of the function? So like if you did iX = 5, would it work?
        XBox Live: VovanSim
        xbox.com (login required)
        Halo 3 Service Record (I fail at FPS...)
        Spore page

        Comment


        • #5
          Very weird

          iX=5 doesn't work either

          Also, if I change it to iTemp = 5 it still doesn't load.

          Comment


          • #6
            I am not a python programmer, but I'm a very experienced programmer in other similar laguages (Object Oriented), like C++,C#,Java etc. Python can not be so much different. So I think I understand what is the problem here. At least I hope.

            It is the difference between "call by value" and "call by reference". Look the C++ code below. Two funtions being defined (f1 and f2), both having an integer as an argument, and both increasing this integer by one. Even if you don't know C++ it is not a difficult example to understand.
            void f1(int x)
            {
            x = x + 1;
            };

            void f2(int &x)
            {
            x = x + 1;
            };
            Now we call this functions from inside the main function
            void main()
            {
            int a,b;
            a = 3;
            b = 6;
            f1(a);
            f2(b);
            };
            After the execution of the main function, the value of 'a' will still be 3, but the value of 'b' will now be 7.

            What happened here is that in the first function, the variable is passed to it "by value", but in the second, "by reference". The '&' in the second function means the variable is passed by reference.

            "Passing by value" means that the value of the actual parameter 'a' is copied to the local parameter 'x' of the f1 function. Then, any operation on the f1's argument 'x', is performed of the local copy of 'a' and not the "external" variable 'a' itself. So 'a' stays intact.

            "Passing by reference" means tha the actual parameter itself ('b' in our example) is beeing passed to the function and not only its value. That means that the 'x' in f2 is not a local copy of 'b' but it is a "pointer" to the "external" variable, so we can refer to this variable from inside the function. So any operation on 'x' is actually performed on 'b'. You can think of 'x' as a second "name" for the same memory slot that holds the value of 'b' ( 'b' beeing the first "name" ). 'b' and 'x' in that case refer to the same memory address, so 'b' and 'x' are the same variable.

            In the first function f1, 'x' refered to a different address than 'a'. In Pascal, passing by reference is achieved through the 'var' keyword, in C++ through the '&' symbol. In C there is no such thing, but we can achieve this indirectly by passing the variable's address, than the variable's value. Eg in the exaple above function f2 should be

            void f2(int *x) // 'x' now is a pointer to an integer
            {
            *x = *x + 1; // we increase the value of the memory address the pointer points to by one
            }

            and the call of f2 now changes to

            f2(&b); // We pass the address of 'b', not the 'b' itself
            In Java and C#, "passing by reference" is the default function calling method. Every value exept built in types (integers, floats, chars etc) are passed by reference.

            In OO programming, where variables represent object instances that we have previously described (class in C++,Java,C#, Object in Pascal etc), "passing by reference is very usefull, and in some cases the only way to pass the object. We avoid the "copy to the local variable" which may be very slow if the object is large enough. Some other objects cannot be copied at all. Eg the 'cout' object in C++ which represent the monitor screen cannot have a twin. Every call to a function that needs the 'cout' as an argument must be "by reference".

            So I think that Python has "pass by value" its default function calling method. I've never programmed in Python, but I think that there must be a method (direct or indirect) to pass a value by reference.

            I don't know if i've answered the question. My english are not very good and maybe I didn't uderstand the question at all. But, check whether there is a way to use "passing by reference" to solve this problem

            Comment


            • #7
              OK, that makes sense for the statements like iX=iUnit, but that doesn't explain why the mod won't load when I put in the statement iX = 5, right?

              iX = 5 should be taking the value locally and doesn't involve passing a value from the calling function.

              Comment


              • #8
                Do you get any error messages when the game starts?

                Have you checked the Python logs to see if it says what the problem is there?

                Comment


                • #9
                  Originally posted by webryder
                  Very weird

                  iX=5 doesn't work either

                  Also, if I change it to iTemp = 5 it still doesn't load.
                  Well... The only thing I can think of is: are you sure all the lines are indented correctly? You are aware that Python delimits blocks of code through indentation, yes?

                  So, like, this won't work:

                  Code:
                  def makeUnit(self, iUnit, pPlayer, tPlot, iNum):
                       # display test message
                       self.displayTestPopup()
                  iTemp = 5
                  XBox Live: VovanSim
                  xbox.com (login required)
                  Halo 3 Service Record (I fail at FPS...)
                  Spore page

                  Comment


                  • #10
                    Originally posted by Trip
                    Do you get any error messages when the game starts?

                    Have you checked the Python logs to see if it says what the problem is there?
                    Trip, I might just be stupid, but... Could you explicitly say how to enable these logs you speak of? I enabled all the logging options in the ini file (changed to 1, except hidepythonexceptions which I set to 0) but nothing ever showed up in the My Games\Civ4\Logs directory. Am I looking in the wrong place? Or is it because no logs were generated, so there's nothing to look at?
                    XBox Live: VovanSim
                    xbox.com (login required)
                    Halo 3 Service Record (I fail at FPS...)
                    Spore page

                    Comment


                    • #11
                      DOH!!! THAT's why it wasn't loading!!! :-)

                      The popup line was indented more than the lines after it - I totally spaced on that one. Boy, I feel stupid.

                      Thanks!

                      Comment


                      • #12
                        OK, that makes sense for the statements like iX=iUnit, but that doesn't explain why the mod won't load when I put in the statement iX = 5, right?
                        Right. After a more carefull review of your post I don't think the problem is on parameter passing.

                        iX = 5 should be taking the value locally and doesn't involve passing a value from the calling function.
                        Have you tried other variable names than iX or iTemp?

                        Comment


                        • #13
                          The problem was an error in the indentation. :-P

                          Everything loads correctly now.

                          Comment


                          • #14
                            Ow. Ok problem solved. But it is really a stupid way to delimit blocks through indentation.

                            What had those Python guys into their heads when they were creating that language?

                            Comment


                            • #15
                              (Edit)
                              Since problem solved, no use to post what I did.
                              Indenting is actually rather helpful. If you had misplaced a { or } in C++, or (worse) a ( or ) in LISP, it wouldn't have been more obvious, would it?
                              Clash of Civilization team member
                              (a civ-like game whose goal is low micromanagement and good AI)
                              web site http://clash.apolyton.net/frame/index.shtml and forum here on apolyton)

                              Comment

                              Working...
                              X