Rebalance resource levels and implement portal costs

This commit is contained in:
thepaperpilot 2023-05-11 21:09:15 -05:00
parent 5d26995a72
commit 653e674484
4 changed files with 95 additions and 54 deletions

View file

@ -1,5 +1,5 @@
import { BoardNode, GenericBoard, GenericBoardNodeAction, NodeLabel } from "features/boards/board";
import Formula, { calculateCost } from "game/formulas/formulas";
import Formula from "game/formulas/formulas";
import { GenericFormula, InvertibleIntegralFormula } from "game/formulas/types";
import Decimal, { formatWhole } from "util/bignum";
import {
@ -16,7 +16,11 @@ import { main } from "./projEntry";
import { DecimalSource } from "lib/break_eternity";
import { ComputedRef } from "vue";
export const resourceLevelFormula = Formula.variable(0).add(1);
export const resourceLevelFormula = Formula.variable(0)
.step(100, x => x.pow(1.5))
.step(Decimal.pow(900, 1.5).add(100), x => x.pow(1.5))
.pow(1.5);
console.log(resourceLevelFormula);
export const deselectAllAction = {
id: "deselect",
@ -324,12 +328,8 @@ export function getResourceLevelProgress(resource: Resources): number {
(main.resourceNodes.value[resource]?.state as unknown as ResourceState | undefined)
?.amount ?? 0;
const currentLevel = main.resourceLevels.value[resource];
const requiredForCurrentLevel = calculateCost(resourceLevelFormula, currentLevel, true);
const requiredForNextLevel = calculateCost(
resourceLevelFormula,
Decimal.add(currentLevel, 1),
true
);
const requiredForCurrentLevel = resourceLevelFormula.evaluate(currentLevel);
const requiredForNextLevel = resourceLevelFormula.evaluate(Decimal.add(currentLevel, 1));
return Decimal.sub(amount, requiredForCurrentLevel)
.max(0)
.div(Decimal.sub(requiredForNextLevel, requiredForCurrentLevel))

View file

@ -119,9 +119,7 @@ export const factory = {
).type;
const text = node.state === resource ? "Disconnect" : tools[resource].name;
const color =
node.state === resource ||
(Decimal.gte(main.energy.value, tools[resource].cost) &&
main.toolNodes.value[resource] == null)
node.state === resource || main.toolNodes.value[resource] == null
? "var(--accent2)"
: "var(--danger)";
return {
@ -189,7 +187,10 @@ export const factory = {
progress: node =>
node.state == null || main.toolNodes.value[node.state as Resources] != null
? 0
: Decimal.div(main.energy.value, tools[node.state as Resources].cost)
: Decimal.div(
Decimal.sqrt(main.energy.value),
Decimal.sqrt(tools[node.state as Resources].cost)
)
.clampMax(1)
.toNumber(),
progressDisplay: ProgressDisplay.Fill,
@ -449,13 +450,24 @@ export const portalGenerator = {
id: "makePortal",
icon: "done",
tooltip: node => ({
text: `Spawn ${(node.state as unknown as PortalGeneratorState).tier}-tier portal`
text: `Spawn ${
(node.state as unknown as PortalGeneratorState).tier
}-tier portal - ${formatWhole(main.computedPortalCost.value)} energy`
}),
fillColor: () =>
Decimal.gte(main.energy.value, main.computedPortalCost.value)
? "var(--accent2)"
: "var(--danger)",
confirmationLabel: () =>
Decimal.gte(main.energy.value, main.computedPortalCost.value)
? { text: "Tap again to confirm" }
: { text: "Cannot afford", color: "var(--danger)" },
onClick(node) {
let id = 0;
while (`portal-${id}` in layers) {
id++;
}
main.energy.value = Decimal.sub(main.energy.value, main.computedPortalCost.value);
const { tier, influences } = node.state as unknown as PortalGeneratorState;
addLayer(
createPlane(

View file

@ -23,7 +23,7 @@ import { State } from "game/persistence";
import type { LayerData, Player } from "game/player";
import player from "game/player";
import settings from "game/settings";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
import Decimal, { DecimalSource, format, formatSmall, formatWhole } from "util/bignum";
import { WithRequired, camelToTitle } from "util/common";
import { render } from "util/vue";
import { ComputedRef, computed, nextTick, reactive, ref, watch } from "vue";
@ -52,6 +52,7 @@ import {
ResourceState,
Resources,
UpgraderState,
influences,
mineLootTable,
resourceNames,
tools
@ -143,21 +144,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
const amount =
(resourceNodes.value[curr]?.state as unknown as ResourceState | undefined)
?.amount ?? 0;
// Sub 10 and then manually sum until we go over amount
let currentLevel = Decimal.floor(resourceLevelFormula.invertIntegral(amount))
.sub(10)
.clampMin(0);
let summedCost = calculateCost(resourceLevelFormula, currentLevel, true, 0);
while (true) {
const nextCost = resourceLevelFormula.evaluate(currentLevel);
if (Decimal.add(summedCost, nextCost).lte(amount)) {
currentLevel = currentLevel.add(1);
summedCost = Decimal.add(summedCost, nextCost);
} else {
break;
}
}
acc[curr] = currentLevel;
acc[curr] = Decimal.floor(resourceLevelFormula.invert(amount));
return acc;
}, {} as Record<Resources, DecimalSource>)
);
@ -185,7 +172,6 @@ export const main = createLayer("main", function (this: BaseLayer) {
)}`}
!
</h3>
<div>Energy gain is now 1.01x higher.</div>
</div>
);
}
@ -488,27 +474,30 @@ export const main = createLayer("main", function (this: BaseLayer) {
return multis;
});
const totalResourceLevels = createSequentialModifier(() =>
resourceNames.map(resource =>
createAdditiveModifier(() => ({
description: () => camelToTitle(resource),
addend: () => resourceLevels.value[resource],
enabled: () => Decimal.gt(resourceLevels.value[resource], 0)
}))
)
);
const computedTotalResourceLevels = computed(() => totalResourceLevels.apply(0));
const energyModifier = createSequentialModifier(() => [
...resourceNames.map(resource =>
createAdditiveModifier(() => ({
addend: computedTotalResourceLevels,
description: "Resource Levels"
})),
createMultiplicativeModifier(() => ({
description: () =>
`${camelToTitle(resource)} (Lv. ${formatWhole(
resourceLevels.value[resource]
)}) (${format(computedmaterialLevelEffectModifier.value)}x per level)`,
multiplier: () =>
Decimal.pow(
computedmaterialLevelEffectModifier.value,
resourceLevels.value[resource]
),
enabled: () =>
resource in resourceNodes.value &&
Decimal.gt(
(resourceNodes.value[resource].state as ResourceState | undefined)
?.amount ?? 0,
0
)
}))
computedTotalResourceLevels.value
),
description: () =>
`${formatSmall(computedmaterialLevelEffectModifier.value)}x per Resource Level`
})),
createMultiplicativeModifier(() => ({
multiplier: () => (isEmpowered("stone") ? 4 : 2),
description: () => (isEmpowered("stone") ? "Empowered " : "") + tools.stone.name,
@ -525,7 +514,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
enabled: () => Decimal.gt(numPoweredMachines.value, 0)
}))
]);
const computedEnergyModifier = computed(() => energyModifier.apply(1));
const computedEnergyModifier = computed(() => energyModifier.apply(0));
const bonusConnectionsModifier = createSequentialModifier(() => [
createAdditiveModifier(() => ({
@ -604,17 +593,56 @@ export const main = createLayer("main", function (this: BaseLayer) {
return acc;
}, {} as Record<Resources, { modifier: WithRequired<Modifier, "invert" | "description">; computedModifier: ComputedRef<DecimalSource>; section: Section }>);
const basePortalCost = computed(() => {
const n = resourceNames.indexOf(
(portalGenerator.value?.state as unknown as PortalGeneratorState | undefined)?.tier ??
"dirt"
);
return Decimal.add(n, 1).times(n).div(2).add(9).pow10();
});
const portalCostModifier = createSequentialModifier(() =>
(Object.keys(influences) as Influences[]).map(influence =>
createMultiplicativeModifier(() => ({
multiplier: influences[influence].cost,
description: influences[influence].display,
enabled: () =>
(
portalGenerator.value?.state as unknown as PortalGeneratorState | undefined
)?.influences.includes(influence) ?? false
}))
)
);
const computedPortalCost = computed(() => portalCostModifier.apply(basePortalCost.value));
const [energyTab, energyTabCollapsed] = createCollapsibleModifierSections(() => [
{
title: "Resource Levels",
modifier: totalResourceLevels,
base: 0
},
{
title: "Energy Gain",
modifier: energyModifier,
base: 1,
base: 0,
unit: "/s"
},
{
title: "Portal Cost",
modifier: portalCostModifier,
base: basePortalCost,
unit: " energy",
baseText: () =>
`${camelToTitle(
(portalGenerator.value?.state as unknown as PortalGeneratorState | undefined)
?.tier ?? "dirt"
)}-tier Base Cost`,
visible: () => portalGenerator.value != null
},
{
title: "Bonus Connections",
modifier: bonusConnectionsModifier,
base: 0
base: 0,
visible: () => Decimal.gt(computedBonusConnectionsModifier.value, 0)
}
]);
const [miningTab, miningTabCollapsed] = createCollapsibleModifierSections(() => [
@ -875,6 +903,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
investments,
resourceLevels,
planarMultis,
computedPortalCost,
display: jsx(() => (
<>
<StickyVue class="nav-container">

View file

@ -399,7 +399,7 @@ export function integratePow10(stack: SubstitutionStack, lhs: FormulaSource) {
export function invertPowBase(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
if (hasVariable(lhs)) {
return lhs.invert(Decimal.ln(value).div(unrefFormulaSource(rhs)));
return lhs.invert(Decimal.ln(value).div(Decimal.ln(unrefFormulaSource(rhs))));
} else if (hasVariable(rhs)) {
return rhs.invert(Decimal.root(unrefFormulaSource(lhs), value));
}