1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

A couple more "quick" inquiries

Discussion in 'Civ5 - Creation & Customization' started by AW Arcaeca, Dec 7, 2014.

  1. LeeS

    LeeS Imperator Supporter

    Joined:
    Jul 23, 2013
    Messages:
    7,075
    Location:
    Illinois, USA
    You can write your own "plot finder" function if you want to. And you can shift a unit using Unit:SetXY(args). You either scan the whole map every time you want to do this, or scan within a radius using William Howard's plot iterators, or you scan the map at game load and store the plot ID#s and thier XY locations of all map tiles that are also land tiles. You could also organize your data by map area ID#s which will allow you to only look at plots on the same continent, for example, or plots within the same water "area".

    Whichever method you decide to use for "getting" all the possible plots, you then look for the closest (for example) plot that does not already have a unit, whose owner conforms to your requirements, and which is on the same continent (ie, map area) as the Unit's starting point. Then you just shift the unit to the desired plot using Unit:SetXY(args).

    But if you want to have this process happen fast as possible you would need to make a new DLL. Assuming yuou aren't doing all this stuff multiple times a turn during the human's turn while they are moving their units around, it shouldn't really be too terrible in time even if you do a lot of this on the same turn and use lua to do it.
     
  2. AW Arcaeca

    AW Arcaeca Deus Vult

    Joined:
    Mar 10, 2013
    Messages:
    2,967
    Gender:
    Male
    Location:
    Operation Padlock ground zero
    So I did finally get a custom unit-jump function up and running. And now I have a new problem! (Always with new problems...)

    I can't figure how what on Earth I would even need to Google to find any answer on how to do this, so I'll have to plump for just describing the problem.

    TL;DR: What would I have to do to a table whose values are numbers, such that the numbers all add up to a new total that I pick and all the resulting table values are integers, with the resulting ratio between numbers being as close to the original as possible?

    Let's say we have some table t whose values are all integers. It doesn't really matter what the keys are; for the sake of simplicity let's say t is an array. One possible configuration of t that fits the bill might be:
    Code:
    t = {}
    t[1] = 3
    t[2] = 2
    t[3] = 2
    t[4] = 6
    t[5] = 1
    t[6] = 1
    t[7] = 0
    Now if we added up the total of the values of this array, we would find that it is 15.

    My question is: how would I go about redistributing the table values so that they add up to a new, specified total, while still remaining integers and retaining the original ratios as closely as possible (liable to large rounding errors, I'm aware) ?

    So I say I wanted the total of t to be 27 instead of 15. Simple math says that you could simply find the ratio between the new and old (27 / 15, or 1.8) and multiply it individually by each of the table values as a scalar multiplier. That would make the new value of t:

    Code:
    t = {}
    t[1] = 3
    t[2] = 2
    t[3] = 2
    t[4] = 6
    t[5] = 1
    t[6] = 1
    t[7] = 0
    
    for k,v in pairs(t) do
        t[k] = t[k] * (27/15)
    end
    
    for k,v in pairs(t) do
        print(k,v)
    end
    
    > 1    5.4
    > 2    3.6
    > 3    3.6
    > 4    10.8
    > 5    1.8
    > 6    1.8
    > 7    0.0
    But of course, 10.8 is definitely not an integer, by any stretch of the imagination. We have preserved the ratio at the loss of the integer-ness (I'm fairly certain I just made up that word) of the values. The resulting table I'm looking for, which preserves the integer-ness at the loss of the ratio, would look something like:
    Code:
    t = {}
    t[1] = 3
    t[2] = 2
    t[3] = 2
    t[4] = 6
    t[5] = 1
    t[6] = 1
    t[7] = 0
    
    do_table_voodoo(t, 27)
    
    for k,v in pairs(t) do
        print(k,v)
    end
    
    > 1    6
    > 2    3
    > 3    3
    > 4    11
    > 5    2
    > 6    2
    > 7    0
    How would I even begin to write the algorithm for do_table_voodoo()?

    Incidentally, the hierarchy importance of various aspects of the resulting table would be: integer-ness as the most important, then correct new total, and finally preserved ratios at the least important.
     
  3. LeeS

    LeeS Imperator Supporter

    Joined:
    Jul 23, 2013
    Messages:
    7,075
    Location:
    Illinois, USA
    Code:
    function RoundDecimal(iNumber, iSigDecimals)
    	local mult = 10^(iSigDecimals or 0)
    	local iOriginalInteger, iFraction = math.modf(iNumber)
    	return iOriginalInteger + (math.floor(iFraction * mult + 0.5) / mult)
    end
    In your case "iSigDecimals" will be zero, so like:
    Code:
    function RoundDecimal(iNumber, iSigDecimals)
    	local mult = 10^(iSigDecimals or 0)
    	local iOriginalInteger, iFraction = math.modf(iNumber)
    	return iOriginalInteger + (math.floor(iFraction * mult + 0.5) / mult)
    end
    function ReAssertTableValues(tTable, iNewInteger, iSigDecimals)
    	local iOriginalTableValue, iAdjustmentRatio = 0, 1
    	local tTempTable = {}
    	for k,v in pairs(tTable) do
    		iOriginalTableValue = iOriginalTableValue + v
    	end
    	if iOriginalTableValue == 0 then return tTable end
    	iAdjustmentRatio = iNewInteger / iOriginalTableValue
    	for k,v in pairs(tTable) do
    		if iSigDecimals == 0 then
    			tTempTable[k] = math.floor(RoundDecimal(v * iAdjustmentRatio, iSigDecimals))
    		else
    			tTempTable[k] = RoundDecimal(v * iAdjustmentRatio, iSigDecimals)
    		end
    	end
    	return tTempTable
    end
    t = {}
    t[1] = 3
    t[2] = 2
    t[3] = 2
    t[4] = 6
    t[5] = 1
    t[6] = 1
    t[7] = 0
    
    t = ReAssertTableValues(t, 27, 0)
    
    for k,v in pairs(t) do
        print(k,v)
    end
    Copy/paste and run here: https://www.lua.org/cgi-bin/demo

    If you add up the values recieved back when using "15" as the orignal value (as you have) and "27" as the new value, you'll actually get "28" as the total of the values because of rounding.
     
    Last edited: Mar 28, 2017
    Troller0001 likes this.
  4. LeeS

    LeeS Imperator Supporter

    Joined:
    Jul 23, 2013
    Messages:
    7,075
    Location:
    Illinois, USA
  5. AW Arcaeca

    AW Arcaeca Deus Vult

    Joined:
    Mar 10, 2013
    Messages:
    2,967
    Gender:
    Male
    Location:
    Operation Padlock ground zero
    Well, this looks both very useful and completely incomprehensible to me in terms of the actual math that's behind it. that probably came out sounding ruder than I intended But as it works, I have no reason to knock it. Thanks again, LeeS! I'll presently incorporate into my utility files, with full credit granted.
    (It strikes me that this kind of problem-solving-ish math would be a more useful thing to learn in school than, like, the ratio test)
     
  6. LeeS

    LeeS Imperator Supporter

    Joined:
    Jul 23, 2013
    Messages:
    7,075
    Location:
    Illinois, USA
    I did just make a small change in ReAssertTableValues() to avoid an issue where you'd get division by 0 errors if all the "V's" in the original table were set to "0".

    I've always struggled with powers (^) so I can understand how it seems like voodo. I wrote the RoundDecimal() function about a year ago based on hints I found around on the internet and then I had to study the math of what was going on for a while.

    Also be aware the math of the code tends to round 10.725 to 10.72 instead of 10.73 when rounding to 2 decimal places. 10.755 gets rounded to 10.75 instead of 10.76, etc. It has to do with when and how the "math.floor" is applied.
     
    Last edited: Mar 28, 2017
  7. AW Arcaeca

    AW Arcaeca Deus Vult

    Joined:
    Mar 10, 2013
    Messages:
    2,967
    Gender:
    Male
    Location:
    Operation Padlock ground zero
    So

    Would it be possible to make so that you can see what an enemy city is producing - e.g. by adding the icon of their current project to the city banner, or by allowing you to view the city screen of that city despite you not owning it - short of a massive UI overhaul?

    Essentially, what I'm going for here is the surveillance benefits of having a diplomat in a city without actually having to have a diplomat in the city. That would include causing the area around the city to be visible, which I'm pretty sure could be done with Plot.ChangeVisibilityCount and Plot.SetRevealed - because even though I don't know what either of them do (I assume the former controls FoW and the latter controls blackmap) they're used in the code for JFD's de Gaulle's France's Café (three possessives in a row?). I don't actually remember if a diplomat renders the current production visible, but if even if it doesn't, that's what I'm trying for - although I have no idea where to start. Any insights?
     

Share This Page