[WIP]Randomized Unique Components, and Traits

@Yuri: (I can call Yuri, right?) So does the program randomize components of nodded civilizations by its now? I didn't quite understand your explanation... :p

(And how does it interact with alternate leaders, mods that add new components to existing civilizations and move existing components to new civilizations?)

Think of it as there is a pool of possible components, and when adding modded civilizations you are adding to this pool, but as most mods have about 2 components for the modded civilization if the number of components per civilization is too high it can't find a way to divide up the components equally, and so restarts the random process till it finds a way.

Mostly just to put it in some terms there are 86 normal components, and 43 civilizations. With events and decisions the number goes up to 172 components which is just enough for 4 components each. Now if you add a modded civilization with 1 civilization, 1 leader, and 2 components the pool becomes :
44 Traits
44 Civilizations
174 Components
174/44 = 3.9545 Which means it'll never find a way to give 4 components to all civilizations as there isn't enough in the pool. Now if you set the number of components to 3 than it'll have no trouble as it just needs to give 3 components for every civilization. Which it has enough to preform this action up to 43 additional civilizations.
Picture :

The "Number of Components" is the option that allows you to decrease the number of components per civilization.

The only problem with civilization splits is the auto-modder. If you manually go into the Defines/Mods/NameOfDuplicateMod, and remove the duplicates you'll have no problems.
 
Update v0.301
Pretty small one just 2 things I noticed, and know a quick fix to.
  • Fixed a issue that could cause the program to run forever. Instead now the system will catch it before it happens, and throw an error message.
  • Also improvements have been changed slightly to make sure it's the actual improvement ID, and not it's art or TXT.
 
"Invalid attachment specified" when clicking the Download link. Also you should update your front page (For the what you want to do in the future) :p

Earlier when I tested a little bit, a few civs' didn't generate from JFD: Hannibal & Dido, Mehmed II & Suleiman, Switzerland, and Kingdom of Two Sicilies. I'll test again in a bit, it could have been my fault in this instance however.

Also I wanted to ask if it was possible for you to implement support for the 3UC and 4UC rejects?
Spoiler :
http://forums.civfanatics.com/downloads.php?do=file&id=24481
 
"Invalid attachment specified" when clicking the Download link. Also you should update your front page (For the what you want to do in the future) :p

Earlier when I tested a little bit, a few civs' didn't generate from JFD: Hannibal & Dido, Mehmed II & Suleiman, Switzerland, and Kingdom of Two Sicilies. I'll test again in a bit, it could have been my fault in this instance however.

Also I wanted to ask if it was possible for you to implement support for the 3UC and 4UC rejects?
Spoiler :
http://forums.civfanatics.com/downloads.php?do=file&id=24481

Fixed that. Yeah going to update it soon.

Didn't generate :
Mehmed II & Suleiman & Hannibal & Dido:
Crashed. Was caused by mod support for community balance patch in both cases.
It's another way I'm gonna have to look at the SQL. Got it fixed pretty quick I'll release the fix after I'm done typing this. You still need to remove any duplicates.

Switzerland & Two Sicilies :
Both had a file with broken XML Code for Text. When I fixed that it worked right away.
The two files were :
Switzerland : Switzerland_GameText_ModSupport.xml:Line 116 "</Row" didn't end with ">".
Two Sicilies : TwoSicilies_GameText.xml:Line 141 "</Row" didn't end with ">".

Just changing those yourself should fix those 2.

Edit: To answer the final question. I'll probably do that. It won't take long now that I have 3rd, and 4th done. It's just adding them to the possible pool. took me like 5 minutes. :D
 
Update v0.31

  • Added the Rejected(Additional) Unique Components mod support. If selected it will add 19 extra components to the pool of possible components when randomizing.
 
Thanks :)

I printed out a list of Civ's in the community by author so I should be able to test in detail relatively soon. :D

EDIT: Error with the download link...Again :p

Also a question: Whenever I add a split, so for example JFD's Louis XIV would it be like introducing a single new Civ to the game as it only adds two uniques or am I looking at it incorrectly. (Would like to know so I can min-max more Civs!
 
