AI assistance requested for a Prophet mod

Use my tutorial (in my signature). Setting up the environment shouldn't be difficult.
Alright, I'm a bit lost at the moment trying to wrap my head around the coding mechanisms so I'd like a brief respite anyhow. Sounds easier to set up than trying to understand how to write these codes.

I think that you're under the impression that the compiler is just like a spell checker.
In some ways it might be, but keep in mind that you don't know the language ;)

Note that it does much more than checking that you have spelled your variables correctly, or that you've defined them at all.
It checks for types, it checks for validity of expressions, it checks whether functions you call exist at all and whether they exist in the specific context in which you try to call them (e.g. whether a function belongs to a class).

And in addition to checking it also translates your code to machine code so you can test it. As Baldyr said, it is probably better to write your function in parts and see if each part works before going forward, unless you know how you want everything to look, and then just compile during the writing.
Alright this will all make more sense once I start trying it I'm sure. I think the part that's confusing me is how to compile just one of the source files... aren't they all put together into one dll? What commands would you use in 2008 express to compile just one file? And in this 'compile' reference, are we meaning just a code check or are we completely recreating the entire dll? Is there a way to just run a quick check on the code that doesn't involve every step taken to form the dll? I opened a file inside 2008 and yeah, ok, I could edit the code in there, but then what?

I'll look into the version control thing there but I must admit, the whole Tortoise program is rather intimidating. I was introduced to the concept of it when I was downloading Afforess's source files for his AND SDK and didn't understand a bit of it. But I'll read your tutorial on that and comment back on it.


I'm not sure what you mean. It does the same job in the sense that it turns something into a runnable program. In any other way it's probably different.
There is some basic (quick basic I think, literally) involved in a Microsoft Access program, where button clicks are concerned and some other tricksy details. Before you just save and accept the programming you've put in place, as is, you should always 'compile' which will highlight any errors you may have made that would halt the program from functioning further. I realize this will be quite different in the sense that the C++ language doesn't run from what is typed but from an encrypted coding that puts it more closely into terms and mathematical binary that the computer processor can use more directly, a code we would likely not understand with any great ease.

In this case, you should use it as the base code like this:
After setting up the environment, copy the original BTS (3.19) files to your working folder (the same folder with the makefile and the Visual Studio project files).
Then copy the AND source files - *.cpp, *.h, *.inl (if they exist), CvGameCoreDLL.rc (if exists) - over these files.
The reason is that not always you have all the required source files in a mod, since sometimes only the source files that were changed are included.
Be careful not to override the makefile or the VS files.
Makes sense... I suppose the previous dll I compiled from just the modified source files I had might even be screwy on this premise of potentially missing files, though it did seem to work just fine. And I just compared the source code file and the core dll file and it seems everything is there so I worry I'm going to mess things up if I try to do a merge at this point... there may be some things in the core (what appear to be superflous, non-source files) that maybe shouldn't be there.


I'm sorry. If you think it'll be more helpful I can try, but It's not always that simple looking at the code and figuring out what's going on with it. That's where the compiler is very handy.
Again, once I start seeing output from the compiler, I'll better understand how this can be helpful. Additionally, I realize this needs to be broken down and looked at just one bit at a time rather than the whole thing splayed out there like it currently is.

Just as an example - the following statement would not have compiled:
Code:
relfounded((ReligionTypes)iI))=1;

This is because relfounded is of type int, and you cannot apply parentheses to this type - it is undefined.

It seems that you want an array there, but accessing it and defining it is different than what you've written.
Yeah, that's the big headache I'm getting right now... rather pinpointed in fact. I'm totally lost on how to define this. To explain my befuddled thinking:
I'm trying to somehow isolate the religions that have been founded so that I can remove them from consideration here. My thinking is, once we know the ones that have been founded, we can also define all the ones that haven't been by assigning a value of 1 to those that have and 0 to those that haven't. Then we can move on to defining what to do if there exists any that have not been yet founded. I suppose one thing I've forgotten entirely in all this also has been to return a False if all religions have already been founded.

