Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
30a9996
Exclude nucleus from specialisation calculation
Accidental-Explorer Mar 13, 2026
f36185d
Switched to using hex counts instead of organelle number to normalize…
Accidental-Explorer Mar 13, 2026
54ff465
Removed the minimum size for specialisation
Accidental-Explorer Mar 13, 2026
42f7527
Simplified specialisation calculation to: most common organelle hexes…
Accidental-Explorer Mar 13, 2026
0a9278f
Switched to Simpson's diversity index for the specialisation calculat…
Accidental-Explorer Mar 13, 2026
7c9757a
Format
Accidental-Explorer Mar 14, 2026
bce0fdb
re-place a comment I did not mean to remove.
Accidental-Explorer Mar 14, 2026
6279409
re-introduce strength factor based on size.
Accidental-Explorer Mar 14, 2026
f5fbf68
missed commit.
Accidental-Explorer Mar 14, 2026
e2382e4
reset constant to match master
Accidental-Explorer Mar 14, 2026
c75093b
Switched to N - 1 for individual and total counts.
Accidental-Explorer Mar 15, 2026
f6f4a2c
Use a more accurate version of Simpson's Diversity Index.
Accidental-Explorer Mar 15, 2026
0a005a0
Corrected usage of the nucleus check.
Accidental-Explorer Mar 16, 2026
49dbad2
Moved assignments of the nucleusDefinition to field in classes.
Accidental-Explorer Mar 16, 2026
f5cd750
Format
Accidental-Explorer Mar 16, 2026
65318e7
Removed assignement of nucelus definition from class in two cases
Accidental-Explorer Mar 16, 2026
5a9949b
Merge remote-tracking branch 'origin/changed-specialisation-calculati…
Accidental-Explorer Mar 17, 2026
199bf6e
Removed assignment of nucleus definition from class in two cases
Accidental-Explorer Mar 16, 2026
4ede9c1
Merge remote-tracking branch 'origin/changed-specialisation-calculati…
Accidental-Explorer Mar 17, 2026
2c22f7f
Merge branch 'master' into changed-specialisation-calculation
Accidental-Explorer Mar 17, 2026
5af9db8
Merge branch 'changed-specialisation-calculation' into specialisation…
Accidental-Explorer Mar 17, 2026
10f8464
Merge branch 'master' into changed-specialisation-calculation
Accidental-Explorer Mar 18, 2026
434b9ec
post-merge adaptation.
Accidental-Explorer Mar 18, 2026
fc546ea
Merge branch 'changed-specialisation-calculation' into specialisation…
Accidental-Explorer Mar 18, 2026
9913baf
Fix merge
Accidental-Explorer Mar 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/auto-evo/simulation/SimulationCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public class SimulationCache
private readonly CompoundDefinition oxytoxy = SimulationParameters.GetCompound(Compound.Oxytoxy);
private readonly CompoundDefinition mucilage = SimulationParameters.GetCompound(Compound.Mucilage);

private readonly OrganelleDefinition nucleusDefinition =
SimulationParameters.Instance.GetOrganelleType("nucleus");

private readonly WorldGenerationSettings worldSettings;