Thanks :)

I printed out a list of Civ's in the community by author so I should be able to test in detail relatively soon. :D

EDIT: Error with the download link...Again :p

Also a question: Whenever I add a split, so for example JFD's Louis XIV would it be like introducing a single new Civ to the game as it only adds two uniques or am I looking at it incorrectly. (Would like to know so I can min-max more Civs!

Have no idea about the download link this time it's working perfectly fine for me =/ Last time it didn't exist :rolleyes: this time don't know why that would be happening. Looked for it at the bottom of the post to find nothing. Don't know why it didn't exist.

Mostly needs to be treated like a additional civ. As long as it's applicable to do so. Sometimes they can do something weird with giving the lua based trait to the original civ. These will unfortunately in the current form always cause problems.

I'm gonna change the way mods work with the next update do something that makes the values in modded civs take priority over the base civilizations.
Also really should do something with this already :
:lol:
 
Oh, I see. But what I didn't get was how to make this work with mods(can I randomize multiple folders at once?)
 
Oh, I see. But what I didn't get was how to make this work with mods(can I randomize multiple folders at once?)

There's a line that says either true or false (lower case) in the Defines\Mods/NAMEOFMOD/randomsupport.txt which if true will add the mod to the random list when modded civs is selected. So just open that file and change false -> true and then the mod is selected for use. Just to put it as the system first looks for that true, and if it finds it it'll add the rest of the files to the pool.
 
Version 0.32 :

Additions :
  • Change Mods button has been unlocked, and now works. Change mods button now opens up a new window which you can enable the modded civilizations you want active. This state is saved for the next run as well. So you can add or remove as you see fit.

Found and Fixed Bugs :
  • Multiple lua based civs will now properly retain their Unique Ability (Note: The reason why this was a bug is most lua based mods the Unique Ability is based on the civilization type, and not the trait itself.).
    v.321 :
  • If a unique improvement isn't given a new civilization (If there is too many Components) the improvement will stay with it's normal civilization (SQL Bug, I don't delete them after they aren't used).

Edit :
Found, and not fixed bugs :
  • If a unique improvement isn't given a new civilization (If there is too many Components) the improvement will stay with it's normal civilization (SQL Bug, I don't delete them after they aren't used).
 
Just a update because I've been working on a civilization, and have something that will make compatibility much easier :
I've made a function in lua that will find your trait just by the name of the trait this is how it works :
Code:
--[[
--This function returns the GameInfoTypes.CIVILIZATION_NAME_OF_CIVILIZATION
]]--
function GetCivilizationByTrait( uType )
	-- Return Value
	local civilization = nil
	
	-- Iterate through traits
	for uniqueTrait in GameInfo.Leader_Traits() do
		
		-- Look for Specified Trait
		if ( uniqueTrait.TraitType == uType ) then
		
			-- Leader Type
			local leader = uniqueTrait.LeaderType
			
			-- Iterate through Civilization_Leaders
			for uniqueLeader in GameInfo.Civilization_Leaders() do
			
				-- Look for Civilization by Leader Type
				if( uniqueLeader.LeaderheadType == leader ) then
					
					-- Civilization String
					local civilizationTXT = uniqueLeader.CivilizationType
					
					-- Iterate through Civilizations
					for uniqueCivilization in GameInfo.Civilizations() do
					
						-- Look for Civilization by Type
						if uniqueCivilization.Type == civilizationTXT then
							
							-- Save ID
							civilization = uniqueCivilization.ID
							break
						end
					end
				end
			end
		end
	end
	-- return ID
	return civilization
end
--My CivID
local KomiToleranceCiv = GetCivilizationByTrait( "TRAIT_KOMI_TOLERANCE" )

This is probably in no way the most efficient method as I can still get choked up with how to access data in Civ5. Though to be honest it's probably only if I'm missing a quicker step than Trait -> Leader -> Civilization -> CivilizationID

Mostly thinking that there will probably be no way to totally make Lua mods work with this without some support from the modders, but this should make it quite a bit easier on your end as I'm also including RandomUtils.lua with every randomization.