Go ahead, you can chuckle now ;) How am I supposed to go about this? Or rather, how would an experienced programmer begin this process?

BTW, I re-read your original post and I understand that you already merged some SDK code, compiled it and tested that it works?
Then why not using that as base and go on from there?
Well, that's what I am doing, so far as I thought... My experience in compiling the dll was limited to simply following the instructions like a lemming and seeing a completed dll file come forth as a result. How to go on from there was too confusing to follow, the debugging and such. I took a 'if it works its obviously fine' approach given how minimal the adjustments I made at the time were. I switched out the old dll with the new one and the thing ran with the intended changes (aka, the first spread of an unfounded religion not only founded the religion but, as the changes suggested they might, also established the holy city at the site of the first spread) like a charm.

Since then, I've been working on source files located within the same folder as the source files I compiled into a .dll. Though, at the moment, I know my coding is so flawed I have only been playing with a notepad++ doc to formulate the above shown template. Since I know it has no hope of being functional, I felt it best not to include it into the actual source file yet, as the only means I understand of testing the code is to recompile the entire dll and run the mod. Perhaps once I understand the compiler programs I'll feel differently about that.

In case I misunderstood you and you didn't - I suggest you first implement the non-AI functionality, and only then (after you've seen that it's working) add the AI, since the AI will need to use this functionality anyway.
That's exactly the stage I'm at. For the human player, the founding of religions via prophets is working just fine (though I suppose I have some xml work to do to really flesh it out still... at the moment, I've only included a couple religions for the prophet to work with for testing purposes. Additionally, I need to create an invisible, unattainable tech to assign religion prereqs to so as to disable achieving religions via technologies and I also plan to make the techs that normally grant a religion give a prophet to the first to achieve instead. Since those last two steps there are much easier for me to understand how to do them, I've left them for a quick wrap up.)

Thank you so much for your help by the way... this stuff is really confusing me. I've been sitting here for days trying to read code and tutorials and attempting to understand what I'm seeing and how to make it work for me and I feel like a blind idiot because so much of it just loses me. I mean...

Quotes like these:
the C++ tutorial said:
The scope operator ( :: ) specifies the class to which the member being declared belongs, granting exactly the same scope properties as if this function definition was directly included within the class definition.
Do little more than make my head spin trying to understand the concept they're trying to express. Nevertheless, I find myself really needing to understand these things and returning to reread them again and finding it doesn't make any more sense than it did the first time I read them. This is just one of a hundred examples.

Then I try to read the codes and while I kinda get the basic concepts of what the code is doing, the specifics are often baffling. Then by the time I understand something I didn't understand before, I find I've forgotten why I needed to understand it in the first place...

Perhaps I'm just trying to swallow it all at once and no stomach can fit that much in one sitting...

@Baldyr: My question then is this... if I compiled little bits of this code and ran it, how would I know if it came back with a True or False? Are you suggesting to test it in game? I'm asking just to be clear because so far that's what I got from your last comment.
 
Alright, I'm a bit lost at the moment trying to wrap my head around the coding mechanisms so I'd like a brief respite anyhow. Sounds easier to set up than trying to understand how to write these codes.

Alright this will all make more sense once I start trying it I'm sure. I think the part that's confusing me is how to compile just one of the source files... aren't they all put together into one dll? What commands would you use in 2008 express to compile just one file? And in this 'compile' reference, are we meaning just a code check or are we completely recreating the entire dll? Is there a way to just run a quick check on the code that doesn't involve every step taken to form the dll? I opened a file inside 2008 and yeah, ok, I could edit the code in there, but then what?

Well, that's what I am doing, so far as I thought... My experience in compiling the dll was limited to simply following the instructions like a lemming and seeing a completed dll file come forth as a result. How to go on from there was too confusing to follow, the debugging and such. I took a 'if it works its obviously fine' approach given how minimal the adjustments I made at the time were. I switched out the old dll with the new one and the thing ran with the intended changes (aka, the first spread of an unfounded religion not only founded the religion but, as the changes suggested they might, also established the holy city at the site of the first spread) like a charm.