#if USE_HASHED_SCORE_KEYS
Expand Down Expand Up @@ -141,7 +144,8 @@ public EnergyBalanceInfoSimple GetEnergyBalanceForSpecies(MicrobeSpecies species
var cached = new EnergyBalanceInfoSimple();

// Assume here that the species specialization factor may not be up to date, so recalculate here
var specialization = MicrobeInternalCalculations.CalculateSpecializationBonus(species.Organelles, workMemory1);
var specialization = MicrobeInternalCalculations.CalculateSpecializationBonus(species.Organelles, workMemory1,
nucleusDefinition);

// Auto-evo uses the average values of compound during the course of a simulated day
ProcessSystem.ComputeEnergyBalanceSimple(species.Organelles, biomeConditions,
Expand Down
53 changes: 30 additions & 23 deletions src/microbe_stage/MicrobeInternalCalculations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -490,9 +490,11 @@ public static void GiveNearNightInitialCompoundBuff(CompoundBag compoundReceiver
WorldGenerationSettings worldSettings)
{
var energyBalance = new EnergyBalanceInfoSimple();
var nucleusDefinition = SimulationParameters.Instance.GetOrganelleType("nucleus");

// Note this assumes this is only used just for single cell types or microbe species!
var specialization = CalculateSpecializationBonus(organelles, new Dictionary<OrganelleDefinition, int>());
var specialization = CalculateSpecializationBonus(organelles, new Dictionary<OrganelleDefinition, int>(),
nucleusDefinition);

var maximumMovementDirection = MaximumSpeedDirection(organelles);
ProcessSystem.ComputeEnergyBalanceSimple(organelles, biomeConditions, environmentalTolerances, specialization,
Expand Down Expand Up @@ -591,7 +593,10 @@ public static (bool CanSurvive, Dictionary<Compound, float> RequiredStorage) Cal
ref Dictionary<Compound, CompoundBalance>? dayCompoundBalances)
{
// Note this assumes this is only used just for single cell types or microbe species!
var specialization = CalculateSpecializationBonus(organelles, new Dictionary<OrganelleDefinition, int>());
var nucleusDefinition = SimulationParameters.Instance.GetOrganelleType("nucleus");

var specialization = CalculateSpecializationBonus(organelles, new Dictionary<OrganelleDefinition, int>(),
nucleusDefinition);

if (dayCompoundBalances == null)
{
Expand Down Expand Up @@ -830,9 +835,9 @@ public static void GetBindingAndSignalling(IReadOnlyList<OrganelleTemplate> orga
}

public static int CalculateMostCommonSpecializationOrganelle(IReadOnlyList<IReadOnlyOrganelleTemplate> organelles,
Dictionary<OrganelleDefinition, int> tempWorkMemory)
Dictionary<OrganelleDefinition, int> tempWorkMemory, OrganelleDefinition nucleusDefinition)
{
int totalOrganelles = 0;
int totalHexCount = 0;
tempWorkMemory.Clear();

var count = organelles.Count;
Expand All @@ -842,13 +847,21 @@ public static int CalculateMostCommonSpecializationOrganelle(IReadOnlyList<IRead

var definition = organelle.Definition;

// Don't count the nucleus, because of its omnipresence and large size
if (definition == nucleusDefinition)
{
continue;
}

var hexCount = definition.HexCount;

tempWorkMemory.TryGetValue(definition, out var existingCount);
tempWorkMemory[definition] = existingCount + 1;
tempWorkMemory[definition] = existingCount + hexCount;

++totalOrganelles;
totalHexCount += hexCount;
}

if (totalOrganelles < 1)
if (totalHexCount < 1)
return 0;

// Merge equivalent organelles to make moving to eukaryotic variants easier
Expand All @@ -872,42 +885,36 @@ public static int CalculateMostCommonSpecializationOrganelle(IReadOnlyList<IRead
}
}

return totalOrganelles;
return totalHexCount;
}

/// <summary>
/// Calculates a specialization bonus for a cell type based on its organelles.
/// </summary>
/// <returns>A multiplier starting from 1 and going up as specialization improves</returns>
public static float CalculateSpecializationBonus(IReadOnlyList<IReadOnlyOrganelleTemplate> organelles,
Dictionary<OrganelleDefinition, int> tempWorkMemory)
Dictionary<OrganelleDefinition, int> tempWorkMemory, OrganelleDefinition nucleusDefinition)
{
int totalOrganelles = CalculateMostCommonSpecializationOrganelle(organelles, tempWorkMemory);
if (totalOrganelles < 1)
return 1;

if (totalOrganelles < Constants.CELL_SPECIALIZATION_APPLIES_AFTER_SIZE)
int totalHexCount = CalculateMostCommonSpecializationOrganelle(organelles, tempWorkMemory, nucleusDefinition);
if (totalHexCount < 2)
return 1;

int maxOrganelleCount = 0;
float concentration = 0.0f;

foreach (var entry in tempWorkMemory)
{
if (entry.Value > maxOrganelleCount)
{
maxOrganelleCount = entry.Value;
}
var hexCount = entry.Value;
concentration += hexCount * (hexCount - 1);
}

// The raw bonus is just the ratio of the main organelle type
var bonus = (float)maxOrganelleCount / totalOrganelles;
concentration /= totalHexCount * (totalHexCount - 1);

// Calculate a strength factor that adjusts things
var strength = Math.Min((float)totalOrganelles / Constants.CELL_SPECIALIZATION_STRENGTH_FULL_AT, 1);
var strength = Math.Min(((float)totalHexCount - 1) / Constants.CELL_SPECIALIZATION_STRENGTH_FULL_AT, 1);
strength *= Constants.CELL_SPECIALIZATION_STRENGTH_MULTIPLIER;

// Then return the final result as the bonus being anything above 1
return 1 + bonus * strength;
return 1 + concentration * strength;
}

private static float MovementForce(float movementForce, float directionFactor)
Expand Down
5 changes: 4 additions & 1 deletion src/microbe_stage/MicrobeSpecies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,12 @@ public override void OnAttemptedInAutoEvo(bool refreshCache)

cachedFillTimes.Clear();

var nucleusDefinition =
SimulationParameters.Instance.GetOrganelleType("nucleus");

SpecializationBonus =
MicrobeInternalCalculations.CalculateSpecializationBonus(Organelles,
new Dictionary<OrganelleDefinition, int>());
new Dictionary<OrganelleDefinition, int>(), nucleusDefinition);
}