So all you need to do is use this to make it compatible (Changing the values of course) :

Code:
include("RandomUtils");
local KomiToleranceCiv = GameInfoTypes.CIVILIZATION_GREATER_PERM
if ( GetCivilizationByTrait ~= nil ) then
	KomiToleranceCiv = GetCivilizationByTrait( "TRAIT_KOMI_TOLERANCE" ) end

Which makes the compatibility easier as I'll just have the Auto-modder look through the Lua files for RandomUtils.lua, and if it finds it it'll just count the lua based mod's Trait as ok for randomization. Mostly just posting this here for now I'll add the fix probably Saturday, but it's just something I came up with trying to make compatibility as painless as possible for modders. I'll also add this to the For Modders section when it's working in the program.

Also this utils also contains :
uType = a String so as example "TRAIT_KOMI_TOLERANCE".
Code:
GetCivilizationByUnique( uType ) 		-- finds the civilization by any unique type. Doesn't require specifying, and doesn't run all that much more. 
GetCivilizationByImprovement( uType ) 		-- finds the Civilization by Unique Improvement.
GetCivilizationByUnit( uType ) 			-- finds the Civilization by Unique Unit.
GetCivilizationByBuilding( uType ) 		-- finds the Civilization by Unique Building
Additional Functions in full :
Spoiler :

--Actually GetCivilizationByUnique is the only one done, but the other functions exist in this one.
Code:
function GetCivilizationByUnique( uType )
	print(uType)
	local civilization = nil

	if ( string.find(uType, "BUILDING", 0) ~=nil ) then
		print("Something")
		for uniqueBuilding in GameInfo.Civilization_BuildingClassOverrides() do
			if ( uniqueBuilding.Type == uType ) then
				local civilizationTXT = uniquBuilding.CivilizationType
				for uniqueCivilization in GameInfo.Civilizations() do
					if uniqueCivilization.Type == civilizationTXT then
						civilization = uniqueCivilization.ID
						break
					end
				end
			end
		end
	end
	
	if ( string.find(uType, "UNIT", 0) ~=nil ) then
		print("Something")
		for uniqueUnit in GameInfo.Civilization_UnitClassOverrides() do
			if ( uniqueUnit.Type == uType ) then
				local civilizationTXT = uniqueUnit.CivilizationType
				for uniqueCivilization in GameInfo.Civilizations() do
					if uniqueCivilization.Type == civilizationTXT then
						civilization = uniqueCivilization.ID
						break
					end
				end
			end
		end
	end
	
	if ( string.find(uType, "IMPROVEMENT", 0) ~=nil ) then
		print("Something")
		for uniqueImprovement in GameInfo.Improvements() do
			if ( uniqueImprovement.Type == uType ) then
				local civilizationTXT = uniqueImprovement.CivilizationType
				for uniqueCivilization in GameInfo.Civilizations() do
					if uniqueCivilization.Type == civilizationTXT then
						civilization = uniqueCivilization.ID
						break
					end
				end
			end
		end
	end
		
	if ( string.find(uType, "TRAIT", 0) ~=nil ) then
		print("Something")
		for uniqueTrait in GameInfo.Leader_Traits() do
			if ( uniqueTrait.TraitType == uType ) then
				local leader = uniqueTrait.LeaderType
				for uniqueLeader in GameInfo.Civilization_Leaders() do
					if( uniqueLeader.LeaderheadType == leader ) then
						local civilizationTXT = uniqueLeader.CivilizationType
						for uniqueCivilization in GameInfo.Civilizations() do
							if uniqueCivilization.Type == civilizationTXT then
								civilization = uniqueCivilization.ID
								break
							end
						end
					end
				end
			end
		end
	end
	print(civilization)
	return civilization
end
 
Mostly thinking that there will probably be no way to totally make Lua mods work with this without some support from the modders, but this should make it quite a bit easier on your end as I'm also including RandomUtils.lua with every randomization.

So all you need to do is use this to make it compatible (Changing the values of course) :