Since then, I've been working on source files located within the same folder as the source files I compiled into a .dll. Though, at the moment, I know my coding is so flawed I have only been playing with a notepad++ doc to formulate the above shown template. Since I know it has no hope of being functional, I felt it best not to include it into the actual source file yet, as the only means I understand of testing the code is to recompile the entire dll and run the mod. Perhaps once I understand the compiler programs I'll feel differently about that.

Well, I think you're trying to chew everything all at once, and I think it's partially my fault...

Anyway, a few things:

First, if you have already successfully compiled the DLL, and even made changes to the code, compiled it, and got a new working DLL - excellent!
Why not using the same infrastructure?
You don't have to go through all the steps everytime you want to compile. Once you've set it up once (and you have), you can just open the solution in VS, change whatever files you want and build.

A short explanation on compilation, which might help you understand it better:

Each cpp file is called a 'compilation unit'. This compilation unit can (and in our case - does) include many header (.h) files which contain declarations of classes, functions and global variables. This is done using the '#include' statement.
The compiler works on a single .cpp file at a time, and creates an object file, which is in machine language.
After compiling all the .cpp files, the linker utility links all those object files to a single DLL file, which the game can use.

The compilation in our case doesn't use the VS 2008 compiler but the compiler which comes with the much older VC++ 2003 toolkit (to match to the already compiled exe). So some of the abilities which VS usually have in its UI are not available, such as compiling a single specific file.
However, when you compile the DLL it will only compile those files which need to be compiled - specifically the ones that you've changed since their object file was last created, and then it will re-link all the object files to create the DLL file.
This is usually the way you work with C++ anyway - you don't compile just a single file, but you let the environment decide which files should be compiled.
One of the drawbacks here, however, is that when the compiler comes across errors - it will stop after failing to compile a specific .cpp file, so you cannot see all the errors at once.

Note that if you change a header file, all the files which include it are considered 'changed', and therefore will be re-compiled.
(I'm currently working on a 2nd part for the DLL tutorial, which will explain how to use VS, so it could help you later easily see what the compiler says about your code)

I'll look into the version control thing there but I must admit, the whole Tortoise program is rather intimidating. I was introduced to the concept of it when I was downloading Afforess's source files for his AND SDK and didn't understand a bit of it. But I'll read your tutorial on that and comment back on it.

I answered you there, and I hope the whole issue doesn't complicate you too much...

Yeah, that's the big headache I'm getting right now... rather pinpointed in fact. I'm totally lost on how to define this. To explain my befuddled thinking:
I'm trying to somehow isolate the religions that have been founded so that I can remove them from consideration here. My thinking is, once we know the ones that have been founded, we can also define all the ones that haven't been by assigning a value of 1 to those that have and 0 to those that haven't. Then we can move on to defining what to do if there exists any that have not been yet founded. I suppose one thing I've forgotten entirely in all this also has been to return a False if all religions have already been founded.

Go ahead, you can chuckle now ;) How am I supposed to go about this? Or rather, how would an experienced programmer begin this process?

You don't have to have a local copy of which religions are founded, since this information is easily accessed. I think that what you want, as a first step, is to count how many religions have already been founded.
For this you need to define an int variable, and add 1 to it for every founded religion.

Thank you so much for your help by the way... this stuff is really confusing me. I've been sitting here for days trying to read code and tutorials and attempting to understand what I'm seeing and how to make it work for me and I feel like a blind idiot because so much of it just loses me. I mean...

No problem. I'm glad to (try to) help.
 
You don't have to have a local copy of which religions are founded, since this information is easily accessed. I think that what you want, as a first step, is to count how many religions have already been founded.
For this you need to define an int variable, and add 1 to it for every founded religion.
How to figure out what I can access easily with a reference and what I can't has been a mystery... After all the tutorial readings, I still don't know where I can look for that. I thought it might be in the header files somewhere but :dunno: .

