Discussion in 'Civ4 - Caveman 2 Cosmos' started by Pit2015, Jul 6, 2020.
Banditry dont gives +5 free units as it dispalys, should be fixed.
You realize it's talking about support for 5 units, not an actual 5 bonus units all of a sudden on the map for you, right? Free units can also be countered by other negative sources and there is no negative free units so if you're looking at the total, make sure you don't have a trait or something that's counteracting the free units you think you should be getting from a particular source.
Well tells me + 5 free units, should meen i dont have to pay for 5 more units, look into my save whats causing this, i should be able to build 5 more units without paying maintenance for them.
I payed for no unit if i build one more unit i have to pay 2 gold, deity handicap 1 and unit 1? So i switched to banditry it tolds me +5 free units so i should be able to build 5 more units without paying maintenance for them, then after 5 more units i have to pay maintenance for them, but that dont works now.
Advisor says he got 60 free units. he's got about 30 units in game. He's got -1 gold per turn from upkeep for 1 unit.
We'll have to look into the code to see how it comes up with that. If I'm not mistaken, some units or sources of costs are exempt from being covered by 'free unit' status.
If we can find errors during an audit and correct them I'm sure players would feel much happier about that. You'll see in the code why I'm not going to touch this with a 10' pole. It's as not simple as it gets and really could use a huge project to improve/overhaul the whole approach.
I plan to rewrite it so that each unit store its own cost, and the player store the sum total.
Whenever the cost stored in the unit change it will update the player stored sum total.
Free units will be changed to a gold amount of unit upkeep that is free instead of an amount of free units, that way we don't get the code issue with having to choose whether the most or least expensive units are free first, which would be more computational heavy (having to sort the cost of all units and perhaps cache the sorting as an array of arrays ((cost, unitID), (cost, unitID), etc) for each player and reorder/rebuild the sorting each time a unit is killed/created/promoted).
I haven't planned it in details yet, just something I want to do some day soon.
That's pretty close to the way it is now.
* Each unit tallies its own.
* Units, along with their total upkeep, are tracked in a vector with unit ID paired to the cost (something granular out to 2 decimals would be optimal)
* Each round the player level runs a function that arranges the vector from most expensive unit to least expensive
* Then it loops through all the units from the most expensive to the least expensive tallying up the total cost for the round, discounting each unit (making them free) from the top (most expensive) to the bottom as long as it has a free unit count to assign.
* Saves what it needs to report to the financial advisor and final tallies to the total gold calculations for the round.
I would like to avoid each player having a 100-1000 long array that needs to be rebuilt each turn per player and then sorted, that is probably a couple thousand codelines processed per player per turn + a lot of extra caching. It also favours the highest scored player as it will have either higher tech units or more merged units which both have higher upkeep than the opposite. Lower scored players may have about the same amount of free units but translated to gold the score leader will save a huge amount more gold from its free units than those below in score will (typically).
Easier with just,
* Each unit tallies its own upkeep, and updates the player level integer sum when it change.
* Each round practically nothing is done, it just subtract the free upkeep sum from the upkeep sum.
* Financial advisor just asks the dll what the free upkeep sum is and what the upkeep sum is and displays those two numbers.
I just don't see how the vector solution is worth the cost.
Don't think it works that way. It just removes maint. off of 5 units you already have. You build 5 more New units and you will pay maint. on them. Been that way for a long long time now.
The Coders can correct me if I'm wrong. But it's what I've seen forever since Banditry was made a Civic choice.
You may be right but I wouldn't think the math would be more intricate than a battle resolution so the delay would not be noticeable really.
The free upkeep sum is not a representative of free gold upkeep but of free units. Perhaps the system could simply average how much a 'unit' is costing for the player and discount that * the free units from the overall cost. That might be faster. Would save a re-organization step and the units could be tracked when added or removed as they are now.
The math would just be "is this number bigger than that" during the sort, and then addition when tallying up the sum while looping through the sorted vector afterwards. Anyhow, most math and logic is quite fast to compute; accessing (read/write) memory is often worse, and when building and sorting a list one has to access memory a lot.
Let's say the player have 100 units, then there's a 100 loops to build the vector, then there's an average of 200 loops to sort that vector (worst case could be a lot more for some sorting algorithms, e.g. 10 000 loops for "quick sort" algorithm); finally there's another 100 loops to tally up the final sum.
If the average amount of codelines within these loops is 10, then this whole process is 4000 operations/codelines. It isn't much, relatively speaking, but it might be more than what's in our combat calculation algorithm.
So, if using the example above, instead of 4000 codelines several times per player per turn; I'm suggesting just a couple codelines several times per player per turn.
Unit upkeep changes during your turn, loosing or gaining a unit or picking a promotion that increase/decrease upkeep, should immediately be reflected in the gold income number in the top left corner UI during your turn.
Also animals did cost maintenance some time before, you can check when that was removed/changed if a bug moved in.
EDIT: (Removing a animal unit will reduce the free units number somehow, but maintenance cost still same, you can check that by removing some animals, 60 will decrease then.)
If this dont takes to long to update let me know here, calculating this correctly will be good, then i will wait with continuing my game, if it takes longer i will continue my game now.
Being as the free units is a count of how many units are considered free rather than a static integer of free gold towards units, I would at least suggest that we get an average of the cost of a unit that a player has to define how much static gold this means. Free units needs to be able to scale to the cost of current units as those will be increasing as tech develops.
My point is if you change it to a flat static amount of gold per 'free unit' then it's not going to adapt to the growing costs of individual units.
You're probably right about how what I suggested is less ideal and besides, why should the MOST expensive or LEAST expensive be considered the units that need to be discounted anyhow. A running average tally would be easy enough to maintain during the processing stages of adding units and adjusting their costs. Being able to directly change a particular unit's cost would be nice as well for numerous reasons. So largely I'm with you here - I just suggest this averaging rather than any kind of static assumption. Shouldn't cost any more processing time and it's only tracking one additional variable in the long term memory. (maybe a few actually so the calculation can be done without running a huge loop...)
I'm going to take some time to think on these thoughts to absorb them fully before commenting further except to say that if it's all just gold then it might as well just be gold. The idea of a 'free unit' is relative to the cost of the unit and in Vanilla that cost was static enough that it could be as simple as it was all setup. With a more dynamic unit cost, we should probably allow the amount of gold that a unit represents to be based on how much modern units are actually costing.
To help understand my take here... in the unit review, I'm adding additional costs for units as they upgrade forms across nearly all unit types.
Perhaps the whole free units thing should be more on a percentage basis regardless - a percent reduction in unit upkeep total in general. Would certainly simplify it but could let it get out of control easier and would have a harder time scaling well unless we did a diminishing return on the overall percentage perhaps. Reason I say this is because +10 free units at the beginning of the game means a hell of a lot more than +10 free units in the next era, whereas +5% free unit coverage would mean nothing at the beginning of the game, maybe covering a unit or two, whereas in the later game it could be a huge modifier.
Base numbers of free units being calculated from total nation population is farther than I've looked into the system myself though I've always suspected that this was a factor.
With the free units, it sounds like you are trying to solve two separate problems here, and conflating the two.
First, you are trying to get the unit costs to update more frequently, multiple times per turn... I think this is unnecessary, and any overhead to create this is wasteful, but I am fine if others disagree with me. Properties don't update more than once/turn, lots of things only update once/turn, the Financial Advisor updates pretty fast, and if you care that much you can get the updates from there if necessary. I recently complained elsewhere that build options (national units) didn't update more than once per turn, and this is just a display mechanic, not a gameplay mechanic. But, if you can create a button or some other trigger to refresh everything like this on command, I say great. Right now, quick save and quick load does what you want here, though.
Second, you are trying to understand the unit upkeep code, by recreating it. That has been done by C2C coders in the past, and has led to part of the issue, I think. I see artifacts in the code from multiple attempts to modify the unit upkeep in multiple ways. The amount was completely dependent upon population size in vanilla, with multiple multiplicative modifiers, and someone changed the civics to additive, making the civics to be not population based. The difficulty modifier was the biggest difference in vanilla, but has been both changed drastically and also changed incompletely and also mostly removed in the code. I assume that someone tried to do a quick balancing at some point when they (basically) increased by 2 the handicap malus to what it is now, but didn't take into account the other changes, for example.
Reading what the three of you want, that have commented thus far in this thread on this topic, it appears it would be much simpler and more effective to just go back to the principle and the actual code was in vanilla, and handle the additional unit costs completely separately from "free support", "handicap costs" and "supply". Code would be faster, equations would be much more opaque to the player, and modifications to units and the underlying code would be much easier. Also more realistic, in that civics and population sizes that impact the 'free support' or 'supply' shouldn't reduce a unit whose cost is 10/turn down to 0/turn, and then also only reduce the next unit from 1/turn only down to 0/turn. I might be so bold as to say that subdued animals, likely the initial reason for the upkeep code changes, would be better off like this... let them have support, but also have them modify gold in the opposite way that advanced expensive units (or law enforcement, or whatever other units that have -x gold/turn currently), but make them pay supply too. Animals away from culture would net 0, or negative if there are enough of them, a few animals in the capital would net a small gain, but many subdued animals in the capital would be a net loss... just by reinstating the vanilla mechanic, and letting the subdued animals give +0.8 (or so) gold/turn. The threshold of these break even points would vary based upon difficulty level, naturally, if using the original vanilla mechanic.
You can read up on the civ4 and bts unit upkeep mechanic here: https://forums.civfanatics.com/threads/unit-maintenance-explained.141475/
Doesn't vanilla tell you the correct income amount for ending the turn? The income value should imo update anytime it changes mid-turn, that includes changes caused by unit upkeep changes that happens mid-turn. I won't make it update more than it currently does in C2C.
The unit upkeep code in C2C is a lightly tweaked version of the vanilla upkeep code, only a couple added modifiers in the equation so to speak, but still the same clunky system.
If promotions and unitcombat variation of a specific unit type should be capable of varying the upkeep cost of it from a low of e.g. 0.87 gold, to a high of 60 000 gold, then the vanilla system is not adequate nor efficient code vice.
e.g. From Solo unitcombat and a 50% reduced upkeep promo, to a Countless unitcombat on a unit that has a base upkeep of 24 gold in its default group size of Company.
Not so sure about lightly but yeah the problem is that we've TRIED to keep it from metastasizing too much while going ahead and metastasizing the hell out of it without rethinking it from the ground up. IMO.
Re: Unit Upkeep Modifications
About income updating immediately… yes, in vanilla, it does. I also agree that it would be great if C2C did the same. But since updating other things mid turn that affect game play (build queue options like national units) is both difficult and low priority, I assumed that updates only affecting displayed values but not impacting gameplay would still be difficult and even lower priority. I have no problem with accurate information being displayed to the player, and encourage anyone that wants to tackle more frequent updates that don’t impact the application’s speed/memory/responsiveness to please go forward with that. But, I will reiterate that, when it comes to unit upkeep costs not changing, it is just a display problem. I tested this months ago, that losing a unit (to mission/battle/delete) does not impact the displayed gold per turn in the upper left of the main screen, but the actual gold per turn lost or gained between turns does accurately reflect the unit changes.
Now, in relation to the unit upkeep code directly… @Toffer90 , no matter what any one other team member’s skills might be, you are obviously the person with the best understanding of the current state and contents of the entire C2C code base, period. So, I am likely to embarrass myself with this line of questioning. But, [redacted] My goal here is to help, and I think I have information, background, skill, and experience that allows me to try.
If I am reading the code correctly, the unit upkeep code is currently located only in CvPlayer.cpp, starting at line 9103.
[here I started on the 9th going through it line by line, tracing definitions through CvGameCoreDLL.cpp, and so forth, and describing exactly what I saw and how it was different than vanilla, and how the C2C xml has some Null values for some difficulties and other values I didn’t like, but it was really long… and then I saw today on discord that you are making changes, and I wasn’t done, so I deleted the paragraphs and decided going through differences didn’t matter. Sorry I didn’t finish and post this 5 days ago.]
To back up a little, the current state of the function doesn’t really matter, except in relation to how difficult it has to be to address our needs. Let’s examine the problems that need to be fixed, or at least the ways in which unit upkeep needs to be handled differently than vanilla civ4. Thus far, I see three separate ones mentioned in this conversation. They are subdued animals, promotions, and unit group size (when the Size Matters game option is activated). Are there any other ways that C2C needs to handle unit upkeep differently than BtS? Let’s examine those three requirements while we wait for a complete list containing anything else that needs to be handled.
I already offered one way that subdued animals could be handled. Another option would be to subtract them from the total amount of units before any math is done, so they aren’t even displayed as “free” units, let alone taken into account in the equation. A third would be something similar to what we have now, adding them to the number of free units after the free unit calculations have been done but before handicap costs are tallied. And so forth. (Another, possibly easier and more accurate method becomes obvious further down in the post.) Whatever we choose, it will have an impact on how supply for the subdued animals will need to be handled. Either way, I think there are a lot of options here, and I don’t see any that are invasive to a final overall solution.
Let’s skip past promotions for a moment, and come back to them. Unit group size is a significant player in this conversation. There are multiple creative ways I can think of for tallying those costs, but I think there is an important restriction in any efforts. Namely, that SM is still an option, not an integral and necessary part of C2C (I gather there is no unanimous outcry to change that, right @JosEPh_II ?) If that is the case, any final solution must be able to handle the option being both on and off. In general, the two different ways of approaching a problem like this would be to either a) have two separate modules that take the same inputs and supply the same outputs in the same format, but are both very different under the hood and and need to be maintained completely separately, or b) have one method that handles both cases through one or a few parameters. Because my personal design preferences lean toward b) whenever possible, I will offer an idea for that approach, but I am also open to a) as a valid design decision. What if, instead of the unit upkeep cost going up or down by group size, we accomplish the exact same outcome through a different way. Say we have 3 companies of clubmen, and they merge to form 1 battalion of clubmen. Under current thought, that would go from 3 units with 1 (1 is arbitrary here, it is just a multiplier and 1 is easiest to demonstrate) gold upkeep/turn, to 1 unit with 1.2 gold upkeep/turn (I assume the 20% number is still accurate, found in post #1 of https://forums.civfanatics.com/thre...-size-matters-game-option-version-2-0.523860/, but again any multiplier works in my example), or a modification of 3/turn to 1.2/turn, if the player were past their ‘free’ unit limit. This is difficult to handle, because each unit’s gold per turn must be handled and stored and ranked exactly as explained above, but also because each unit’s gold per turn will need to be handled completely differently if the SM option is switched off. Tangentially, balancing unit types and technological levels through upkeep costs would be somewhere between difficult and impossible, when switching between SM on and off. My suggestion is that each unit would not have a gpt value at all, let alone one to be handled and ranked. Instead we would just count units. Let me illustrate: when we have our 3 companies of clubmen, that is 3 units total for upkeep purposes (again, our 1 is arbitrary, I think companies are closer to 0.83, but this is just an illustration). When they merge, our 1 battalion is 1.2 units total for upkeep purposes. Just as before, as long as the player is past their ‘free’ unit limit, we go from 3 to 1.2, and so merge has the same effect on unit upkeep. Now, how much a single ‘unit’ costs in upkeep, whether that is 1 gold or more or less, is just a multiplier. How ever many free units there are or which ones are free doesn’t matter, the free unit count is created before the turn starts and is only modified when there is a population or civic change during the player turn, when a lot of other things are happening too. A nice accidental positive here is that graphical updates are easy, since when a unit is removed from the game (merge/split/mission/battle/delete/etc.), the existing code that handles that can just add or subtract from the variable containing the number of units, and call the module that does the subtraction from the free units to refresh the display. The easiest way to have the code handle this, is assume that every unit has a ‘unit upkeep number’ of 1, whether SM is on or off, and let the already coded upkeep variances for different size groups stay in place. Another option, that also wouldn’t conflict with SM being on or off, would be to have someone do a massive full unit audit (cough @Thunderbrd ), and allow them to use ‘unit upkeep number’ (or a more aptly name property, call it what you will in the xml) as a tool to more finely tweak and balance units in relation to each other. (A coarse example might be culture units having 0.9 if all other units are 1, in order to make cultures just slightly more valuable, in a way that just isn’t possible in the current upkeep schema, or another might be to make nukes 1.1 or 1.5, which would slightly discourage having huge numbers of nukes just sitting around in a more nuanced way than properties or happiness can currently do.) This would also be a handy multiplier or comparison tool for the upcoming equipment mod. And it would be relatively easy to add this information to the mouseover in the build queue, in the format of “[100 - 100*value/default]% upkeep difference from a normal unit” (in our example, default is 1). I am sure there are other ways to handle the SM on/off option for unit upkeep, but this one seems easier to implement and easier for the player to understand than other ones I thought of, as well as easier to expand upon and tweak for modders.
Now, back to promotions (and equipment, in future versions). If we were to use the above to handle the SM option, we could very easily make promotions do the same thing… as long as the promotions we are dealing with are all percent modifiers. I have to admit my weakness here, that I don’t know the future plans for promotions that are supposed to impact costs, and I haven’t studied the late game well enough to remember all the current promotions, but I can’t think of any promotions currently in use that modify upkeep. If my understanding and recollection is correct, then we have an opportunity to devise that from the ground up. But even if not, I think we are ok. Let me give a few examples of one way promotions might work in this paradigm. Say we want to balance the Might promotions (not saying we need to, just an example). Each level of Might could multiply the modified ‘unit upkeep number’ by +25%. So, with a unit that naturally has a ‘unit upkeep number’ of 1, the promotion would make it worth 1.25 units for upkeep purposes. Or say we had a national unit (0.9 in an example above, again just an example), merged two levels, with Might, it would be worth 0.9*(1.2*1.2)*(1+0.25)=1.62 units. If the same unit also had a 50% reduced upkeep promo, it would then be worth 0.9*(1.2*1.2)*(1+0.25-0.5)=0.972 units. This sort of math will make sense to anyone who has taken apart the code for SM, and tried to understand how quality and group size interact. For those that haven’t, or don’t want anything to do with SM, our example wouldn’t have a merged unit, and the national unit with Might and reduced upkeep would be worth 0.9*(1+0.25-0.5)=0.675 units, which is going to look a whole lot like regular combat calculations, the kind you see in the combat odds mouseover. Separately, if there were promotions that didn’t give a percentage but instead a specific amount of gold per turn (hard to think of a good example, but maybe state sponsored media, so entertainer units would add 0.5 gpt to the treasury, or maybe a general unit that costs a flat salary for his retinue of 2 gpt from the treasury), the ‘free support’ mechanic really shouldn’t impact that, but instead be like buildings or trade income. Pretty easy for the player to understand. In the future, say around v43 or so, or whenever equipment starts making an appearance, we could do some fancy things like saying units with Bottleneck are more efficient in smaller groups and less efficient in larger groups, so Bottleneck would reduce upkeep by 1% or 5% of the unit, for every level lower than ‘normal’ the unit has split, but increase it by the same amount for every level higher than ‘normal’ the unit has merged. That requires a little algebra, but it isn’t a difficult line of code, per se. With SM off, these calculations (and these promotions) would simply and naturally have no impact on gameplay, and would not require any changes or separate maintenance, but any promotions that impact upkeep but have nothing to do with SM would still work the same way. Sure, there will always be difficult work to make units balanced under SM and also not, but upkeep wouldn’t play a role in that discussion (whereas I think it does now).
So, what would this look like at an empire wide scale? Say we have 100 units at various group sizes and promotion levels, all adding up to a modified and multiplied ‘unit upkeep number’ (I hate that name, I wish I were better at naming) of 127.63. We know that civ4 rounds all decimals down, and where they use the floor function has produced screaming fits in thousands of people, but you can decide for yourself where (or if) to use the floor function, whether at the unit level, the ‘unit upkeep number’ level, after it has been combined with unit handicap and supply, or after that number has been combined with the rest of the income and expenses. If my civ had 8 cities, each with 6 population, and I were at Settler difficulty (the iFreeUnits value in the SVN currently is 36), and my civic gave me an extra 5 free units (this will be based upon population instead of a hard coded number, but I understand that will take some time to balance) I would get 0.24*48 + 36 + 5 + 4 = 51.52 free units (the 4 is hard coded into the support mechanism, don’t know why), and would pay upkeep costs for 127.63 - 51.52 = 76.11 units (or however you round). If population or civic changed mid turn, the 51.52 would go up or down, and the trigger is easy. If units are created (subdued/captured) or removed (mission/killed/deleted) the 127.63 would go up or down, and the trigger is easy. Whenever these values are updated, a GUI refresh could be sent.
Also, I suggest this conversation be split off into its own thread, somewhere between post 2204 and 2208.
And to be clear, no part of this is meant to address supply, distance modifiers, or military unit cost (which is purely a civic setting). I think that supply could become more obvious for the player by better mouseover game text, but that can wait a few versions, and anything else along those lines can be more easily tweaked once this is clear and balanced and working well. But those lines of code are probably easier than the ones we are working with, in proximity, and use many of the same variables, so some people may want to voice opinions on those things here, now.
Anyway, this makes sense to me. In code, as a player, and in context of the future conversations I have been hearing about. I know I have only been lurking and listening for less than a year, and I hope that me having an opinion on the direction of a part of the mod isn’t offensive, but this seems to meet the goals of transparency, ability to be built upon, and easier to understand and maintain by multiple coders.
Exactly what I think Toffer and I agree would not be ideal.
As you can see from the plan here, the extra gold cost by unit has been considered a very useful way to leverage the variety of powers a unit may have for or against a unit's use in your ranks.
Toffer informed me today that his plan is to replace this tag with a tag that is generally the iExtraGold +1 except in situations like animals that have a base of 0. I think I can get behind where he's going because that makes it easier to then modify that base according to SM adjustments, which have been extruded into a generic adjustment process by rankshifts away from the average or starting amount (which is handled somewhat variably depending on Uncut or not.)
I don't think it's going to make it impossible to work with or without the option either but I'm curious to see how he's intending to work some aspects of his approach there.
Right. Ok, so you put this forward as another option... sorry, just commenting on what I read as I go because woo that's a long post.
Yeah. It's funny how much planning is in place to give us enough working variation levers and buttons and dials to use on units is being setup primarily to make such a mod not only possible, but meaningful beyond just STR upgrades. Upkeep modifiers on equipment are indeed something one might want to have to vary different kinds of equipment to encompass the depth of what such a mod should introduce.
I'm almost certain he'll be looking to make SM rank shifts adjust the end total support cost of the unit in the same way it adjusts strengths, so that it's an exponential growth per rank increase rather than just an additional % modifier - this makes the other modifiers mean more and it makes it more possible to balance the value of a shift in size rank against those other modifiers. Again, such rank adjustments to final values taking place through some generalized functions is something Toffer, Bill, and I sorted out recently - even though I had somewhat begun that process of having general functions to do these things - we improved them to the point that this sort of adjustment already has the mathematical procedure worked out if we just plug in the end total modified base to get a final total after rank shifts are considered. Toffer may remember the function names - I'd have to go look for them at this point and I'm not opening the coding to respond here.
What I think we'll need, however, is to track how many units worth of 'free units' a given unit, based on its rank differences, represents... A unit merged one layer should probably count as 1.5 units of free units, which is somewhat similar to what happens now in terms of the accounting.
It's always better to talk things out and the more minds on a problem the better.
As for splitting this conversation, I'm not sure any of us have that kind of admin power so its something we'd have to call a forum admin in to help with...
Separate names with a comma.