Code:
include("RandomUtils");
local KomiToleranceCiv = GameInfoTypes.CIVILIZATION_GREATER_PERM
if ( GetCivilizationByTrait ~= nil ) then
	KomiToleranceCiv = GetCivilizationByTrait( "TRAIT_KOMI_TOLERANCE" ) end

Yeah, since most modders use the assumption that the trait would always belong to the civilization they give it to - a correct assumption, before you released this, but an assumption nonetheless. :p

I feel that a lot of civilizations could be made compatible in this way, but there's one instance I'm thinking of where this probably wouldn't be enough: where faux-UUs, UBs and UIs are used to implement a UA's effects (I do this for my Walmington-on-Sea civilization, and I know others do it for theirs as well). This would require some additional code changes so that these components are given to the civilization that has the trait, rather than making the same assumption as the Lua does.

I am also worried about another issue relating to this - what happens when the randomiser encounters a mod civilization that has more than the normal two unique components (or 3 or 4 if 3rd or 4th Unique Components is active)? I can see this being a problem if:
  • The civilization uses faux-uniques for the trait, as described above; or
  • The civilization just has more than two uniques for whatever reason.
I can't see this playing well with my upcoming Oarai civilization, for instance, as it has eight unique Tank units to choose from, and I don't feel they should be randomly allocated to just any civilizations - and if they were, the dummy uniques that make sure Oarai looks okay in the select menu will mess things up.
 
Is there any chance for the next versions to alllow randomizing multiple folders at once?

(Takes ages to randomize every single mod I use, especially since I have to get into the mods folder time and time again.)
 
Yeah, since most modders use the assumption that the trait would always belong to the civilization they give it to - a correct assumption, before you released this, but an assumption nonetheless. :p

I feel that a lot of civilizations could be made compatible in this way, but there's one instance I'm thinking of where this probably wouldn't be enough: where faux-UUs, UBs and UIs are used to implement a UA's effects (I do this for my Walmington-on-Sea civilization, and I know others do it for theirs as well). This would require some additional code changes so that these components are given to the civilization that has the trait, rather than making the same assumption as the Lua does.

I am also worried about another issue relating to this - what happens when the randomiser encounters a mod civilization that has more than the normal two unique components (or 3 or 4 if 3rd or 4th Unique Components is active)? I can see this being a problem if:
  • The civilization uses faux-uniques for the trait, as described above; or
  • The civilization just has more than two uniques for whatever reason.
I can't see this playing well with my upcoming Oarai civilization, for instance, as it has eight unique Tank units to choose from, and I don't feel they should be randomly allocated to just any civilizations - and if they were, the dummy uniques that make sure Oarai looks okay in the select menu will mess things up.

It's a fair assumption. I did it as well with any Civilization I released before this.

Also just having more Components just increases the size of the pool like 3rd, and 4th unique components. Any excess Components are just removed from the game with SQL which is done because if a excess Component was a Improvement it would stay with it civilization :
Code:
/*
####################################################################
# REMOVED COMPONENT : (0)	UNIT_JAPANESE_ZERO
####################################################################
*/
DELETE FROM Units WHERE Type  = 'UNIT_JAPANESE_ZERO';

Eight is a bit much I only have a way to make it compatible with one, and that component is counted towards the number of Components. I think I'm going to change the way the information is saved in the defines to have more Compatibility with that, but will probably make sure that the old system works as well so you (or me because the defines took forever to do at first :lol:) can just use the same files. Though to get the auto-modder to pick this up is near impossible without a RandomSupport.txt in there.
Here's a update to how the TRAITS part of the RandomSupport.txt should look (The added comments make it look like more than it is) :
Code:
	--Every line after "TRAITS = { ", and before the connected "};" are added to the Traits.txt.
	TRAITS = {
		TRAIT = {
			--Required adds to the Pool of traits.
			Type = 'TRAIT_KOMI_TOLERANCE';
			
			--Not Required you could just remove this, but will keep these components with the Trait.
			--These components ARE counted towards the number of components per Civilization, 
			--and should be added to normal Components or it won't add the component.
			Components = {
				COMPONENT = {
					Type = '';
					Class= '';
				};
				COMPONENT = {
					Type = '';
					Class= '';
				};
			};
			
			--Not Required you could just remove this, but will keep these components with the Trait.
			--These components ARE NOT counted towards the number of components per Civilization, 
			--and should NOT be added to normal Components. 
			--They are added with the trait to the designated Civilization around the same time.
			--Just add, or remove COMPONENTS for the number you need.
			TraitComponents = {
				COMPONENT = {
					Type = '';
					Class= '';
				};
				COMPONENT = {
					Type = '';
					Class= '';
				};
			};
		};
	};
