[Map Script] PerfectWorld.py

Oh, ok, its probably just my impatience :D

:lol: Was it you cephalo who suggested that while waiting for the script to do its job, one can go and make a sandwich or a cuppa tea?

Another thing I think you mentioned is that if the background music is still playing it probably means the game hasn't frozen.

I can't remember if I've already said it buy great mapscript by the way! :goodjob:.
 
Yah, I saw someone mention this mapscript in another thread, so I decided to check it out and it looks amazing! Though does it mean its frozen if the cursor never goes into its loading animation? If it just stays the regular cursor? Anyways, the first couple times I would load it when it stopped I would go to task manager and it would say BTS isn't responding, is that b/c of the slow loading or is there some other problem?
 
Task manager is not always that helpful. When a task says it is not responding it's not necessarily locked up. I was about to describe what it can mean, but I think it's literally what it says - not responding. That could mean it's just busy.

Give it a go on a duel size map, and give it at least 5 minutes. If it still doesn't work then something might be wrong. Unless you have a very very old computer...
 
I'll give it a go on duel, and my computer isn't that old, got it on '07, its a Dell with 2 Ghz of precessing speed and 2.00 GB of RAM
 
Wow, it really was my impatience, the duel load took about 2 seconds, and the Huge map load (what I normally play) takes about 5 minutes... thanks for the help guys :D
 
Yes, the process of planet creation is not a quick one. Just be glad you can create planets to play on in five minutes and not millions of years. :p
 
One other thing I noticed is that I always see the following in PythonErr.log:

Code:
Traceback (most recent call last):

  File "PerfectWorld_Original", line 4074, in addBonuses

  File "PerfectWorld_Original", line 2106, in AddBonuses

  File "PerfectWorld_Original", line 2293, in AssignBonusAreas

  File "PerfectWorld_Original", line 2507, in CalculateAreaSuitability

  File "PerfectWorld_Original", line 2483, in GetSameClassTypeCountInArea

TypeError: 'int' object is not callable
ERR: Python function addBonuses failed, module PerfectWorld

I don't know if this is significant or not. I'm on a mac, btw.
 
One other thing I noticed is that I always see the following in PythonErr.log:

Code:
Traceback (most recent call last):

  File "PerfectWorld_Original", line 4074, in addBonuses

  File "PerfectWorld_Original", line 2106, in AddBonuses

  File "PerfectWorld_Original", line 2293, in AssignBonusAreas

  File "PerfectWorld_Original", line 2507, in CalculateAreaSuitability

  File "PerfectWorld_Original", line 2483, in GetSameClassTypeCountInArea

TypeError: 'int' object is not callable
ERR: Python function addBonuses failed, module PerfectWorld

I don't know if this is significant or not. I'm on a mac, btw.

What is "PerfectWorld_Original"? The line numbers don't match up in my version. If someone copied text from there to make a modified PerfectWorld, it's possible that the tabs don't line up, causing Python to interpret things wrong.
 
What is "PerfectWorld_Original"? The line numbers don't match up in my version. If someone copied text from there to make a modified PerfectWorld, it's possible that the tabs don't line up, causing Python to interpret things wrong.

It's the original version; I just renamed it to keep it safe from my experimentation. Maybe I goofed, I don't think so, though; I'll check again.

When you say they don't line up, do you mean you see different line numbers when you run it, or do you not see this at all? If I download the version linked at the top of the thread, line 2507 is

Code:
sameClassTypesInArea = self.GetSameClassTypeCountInArea(area,eBonus)

This seems to agree with the errors messages I'm seeing. Line 2483 is

Code:
uRange = classInfo.getUniqueRange()

I don't know enough about python to know if this can generate that message.
 
This seems to agree with the errors messages I'm seeing. Line 2483 is

Code:
uRange = classInfo.getUniqueRange()

I don't know enough about python to know if this can generate that message.

This is line 2471 for me. The context is...
Code:
        classInfo = gc.getBonusClassInfo(eClass)
        if classInfo == None:
            return 0
        uRange = classInfo.getUniqueRange() (line 2471)
So classInfo should be a valid bonus class and if not, the function should end. Keep in mind that indentation can completely change the meaning of Python code. Significant white space is one of the really annoying things about Python. If you use a non-Python IDE you can really create some confusion if spaces look like a tab etc.
 
I'm not sure what to say, when I download a fresh copy of PerfectWorld.py, the uRange = classInfo.getUniqueRange() is line 2483. Are you sure you're looking at the same version of the file that's posted there? I don't see what could be causing the difference, I'm looking at a freshly downloaded file.

Edit: The API reference here lists getUniqueRange as an attribute not a method. Should this line read

Code:
uRange = classInfo.getUniqueRange

instead of

Code:
uRange = classInfo.getUniqueRange()

??? That seems like it could explain this message. But 'getUniqueRange' seems like a funny name for an attribute, maybe the API reference is wrong?
 
I'm not sure what to say, when I download a fresh copy of PerfectWorld.py, the uRange = classInfo.getUniqueRange() is line 2483. Are you sure you're looking at the same version of the file that's posted there? I don't see what could be causing the difference, I'm looking at a freshly downloaded file.

Edit: The API reference here lists getUniqueRange as an attribute not a method. Should this line read

Code:
uRange = classInfo.getUniqueRange

instead of

Code:
uRange = classInfo.getUniqueRange()

??? That seems like it could explain this message. But 'getUniqueRange' seems like a funny name for an attribute, maybe the API reference is wrong?

Ok, I was using a messed up version I had at work when I was looking at the line numbers. The line numbers you mentioned are the correct ones. However, after coming home and trying a fresh copy with the game, I did not get the error message in my log. You mentioned that you are using a Mac, and in fact the Mac version and Windows version of CivIV use different versions of python. A while back I had some Mac issues because I was doing things only valid in Python 2.4, while the Mac version uses Python 2.3. I thought I had stripped out all the 2.4isms but there may be more.

Are you still getting the message when trying a fresh copy with the game? I wanna make sure it's not an indentation issue before I start looking at Mac specific stuff.
 
Okay, so I did what you asked. I moved any versions of PerfectWorld.py out of the PublicMaps folder. Then I started Civ and went to the custom game screen just to make sure that PerfectWorld was not available as an option. It wasn't. So then I unzipped a clean version of PerfectWorld.py and put it in the PublicMaps folder. Restarted Civ and started a game with PW. Got the error I reported above.

So then I went into PW and deleted the parentheses at the end of line 2483 like I suggested above and reran civ. This time I got this error message:

Code:
Traceback (most recent call last):

  File "PerfectWorld", line 4074, in addBonuses

  File "PerfectWorld", line 2112, in AddBonuses

  File "PerfectWorld", line 2203, in AddBonusType

  File "PerfectWorld", line 2331, in CanPlaceBonusAt

TypeError: 'int' object is not callable
ERR: Python function addBonuses failed, module PerfectWorld

Same message, different line. That line also has " uRange = classInfo.getUniqueRange()". So I deleted the parentheses there and at the one other location where that appears. Ran Civ again ... this time the error is
Code:
Traceback (most recent call last):

  File "PerfectWorld", line 4074, in addBonuses

  File "PerfectWorld", line 2112, in AddBonuses

  File "PerfectWorld", line 2203, in AddBonusType

  File "PerfectWorld", line 2344, in CanPlaceBonusAt

TypeError: bad operand type for unary -
ERR: Python function addBonuses failed, module PerfectWorld

So my changes are making the original errors disappear, but are obviously not fixing the situation. Let me know if you want me to do some more testing/investigation.
 
So my changes are making the original errors disappear, but are obviously not fixing the situation. Let me know if you want me to do some more testing/investigation.

The function in question should just be a regular function call similar to others in the info classes. It basically just returns the appropriate XML value. I would think there would be some preceding error. Do you have popups turned on in your ini file? I wonder if you might see a popup that happens before this error.

After getting another clean copy, put this line right before the one in question:

print "classInfo = %d" % (classInfo) :EDIT no don't do this
Do this:
print "classInfo ="
print classInfo

Otherwise print requires a specific type.

I wonder what value is in there. I also wonder if my testing of 'None' is failing. Maybe the Mac version returns a zero instead of 'None' or something like that. Look in your logs for the PythonDbg.log file, you should be able to find your print statement (uh... mixed in with some other junk, use the find feature in your text editor)
 
Okay, I didn't do exactly what you said, but I think I found/fixed the problem. What I'm not sure of is why you don't get the same error! Maybe more recent versions of python are more forgiving or more flexible in how you can access attributes?

Anyway, I'll just cut to the chase. There are three uses of getUniqueRange in PW. According to the API reference, getUniqueRange is an attribute of CvBonusClassInfo but a method of CvBonusInfo. So what works for me is

Code:
classInfo.getUniqueRange

but

Code:
bonusInfo.getUniqueRange()

Interestingly, I was beginning to think from the games I've played that the maps were relatively resource poor (not for all resources, though). I wonder if that will change.

Edit: Did the API change in Warlords/BTS? I'm testing this in Vanilla Civ, maybe that's the difference?

More info under the spoiler tag.

Spoiler :

I modified the code as follows in the three places that getUniqueRange appears:

Code:
            print "(Added by dr_s at 2331) classInfo = "
            print classInfo
            iRange = classInfo.getUniqueRange
            print "(Added by  dr_s) iRange = "
            print iRange