public override bool RepositionToOrigin()
Expand Down
6 changes: 4 additions & 2 deletions src/microbe_stage/editor/CellEditorComponent.GUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -478,13 +478,15 @@ private void OnUnlockedOrganellesChanged()
private void UpdateSpecializationDisplay()
{
var specializationBonus =
MicrobeInternalCalculations.CalculateSpecializationBonus(editedMicrobeOrganelles, tempMemory3);
MicrobeInternalCalculations.CalculateSpecializationBonus(editedMicrobeOrganelles, tempMemory3,
nucleusDefinition);

// Calculate the most common organelle to show what we should recommend the player place more
var temp = tempMemory3;
var organelles = editedMicrobeOrganelles;

int organelleCount = MicrobeInternalCalculations.CalculateMostCommonSpecializationOrganelle(organelles, temp);
int organelleCount = MicrobeInternalCalculations.CalculateMostCommonSpecializationOrganelle(organelles, temp,
nucleusDefinition);

// And then with all the info, update the tooltip and display
if (organelleCount < 1)
Expand Down
9 changes: 7 additions & 2 deletions src/microbe_stage/editor/CellEditorComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ public partial class CellEditorComponent :

private readonly List<EditorUserOverride> ignoredEditorWarnings = new();

private readonly OrganelleDefinition nucleusDefinition =
SimulationParameters.Instance.GetOrganelleType("nucleus");

#pragma warning disable CA2213

// Selection menu tab selector buttons
Expand Down Expand Up @@ -2142,7 +2145,8 @@ private void CalculateEnergyAndCompoundBalance(IReadOnlyList<OrganelleTemplate>

var maximumMovementDirection = MicrobeInternalCalculations.MaximumSpeedDirection(organelles);

var specialization = MicrobeInternalCalculations.CalculateSpecializationBonus(organelles, tempMemory3);
var specialization = MicrobeInternalCalculations.CalculateSpecializationBonus(organelles, tempMemory3,
nucleusDefinition);

var tolerances = CalculateLatestTolerances();
ProcessSystem.ComputeEnergyBalanceFull(organelles, conditionsData, tolerances, specialization,
Expand Down Expand Up @@ -2219,7 +2223,8 @@ private void HandleProcessList(EnergyBalanceInfoFull energyBalance, IBiomeCondit
float consumptionProductionRatio = energyBalance.TotalConsumption / energyBalance.TotalProduction;

var specialization =
MicrobeInternalCalculations.CalculateSpecializationBonus(editedMicrobeOrganelles, tempMemory3);
MicrobeInternalCalculations.CalculateSpecializationBonus(editedMicrobeOrganelles, tempMemory3,
nucleusDefinition);

var speedModifier = tolerances.ProcessSpeedModifier * specialization;

Expand Down
5 changes: 4 additions & 1 deletion src/microbe_stage/editor/MicrobeEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ public partial class MicrobeEditor : EditorBase<EditorAction, MicrobeStage>, IEd
// loaded
private readonly MicrobeSpeciesComparer speciesComparer = new();

private readonly OrganelleDefinition nucleusDefinition =
SimulationParameters.Instance.GetOrganelleType("nucleus");

#pragma warning disable CA2213
[Export]
private MicrobeEditorReportComponent reportTab = null!;
Expand Down Expand Up @@ -631,7 +634,7 @@ private IPlayerDataSource GetPlayerDataSource()

var specialization =
MicrobeInternalCalculations.CalculateSpecializationBonus(editedSpecies.ModifiableOrganelles.Organelles,
tempMemory1);
tempMemory1, nucleusDefinition);

ProcessSystem.ComputeEnergyBalanceSimple(editedSpecies.ModifiableOrganelles.Organelles,
CurrentPatch.Biome, in tolerances, specialization, editedSpecies.MembraneType, Vector3.Zero, false, true,
Expand Down
4 changes: 3 additions & 1 deletion src/multicellular_stage/CellType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,11 @@ public bool IsMuscularTissueType()

public void CalculateSpecialization()
{
var nucleusDefinition =
SimulationParameters.Instance.GetOrganelleType("nucleus");
SpecializationBonus =
MicrobeInternalCalculations.CalculateSpecializationBonus(ModifiableOrganelles,
new Dictionary<OrganelleDefinition, int>());
new Dictionary<OrganelleDefinition, int>(), nucleusDefinition);
}

public void SetupWorldEntities(IWorldSimulation worldSimulation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ private void HandleProcessList(EnergyBalanceInfoFull energyBalance, IBiomeCondit

var specialization =
MicrobeInternalCalculations.CalculateSpecializationBonus(cellType.Key.ModifiableOrganelles,
tempMemory3);
tempMemory3, nucleusDefinition);

for (int i = 0; i < newProcesses.Count; ++i)
{
Expand Down Expand Up @@ -249,7 +249,8 @@ private void UpdateSpecializationDisplay()
var type = GetEditedCellDataIfEdited(cells[i].Data!.ModifiableCellType);

var specialization =
MicrobeInternalCalculations.CalculateSpecializationBonus(type.ModifiableOrganelles, tempMemory3);
MicrobeInternalCalculations.CalculateSpecializationBonus(type.ModifiableOrganelles, tempMemory3,
nucleusDefinition);

// TODO: calculate adjacency specialization values
// https://github.com/Revolutionary-Games/Thrive/issues/6764
Expand Down
11 changes: 8 additions & 3 deletions src/multicellular_stage/editor/CellBodyPlanEditorComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public partial class CellBodyPlanEditorComponent :

private readonly Dictionary<CellType, int> cellTypesCount = new();

private readonly OrganelleDefinition nucleusDefinition =
SimulationParameters.Instance.GetOrganelleType("nucleus");

/// <summary>
/// Stores cells that end up being disconnected from the colony because of growth order
/// </summary>
Expand Down Expand Up @@ -1264,7 +1267,8 @@ private void UpdateCellTypeTooltipAndWarning(CellTypeTooltip tooltip, CellTypeSe
MicrobeInternalCalculations.MaximumSpeedDirection(cellType.ModifiableOrganelles);

var specialization =
MicrobeInternalCalculations.CalculateSpecializationBonus(cellType.ModifiableOrganelles, tempMemory3);
MicrobeInternalCalculations.CalculateSpecializationBonus(cellType.ModifiableOrganelles, tempMemory3,
nucleusDefinition);

ProcessSystem.ComputeEnergyBalanceFull(cellType.ModifiableOrganelles, Editor.CurrentPatch.Biome,
environmentalTolerances, specialization,
Expand Down Expand Up @@ -1454,7 +1458,8 @@ private void CalculateEnergyAndCompoundBalance(IReadOnlyList<HexWithData<CellTem
foreach (var hex in cells)
{
var specialization =
MicrobeInternalCalculations.CalculateSpecializationBonus(hex.Data!.ModifiableOrganelles, tempMemory3);
MicrobeInternalCalculations.CalculateSpecializationBonus(hex.Data!.ModifiableOrganelles, tempMemory3,
nucleusDefinition);

// TODO: adjacency bonuses from body plan (GetAdjacencySpecializationBonus)

Expand Down Expand Up @@ -1501,7 +1506,7 @@ private Dictionary<Compound, CompoundBalance> CalculateCompoundBalanceWithMethod
{
var organelles = GetEditedCellDataIfEdited(cell.Data!.ModifiableCellType).ModifiableOrganelles;
var specialization =
MicrobeInternalCalculations.CalculateSpecializationBonus(organelles, tempMemory3);
MicrobeInternalCalculations.CalculateSpecializationBonus(organelles, tempMemory3, nucleusDefinition);

// TODO: efficiency from cell layout positions (GetAdjacencySpecializationBonus)

Expand Down
4 changes: 3 additions & 1 deletion src/multicellular_stage/editor/MulticellularEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,8 @@ private IPlayerDataSource GetPlayerDataSource()
throw new Exception("Tried to get player unlocks data source without an edited species being set");
}

var nucleusDefinition = SimulationParameters.Instance.GetOrganelleType("nucleus");

var energyBalance = new EnergyBalanceInfoSimple();

var tolerances = MicrobeEnvironmentalToleranceCalculations.ResolveToleranceValues(
Expand All @@ -772,7 +774,7 @@ private IPlayerDataSource GetPlayerDataSource()
// TODO: specialization from positions (GetAdjacencySpecializationBonus)
var specialization =
MicrobeInternalCalculations.CalculateSpecializationBonus(cellType.ModifiableOrganelles.Organelles,
tempMemory1);
tempMemory1, nucleusDefinition);

ProcessSystem.ComputeEnergyBalanceSimple(cellType.ModifiableOrganelles.Organelles, CurrentPatch.Biome,
in tolerances, specialization, cellType.MembraneType, Vector3.Zero, false, true,
Expand Down