RandomizedTraits.txt :
Spoiler :
Code:
TraitBasedLua = 'TRUE';

OVERRIDE_AUTO  = { 
	MOD_SUPPORT = {
		Civ4Traits = {

			--Change to your Civilization Leader just used my Castle Town as a example for this
 			--just used Castle Town for it could be slightly harder to explain. 
			LEADER_AKANE = {
				Leader 	= 	'LEADER_AKANE';
				LeaderTXT	=	'Akane ';
			};
		};
	};
	CIVILIZATIONS = {
		CIVILIZATION = {
			Civilization = 'CIVILIZATION_ID';
			Leader = 'LEADER_ID';
		};
	};
	
	COMPONENTS = {
		COMPONENT = {
			Type = 'TYPE_ID';
			Class = 'CLASS_ID';
		};
		COMPONENT = {
			Type = 'TYPE_ID';
			Class = 'CLASS_ID';
		};
	};
	TRAITS = {
		TRAIT = {
			--Required adds to the Pool of traits.
			Type = 'TRAIT_KOMI_TOLERANCE';
			
			--Not Required you could just remove this, but will keep these components with the Trait.
			--These components ARE counted towards the number of components per Civilization, 
			--and should be added to normal Components or it won't add the component.
			Components = {
				COMPONENT = {
					Type = '';
					Class= '';
				};
				COMPONENT = {
					Type = '';
					Class= '';
				};
			};
			
			--Not Required you could just remove this, but will keep these components with the Trait.
			--These components ARE NOT counted towards the number of components per Civilization, 
			--and should NOT be added to normal Components. 
			--They are added with the trait to the designated Civilization around the same time.
			TraitComponents = {
				COMPONENT = {
					Type = '';
					Class= '';
				};
				COMPONENT = {
					Type = '';
					Class= '';
				};
			};
		};
	};
};
In SQL (Example was randomly used.) :
Spoiler :
Code:
INSERT INTO Leader_Traits
	(	LeaderType, 			TraitType)
VALUES	(	'LEADER_WU_ZETIAN', 		'TRAIT_SPICE');
/*
################################################
# Trait Components (Doesn't add to number of Components for this Civilization)
################################################
*/
INSERT INTO Civilization_UnitClassOverrides
	(	CivilizationType, 			UnitClassType, 							UnitType)
VALUES	(	'CIVILIZATION_CHINA', 		'UNITCLASS_WARRIOR',		'UNIT_POLYNESIAN_MAORI_WARRIOR');

Is there any chance for the next versions to alllow randomizing multiple folders at once?

(Takes ages to randomize every single mod I use, especially since I have to get into the mods folder time and time again.)