Ok, so what we first do then is attempt to get a count of all founded religions? I'm struggling to see how that would be helpful data to isolate... hmm... maybe this is a big part of what I'm not understanding about methods being employed in the current codes.

Here's what I'm attempting to do:

* Isolate all the un-founded religions into a list. (And this is what I'm trying to suggest with the first part of my convoluted code.)
* Tell the AI to push the mission select for its 'favorite' religion if it is on that list and return true.
* If the favored religion isn't on the list then we assign each religion on that list a value = leaderhead flavor x religion flavor (been working on putting flavors in the religions along the lines of our local tutorial but have run up against the problem that he didn't complete the xml tag tutorial for arrays - another matter to address entirely but I may be able to figure it out based on well developed tutorials on the non-arrays)
* We then compare all those values for the top value on that list.
* Then we tell the AI to push the mission select for the religion with the highest value and return true.
* Otherwise, we return false and allow the prophet to go on with the rest of its potential action evaluations. This priority is being placed just after the first one so 'building a shrine, if possible' takes precedence.

In part, much of this logic is based on understanding that a prophet is going to start inside a city (unless some crazy python developer comes along with a new way to generate one ;) ) so it becomes unneccessary to tell the unit to move anywhere in this routine. (Still... as a curiosity... what would happen if it attempted to push a mission that can't be pushed? Would it crash or would it just return false? I suppose that check should be built into this to avoid such a possible problem... but again... how to reference this in the code?)

I think I might just be struggling to understand how to write this because I'm still working on understanding how to use loops and arrays properly and not knowing what reference calls I can use for this.
 
I don't think your logic is lacking, but you should probably just read more on C++ and the issues you're struggling with, like loops and arrays. It wouldn't be easier for someone (Asaf) to explain it than it would be to read some textbook that already explains it. It would in fact be easier for him to just do this function for you and explain what each line/statement does. I'm not sure if this would help you learn any of it.
 
Well, this is how I see it (in pseudo-code):

Code:
if favorite religion of current player was not founded:
    push mission 'found religion' with parameter 'favorite religion' and return true

bestValue = 0
bestReligion = NO_RELIGION

go over all religions:
    if religion was not founded:
        [COLOR="DarkGreen"]// Note that there's already a CvPlayerAI::AI_religionValue() method, but this will only work for already founded religions.[/COLOR]
        value = calculateUnfoundedReligionValue(eReligion)
        if value > bestValue:
            bestReligion = eReligion
            bestValue = value

if bestReligion != NO_RELIGION:
    push mission 'found religion' with parameter 'bestReligion' and return true

return false

(I imagine you mean whether religion was founded, and not whether player has this religion)

Does it look like what you thought of?

What do you mean a mission which can't be pushed? Why won't you be able to push it?

Here's another issue I thought of: What if the prophet fails spreading the new religion? Should it be allowed to fail? Does it influence the choice of city?

And does the compilation work OK?
 
Wow... that's awesome Asaf... I can tell by looking at your pseudo-code that I really overthink things too far. That's exactly the sort of routine I'm looking for and in the structure I needed to maybe work out the rest. (You couldn't point me to a reference library for the SDK could you? I guess it could be in some of the other files... I'll do some hunting. For example, how to reference isReligionFounded... correctly anyhow, and how to see if such a reference exists...) Yes... I do just mean if the religion has been founded anywhere. I considered determining this by searching if there is a holy city but that seems silly considering holy cities can be destroyed but the religion has still been founded.

What I meant by 'if you can't push the mission' was... if the prophet isn't inside a city, it can't spread a religion. So if a prophet somehow spawns outside a city for the AI (probably due to some strange sort of python routine put in place by a future developer), then it won't be in a city when the AI first attempts to figure out what to do with him. Provided there is not a shrine to build, this would lead the ai to some confusion that the prophet can't immediately found a religion, despite there being foundable religions left, wouldn't it? Unless we told it to go to a city first, something that shouldn't be a worry normally as it would start inside a city if it were born or given out as a bonus for being first to a tech (whatever city it ends up in should just become the center of the next AI determined religion).

I figured I could control the likelyhood of the spread inside the XML. UnitInfos allowed me to insert the spread ability for a particular religion to the Prophet, and as I recall, along with that was a base percentage chance of success (default for the missionaries has been set to 40 or so which obviously gets greatly improved with one or two religions in the city). I figured if I just set that number up to 100 then it should have, theoretically, no chance of failure. That said, I was also going to read the SDK to find out where this chance is determined to make sure that I'm doing it right... for all I know, 40 might be the chance for failure (and through a quick playtest would become immediately obvious if increasing the number suddenly meant none of them were succeeding.)

And does the compilation work OK?
I'm not entirely sure what you are asking here but if you mean what I think you mean, regarding the Tortoise stuff, I just got back in from RL and should be working on that soon. (though I must admit, you've provided me with the insight I think I needed to figure out this code so I'm excited to get right on that immediately...) So far, I haven't altered ANY of the source documents in the working file that I compiled my last .dll from... just been working on a copy and was going to just replace the working file source documents where I've made changes, keeping the original ones put aside and safe as backups. I'm sure it takes a bit more effort that way, but until I figure out Tortoise, it suffices for now.

I must admit, I'm a bit scared to try working with the tortoise methods right now because at the moment, its already in place where I have the backups it's automatically made from any file I've manipulated... I'm worried starting that process in the middle of things would somehow screw up my current .bak files.
 
Ok, so this is what I've worked up. I thought it just might work so I attempted a compile and got numerous errors regarding CivInfos so I obviously need to go back to the Xienwolf tutorial and see what elements I either did not complete... or did wrong. Nevertheless, it didn't get around to checking this and errored out beforehand so I figured I'd check with you as I work on CivInfos. What do you think of this?

Spoiler :
Code:
/*TB Prophet Mod begin*/

bool CvUnitAI::AI_foundReligion()
{
	PROFILE_FUNC();

	ReligionTypes eBestReligion;
	ReligionTypes eReligion;
	FlavorTypes FlavorValue
	int iI;
	int iJ;
	int bestValue;

	eBestReligion = NO_RELIGION;
	
	ReligionTypes eFavorite = (ReligionTypes)GC.getLeaderHeadInfo(getLeaderType()).getFavoriteReligion();
	
//if favorite religion of current player was not founded:
	if (NO_RELIGION != eFavorite && !GC.getGameINLINE().isReligionFounded(eFavorite))
	{
//	push mission 'found religion' with parameter 'favorite religion' and return true
		getGroup()->pushMission(MISSION_SPREAD, eFavorite);
		return true;
	}


bestValue = 0
eBestReligion = NO_RELIGION

//go over all religions:
	for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
	{
		if (m_pUnitInfo->getReligionSpreads((ReligionTypes)iI) > 0)
		{
			if (!GC.getGameINLINE().isReligionFounded((ReligionTypes)iI)
			{
				for (iJ = 0; iJ < GC.getNumFlavorTypes(); iJ++)
				{
				ivalue += AI_getFlavorValue((FlavorTypes)iJ) * GC.getReligionInfo((eReligion)iI).getFlavorValue((FlavorTypes)iJ);
					if (value > bestValue)
						{
						bestReligion = eReligion
						bestValue = value
						}
				}
			}
		}
	}
	
	if eBestReligion != NO_RELIGION
	{
//	push mission 'found religion' with parameter 'eReligion' and return true
		getGroup()->pushMission(MISSION_SPREAD, eReligion);
		return true;
	}
return false
}
int CvUnitAI::AI_getFlavorValue(FlavorTypes eFlavor) const
{
	FAssertMsg((getPersonalityType() >= 0), "getPersonalityType() is less than zero");
	FAssertMsg((eFlavor >= 0), "eFlavor is less than zero");
	return GC.getLeaderHeadInfo(getPersonalityType()).getFlavorValue(eFlavor);
}

/*TB Prophet Mod end*/
Might I have made some other unforseen errors?
 
I suggest you start by fixing the errors which the compiler gives you.

(You can try reading the new 'Working with VS' section I added to my DLL tutorial. I think it could help you, and there's no need to install anything new!)

Keep in mind that the code base you work on is much different than what I look at (I look at BTS 3.19), so there might be more functionality which I don't know.

You can start by posting some of the compiler errors and I can help you fix them. It'll become easier over time.

Looking at the beginning of your code (sorry, but I'll have to read the rest of your code later) it seems alright.
The main problems I see here are that you try to access the player's methods without the player instance (for example: getLeaderType()).
You can get the player instance using:
Code:
GET_PLAYER(getOwnerINLINE()).getLeaderType()

As for the 'not in city' issue - see how it's done in AI_construct (the pushed mission is actually to go to the city first).
 
Spoiler :
Code:
/*TB Prophet Mod begin*/

bool CvUnitAI::AI_foundReligion()
{
	PROFILE_FUNC();

	ReligionTypes eBestReligion;
	ReligionTypes eReligion;
	int iI;
	int iJ;
	int value;
	int bestValue;

	eBestReligion = NO_RELIGION;

	ReligionTypes eFavorite = (ReligionTypes)GC.getLeaderHeadInfo(GET_PLAYER(getOwnerINLINE()).getLeaderType()).getFavoriteReligion();
	
//if favorite religion of current player was not founded:
	if (NO_RELIGION != eFavorite && !GC.getGameINLINE().isReligionFounded(eFavorite))
	{
//	push mission 'found religion' with parameter 'favorite religion' and return true
		getGroup()->pushMission(MISSION_SPREAD, eFavorite);
		return true;
	}

value = 0;
bestValue = 0;
eBestReligion = NO_RELIGION;

//go over all religions:
	for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
	{
		if (m_pUnitInfo->getReligionSpreads((ReligionTypes)iI) > 0)
		{
			if (!GC.getGameINLINE().isReligionFounded((ReligionTypes)iI))
			{
				for (iJ = 0; iJ < GC.getNumFlavorTypes(); iJ++)
				{
				value += AI_getFlavorValue((FlavorTypes)iJ) * GC.getReligionInfo((ReligionTypes)iI).getFlavorValue((FlavorTypes)iJ);
					if (value > bestValue)
						{
						eBestReligion = ((ReligionTypes)iI);
						bestValue = value;
						}
				}
			}
		}
	}
	eReligion = eBestReligion;
	if (eReligion != NO_RELIGION)
	{
//	push mission 'found religion' with parameter 'eReligion' and return true
		getGroup()->pushMission(MISSION_SPREAD, eReligion);
		return true;
	}
return false;
}
int CvUnitAI::AI_getFlavorValue(FlavorTypes eFlavor) const
{
	FAssertMsg((getPersonalityType() >= 0), "getPersonalityType() is less than zero");
	FAssertMsg((eFlavor >= 0), "eFlavor is less than zero");
	return GC.getLeaderHeadInfo(GET_PLAYER(getOwnerINLINE()).getLeaderType()).getFlavorValue(eFlavor);
}

/*TB Prophet Mod end*/

IT WORKS! Like a charm! I couldn't have done it without you Asaf! Thank you so much for your kind and very skilled assistance! You've given me an enormous breakthrough here and I really owe ya one!

Leaders are using their prophets to initiate religions they prefer first, then accessing the flavors to determine what to initiate next (well.. haven't done the math to make sure of that but on a cursory glance at their choices, it seems they are.) At first I was worried that it was only working for the first portion - initiating their favorite religions only, then I realized I'd put it in the order that they'd want to build a shrine with the next prophet and I'd only given them two so that must've been what they'd done with that one. Giving the same leader another led to the next religion being founded immediately.

Now then... the next step is to make this an option - one that works into behaving differently depending on other religion options such as Limited Religions and Choose Religions (on or off).

I'll spend a bit of time researching about through the files to see where and how I can do that... I have some theories already forming. Perhaps, along the way, I'll be able to fix the bug that started me working on this in the first place (I wanted this sorta thing since I started playing vanilla so a nudge was all it took...)

I'm sure I'll be coming up with more questions along the rest of the way here but what a feel must be the biggest hurdle here has been cleared so I'm breathing a massive sigh of relief right now...

I'd say my next step is to figure out how to make the usually religion granting techs give a prophet instead. But I'll work on making this a gameoption first so I can make that completely conditional - either give a prophet or give the religion depending on whether our option is on or not. (Do you happen to know which source file controls the delivery of a religion on achieving a particular tech?)

Also... will start working with that tortoise program again immediately. From what I'm reading there, seems getting it down would offer some pretty cool longterm results. And I've got some graphic skills to develop here too...
 
Thunderbrd: Congrats! :goodjob: I'm pretty stunned, actually.
 
Very nice! You did a very good job with very little help. Especially for a C++ first timer. :goodjob:
Glad I could help :)

A few suggestions for your code:
- I think you should use CvUnit::canSpread() with the current unit's plot, both instead of getReligionSpreads() (canSpread already does that) and inside the 'favorite religion' if clause.
- You don't really need to define CvUnitAI::AI_getFlavorValue(). You can just replace the call to it with
Code:
GET_PLAYER(getOwnerINLINE()).AI_getFlavorValue()
This will call CvPlayerAI::AI_getFlavorValue() which does the same.

Did you check the probability of spread issue? The actual calculation is done in CvUnit::spread().

Do you happen to know which source file controls the delivery of a religion on achieving a particular tech?

Check CvTeam::setHasTech() - Look for this line:
Code:
if (GC.getReligionInfo((ReligionTypes)iI).getTechPrereq() == eIndex)

(unless it is different in RoM AND).
It has the entire logic of selecting a player in the team (since research is shared for the entire team) and the actual call to found the religion.
The founding tech is actually a property of the religion, and not vice versa.
 
Thunderbrd: Congrats! :goodjob: I'm pretty stunned, actually.

Thanks!... I am too by the way. That compiler is a genius little thing that actually really helps define what you've done wrong line by line. And not just with error codes which force you to look through a library of codes to figure out what went wrong either.

@Asaf... thanks for pointing those out. I posted the code, despite it working, here, because I realized there'd still be most likely some better ways of going about a few things than I did them. I'll work on streamlining a bit at this point.

I haven't checked the probability of spread issue but have set the xml fields I mentioned to 100 each and they didn't fail to spread (but then, I figured I'd look at the code before an ingame test regarding that.)

I'll take a look in the team cpp for that... thanks for the ongoing guidance!
 
That compiler is a genius little thing that actually really helps define what you've done wrong line by line. And not just with error codes which force you to look through a library of codes to figure out what went wrong either.
I wouldn't know, at this point, but I have a feeling that moving up to C++ programming will be a revelation. It might be less forgiving, but that is probably a good thing, as you're much more conscious of what you're doing. Like you actually have to defined the types of variables, allocate memory to them, that sort of thing.
 
That compiler is a genius little thing that actually really helps define what you've done wrong line by line. And not just with error codes which force you to look through a library of codes to figure out what went wrong either.

I don't want to say I told you so, so... :lol:
 
Well... it wouldn'ta helped me much from where I was starting there but yeah, more helpful than I thought it would be.


Ok, so, I attempted this:
- I think you should use CvUnit::canSpread() with the current unit's plot, both instead of getReligionSpreads() (canSpread already does that) and inside the 'favorite religion' if clause.
but it led to a tsunami of other problems. The second portion you mentioned was easily resolved but there's a lot more to 'canSpread' than I understand apparently. Referring to a plot is not so straightforward as I'd hoped apparently.

Now, in my tests, I find that the one flaw in this design is probably something you had intended me to begin the process of correcting with the above note. If I put a prophet outside a city for an AI, the prophet will basically just sit there doing nothing until there are no more religions left to found (oddly, it will even do so if there is a shrine yet to be built... ?). Only after all religions have been founded, will the prophet that's not inside a city activate and move.

This is a really minor thing in my opinion, as it is exceedingly uncommon for an AI to have any given reason to wind up with a prophet starting outside a city. When they are birthed, they start in a city and when they are given out for free as a result of achieving a tech, they should start in a city, so the only way this is going to happen is if a player (because we know AI's aren't going to have any reason to do this) actually gifts a prophet to an AI. Eventually, I will return to address this when I understand how the AI plots movements but when I try to read those portions of code in other sections, I'm getting quickly lost. So... for now... its a known bug (at least not one that leads to CTDs which I was getting when I tried to change the code as suggested above (probably because I didn't know what I was doing there))

Anyhow, more important to address at this time will be making this an option, and conditionally disabling tech requirements for the religions, while conditionally programming in the granting of a free prophet when those techs are achieved.

However, next up right away is working out that version control!
 
First, just in case you couldn't find it: plot() inside the unit's methods returns the current plot of the unit.
So this is how the call would look like:

Code:
canSpread(plot(), eReligion)

About the prophet freeze - I'm not surprised that it won't found any religions, since there is no code to tell it to move to a city first, so the 'illegal mission' is pushed (as you've mentioned a few posts ago), and this is probably the result - a unit which does nothing.
I am puzzled, however, by the fact that it won't construct any shrines. I think there's code to move the unit to a city in AI_construct.
Maybe you could try debugging it?

When you get to it, I suppose.

Good luck with the other stuff! let me know if you have any questions.
 
Wow... this stuff is like riding a bike... once you've done it once it just gets easier and easier, quite rapidly.

I've completed my mod in its entirety (thanks to your help!).

You can check out the results here!
 
Did you check out the True Prophet Mod or did you choose to reinvent the wheel?

Congratulations on figuring out how to modify the dll though, that's what prevents most people from doing interesting stuff like this :)
 
I did check that out, but there were two problems there. 1st, I didn't want to have proxy buildings in place for that purpose... I guess it just didn't seem like the right answer to me. And 2nd, that mod works with vanilla civ religions only so would have required as much or more work to adapt to C2C with all its extra religions.

With the way this mod is programmed, it works hand in hand with the Choose Religions option. (This mod is an option itself now, Divine Prophets.) When Choose Religions is on, any prophet can spread any religion at any time (and the first city to receive a given religion becomes the holy city for that religion.) Without Choose Religions on, only those religions that you have qualified for by reaching the tech prereq are available to be spread by prophets.

I do have one more big edit I'd like to make to this mod now, however, that I really looked into how to develop, and that's the button art. Would like to make an unfounded religion spread button appear different from a founded religion. Haven't worked much with the art side of things and not sure which source files control art tags so I can insert the proper if/then sequence there but I'm sure with a little digging I'll come up with something.

So far in playtesting, this has been a lot of fun. Allows me to build new cities without delaying to make sure most of my religions end up in my capital for one thing... and if I wish to specialize a city now, its not so difficult to put different religions, as they have varying shrine benefits, in one city or another. I had a CTD right at a point when I figured a civ was going to use a prophet to found a religion which gave me a scare that I might've done something wrong, but I think it was just my computer's time for a crash (it does that on this mod anyhow...) because upon reloading the last autosave, it played right through that juncture without a hitch. The AI chose his religion and we moved on (there's no random element in their decision making process there so it couldn't have been because he selected a different religion).

Anyhow, yes, working just as I'd hoped so far.
 
Back
Top Bottom