Skip to content

Commit

Permalink
Improve module calculation (#282)
Browse files Browse the repository at this point in the history
This PR adds speed-related module calculation into the module autofill.
The main motivation is that previously bio/alien modules did not work
with autofill because they only provide speed stats and have no effect
on productivity or energy.

This PR uses the cost of buildings as a way to model the benefit of
using speed-related modules.
From my testing, it works well with pY and vanilla.

In vanilla, a speed module is preferred only when the payback time is
less then an hour. After that, the Efficiency Modules are preferred,
which is similar to the behavior before this PR.

<img width="1510" alt="Screenshot 2024-09-12 at 7 28 25 PM"
src="https://github.com/user-attachments/assets/50c7ac53-9321-425f-9f45-9c94b22818e8">
<img width="1263" alt="Screenshot 2024-09-12 at 7 25 10 PM"
src="https://github.com/user-attachments/assets/e124f5ef-6ada-4367-8bff-b5d8a27d487f"
>
  • Loading branch information
shpaass committed Sep 17, 2024
2 parents cd421ef + 926bee3 commit b1fe1c1
Showing 1 changed file with 27 additions and 2 deletions.
29 changes: 27 additions & 2 deletions Yafc.Model/Model/ModuleFillerParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,31 @@ internal void AutoFillBeacons(RecipeOrTechnology recipe, EntityCrafter entity, r
private void AutoFillModules((float recipeTime, float fuelUsagePerSecondPerBuilding) partialParams, RecipeRow row, EntityCrafter entity, ref ModuleEffects effects, ref UsedModule used) {
RecipeOrTechnology recipe = row.recipe;
if (autoFillPayback > 0 && (fillMiners || !recipe.flags.HasFlags(RecipeFlags.UsesMiningProductivity))) {
/*
Auto Fill Calculation
The goal is to find the best module to fill the building with, based on the economy (cost per second) of the configuration.
A module can provide productivity, speed or efficiency (energy).
Productivity stats reduces the recipe cost
Speed stats reduces the building cost
Efficiency stats (effectivity) reduces the energy/fuel cost
The user can also set a payback time, which is the time it takes for the module to pay for itself.
The payback time is calculated as the module cost divided by the economy gain per second.
For the sake of simplicity, payback time is calculated assuming we fill the same module as many times as possible in all buildings.
Note:
- when the payback time is short, speed modules are mathematically preferred over efficiency modules.
- However if the payback time is infinite, the only long term benefit of speed modules is to reduce the area of the factory which can not be modeled here.
- But in real game play, late game power has very low marginal cost, reducing factory size is more useful than reducing power consumption. the current model cannot reflect this.
- This calculation also does not take into account the effect of beacons.
- This calculation also does not take into account the effect of modules on input cost.
*/


float productivityEconomy = recipe.Cost() / partialParams.recipeTime;
float effectivityEconomy = partialParams.fuelUsagePerSecondPerBuilding * row.fuel?.Cost() ?? 0;
float speedEconomy = Math.Max(0.0001f, entity.Cost()) / autoFillPayback;
float effectivityEconomy = partialParams.fuelUsagePerSecondPerBuilding * row.fuel?.Cost() ?? 0f;
if (effectivityEconomy < 0f) {
effectivityEconomy = 0f;
}
Expand All @@ -133,7 +156,9 @@ private void AutoFillModules((float recipeTime, float fuelUsagePerSecondPerBuild
Module? usedModule = null;
foreach (var module in recipe.modules) {
if (module.IsAccessibleWithCurrentMilestones() && entity.CanAcceptModule(module.moduleSpecification)) {
float economy = (MathF.Max(0f, module.moduleSpecification.productivity) * productivityEconomy) - (module.moduleSpecification.consumption * effectivityEconomy);
float economy = module.moduleSpecification.productivity * productivityEconomy
+ module.moduleSpecification.speed * speedEconomy
- module.moduleSpecification.consumption * effectivityEconomy;
if (economy > bestEconomy && module.Cost() / economy <= autoFillPayback) {
bestEconomy = economy;
usedModule = module;
Expand Down

0 comments on commit b1fe1c1

Please sign in to comment.