While checking the Change Mods button I noticed for some reason (didn't debug yet) it isn't un-checking the disabled Mods when the window pops up. Though it still works the same if you uncheck them all then recheck the ones you want. I'll be working on that fix right away, but just a FYI for now.

Fixed that problem. The code that checks if the mod was enabled was checking for true, and changing the check boxes that were to true. Which doesn't do anything with Java as Check Boxes default to true. Changed it to check for false(or not "true"), and changed the check box to false.
 
Update Now :
Lately I've been playing Rising Tide, and wanted to experiment with randomizing that.

So if you see the first post there is a version with [RisingTide]Randomized Game. Which is the one for Beyond Earth (Rising Tide needed for this to work. Going to need a completely opposite way of handling things for Vanilla).

Got it working in about 2 hours, but made it separate(even though it's the same thing). Mostly because I had to make sure it was working with some old source, and not my current project. It'll just be a included option later, but didn't want to change the current release to add this.

On Future Update :

Also wanted to give a update on how things are. The next update is where I would say I'm heading into what I'll actually put out as Version 1. Like take it out of exactly a "Work In Progress" which I would question if it's that right now. This is all for that version which is probably going to be released in January. It's a hefty one.

Mostly the differences are (also note ALL of these are optional, and just work at making a experience more in line with what you want.) :
  • A complete overhaul of the file system. One that'll give more data to each Component / Trait (at least vanilla / Supported Mods)
    1. Civilization Spawn Priorities - Like Brazilwood camp will give a preference to Jungle.
    2. Personality Modifications - Civilizations that have very warlike traits, or early units are more likely to declare war. Same goes for being peaceful with Swedish trait.
    3. Traits can contain Components that are part of the Trait, and not count to the number of Components (For some modded Civilizations).
    4. Also just so I'm covering the future. I'll be adding in a Value system. Which is more along the lines of trying to slightly balance the Traits, and Component combinations. This will not be in this "Version 1"

  • Pseudo Random Personalities - makes randomized Personalities that are random, but take the Components and trait into account while giving the value. This is for a better more competitive AI that still has some random elements.

  • Your selected options will save in this version so you don't need to change all the buttons every time.

  • You will be allowed to change what Civilizations, Traits, and Components are used in the randomizer. This also includes giving them a delete status which will remove them all together from the created mod.

  • Modders : sorry if you made support already, but I'll give the full rundown of how to make a Mod Compatible with this "Version 1". It should contain everything I need for any changes in the future like Adjective, Name of Civilization, and additions that add stuff. Also don't listen to the Randomized Support of the past. I've decided that method while seemed okay isn't actually the best for creating the system. Instead the new version will be tables in SQL or XML like:
    Spoiler :

    Code:
    INSERT INTO Ranomized_Component
    			( 	Type, 			
    				Class, --Only if not improvement
    				CivilizationType, --Only if Improvement
    				-- A list of all the possible Priorities I'm not going into yet. I'll give Diplomacy War as a example. 
    				
    				-- Will increase the Leader's War personality number given, but caps at 12. 
    				DiploWar, 
    				
    				-- Will Decrease the Leader's War personality number given, but will default to 0 if negative.
    				DiploNegWar, 
    				
    				-- Not recommended as it will set the War to exactly what you put. So if 2 Components have one it'll be set to the Component that was added last.
    				DiploWarOverride 
    			)
    VALUES 		( 	'COMPONENT_TYPE',
    				'COMPONENTCLASS_TYPE',
    				'CIVILIZATION_YOUR_IMPROVEMENT_CIVILIZATION',
    				0,
    				0,
    				7
    			);



  • Update notification : The next update will now tell you if a new version has come up, and if there is will tell you what has been added.

  • The Source will be the biggest point of why this is going to take a while. It's a complete mess so want to redo a lot of the code. Clear up some unneeded stuff, and actually comment this time. Which the only thing this will effect at the end user end is it'll run slightly faster, and maybe take up less space. Compared to what it would have if I didn't do this.

It's heck of a lot of work for this next version on my end, and should help some of the main complaints I could have about this myself with improving the AI, and start biases.
 
Will the next version allow us to generate the files required to randomize multiple civs at once?

(Sorry to bother you again, thank you very much for the work you've put into this truly unique mod)
 
Will the next version allow us to generate the files required to randomize multiple civs at once?

(Sorry to bother you again, thank you very much for the work you've put into this truly unique mod)

Do you mean like being able to select multiple mods, and generate all selected ones with the Auto-Modder?
Which yeah. It's actually something that won't take long at all. Actually already did it, but I'm going to have to wait for the next version to release. The current version isn't stable for use on my end.
 
Yay! Thank youuuu
 
I finally had the free time to try this mod out, but the link to DropBox isn't working.
 
Top Bottom