Help has moved to the Planio platform. All logins and passwords remained the same. All users will be able to login and use Redmine just as before. Read more...

Bug #920222


Exploit flaw/bug in Unit_Value_Shield_Pct recycle/disbanding

Added by Lexxie L over 2 years ago. Updated over 2 years ago.

Start date:
Due date:
% Done:


Estimated time:


The Unit_Value_Shield_Pct feature and merging recycle_unit with help_build_wonder was great for empowering ruleset designers!!!! Why? Because having the effect Unit_Value_Shield_Pct tied to certain requirements or legal actionenablers, gives ruleset control over when/how/where/what kind of shield value is legal and how much.
That's why those are great features!

However, it was discovered an unintended exploit that nullifies almost all possible benefits of this feature. :-{ Specifically, pcity->disbanded_shields will count toward any production type you change to later in
the turn. Therefore, any actionenabler restraints for BuildingGenus or even being allowed to recycle, are rendered
useless! There is a way for the player to always get maximum bonus and legally recycle, with an exploit. Here is the exploit: 1) change building product temporarily to a legal one or the one that gets the most bonus or least penalty, 2) then recycle the unit, 3) Then change it back to desired product target. Voila! Legal recycling for max bonus into whatever production type you want!

For this new feature to have any fair use and not just be a backdoor for exploiters/cheaters, we have to re-think
how pcity->disbanded_shields gets counted and credited.

Here is the TERRIBLE hack fix we have to use now, that makes whatever product type you disband into, a commitment for those shields to be dedicated to that product. Any change loses the disband shields completely, even if you switch back.. This is a terrible. So if it's better than before, and we're forced to use this, then you know it's broken before. I hope this code isn't released with the hack or with this code staying as how it is, because both would be terrible.

Let's please empower the great potential in these features!

Help build the current production in a city. {
const char *work;
const char *prod;
const char *action_name;
const char *info_emoji;
int shields;

/* Sanity check: The actor still exists. */
fc_assert_ret_val(pplayer, FALSE);
fc_assert_ret_val(punit, FALSE);
/* Sanity check: The target city still exists. */
fc_assert_ret_val(pcity_dest, FALSE);
shields = unit_shield_value(punit, unit_type_get(punit), paction);
bool full_contributor = (shields >= unit_type_get(punit)->build_cost) 
? true : false;
bool three_quarters = three_quarters =
&& shields >= (float)unit_type_get(punit)->build_cost*70/100)
? true : false;
if (action_has_result(paction, ACTION_HELP_WONDER)) {
/* Add the caravan shields */
pcity_dest->shield_stock += shields;
/* Will be punished for changing production to something that can't
 * receive "Help Wonder" help. /
pcity_dest->caravan_shields += shields;
} else {
fc_assert(action_has_result(paction, ACTION_RECYCLE_UNIT));
Add the shields from recycling the unit to the city's current * production. */
pcity_dest->shield_stock += shields;
// This had to change, otherwise there is no control at all over what 
// production types can get a Unit_Shield_Value_Pct penalty/bonus, since
// you can just change production to allowed/bonus type, disband, then
// change back again:
// ...
/* If we change production later at this turn. No penalty is added. */
//pcity_dest->disbanded_shields += shields;
// ...
// Shield type for disbanding is credited to whatever output was being made (see above),
// and is lost forever if production type is changed.
[ changes in function from here ...]
Actions #1

Updated by Alexandro Ignatiev over 2 years ago

Do we actually need to change much here from old good times? We can hardcode that "Help Wonder" sends shields into caravan_shields and "Recycle Unit" into disband_shields. Then we can make a handful of settings of what % of these counters is added to what production. I think for most rulesets it's enough of cotrol.

A good solution with fine control "we can take soldiers and retrain them all into workers but not anybody can be an engneer, at average one tank plus one soldier converts to a good bulldozer" would be Civ4-like production "each single production kind has its own prod stock" but it's a farther future, I think.

Actions #2

Updated by Sveinung Kvilhaugsvik over 2 years ago

I'm a bit to tired to trust that I read you correctly or in my ability to reply properly. Some initial thoughts:
This is a known class of problems. See for example gna patch #6357
I haven't had time to work on it because I have prioritized other things higher.
I think I had a solution but I don't recall what it was. I think it depended on stuff that was far ahead back then - like counters, generalized actions or setting production as an enabler controlled action with a city actor.
A good solution must be able to express the old rules so people that prefer the old way can keep it in their rulesets.

Actions #3

Updated by Sveinung Kvilhaugsvik over 2 years ago

Sveinung Kvilhaugsvik wrote:

I haven't had time to work on it because I have prioritized other things higher.

Knowing that a ruleset author wants to use this in a ruleset with many players obviously increases its priority.

Actions #4

Updated by Alexandro Ignatiev over 2 years ago

Sveinung Kvilhaugsvik wrote:

This is a known class of problems. See for example gna patch #6357

Now, I understand it better. Likely, we can get away in the case "some wonders can't be helped" with just a flag or two that block adding caravan or disband shields to a specific production while they are still kept until the next turn and can be used for another production if switched to. For the complicated case "spending each unit on each building has its own efficiency that is recounted if switched to another production" we should store caravan/disband_shields in arrays per spent unit type and calculate the sum with specific efficiencies applied. Alternatively, we can use the semi-Civ4 mode "all units you have spent this turn are assigned to a specific production type" and store the shields with effect applied immediately per all production types. I obviously mean that we should have a switch to apply this system(s) only in specific rulesets not affecting other ones.

Actions #5

Updated by Lexxie L over 2 years ago

OK I didn't understand the example into the abstraction of the solution. Tell me if that works for this use case:

Ruleset designer wants to give start units which can disband only into Building Genus = B. So that even at the game start, there are big choices to make, maybe little 50 shield wonders that define characteristics of your nation-race civilization. What ruleset does not want is: City builds legal building like Barracks, unit disbands into it, then city changes its production to something exploiting, like military units, settlers, or something like that.

This is a lot easier to fix except keeping 100% compatibility to old behaviour of you can change your mind on that same turn. That makes it very hard to do, and I don't understand for sure the suggested solutions yet.

Also available in: Atom PDF