Skip to content

Conversation

@phillip-simons
Copy link

@phillip-simons phillip-simons commented Nov 18, 2025

Problem

The sumGeometricSeries and maxGeometricSeries functions in js/util.js are not inverses of each other, causing incorrect upgrade cost calculations.

Root cause: sumGeometricSeries uses rate ** (n + 1) instead of rate ** n, calculating one extra term than intended.

  // Current (buggy)
  return base * (1 - rate ** (n + 1)) / (1 - rate);

  // Fixed
  return base * (1 - rate ** n) / (1 - rate);

Example

For a card with levelCost: [10, 2] (base=10, rate=2):

Levels Expected Cost Current Cost maxGeometricSeries
1 10 10
2 30 70 Says 2 affordable with 30
3 70 150 Says 3 affordable with 70

Impact on Autobuy

This mismatch causes autobuy to fail silently, especially noticeable with low balance currencies:

  1. getCardLevelMax calculates player can afford N levels
  2. levelUpCard calculates cost for N levels using buggy formula (too high)
  3. Affordability check fails → no purchase happens
  4. Currencies appear "deleted" because expected upgrades never occur

Affected Areas

  • Card level upgrades (manual & autobuy)
  • Cost display in tooltips, popups, and collection UI

All costs will be lower after this fix, as players were previously being overcharged.

Addresses #41

@phillip-simons phillip-simons marked this pull request as ready for review November 18, 2025 20:18
@mzxrules
Copy link

Not sure if this PR really helps with #41.

The core issue there as I understand it is that currency is being deducted without the card level being updated at all. Like it shouldn't matter that getCardLevelCost is returning the wrong value because the affordability check should prevent currency from being deducted.

That said, this probably helps with a different bug with the auto-buyer. The auto-buyer logic incorrectly assumes that levelUpCard can never fail and increments the autobuyCount without making sure currency is deducted. So in cases where the affordability check causes levelUpCard to silently fail, you can pump up autobuyCount indefinitely without actually spending currency by spamming the auto-buy button.


function sumGeometricSeries(base, rate, n, owned = 0) {
base *= rate ** owned;
if (n == 1) return base;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This early return is still worth keeping because it prevents pointless exponentiation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants