View Full Version : Python help Event to place units on a certain date.
wotan321 Aug 30, 2006, 11:53 AM Could one of you capable python coders provide us with the code we can plop into our events file that places a unit(s), say a warrior, on a plot (or an adjacent empty plot) on a certain years and month date?
That would be very helpful, and much appreciated.
Gunner Aug 30, 2006, 12:01 PM If you have Rhye's mod just look under the barbarians python event file. That should give you a pretty clear and easy example of what you want.
wotan321 Aug 30, 2006, 04:26 PM Thanks for the reply, I appreciate the help.
Okay, I looked at that file, and I have a question.
Now, keep in mind I am asking how to do something in Python because I don't know how to program in python myself. The bit of code I have a question about is:
if (iGameTurn >= i190AD and iGameTurn <= i1600AD):
self.spawnUnits( (60, 10), (75, 26), iSkirmisher, 2 + iHandicap, iGameTurn, 5, 4, self.outerInvasion)
If I simply put this in my mod, any mod, say the Sevo Mod or Mylon Mod or any mod.... just simply add these lines, will a unit show up on the map...when? Or are are these lines using variables defined earlier in the file or in another file?
Thanks.
wotan321 Aug 31, 2006, 07:51 AM Yeah, that's what I thought you would say....
On the outside chance anyone views this thread again, or actually responds to the request for help.... here's the rub for non-python literate types like me.
I know in the programming world, respectable, object oriented programming is where tasks that are made up of sub-tasks are broken down into those subtasks, so you don't have to repeat code in your file. But for those of us who are NOT programmers, we need the whole process in one package.
I am hoping someone will provide me with the code that I can put in whatever the events file is of a mod. The code needs to run on a certain year/month, examine an area around a plot for an empty one, then place on that empty spot a unit from a certain civ.
Maybe that code I posted above does just that, without referencing variables and other modules in that file or other files, but again, I am not educated in python, so I don't know. But the little I do know tells me that all that bit of code will do is give me error messages.
When folks respond to requests for help by telling them "Go look at this or that and mimic it", what you are really saying is "Go learn python". And that is great advice. But I am asking because I don't know python, and simply want someone out of kindness to share some of their superior knowledge. I know that any response and advice on how to get my info is a kind thing, and I am grateful.
But when you don't answer the question, and only say that the answer does exist (though in this case, I believe the solution I am asking for is NOT in Rhyes files), then everyone else who sees the thread will say "Gosh, I see the question is answered and I am not going to type in the simple solution he is asking for".
Yes, I am being an ingrate, and a lazy one at that for not taking the hours to learn python and simply figure it out myself. But I just thought it would be nice if one of the dozens of capable python programmers could take 2 minutes and give me a piece of code that another dozen dozen noobs would LOVE to have. For non-programmers, OOP is not good for us, we need the whole process in one handy unit we can plop into our events file.
The Great Apple Aug 31, 2006, 08:38 AM def onBeginGameTurn(self, argsList):
iGameTurn, iPlayer = argsList
if iPlayer == <Insert player number here>:
if iGameTurn == <Insert the game turn here>:
iPlotX = <Insert plot X co-ordinate here>
iPlotY = <Insert plot X co-ordinate here>
pPlot = CyMap().plot(iPlotX, iPlotY)
bPlotValid = True
for i in range(pPlot.getNumUnits()):
if gc.getTeam(pPlot.getUnit(i).getTeam()).isAtWar(gc. getPlayer(iPlayer).getTeam()):
bPlotValid = False
break
if bPlotValid:
pUnit = gc.getPlayer(iPlayer).initUnit(gc.getInfoTypeForSt ring("<Insert unit name as in XML here>", iPlotX, iPlotY, NO_UNITAI)
else:
validPlotList = []
for iX in range(-1, 2):
for iY in range(-1, 2):
if iX == iY == 0:
continue
bPlotValid = True
pPlot = CyMap().plot(iPlotX + iX, iPlotY + iY)
for i in range(pPlot.getNumUnits()):
if gc.getTeam(pPlot.getUnit(i).getTeam()).isAtWar(gc. getPlayer(iPlayer).getTeam()):
bPlotValid = False
break
if bPlotValid:
validPlotList.append(pPlot)
if len(validPlotList):
rand = CyGame().getSorenRandNum(len(vaildPlotList), "Random unit plot")
iPlotX = validPlotList[rand].getX()
iPlotY = validPlotList[rand].getY()
pUnit = gc.getPlayer(iPlayer).initUnit(gc.getInfoTypeForSt ring("<Insert unit name as in XML here>", iPlotX, iPlotY, NO_UNITAI)
Should work. Haven't tested it. It's also pretty rough, could use a cleanup. Make sure you enable python error logging or it won't tell you that it's not working. Assuming you're not planning on having much more python, or you don't need good compatabily just replace the function in CvEventManger.py with this on.
Definately took me more then 2 minutes. It might have been a bit quicker if you didn't want it on a random plot if the current one was occupied, but still more then 2 minutes.
The check checks for enemy units, I didn't know if that's what you wanted or not. Often with this kind of request it's alot easier if you write some psudocode (if this then do this) so that people can understand more easily what you want.
Gunner Aug 31, 2006, 09:12 AM Yeah, that's what I thought you would say....
On the outside chance anyone views this thread again, or actually responds to the request for help.... here's the rub for non-python literate types like me.
I know in the programming world, respectable, object oriented programming is where tasks that are made up of sub-tasks are broken down into those subtasks, so you don't have to repeat code in your file. But for those of us who are NOT programmers, we need the whole process in one package.
I am hoping someone will provide me with the code that I can put in whatever the events file is of a mod. The code needs to run on a certain year/month, examine an area around a plot for an empty one, then place on that empty spot a unit from a certain civ.
Maybe that code I posted above does just that, without referencing variables and other modules in that file or other files, but again, I am not educated in python, so I don't know. But the little I do know tells me that all that bit of code will do is give me error messages.
When folks respond to requests for help by telling them "Go look at this or that and mimic it", what you are really saying is "Go learn python". And that is great advice. But I am asking because I don't know python, and simply want someone out of kindness to share some of their superior knowledge. I know that any response and advice on how to get my info is a kind thing, and I am grateful.
But when you don't answer the question, and only say that the answer does exist (though in this case, I believe the solution I am asking for is NOT in Rhyes files), then everyone else who sees the thread will say "Gosh, I see the question is answered and I am not going to type in the simple solution he is asking for".
Yes, I am being an ingrate, and a lazy one at that for not taking the hours to learn python and simply figure it out myself. But I just thought it would be nice if one of the dozens of capable python programmers could take 2 minutes and give me a piece of code that another dozen dozen noobs would LOVE to have. For non-programmers, OOP is not good for us, we need the whole process in one handy unit we can plop into our events file.
Well I'm sorry that my help for your question wasn't enough. I'm really not a very good python programmer myself, and I've never actually done what you asked in your question. Believe it or not, the progression in python ablilities for a person does not go from "Not Knowing Python" immediantly to "Python God." But I figured that it would be better for me to say where I've seen what you were asking for before than just not say anything.
I'm glad that TGA came along to show something more useful :)
Oh and thank you very much for that code snippet TGA. That little process for finding a valid plot is very interesting and has helped me. Maybe you could post it in the Sample Python code thread?
wotan321 Aug 31, 2006, 09:32 AM Wow, this whining stuff really works......
TGA noted:
Often with this kind of request it's alot easier if you write some psudocode (if this then do this) so that people can understand more easily what you want.
Yes, that is a good point. I was embarassed to use a Civ2 scripting example, but that would have helped.
..and Gunner, thanks to you too, I really do appreciate your desire and action to help me. Its your attitude, like TGA's, that repeatedly impress me with the Civ community.
Yes, learning python is something I am working on when I can... I have reached that "knows enough to be dangerous" stage, where the imporant value of "backups" is stressed by each painful lesson. Its gonna take some time and practice.... I appreciate your insights and encouragement.
To both of you, much thanks.
...I guess I should try the code before I get all gushy....<g>.
Thorn Aug 31, 2006, 11:34 AM Believe it or not, the progression in python ablilities for a person does not go from "Not Knowing Python" immediantly to "Python God."
True, but there seems to be something missing here in the learning process. There are great Python tutorials on this site and there are awesome Mods, sample python scripts and Civ4 library references. But what's missing is a tutorial on 'Civ4 Python'. For example, even a tutorial starting with printing 'Hello World!' on the Civ4 in-game screen would be nice. I would bet that most people wouldn't be able to do it even after going through the 'regular' Python tutorials. It would be nice to start a tutorial with the 'Hello World!' type message, then progress up slowly to more difficult concepts like the code in this request. Just a thought. :)
Gunner Aug 31, 2006, 08:23 PM Hey wotan, sorry about getting kinda angry there. I obviously misinterpreted your tone from that post I had quoted. Plus I was posting early in the morning, which is always a bad idea :crazyeye:
Hope everything works out!
@Thorn
You might want to check out TGA's tutorial for Civ4 in his sig. Its not quite as basic as you were describing, but I think its a godsend for anyone looking to learn python for Civ4.
Gerikes Aug 31, 2006, 09:45 PM def onBeginGameTurn(self, argsList):
iGameTurn, iPlayer = argsList
if iPlayer == <Insert player number here>:
if iGameTurn == <Insert the game turn here>:
iPlotX = <Insert plot X co-ordinate here>
iPlotY = <Insert plot X co-ordinate here>
pPlot = CyMap().plot(iPlotX, iPlotY)
bPlotValid = True
for i in range(pPlot.getNumUnits()):
if gc.getTeam(pPlot.getUnit(i).getTeam()).isAtWar(gc. getPlayer(iPlayer).getTeam()):
bPlotValid = False
break
if bPlotValid:
pUnit = gc.getPlayer(iPlayer).initUnit(gc.getInfoTypeForSt ring("<Insert unit name as in XML here>", iPlotX, iPlotY, NO_UNITAI)
else:
validPlotList = []
for iX in range(-1, 2):
for iY in range(-1, 2):
if iX == iY == 0:
continue
bPlotValid = True
pPlot = CyMap().plot(iPlotX + iX, iPlotY + iY)
for i in range(pPlot.getNumUnits()):
if gc.getTeam(pPlot.getUnit(i).getTeam()).isAtWar(gc. getPlayer(iPlayer).getTeam()):
bPlotValid = False
break
if bPlotValid:
validPlotList.append(pPlot)
if len(validPlotList):
rand = CyGame().getSorenRandNum(len(vaildPlotList), "Random unit plot")
iPlotX = validPlotList[rand].getX()
iPlotY = validPlotList[rand].getY()
pUnit = gc.getPlayer(iPlayer).initUnit(gc.getInfoTypeForSt ring("<Insert unit name as in XML here>", iPlotX, iPlotY, NO_UNITAI)
This is good, but I wonder if you can't just put the unit on the plot, then check if it's a valid plot and if not use pUnit.jumpToNearestValidPlot()
The Great Apple Sep 01, 2006, 02:11 AM That would be a much better method. I don't check the domains or anything here so you could end up with a land unit in water or something similar.
Except... if you initiate a unit on a plot with an enemy unit on it kills the enemy unit IIRC. You have to find the plot before initiating the unit.
wotan321 Sep 01, 2006, 06:57 AM TGA, thanks again. What needs to be amended in your earlier code to place multiples of the same unit?
..and Gunner, I apologize for my snarky and sarcastic tone, I was simply being impatient. Your help is much appreciated. Thanks again to all of you who have offered information and advice.
Gerikes Sep 01, 2006, 10:12 AM That would be a much better method. I don't check the domains or anything here so you could end up with a land unit in water or something similar.
Except... if you initiate a unit on a plot with an enemy unit on it kills the enemy unit IIRC. You have to find the plot before initiating the unit.
Ah, you're right.
That's too bad they didn't make the checking for a valid plot a seperate function to use.
The Great Apple Sep 01, 2006, 10:26 AM Instead of
pUnit = gc.getPlayer(iPlayer).initUnit(gc.getInfoTypeForSt ring("<Insert unit name as in XML here>", iPlotX, iPlotY, NO_UNITAI)
for i in range(<Number of units>):
pUnit = gc.getPlayer(iPlayer).initUnit(gc.getInfoTypeForSt ring("<Insert unit name as in XML here>", iPlotX, iPlotY, NO_UNITAI)
should work.
I might have a fiddle around and make it so that it checks for a proper valid plot.
Thorn Sep 01, 2006, 10:43 AM @Thorn
You might want to check out TGA's tutorial for Civ4 in his sig. Its not quite as basic as you were describing, but I think its a godsend for anyone looking to learn python for Civ4.
Yes, that is a great tutorial and very useful for learning. But what I was wondering if there were any tutorials that would walk you through an actual mod example. Just something as basic as- If a Warrior unit dies anywhere on the map, then have a message popup that says 'A warrior has been lost...'.
The tutorial would describe step by step what files need to be changed/created, what the lines of code do, what directories to put the files, etc. etc. At the end of the tutorial you should be able to actually run the mod and show the desired output. A couple of tutorials like this getting a little more advanced each time would be really helpful. Of course, I also realize that it would be time consuming for someone to do that :p
Gunner Sep 01, 2006, 10:51 AM I wonder if this would work. It should, but then again you might want to wait till TGA or someone approves it ;)
def makeUnit(self, iUnit, iPlayer, tCoords, iNum): #by LOQ
'Makes iNum units for player iPlayer of the type iUnit at tCoords.'
for i in range(iNum):
player = gc.getPlayer(iPlayer)
player.initUnit(iUnit, tCoords[0], tCoords[1], UnitAITypes.NO_UNITAI)
def onBeginGameTurn(self, argsList):
iGameTurn, iPlayer = argsList
if iPlayer == <Insert player number here>:
if iGameTurn == <Insert the game turn here>:
iPlotX = <Insert plot X co-ordinate here>
iPlotY = <Insert plot X co-ordinate here>
pPlot = CyMap().plot(iPlotX, iPlotY)
bPlotValid = True
for i in range(pPlot.getNumUnits()):
if gc.getTeam(pPlot.getUnit(i).getTeam()).isAtWar(gc. getPlayer(iPlayer).getTeam()):
bPlotValid = False
break
if bPlotValid:
pUnit = self.makeUnit(gc.getInfoTypeForString("<Insert unit name as in XML here>"),gc.getPlayer(iPlayer),(iPlotX, iPlotY), "<Insert number of units you want here>")
else:
validPlotList = []
for iX in range(-1, 2):
for iY in range(-1, 2):
if iX == iY == 0:
continue
bPlotValid = True
pPlot = CyMap().plot(iPlotX + iX, iPlotY + iY)
for i in range(pPlot.getNumUnits()):
if gc.getTeam(pPlot.getUnit(i).getTeam()).isAtWar(gc. getPlayer(iPlayer).getTeam()):
bPlotValid = False
break
if bPlotValid:
validPlotList.append(pPlot)
if len(validPlotList):
rand = CyGame().getSorenRandNum(len(vaildPlotList), "Random unit plot")
iPlotX = validPlotList[rand].getX()
iPlotY = validPlotList[rand].getY()
pUnit = self.makeUnit(gc.getInfoTypeForString("<Insert unit name as in XML here>"),gc.getPlayer(iPlayer),(iPlotX, iPlotY), "<Insert number of units you want here>")
You have to make sure that the two definitions are in the same class.
Also, don't you need a closing parenthese for this line?
gc.getInfoTypeForString("<Insert unit name as in XML here>")
Edit: Saw that TGA beat me to it, and his looks a lot smaller too. It would still be great if someone told me if my way would work :)
The Great Apple Sep 01, 2006, 11:14 AM Almost. You're passing a player pointer to the function where it wants a player ID:
self.makeUnit(gc.getInfoTypeForString("<Insert unit name as in XML here>"), iPlayer, (iPlotX, iPlotY), "<Insert number of units you want here>")
is better.
Also, the function above doesn't return anything, so you'll want to remove the "pUnit =" thingy - that was just in case he wanted to do something with the unit.
wotan321 Sep 01, 2006, 11:31 AM Okay, so if I want to put in 2 different (or 3 or 4) different unitclasses, I simply repeat that line
self.makeUnit(gc.getInfoTypeForString("<Insert unit name as in XML here>"), iPlayer, (iPlotX, iPlotY), "<Insert number of units you want here>")
but put in the unique unitclass name.
In that way I could lay down a warrior, 2 pikeman and a scientist on a certain date?
This is great info, if I hadn't mentioned that already.....
Thanks.
Gunner Sep 01, 2006, 11:31 AM Thanks TGA. What a silly mistake about that pointer/ID thing.
And yeah, I had no clue about that pUnit thing either. I figured that since you did it in the first one I might as well copy it ;)
wotan321 Sep 01, 2006, 06:38 PM Okay, I came home and tried to implement this.
A couple of basic questions.
1. What file do I put this in if I am creating my own mod?
\Mods\TestMod\Assets\Python\CvEventManager.py
2. In the line
if iGameTurn == <Insert the game turn here>:
are we talking about the year in the game, as in 3800BC, or the game turn 4?
3. So, after the discussion in previous posts about what is the better code, what is the final product?
Again, big globs of thanks.
The Great Apple Sep 01, 2006, 07:20 PM 1) Yes. This way is very poor for compatability. There are two or three ways you can make it better - check out how TheLopez sets it up (I know you hate it when people say that, but I haven't checked it out myself - I do something different...)
2) Game turn. Might be a function to turn year into game turn (gets messy with different game speeds).
3) Not sure there was one. Hold on, I'll sort one out for you...
The Great Apple Sep 01, 2006, 07:33 PM Okies:
def onBeginGameTurn(self, argsList):
iGameTurn, iPlayer = argsList
unitType = gc.getInfoTypeForString("<Insert unit name as in XML here>")
numUnits = <Insert num units here>
if iPlayer == <Insert player number here>:
if iGameTurn == <Insert the game turn here>:
iPlotX = <Insert plot X co-ordinate here>
iPlotY = <Insert plot X co-ordinate here>
pPlot = CyMap().plot(iPlotX, iPlotY)
bPlotValid = True
for i in range(pPlot.getNumUnits()):
if gc.getTeam(pPlot.getUnit(i).getTeam()).isAtWar(gc. getPlayer(iPlayer).getTeam()):
bPlotValid = False
break
if bPlotValid:
for i in range(numUnits):
gc.getPlayer(iPlayer).initUnit(unitType, iPlotX, iPlotY, NO_UNITAI)
else:
validPlotList = []
for iX in range(-1, 2):
for iY in range(-1, 2):
if iX == iY == 0:
continue
bPlotValid = True
pPlot = CyMap().plot(iPlotX + iX, iPlotY + iY)
if pPlot.getPlotType() == PlotTypes.PLOT_PEAK or (gc.getUnitInfo(unitType).getDomainType() == DomainTypes.DOMAIN_SEA and pPlot.getPlotType() == PlotTypes.PLOT_OCEAN)
or (gc.getUnitInfo(unitType).getDomainType() == DomainTypes.DOMAIN_LAND and pPlot.getPlotType() == PlotTypes.PLOT_LAND):
bPlotValid = False
for i in range(pPlot.getNumUnits()):
if gc.getTeam(pPlot.getUnit(i).getTeam()).isAtWar(gc. getPlayer(iPlayer).getTeam()):
bPlotValid = False
break
if bPlotValid:
validPlotList.append(pPlot)
if len(validPlotList):
rand = CyGame().getSorenRandNum(len(vaildPlotList), "Random unit plot")
iPlotX = validPlotList[rand].getX()
iPlotY = validPlotList[rand].getY()
for i in range(numUnits):
gc.getPlayer(iPlayer).initUnit(unitType, iPlotX, iPlotY, NO_UNITAI)
Now checks that the plot is valid for the unit (sea for water units, land for land units, and peak for no units.)
The more I write, the less chance it'll work first time. Gunner picked up one of my mistakes last time, but I don't know if there are any more in here now.
wotan321 Sep 02, 2006, 01:25 PM Thanks so much.
wotan321 Sep 02, 2006, 01:32 PM Uh... got an error on the line:
if pPlot.getPlotType() == PlotTypes.PLOT_PEAK or (gc.getUnitInfo(unitType).getDomainType() == DomainTypes.DOMAIN_SEA and pPlot.getPlotType() == PlotTypes.PLOT_OCEAN)
The Great Apple Sep 02, 2006, 01:51 PM Hmmm. Try moving the next line to follow after it:
if pPlot.getPlotType() == PlotTypes.PLOT_PEAK or (gc.getUnitInfo(unitType).getDomainType() == DomainTypes.DOMAIN_SEA and pPlot.getPlotType() == PlotTypes.PLOT_OCEAN) or (gc.getUnitInfo(unitType).getDomainType() == DomainTypes.DOMAIN_LAND and pPlot.getPlotType() == PlotTypes.PLOT_LAND):
I probably moved it down so that I could see it all on my screen, but I'm pretty sure that isn't valid syntax.
I'm assuming it was a syntax error. It should have told you.
wotan321 Sep 03, 2006, 09:37 AM Okay, I made the recommended changes and after a bunch of testing and editing and more testing... I am still getting an error message in the PythonErr.log file, and no units are appearing. It makes me sad.....<g>. And even though experimenting and trying things out is fun and educational, since I am not making progress, its bumming me out.
Attached is a .zip file containing the CvEventsInterface from Vanilla civ (there doesn't seem to be such a file in Warlords), also included is the CvEventManager from my Testmod\Python folder where the testmod is. The PythonErr.log file is there, and the Testmod.WarlordsWBSave file too.
To save you the unzipping, here is module from CvEventManager.py
def onBeginGameTurn(self, argsList):
'Called at the beginning of the end of each turn'
iGameTurn,iPlayer = argsList
CvTopCivs.CvTopCivs().turnChecker(iGameTurn)
###added stuff
unitType = gc.getInfoTypeForString("UNITCLASS_PIKEMAN")
numUnits = 3
if iPlayer == 0:
if iGameTurn == 333:
iPlotX = 28
iPlotY = 9
pPlot = CyMap().plot(iPlotX, iPlotY)
bPlotValid = True
for i in range(pPlot.getNumUnits()):
if gc.getTeam(pPlot.getUnit(i).getTeam()).isAtWar(gc. getPlayer(iPlayer).getTeam()):
bPlotValid = False
break
if bPlotValid:
for i in range(numUnits):
gc.getPlayer(iPlayer).initUnit(unitType, iPlotX, iPlotY, NO_UNITAI)
else:
validPlotList = []
for iX in range(-1, 2):
for iY in range(-1, 2):
if iX == iY == 0:
continue
bPlotValid = True
pPlot = CyMap().plot(iPlotX + iX, iPlotY + iY)
if pPlot.getPlotType() == PlotTypes.PLOT_PEAK or (gc.getUnitInfo(unitType).getDomainType() == DomainTypes.DOMAIN_SEA and pPlot.getPlotType() == PlotTypes.PLOT_OCEAN) or (gc.getUnitInfo(unitType).getDomainType() == DomainTypes.DOMAIN_LAND and pPlot.getPlotType() == PlotTypes.PLOT_LAND):
bPlotValid = False
for i in range(pPlot.getNumUnits()):
if gc.getTeam(pPlot.getUnit(i).getTeam()).isAtWar(gc. getPlayer(iPlayer).getTeam()):
bPlotValid = False
break
if bPlotValid:
validPlotList.append(pPlot)
if len(validPlotList):
rand = CyGame().getSorenRandNum(len(vaildPlotList), "Random unit plot")
iPlotX = validPlotList[rand].getX()
iPlotY = validPlotList[rand].getY()
for i in range(numUnits):
gc.getPlayer(iPlayer).initUnit(unitType, iPlotX, iPlotY, NO_UNITAI)
###
...and the PythonErr.log file says:
Traceback (most recent call last):
File "CvEventInterface", line 23, in onEvent
File "CvEventManager", line 172, in handleEvent
File "CvEventManager", line 324, in onBeginGameTurn
ValueError: need more than 1 value to unpack
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):
File "CvEventInterface", line 23, in onEvent
File "CvEventManager", line 172, in handleEvent
File "CvEventManager", line 324, in onBeginGameTurn
ValueError: need more than 1 value to unpack
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):
File "CvEventInterface", line 23, in onEvent
File "CvEventManager", line 172, in handleEvent
File "CvEventManager", line 324, in onBeginGameTurn
ValueError: need more than 1 value to unpack
ERR: Python function onEvent failed, module CvEventInterface
....and how the heck do you get the quotes to indent properly?
The Great Apple Sep 03, 2006, 09:48 AM Default (and what I wrote) is:
iGameTurn, iPlayer = argsList
What you have (on line 324) is:
iGameTurn,iPlayer = argsList
I'm pretty sure (though not certain) that's your problem.
To indent properly use <text>. It also makes it quotable, which is useful.
EDIT: Also, instead of UNITCLASS_PIKEMAN you need UNIT_PIKEMAN.
wotan321 Sep 03, 2006, 10:02 AM Wow, TGA, that is fast.
I do not think the space is the problem, I tried it with and without the space, same error.
wotan321 Sep 03, 2006, 10:04 AM I replaced the line
iGameTurn = argsList[0]
with
iGameTurn, iPlayer = argsList
Would that have anything to do with it?
The Great Apple Sep 03, 2006, 11:23 AM Oh. Ooops. Should be onBeginPlayerTurn not onBeginGameTurn. Thought that space wouldn't have mattered, but it was the only thing I could see.
wotan321 Sep 03, 2006, 11:59 AM Queue the intro music!
It worked perfectly. Here is the amended and fully correct code.
def onBeginPlayerTurn(self, argsList):
'Called at the beginning of a players turn'
iGameTurn, iPlayer = argsList
###added stuff
unitType = gc.getInfoTypeForString("UNIT_PIKEMAN")
numUnits = 3
if iPlayer == 0:
if iGameTurn == 333:
iPlotX = 28
iPlotY = 9
pPlot = CyMap().plot(iPlotX, iPlotY)
bPlotValid = True
for i in range(pPlot.getNumUnits()):
if gc.getTeam(pPlot.getUnit(i).getTeam()).isAtWar(gc. getPlayer(iPlayer).getTeam()):
bPlotValid = False
break
if bPlotValid:
for i in range(numUnits):
gc.getPlayer(iPlayer).initUnit(unitType, iPlotX, iPlotY, UnitAITypes.NO_UNITAI)
else:
validPlotList = []
for iX in range(-1, 2):
for iY in range(-1, 2):
if iX == iY == 0:
continue
bPlotValid = True
pPlot = CyMap().plot(iPlotX + iX, iPlotY + iY)
if pPlot.getPlotType() == PlotTypes.PLOT_PEAK or (gc.getUnitInfo(unitType).getDomainType() == DomainTypes.DOMAIN_SEA and pPlot.getPlotType() == PlotTypes.PLOT_OCEAN) or (gc.getUnitInfo(unitType).getDomainType() == DomainTypes.DOMAIN_LAND and pPlot.getPlotType() == PlotTypes.PLOT_LAND):
bPlotValid = False
for i in range(pPlot.getNumUnits()):
if gc.getTeam(pPlot.getUnit(i).getTeam()).isAtWar(gc. getPlayer(iPlayer).getTeam()):
bPlotValid = False
break
if bPlotValid:
validPlotList.append(pPlot)
if len(validPlotList):
rand = CyGame().getSorenRandNum(len(vaildPlotList), "Random unit plot")
iPlotX = validPlotList[rand].getX()
iPlotY = validPlotList[rand].getY()
for i in range(numUnits):
gc.getPlayer(iPlayer).initUnit(unitType, iPlotX, iPlotY, UnitAITypes.NO_UNITAI)
###
What it does. It puts unit(s) you specify on a location you specify on a gameturn you specify, without any other modules required.
One word was missing from the NO_UNITAI, it wanted the UnitAITypes.NO_UNITAI instead.
And yes, I did go look at other examples to see what the error code was telling me. See, I can be taught.... for the most part...:D
Gunner Sep 03, 2006, 01:43 PM Congrats wotan :thumbsup:
wotan321 Sep 03, 2006, 07:45 PM Congrats wotan
Yes, life is good. All the help and encouragement is greatly appreciated.
wotan321 Sep 03, 2006, 08:25 PM Okay, one more question and I SWEAR, I won't ask another one... for days, perhaps a week!
What if I wanted to put 3 ENEMY units at a certain area on a certain game turn?
...uh, and with a popup box telling me they are there.
No more questions... I mean it..... really.... for a while... maybe a week.... at least a few days..... seriously.... I mean it....
The Great Apple Sep 04, 2006, 06:58 AM What do you mean by enemy? If I understand you correctly enemy units should be able to be done with the above code.
Popups... urrrgh. I hate popups. I'm going to annoy you by suggesting you look at Kael's tutorial in the tutorials forum... which I just see you have already posted on.
wotan321 Sep 04, 2006, 01:38 PM Yep, I figured I would spread the love around so I asked about popups on the popup thread.... though I have come to love that Zulu "Wrong Forum" message.
My vague question was.... well I see how it places MY (the human) units on the map, but what line would place say.... player 2's units on the map.
Is it that last two lines:
for i in range(numUnits):
gc.getPlayer(iPlayer).initUnit(unitType, iPlotX, iPlotY, UnitAITypes.NO_UNITAI)
The Great Apple Sep 04, 2006, 01:40 PM Nope - this line should do the trick:
if iPlayer == 0:
Gunner Sep 04, 2006, 02:12 PM How do you determine a player's iPlayer value? Is it just the order that they are listed in the WBS? Or is there some type of gc.getInfoTypeForString thing that you can do?
The Great Apple Sep 04, 2006, 02:23 PM Hmmm. Good question.
You'd probably have to iterate through all the player's to find the one with the right Civ:
iCivPlayer = -1
for i in range(gc.getMAX_CIV_PLAYERS()):
if gc.getPlayer(i).getCivilizationType() == gc.getInfoTypeForString("<Insert civ name>"):
iCivPlayer = i
break
Gunner Sep 04, 2006, 02:34 PM Thanks TGA.
Oh and forgive me if this is wrong, but shouldn't it be gc.getPlayer(i).getCivilizationType() instead of gc.getPlayer(iPlayer).getCivilizationType()? With the thing you have up there it doesn't look like you are using the i range value anywhere.
Gerikes Sep 04, 2006, 02:35 PM Hmmm. Good question.
You'd probably have to iterate through all the player's to find the one with the right Civ:
iCivPlayer = -1
for i in range(gc.getMAX_CIV_PLAYERS()):
if gc.getPlayer(i).getCivilizationType() == gc.getInfoTypeForString("<Insert civ name>"):
iCivPlayer = i
break
I would think that if you're trying to figure out how to get a players id, there would be some sort of reference (either a city, unit, plot, etc.) that you are drawing from. Isn't it possible to have multiple players be the same civ type?
wotan321 Sep 04, 2006, 02:35 PM Okay, I am confused. I thought that line
if iPlayer == 0:
was asking if the player taking the turn is player 0, ie the human player.
I want, on my (the human players) turn, for one of the AI civ's units to show up on a plot. So I want the code to ask
If is the human players turn, and if there turn is X, then have 3 AI units created on a plot
The Great Apple Sep 04, 2006, 02:35 PM I don't know what you're talking about. :mischief:
I fixed it shortly after I posted it.
Gunner Sep 04, 2006, 02:38 PM Okay, I am confused. I thought that line
if iPlayer == 0:
was asking if the player taking the turn is player 0, ie the human player.
I want, on my (the human players) turn, for one of the AI civ's units to show up on a plot. So I want the code to ask
If is the human players turn, and if there turn is X, then have 3 AI units created on a plot
Is it really necessary that the AI unit must show up on the human player's turn rather than the AI player's turn? Doesn't seem like it would really make much of a difference.
@TGA
Talking about what? I swear, sometimes my eyes play tricks on me ;)
The Great Apple Sep 04, 2006, 02:41 PM I would think that if you're trying to figure out how to get a players id, there would be some sort of reference (either a city, unit, plot, etc.) that you are drawing from. Isn't it possible to have multiple players be the same civ type?True. Some referance would be better. You could always check other stuff such as the leaderheard.
@wotan321
Oh right. In that case replace iPlayer in that line with the player ID of the player you want to spawn the thing of.
wotan321 Sep 04, 2006, 05:09 PM In that case replace iPlayer in that line with the player ID of the player you want to spawn the thing of.
Excellent suggestion.... how would I express that in code? Instead of iPlayer, I would put in there..... what? How do I identify the players?
The Great Apple Sep 04, 2006, 05:13 PM A number. If you slot the code I put above in, assuming you only have one player per Civ, it should find the right player and iCivPlayer will be assigned to that player.
If you have more then one player for Civ then it would need some tinkering - I'd need to know what is unique about each player.
wotan321 Sep 05, 2006, 05:32 AM Thanks again, that worked perfectly.
|
|