Code:
        print "(Added by dr_s at 2343) bonusInfo = "
        print bonusInfo
        iRange = bonusInfo.getUniqueRange()
        print "(Added by dr_s) iRange = "
        print iRange

Code:
        print "(Added by dr_s at 2483) classInfo = "
        print classInfo
        uRange = classInfo.getUniqueRange
        print "(Added by dr_s) uRange = "
        print uRange

The output from this is (each repeated many times, of course):

Code:
(Added by dr_s at 2331) classInfo = 
<CvPythonExtensions.CvBonusClassInfo object at 0x18325148>
(Added by  dr_s) iRange = 
4

Code:
(Added by dr_s at 2343) bonusInfo = 
<CvPythonExtensions.CvBonusInfo object at 0x183250d8>
(Added by dr_s) iRange = 
7

Code:
(Added by dr_s at 2483) classInfo = 
<CvPythonExtensions.CvBonusClassInfo object at 0x18325068>
(Added by dr_s) uRange = 
5

With this code I get no errors in PythonErr.log and what seem like reasonable values for everything in PythonDbg.log.


 
That is very strange. I don't know what's going on with that. I never used the API reference you mentioned, I used the SDK in Visual Studio to find calling parameters and such. Generally, the methods exposed to python use the same format as their counterparts in the SDK.
Code:
int CvBonusClassInfo::getUniqueRange() const
{
	return m_iUniqueRange; 
}

I'm surprised that you are getting reasonable values for your uRange variable. In the CIV4BonusClassInfos.xml file, the iUnique values are either 0,4,5 or 8.

Also, that error you are getting is very strange. Clearly, the classInfo var is holding an object, yet you get an error saying you can't call a method on an 'int'. But it's not an int.... EDIT, oh wait, I get it now. It's already an int. Hmmm...

When I get home I'm going to make sure I'm getting the 0,4,5 or 8 on these values, and maybe try it without the parenthesis but I would expect an error. I haven't seen anything in Civ modding that uses attributes that way.
 
Also, that error you are getting is very strange. Clearly, the classInfo var is holding an object, yet you get an error saying you can't call a method on an 'int'. But it's not an int....

No, but if the API reference is right, then classInfo.getUniqueRange is an int, so classInfo.getUniqueRange() would return that error. (At least I think so, based on my googling.)

My hypothesis is that getUniqueRange is supposed to be a method, based on its name, for both CivBonusInfo and CivBonusClassInfo, but it's not, at least not in the Mac version of Civ (or maybe in Civ Vanilla).

On an unrelated matter, I sometimes see very food-poor starting locations (see attached screenshot) and I wonder if you have a comment about that. (BTW, there isn't any nearby food just out of range of the screenshot.)
 

Attachments

  • Start.jpg
    Start.jpg
    275.4 KB · Views: 299
My hypothesis is that getUniqueRange is supposed to be a method, based on its name, for both CivBonusInfo and CivBonusClassInfo, but it's not, at least not in the Mac version of Civ (or maybe in Civ Vanilla).

Ugh, that's an annoying version difference. I wonder what else is out there that is simply not working at all for Mac people. If addBonus fails it will resort to the default method, which will result in a very resource poor map since PW likes alot of trees. My bonus placer will place food bonuses over trees while the default one will not.

On an unrelated matter, I sometimes see very food-poor starting locations (see attached screenshot) and I wonder if you have a comment about that. (BTW, there isn't any nearby food just out of range of the screenshot.)

Actually it is very related. :) If you can get it working, as you have hopefully done, this problem should go away. Check to make sure you are getting the expected iUnique range values from the XML file using that attribute.

However, I'm not sure what I ought to do about this... I don't have a Mac for testing purposes.
 
Ok, I think I have determined it is a Vanilla issue. I googled some old discussions regarding some confusion with that function, and also the BtS version of the API reference you mentioned lists it as a method, while in vanilla it is an attribute as you said. So, they must have changed it. I didn't start modding until BtS came out, so that's why I never noticed it.

You definately want my version of the bonus placer, not only will it deal with the forests better, it will also put resources on the smaller islands while the default placer will not.

Thanks for pointing out that bug! It's good to know. :goodjob:
 
Glad you figured it out. Is there a workaround, so that a single version will work on both Vanilla and BTS?

BTW, I'm pretty sure the start I posted above was made with the fixed code. But even if it was not, here are two more low-food starts that I've seen. These were definitely made with a working script.
 

Attachments

  • Start 1.jpg
    Start 1.jpg
    274.5 KB · Views: 327
  • Start 2.jpg
    Start 2.jpg
    258.5 KB · Views: 284
Top Bottom