Finished balancing

This commit is contained in:
thepaperpilot 2022-12-23 20:59:16 -06:00
parent 191d07075b
commit 251cf47c6a

View file

@ -9,23 +9,22 @@ import { main } from "data/projEntry";
import { createBar, GenericBar } from "features/bars/bar"; import { createBar, GenericBar } from "features/bars/bar";
import { BoardNode, BoardNodeLink, createBoard, Shape } from "features/boards/board"; import { BoardNode, BoardNodeLink, createBoard, Shape } from "features/boards/board";
import { createClickable } from "features/clickables/clickable"; import { createClickable } from "features/clickables/clickable";
import { jsx } from "features/feature"; import { jsx, showIf } from "features/feature";
import { createMilestone } from "features/milestones/milestone"; import { createMilestone } from "features/milestones/milestone";
import MainDisplay from "features/resources/MainDisplay.vue"; import MainDisplay from "features/resources/MainDisplay.vue";
import { createResource } from "features/resources/resource"; import { createResource } from "features/resources/resource";
import { createTab } from "features/tabs/tab";
import { createTabFamily } from "features/tabs/tabFamily";
import { globalBus } from "game/events"; import { globalBus } from "game/events";
import { BaseLayer, createLayer } from "game/layers"; import { BaseLayer, createLayer } from "game/layers";
import { import {
createAdditiveModifier, createAdditiveModifier,
createExponentialModifier,
createMultiplicativeModifier, createMultiplicativeModifier,
createSequentialModifier createSequentialModifier
} from "game/modifiers"; } from "game/modifiers";
import { persistent } from "game/persistence"; import { persistent } from "game/persistence";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum"; import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
import { Direction } from "util/common"; import { Direction } from "util/common";
import { render, renderCol, renderRow } from "util/vue"; import { render, renderRow } from "util/vue";
import { computed, ComputedRef, ref, unref, watchEffect } from "vue"; import { computed, ComputedRef, ref, unref, watchEffect } from "vue";
import "./styles/routing.css"; import "./styles/routing.css";
@ -64,14 +63,19 @@ const layer = createLayer(id, function (this: BaseLayer) {
const name = "Routing"; const name = "Routing";
const color = "navajowhite"; const color = "navajowhite";
const citiesGoal = 25; const citiesGoal = 10;
const citiesCompleted = createResource<DecimalSource>(0, "cities solved"); const citiesCompleted = createResource<DecimalSource>(0, "cities solved");
const currentCity = persistent<number[][]>([]); const currentCity = persistent<number[][]>([]);
const routeIndex = persistent<number>(0); const routeIndex = persistent<number>(0);
const checkRouteProgress = persistent<number>(0); const checkRouteProgress = persistent<number>(0);
const redundanciesRemoved = persistent<number>(0);
const currentRoutes = computed(() => { const currentRoutes = computed(() => {
// Manually check milestone req here due to calling generateCity() before milestones get earned
if (Decimal.gte(citiesCompleted.value, 7)) {
return Decimal.factorial(currentCity.value.length).div(2).toNumber();
}
// Permutation code from https://stackoverflow.com/a/37580979 // Permutation code from https://stackoverflow.com/a/37580979
const length = currentCity.value.length; const length = currentCity.value.length;
const permutation = new Array(length).fill(0).map((_, i) => i); const permutation = new Array(length).fill(0).map((_, i) => i);
@ -97,6 +101,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
}); });
const redundantRoutes = computed(() => { const redundantRoutes = computed(() => {
const routes = currentRoutes.value; const routes = currentRoutes.value;
if (typeof routes === "number") {
return [];
}
const redundancies = []; const redundancies = [];
for (let i = 0; i < routes.length; i++) { for (let i = 0; i < routes.length; i++) {
if (routes[i][0] > routes[i][1]) { if (routes[i][0] > routes[i][1]) {
@ -107,14 +114,18 @@ const layer = createLayer(id, function (this: BaseLayer) {
}); });
const routesToSkip = persistent<number[]>([]); const routesToSkip = persistent<number[]>([]);
const currentRoute: ComputedRef<number[] | undefined> = computed( const currentRoute: ComputedRef<number[] | number | undefined> = computed(() =>
() => currentRoutes.value[routeIndex.value] typeof currentRoutes.value === "number"
? currentCity.value.length
: currentRoutes.value[routeIndex.value]
); );
const currentRouteDuration = computed(() => { const currentRouteDuration = computed(() => {
const route = currentRoute.value; const route = currentRoute.value;
if (route == null) { if (route == null) {
return 0; return 0;
} else if (typeof route === "number") {
return Decimal.times(route, computedMinWeight.value).floor().toNumber();
} }
let duration = 0; let duration = 0;
for (let i = 0; i < route.length - 1; i++) { for (let i = 0; i < route.length - 1; i++) {
@ -138,7 +149,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
function generateCity() { function generateCity() {
const numHouses = new Decimal(computedHouses.value).clampMin(3).toNumber(); const numHouses = new Decimal(computedHouses.value).clampMin(3).toNumber();
const min = computedMinWeight.value; const min = computedMinWeight.value;
const max = computedMaxWeight.value; const max = milestone6.earned.value ? min : computedMaxWeight.value;
const diff = Decimal.sub(max, min); const diff = Decimal.sub(max, min);
const city: number[][] = []; const city: number[][] = [];
for (let i = 0; i < numHouses; i++) { for (let i = 0; i < numHouses; i++) {
@ -156,18 +167,23 @@ const layer = createLayer(id, function (this: BaseLayer) {
} }
currentCity.value = city; currentCity.value = city;
routeIndex.value = 0; routeIndex.value = 0;
redundanciesRemoved.value = Decimal.gte(citiesCompleted.value, 7)
? Decimal.factorial(currentCity.value.length).div(2).toNumber()
: 0;
routesToSkip.value = []; routesToSkip.value = [];
getNextRoute(); getNextRoute();
} }
function getNextRoute() { function getNextRoute() {
while ( const numRoutes =
routeIndex.value <= currentRoutes.value.length && typeof currentRoutes.value === "number"
routesToSkip.value.includes(routeIndex.value) ? currentRoutes.value
) { : currentRoutes.value.length;
while (routeIndex.value <= numRoutes && routesToSkip.value.includes(routeIndex.value)) {
routeIndex.value++; routeIndex.value++;
} }
if (routeIndex.value >= currentRoutes.value.length) { console.log(numRoutes);
if (routeIndex.value >= numRoutes) {
citiesCompleted.value = Decimal.add(citiesCompleted.value, 1); citiesCompleted.value = Decimal.add(citiesCompleted.value, 1);
generateCity(); generateCity();
} else { } else {
@ -274,6 +290,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
style: { style: {
minHeight: "40px" minHeight: "40px"
}, },
visibility: () => showIf(!milestone7.earned.value),
canClick: () => canClick: () =>
Decimal.gte(redundantProgress.value, computedRedundantCooldown.value) && Decimal.gte(redundantProgress.value, computedRedundantCooldown.value) &&
routesToSkip.value.length < redundantRoutes.value.length, routesToSkip.value.length < redundantRoutes.value.length,
@ -286,6 +303,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
redundantRoutes.value[routesToSkip.value.length] redundantRoutes.value[routesToSkip.value.length]
]; ];
redundantProgress.value = 0; redundantProgress.value = 0;
redundanciesRemoved.value++;
} }
})); }));
@ -364,33 +382,38 @@ const layer = createLayer(id, function (this: BaseLayer) {
const citySize = currentCity.value.length; const citySize = currentCity.value.length;
let completedLegs = 0; let completedLegs = 0;
let progress = 0; let progress = 0;
for (let i = 0; i < route.length - 1; i++) { let partialLeg = 0;
const weight = progress + currentCity.value[route[i]][route[i + 1]]; if (typeof route !== "number") {
if (checkRouteProgress.value > weight) { for (let i = 0; i < route.length - 1; i++) {
completedLegs++; const weight = progress + currentCity.value[route[i]][route[i + 1]];
progress = weight; if (checkRouteProgress.value > weight) {
} else { completedLegs++;
break; progress = weight;
} else {
break;
}
} }
partialLeg =
(checkRouteProgress.value - progress) /
currentCity.value[route[completedLegs]][route[completedLegs + 1]];
} }
const partialLeg =
(checkRouteProgress.value - progress) /
currentCity.value[route[completedLegs]][route[completedLegs + 1]];
for (let i = 0; i < citySize; i++) { for (let i = 0; i < citySize; i++) {
for (let j = 0; j < citySize; j++) { for (let j = 0; j < citySize; j++) {
if (i !== j) { if (i !== j) {
let progress = 0; let progress = 0;
const iIndex = route.indexOf(i); if (typeof route !== "number") {
const jIndex = route.indexOf(j); const iIndex = route.indexOf(i);
if ( const jIndex = route.indexOf(j);
iIndex >= 0 && if (
jIndex >= 0 && iIndex >= 0 &&
(route[iIndex + 1] === j || route[jIndex + 1] === i) jIndex >= 0 &&
) { (route[iIndex + 1] === j || route[jIndex + 1] === i)
if (jIndex < completedLegs || iIndex < completedLegs) { ) {
progress = 1; if (jIndex < completedLegs || iIndex < completedLegs) {
} else if (jIndex === completedLegs || iIndex === completedLegs) { progress = 1;
progress = partialLeg; } else if (jIndex === completedLegs || iIndex === completedLegs) {
progress = partialLeg;
}
} }
} }
links.push({ links.push({
@ -444,10 +467,85 @@ const layer = createLayer(id, function (this: BaseLayer) {
effectDisplay: "Each city solved doubles manual and auto processing speed" effectDisplay: "Each city solved doubles manual and auto processing speed"
}, },
shouldEarn() { shouldEarn() {
return Decimal.gte(citiesCompleted.value, 2); return Decimal.gte(citiesCompleted.value, 1);
} }
})); }));
const milestones = { milestone1 }; const milestone2 = createMilestone(() => ({
display: {
requirement: "2 Cities Solved",
effectDisplay:
"Manually checking routes does additional work based on number of routes checked in this city"
},
shouldEarn() {
return Decimal.gte(citiesCompleted.value, 2);
},
visibility: () => showIf(milestone1.earned.value)
}));
const milestone3 = createMilestone(() => ({
display: {
requirement: "3 Cities Solved",
effectDisplay:
"Each city solved makes the cooldown for removing a redundant route 25% shorter"
},
shouldEarn() {
return Decimal.gte(citiesCompleted.value, 3);
},
visibility: () => showIf(milestone2.earned.value)
}));
const milestone4 = createMilestone(() => ({
display: {
requirement: "4 Cities Solved",
effectDisplay:
"Automatic processing speed is multiplied by the amount of redundant routes removed from this city"
},
shouldEarn() {
return Decimal.gte(citiesCompleted.value, 4);
},
visibility: () => showIf(milestone3.earned.value)
}));
const milestone5 = createMilestone(() => ({
display: {
requirement: "5 Cities Solved",
effectDisplay: "Remove 1 house"
},
shouldEarn() {
return Decimal.gte(citiesCompleted.value, 5);
},
onComplete() {
generateCity();
},
visibility: () => showIf(milestone4.earned.value)
}));
const milestone6 = createMilestone(() => ({
display: {
requirement: "6 Cities Solved",
effectDisplay:
"Lower max weight to the min weight, and uncap amount of routes that can be checked per tick"
},
shouldEarn() {
return Decimal.gte(citiesCompleted.value, 6);
},
visibility: () => showIf(milestone5.earned.value)
}));
const milestone7 = createMilestone(() => ({
display: {
requirement: "7 Cities Solved",
effectDisplay: "All redundancies are removed"
},
shouldEarn() {
return Decimal.gte(citiesCompleted.value, 7);
},
visibility: () => showIf(milestone6.earned.value)
}));
const milestones = {
milestone1,
milestone2,
milestone3,
milestone4,
milestone5,
milestone6,
milestone7
};
const { collapseMilestones, display: milestonesDisplay } = const { collapseMilestones, display: milestonesDisplay } =
createCollapsibleMilestones(milestones); createCollapsibleMilestones(milestones);
@ -455,6 +553,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
createAdditiveModifier(() => ({ createAdditiveModifier(() => ({
addend: citiesCompleted, addend: citiesCompleted,
description: "Cities Completed" description: "Cities Completed"
})),
createAdditiveModifier(() => ({
addend: 1,
description: "5 Cities Completed",
enabled: milestone5.earned
})) }))
]); ]);
const computedHouses = computed(() => houses.apply(3)); const computedHouses = computed(() => houses.apply(3));
@ -469,10 +572,21 @@ const layer = createLayer(id, function (this: BaseLayer) {
createAdditiveModifier(() => ({ createAdditiveModifier(() => ({
addend: citiesCompleted, addend: citiesCompleted,
description: "Cities Completed" description: "Cities Completed"
})),
createExponentialModifier(() => ({
exponent: 3,
description: "Cities Completed",
enabled: milestone7.earned
})) }))
]); ]);
const computedMinWeight = computed(() => minWeight.apply(2)); const computedMinWeight = computed(() => minWeight.apply(2));
const manualBoost = createSequentialModifier(() => []); const manualBoost = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend: () => Decimal.add(routeIndex.value, 1).sqrt(),
description: "2 Cities Solved",
enabled: milestone2.earned
}))
]);
const computedManualBoost = computed(() => manualBoost.apply(1)); const computedManualBoost = computed(() => manualBoost.apply(1));
const manualCooldown = createSequentialModifier(() => [ const manualCooldown = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
@ -482,13 +596,24 @@ const layer = createLayer(id, function (this: BaseLayer) {
})) }))
]); ]);
const computedManualCooldown = computed(() => manualCooldown.apply(1)); const computedManualCooldown = computed(() => manualCooldown.apply(1));
const redundantCooldown = createSequentialModifier(() => []); const redundantCooldown = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.pow(0.75, citiesCompleted.value),
description: "3 Cities Solved",
enabled: milestone3.earned
}))
]);
const computedRedundantCooldown = computed(() => redundantCooldown.apply(10)); const computedRedundantCooldown = computed(() => redundantCooldown.apply(10));
const autoProcessing = createSequentialModifier(() => [ const autoProcessing = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({ createMultiplicativeModifier(() => ({
multiplier: () => Decimal.pow(2, citiesCompleted.value), multiplier: () => Decimal.pow(2, citiesCompleted.value),
description: "1 City Solved", description: "1 City Solved",
enabled: milestone1.earned enabled: milestone1.earned
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.add(redundanciesRemoved.value, 1),
description: "4 Cities Solved",
enabled: milestone4.earned
})) }))
]); ]);
const computedAutoProcessing = computed(() => autoProcessing.apply(1)); const computedAutoProcessing = computed(() => autoProcessing.apply(1));
@ -500,10 +625,16 @@ const layer = createLayer(id, function (this: BaseLayer) {
base: 3 base: 3
}, },
{ {
title: "Minimum Weight", title: () => (milestone6.earned.value ? "Weight" : "Minimum Weight"),
modifier: minWeight, modifier: minWeight,
base: 2 base: 2
}, },
{
title: "Maximum Weight",
modifier: maxWeight,
base: 10,
visible: () => !milestone6.earned.value
},
{ {
title: "Manual Processing Amount", title: "Manual Processing Amount",
modifier: manualBoost, modifier: manualBoost,
@ -576,7 +707,21 @@ const layer = createLayer(id, function (this: BaseLayer) {
.add(checkRouteProgress.value) .add(checkRouteProgress.value)
.toNumber(); .toNumber();
if (checkRouteProgress.value > currentRouteDuration.value) { if (checkRouteProgress.value > currentRouteDuration.value) {
const overflow = checkRouteProgress.value - currentRouteDuration.value;
routeIndex.value++; routeIndex.value++;
if (milestone6.earned.value && currentRoute.value != null) {
const length =
typeof currentRoute.value === "number"
? currentRoute.value
: currentRoute.value.length;
const extraRoutes = Decimal.div(
overflow,
Decimal.times(length, computedMinWeight.value)
)
.floor()
.toNumber();
routeIndex.value += extraRoutes;
}
getNextRoute(); getNextRoute();
} }
}); });
@ -586,6 +731,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
width: 600, width: 600,
height: 25, height: 25,
fillStyle: `backgroundColor: ${color}`, fillStyle: `backgroundColor: ${color}`,
textStyle: {
color: "var(--feature-foreground)"
},
progress: () => progress: () =>
main.day.value === day ? Decimal.div(citiesCompleted.value, citiesGoal) : 1, main.day.value === day ? Decimal.div(citiesCompleted.value, citiesGoal) : 1,
display: jsx(() => display: jsx(() =>
@ -606,6 +754,25 @@ const layer = createLayer(id, function (this: BaseLayer) {
}); });
function displayRoutes() { function displayRoutes() {
if (currentRoute.value == null) {
return "";
}
if (typeof currentRoutes.value === "number") {
return (
<div class="routes-list">
{routeIndex.value > 0 ? (
<div class="checked">{formatWhole(routeIndex.value)} already checked</div>
) : null}
<div>
{formatWhole(currentRoutes.value - routeIndex.value)} routes left to check
</div>
</div>
);
}
if (typeof currentRoutes.value === "number") {
console.error("Something went horribly wrong");
return;
}
const routes = currentRoutes.value.slice(); const routes = currentRoutes.value.slice();
let showPrevious = false; let showPrevious = false;
let showNext = 0; let showNext = 0;
@ -659,6 +826,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
currentRoutes, currentRoutes,
redundantRoutes, redundantRoutes,
routesToSkip, routesToSkip,
redundanciesRemoved,
city, city,
milestones, milestones,
collapseMilestones, collapseMilestones,