Compare commits

...

102 Commits

Author SHA1 Message Date
github-actions[bot]
affd704443 [Automated] Merge dev into gh-pages 2026-02-14 11:36:55 +00:00
mdouros
7f06fd383a Handle "Wrinkler ambergris" in CPS calculations (#1250) 2026-02-14 12:36:46 +01:00
github-actions[bot]
0f5aa41305 [Automated] Merge dev into gh-pages 2025-11-12 08:39:10 +00:00
srs42006
acd0fbbaf5 Garden Probability Bug Fixes (#1245)
* Fix icons for locked plants in garden not showing

* Fix NaNs for weed mult edge case

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Fix ESLint issue caused by pre-commit

---------

Co-authored-by: srs42006 <45675882+srs42006@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-11-12 09:39:01 +01:00
github-actions[bot]
63e06d7133 [Automated] Merge dev into gh-pages 2025-11-10 20:33:32 +00:00
srs42006
38636f6323 Add Garden Tile Probabilities 2025-11-10 21:33:21 +01:00
github-actions[bot]
5a37e21d10 [Automated] Merge dev into gh-pages 2025-09-16 20:49:33 +00:00
Lilium
082bc89a4a Fix "Extra Dragon Auro Info" causing the Dragon Aura window to flicker by increasing the minHeight 2025-09-16 22:49:23 +02:00
github-actions[bot]
8675bd041a [Automated] Merge dev into gh-pages 2025-03-16 19:43:15 +00:00
github-actions[bot]
570c0b760e [Automated] Merge dev into gh-pages 2025-03-03 19:44:54 +00:00
github-actions[bot]
fcd39a3860 [Automated] Merge dev into gh-pages 2025-02-26 20:42:31 +00:00
github-actions[bot]
859045b475 [Automated] Merge dev into gh-pages 2025-02-24 08:30:22 +00:00
github-actions[bot]
60e9ced10e [Automated] Merge dev into gh-pages 2025-02-24 08:29:46 +00:00
github-actions[bot]
9f9a28b008 [Automated] Merge dev into gh-pages 2025-02-24 08:26:15 +00:00
github-actions[bot]
5f26d36cc2 [Automated] Merge dev into gh-pages 2025-02-24 08:23:58 +00:00
github-actions[bot]
5403aa8bac [Automated] Merge dev into gh-pages 2025-02-17 20:45:13 +00:00
github-actions[bot]
65add868f1 [Automated] Merge dev into gh-pages 2025-02-16 14:01:10 +00:00
github-actions[bot]
888b175f25 [Automated] Merge dev into gh-pages 2025-02-16 13:56:53 +00:00
github-actions[bot]
b17a8625bc [Automated] Merge dev into gh-pages 2024-09-08 09:17:13 +00:00
github-actions[bot]
df31286af0 [Automated] Merge dev into gh-pages 2024-09-02 07:22:13 +00:00
github-actions[bot]
9291403f58 [Automated] Merge dev into gh-pages 2024-05-11 08:01:18 +00:00
github-actions[bot]
5718e621f7 [Automated] Merge dev into gh-pages 2024-05-11 07:59:55 +00:00
github-actions[bot]
370940000b [Automated] Merge dev into gh-pages 2024-05-11 07:59:40 +00:00
github-actions[bot]
ee3e44cbba [Automated] Merge dev into gh-pages 2024-05-11 07:59:18 +00:00
github-actions[bot]
f5769ed74b [Automated] Merge dev into gh-pages 2024-05-11 07:57:56 +00:00
github-actions[bot]
dc96341087 [Automated] Merge dev into gh-pages 2023-08-22 07:37:44 +00:00
github-actions[bot]
7a7419a2f6 [Automated] Merge dev into gh-pages 2023-07-17 18:18:19 +00:00
github-actions[bot]
33b968cab8 [Automated] Merge dev into gh-pages 2023-07-17 07:40:43 +00:00
github-actions[bot]
096f18deef [Automated] Merge dev into gh-pages 2023-06-22 19:27:10 +00:00
github-actions[bot]
a241ea51e7 [Automated] Merge dev into gh-pages 2023-05-07 11:20:04 +00:00
github-actions[bot]
86523a4a6c [Automated] Merge dev into gh-pages 2023-04-18 15:10:06 +00:00
github-actions[bot]
bbc8ed6ec2 [Automated] Merge dev into gh-pages 2023-04-18 14:57:44 +00:00
github-actions[bot]
6c939d0591 [Automated] Merge dev into gh-pages 2023-03-15 08:04:35 +00:00
github-actions[bot]
78bb328d5d [Automated] Merge dev into gh-pages 2023-03-13 07:55:33 +00:00
github-actions[bot]
b8f8c3ef0c [Automated] Merge dev into gh-pages 2023-03-13 07:54:03 +00:00
github-actions[bot]
0c64005603 [Automated] Merge dev into gh-pages 2023-03-13 07:53:28 +00:00
github-actions[bot]
f24e07465b [Automated] Merge dev into gh-pages 2022-07-20 07:08:02 +00:00
github-actions[bot]
bed1647332 [Automated] Merge dev into gh-pages 2022-07-18 02:59:02 +00:00
github-actions[bot]
a02423f25b [Automated] Merge dev into gh-pages 2022-07-08 13:11:08 +00:00
github-actions[bot]
b409ddd2ed [Automated] Merge dev into gh-pages 2022-06-23 12:07:40 +00:00
github-actions[bot]
7c78299ade [Automated] Merge dev into gh-pages 2022-06-19 19:05:03 +00:00
github-actions[bot]
1ac83d901a [Automated] Merge dev into gh-pages 2022-06-19 19:02:53 +00:00
github-actions[bot]
7b75ddddea [Automated] Merge dev into gh-pages 2022-06-19 18:51:25 +00:00
github-actions[bot]
9f55f279e7 [Automated] Merge dev into gh-pages 2022-06-19 18:42:45 +00:00
github-actions[bot]
1c14ee0267 [Automated] Merge dev into gh-pages 2022-06-16 12:40:16 +00:00
github-actions[bot]
8bae0fdb85 [Automated] Merge dev into gh-pages 2022-06-06 20:12:41 +00:00
github-actions[bot]
362d403601 [Automated] Merge dev into gh-pages 2022-06-06 20:05:44 +00:00
github-actions[bot]
4b16c896f1 [Automated] Merge dev into gh-pages 2022-06-06 20:04:29 +00:00
github-actions[bot]
33c463b15a [Automated] Merge dev into gh-pages 2022-06-06 20:03:12 +00:00
github-actions[bot]
5b982cf9cf [Automated] Merge dev into gh-pages 2022-06-06 20:02:32 +00:00
github-actions[bot]
e0ef8d7b11 [Automated] Merge dev into gh-pages 2022-06-04 08:42:32 +00:00
github-actions[bot]
38f33e2478 [Automated] Merge dev into gh-pages 2022-06-03 10:19:21 +00:00
github-actions[bot]
9bc392a0c5 [Automated] Merge dev into gh-pages 2022-06-02 06:26:18 +00:00
github-actions[bot]
50d4e3e215 [Automated] Merge dev into gh-pages 2022-06-01 17:10:31 +00:00
github-actions[bot]
17ac30177c [Automated] Merge dev into gh-pages 2022-06-01 08:59:35 +00:00
github-actions[bot]
ef6585b9af [Automated] Merge dev into gh-pages 2022-06-01 08:53:46 +00:00
github-actions[bot]
a89f440809 [Automated] Merge dev into gh-pages 2022-06-01 08:51:42 +00:00
github-actions[bot]
e928c0227e [Automated] Merge dev into gh-pages 2022-04-20 19:02:18 +00:00
github-actions[bot]
c20abff9f4 [Automated] Merge dev into gh-pages 2022-04-20 18:56:46 +00:00
github-actions[bot]
26672fe57b [Automated] Merge dev into gh-pages 2022-04-20 18:56:35 +00:00
github-actions[bot]
f59b041e96 [Automated] Merge dev into gh-pages 2022-04-20 18:54:10 +00:00
github-actions[bot]
89c94ea934 [Automated] Merge dev into gh-pages 2022-04-20 18:53:41 +00:00
github-actions[bot]
3e525da15c [Automated] Merge dev into gh-pages 2022-04-20 18:53:31 +00:00
github-actions[bot]
c498574a77 [Automated] Merge dev into gh-pages 2022-04-20 18:52:10 +00:00
github-actions[bot]
0a6113cf72 [Automated] Merge dev into gh-pages 2021-12-30 08:28:30 +00:00
github-actions[bot]
248be6d9ce [Automated] Merge dev into gh-pages 2021-09-29 21:03:57 +00:00
github-actions[bot]
a0b4d5eecb [Automated] Merge dev into gh-pages 2021-09-29 19:10:49 +00:00
github-actions[bot]
aa2e866cc5 [Automated] Merge dev into gh-pages 2021-09-22 10:34:56 +00:00
github-actions[bot]
46202be466 [Automated] Merge dev into gh-pages 2021-09-14 19:15:52 +00:00
github-actions[bot]
b2fcbcdb81 [Automated] Merge dev into gh-pages 2021-09-14 19:07:52 +00:00
github-actions[bot]
386dae3830 [Automated] Merge dev into gh-pages 2021-09-14 19:06:41 +00:00
github-actions[bot]
5ac33725b7 [Automated] Merge dev into gh-pages 2021-09-10 08:14:55 +00:00
github-actions[bot]
96fa090f0d [Automated] Merge dev into gh-pages 2021-09-10 07:47:13 +00:00
Daniël van Noord
e4143126a0 Update bug-report.yml 2021-09-10 09:46:59 +02:00
github-actions[bot]
c8a5a3c34f [Automated] Merge dev into gh-pages 2021-09-10 07:46:51 +00:00
Daniël van Noord
0616887d28 Update bug-report.yml 2021-09-10 09:46:40 +02:00
github-actions[bot]
196a911e2d [Automated] Merge dev into gh-pages 2021-09-10 07:46:26 +00:00
Daniël van Noord
2695fdb140 Create bug-report.yml 2021-09-10 09:46:15 +02:00
github-actions[bot]
11b1be5c71 [Automated] Merge dev into gh-pages 2021-09-10 07:45:52 +00:00
Daniël van Noord
bf4f910cee Update bug-report.yml 2021-09-10 09:45:40 +02:00
github-actions[bot]
b0ad9b9786 [Automated] Merge dev into gh-pages 2021-09-10 07:45:26 +00:00
Daniël van Noord
eb0861c5d7 Update bug-report.yml 2021-09-10 09:45:12 +02:00
github-actions[bot]
4ebc2d597e [Automated] Merge dev into gh-pages 2021-09-10 07:43:49 +00:00
Daniël van Noord
4a76fa9f95 Update bug-report.yml 2021-09-10 09:43:37 +02:00
github-actions[bot]
3b8adb7b9f [Automated] Merge dev into gh-pages 2021-09-10 07:42:57 +00:00
Daniël van Noord
9c28ef5411 Rename bug_report.yml to bug-report.yml 2021-09-10 09:42:44 +02:00
github-actions[bot]
b1ba7f02f7 [Automated] Merge dev into gh-pages 2021-09-10 07:42:20 +00:00
Daniël van Noord
c78b06b16a Delete feature_request.md 2021-09-10 09:42:17 +02:00
Daniël van Noord
ea1d288c39 Create feature-request.yml 2021-09-10 09:42:07 +02:00
github-actions[bot]
d69e249d58 [Automated] Merge dev into gh-pages 2021-09-10 07:39:32 +00:00
Daniël van Noord
a2db049b71 Update bug_report.yml 2021-09-10 09:39:21 +02:00
github-actions[bot]
beb894557b [Automated] Merge dev into gh-pages 2021-09-10 07:36:16 +00:00
Daniël van Noord
6d9f6d61f4 Delete bug_report.md 2021-09-10 09:36:04 +02:00
github-actions[bot]
0dd3f2594b [Automated] Merge dev into gh-pages 2021-09-10 07:35:55 +00:00
Daniël van Noord
75b59fdaa8 Create bug_report.yml 2021-09-10 09:35:40 +02:00
github-actions[bot]
627fcb7b52 [Automated] Merge dev into gh-pages 2021-09-06 13:46:51 +00:00
github-actions[bot]
1cde6308fa [Automated] Merge dev into gh-pages 2021-09-05 18:15:24 +00:00
github-actions[bot]
fa49f84262 [Automated] Merge dev into gh-pages 2021-09-05 15:35:05 +00:00
github-actions[bot]
2b174fe323 [Automated] Merge dev into gh-pages 2021-09-05 15:31:42 +00:00
github-actions[bot]
aaeb8a62eb [Automated] Merge dev into gh-pages 2021-09-05 11:02:23 +00:00
github-actions[bot]
1c0a0a9851 [Automated] Merge dev into gh-pages 2021-09-04 14:18:38 +00:00
Daniël van Noord
b1ec82b4b8 Merge pull request #962 from CookieMonsterTeam/dev
Add delay for steam
2021-09-03 12:41:00 +02:00
13 changed files with 569 additions and 40 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "@cookiemonsterteam/cookiemonster-mod", "name": "@cookiemonsterteam/cookiemonster-mod",
"version": "2.053.10", "version": "2.058.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@cookiemonsterteam/cookiemonster-mod", "name": "@cookiemonsterteam/cookiemonster-mod",
"version": "2.053.10", "version": "2.058.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@cookiemonsterteam/cookiemonsterframework": "0.2.3", "@cookiemonsterteam/cookiemonsterframework": "0.2.3",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@cookiemonsterteam/cookiemonster-mod", "name": "@cookiemonsterteam/cookiemonster-mod",
"version": "2.053.10", "version": "2.058.0",
"description": "Cookie Monster is an add-on that you can load into Cookie Clicker which offers a wide range of tools and statistics to enhance the game. It is not a cheat interface although it does offer helpers for golden cookies and such, everything can be toggled off at will to only leave how much information you want. This is a helper and everything is an option.", "description": "Cookie Monster is an add-on that you can load into Cookie Clicker which offers a wide range of tools and statistics to enhance the game. It is not a cheat interface although it does offer helpers for golden cookies and such, everything can be toggled off at will to only leave how much information you want. This is a helper and everything is an option.",
"main": "CookieMonster.js", "main": "CookieMonster.js",
"keywords": [ "keywords": [

View File

@@ -104,6 +104,11 @@ export let CacheDoRemakeBuildPrices;
export let CacheHadBuildAura; export let CacheHadBuildAura;
export let CacheFarmLevel = -1;
export let CacheGardenSoil = -1;
export let CacheSupremeIntellect = -1;
export let CachePlotChances = [[], [], [], [], [], []];
/** Store the CPS effect of each god if it was put into each slot */ /** Store the CPS effect of each god if it was put into each slot */
export let CacheGods = { export let CacheGods = {
0: [0, 0, 0], 0: [0, 0, 0],

View File

@@ -18,7 +18,7 @@ export function AddAuraInfo(aura) {
if (Game.cookiesPs === 0) bonusCPSPercentage = Beautify(Infinity); if (Game.cookiesPs === 0) bonusCPSPercentage = Beautify(Infinity);
else bonusCPSPercentage = Beautify((bonusCPS / Game.cookiesPs) * 100); else bonusCPSPercentage = Beautify((bonusCPS / Game.cookiesPs) * 100);
l('dragonAuraInfo').style.minHeight = '60px'; l('dragonAuraInfo').style.minHeight = '120px';
l('dragonAuraInfo').style.margin = '8px'; l('dragonAuraInfo').style.margin = '8px';
l('dragonAuraInfo').appendChild(document.createElement('div')).className = 'line'; l('dragonAuraInfo').appendChild(document.createElement('div')).className = 'line';
const div = document.createElement('div'); const div = document.createElement('div');

View File

@@ -0,0 +1,162 @@
/* eslint-disable no-continue */
import { CachePlotChances } from '../../Cache/VariablesAndData.js';
import CalculateSingleTileChances from './CalculateSingleTileChances.js';
/**
* Calculates the possible plants for the next garden tick and updates **`CachePlotChances`** accordingly (expensive.)
*
* @param {Object} minigame a reference to the garden minigame
* @param {number} auraMult the current value of the "Supreme Intellect" dragon aura multiplier
*/
export default function CalculateAllPlotChances(minigame, auraMult) {
const { plantsById, soilsById, soil, isTileUnlocked, getTile } = minigame;
const dragonBoost = 1 + 0.05 * auraMult;
// calculate boosts from neighbors for next tick
const boosts = [];
for (let y = 0; y < 6; y++) {
boosts[y] = [];
for (let x = 0; x < 6; x++) boosts[y].push([1, 1]); // [aging, weed]
}
const ApplyMultsToNearbyTiles = function (x, y, range, mults) {
for (let dy = -range; dy <= range; dy++) {
for (let dx = -range; dx <= range; dx++) {
if ((dx !== 0 || dy !== 0) && isTileUnlocked(x + dx, y + dy)) {
boosts[y + dy][x + dx][0] *= mults[0];
boosts[y + dy][x + dx][1] *= mults[1];
}
}
}
};
for (let y = 0; y < 6; y++) {
for (let x = 0; x < 6; x++) {
const tile = getTile(x, y);
if (tile[0] === 0) continue;
let ageMult;
let weedMult;
let range;
const id = tile[0] - 1;
switch (id) {
case 7:
ageMult = 1.03;
weedMult = 1;
range = 1;
break;
case 31:
ageMult = 1;
weedMult = 0;
range = 2;
break;
case 32:
ageMult = 1;
weedMult = 0;
range = 1;
break;
case 33:
ageMult = 0.5;
weedMult = 1;
range = 1;
break;
default:
continue;
}
let mult = soilsById[soil].effMult;
const matureAge = plantsById[id].mature;
const stage = 1 + (tile[1] >= matureAge ? 3 : Math.floor(tile[1] / (matureAge * 0.333)));
// eslint-disable-next-line default-case
switch (stage) {
case 1:
mult *= 0.1;
break;
case 2:
mult *= 0.25;
break;
case 3:
mult *= 0.5;
break;
}
if (ageMult > 1 || mult < 1) ageMult = (ageMult - 1) * mult + 1;
else ageMult /= mult;
ApplyMultsToNearbyTiles(x, y, range, [ageMult, weedMult]);
}
}
// initialize all probabilities to current state
const plotOutcomes = [[], [], [], [], [], []];
for (let y = 0; y < 6; y++) {
for (let x = 0; x < 6; x++) {
if (!isTileUnlocked(x, y)) continue;
const tile = getTile(x, y);
if (tile[0] === 0) plotOutcomes[y][x] = [{ plantId: -1, isMature: false, p: 1 }];
else {
const plantId = tile[0] - 1;
plotOutcomes[y][x] = [{ plantId, isMature: tile[1] >= plantsById[plantId].mature, p: 1 }];
}
}
}
// update each tile's chances
for (let y = 0; y < 6; y++) {
for (let x = 0; x < 6; x++) {
if (!isTileUnlocked(x, y)) continue;
// collect neighbor probabilities
const neighResults = [];
const cardinals = [];
for (let dy = -1; dy <= 1; dy++)
for (let dx = -1; dx <= 1; dx++) {
if ((dx !== 0 || dy !== 0) && isTileUnlocked(x + dx, y + dy)) {
neighResults.push(plotOutcomes[y + dy][x + dx]);
if (dx === 0 || dy === 0) cardinals.push(neighResults.length - 1); // save indices of cardinal neighbors
}
}
const tile = getTile(x, y);
plotOutcomes[y][x] = CalculateSingleTileChances(
minigame,
tile[0] - 1,
tile[1],
neighResults,
cardinals,
boosts[y][x],
dragonBoost,
);
// save results
CachePlotChances[y][x] = [];
const emptyP = plotOutcomes[y][x]
.filter((o) => o.plantId === -1)
.reduce((s, o) => s + o.p, 0);
if (emptyP > 0) CachePlotChances[y][x].push({ plantId: -1, maturityP: 0, p: emptyP });
for (let id = 0; id < plantsById.length; id++) {
const matches = plotOutcomes[y][x].filter((o) => o.plantId === id);
if (matches.length > 1) {
const plantP = matches.reduce((s, o) => s + o.p, 0);
const maturityP =
matches.filter((o) => o.isMature === true).reduce((s, o) => s + o.p, 0) / plantP;
CachePlotChances[y][x].push({ plantId: id, maturityP, p: plantP });
} else if (matches.length === 1)
CachePlotChances[y][x].push({
plantId: id,
maturityP: matches[0].isMature ? 1 : 0,
p: matches[0].p,
});
}
CachePlotChances[y][x].sort((a, b) => a.plantId - b.plantId);
}
}
}

View File

@@ -0,0 +1,240 @@
/* eslint-disable guard-for-in */
/* eslint-disable no-continue */
/* eslint-disable no-restricted-syntax */
/* eslint-disable no-param-reassign */
/**
* Calculates the possible plants for a tile after the next garden tick.
*
* @param {Object} minigame A reference to the garden minigame
* @param {number} plantId The ID of the tile's current plant (-1 if empty)
* @param {number} age The age of the tile's current plant (ignored if empty)
* @param {Object[][]} neighResults The calculated results of each neighboring tile
* @param {number[]} cardinals The indices of orthogonally adjacent tiles in `neighResults`
* @param {number[]} tileBoosts The boosts to aging and weed spawning this tile is recieving from nearby tiles in the format `[ageMult, weedMult]`
* @param {number} dragonBoost The current calculated value of the boost from the "Supreme Intellect" dragon aura
* @returns {{plantId: number, isMature: boolean, p: number}[]} The possible resulting tile states and their probabilities
*/
export default function CalculateSingleTileChances(
minigame,
plantId,
age,
neighResults,
cardinals,
tileBoosts,
dragonBoost,
) {
const { getMuts, plants, plantsById, plantContam, soilsById, soil } = minigame;
const soilWeedMult = soilsById[soil].weedMult;
const epsilon = 1e-12;
const futureStates = [];
const AddOutcome = function (outcome) {
if (outcome.p < epsilon) return;
const existing = futureStates.find(
(o) =>
o.plantId === outcome.plantId &&
(outcome.plantId === -1 || o.isMature === outcome.isMature),
);
if (existing) existing.p += outcome.p;
else futureStates.push(outcome);
};
let runningP = 1;
if (plantId !== -1) {
// tile has plant
const currentPlant = plantsById[plantId];
const AgeThresholdP = function (multiplier, threshold) {
// probability that plant's age increases by at least threshold
const minAge = currentPlant.ageTick * multiplier;
const maxAge = minAge + currentPlant.ageTickR * multiplier;
if (Math.abs(maxAge - minAge) < epsilon) {
if (minAge >= threshold) return 1;
if (minAge < threshold - 1) return 0;
return minAge - (threshold - 1);
}
if (threshold <= minAge) return 1;
if (threshold - 1 >= maxAge) return 0;
const lower = Math.max(minAge, threshold - 1);
const upper = Math.min(maxAge, threshold);
const a = 0.5 * (upper - (threshold - 1)) ** 2 - 0.5 * (lower - (threshold - 1)) ** 2;
const b = Math.max(0, maxAge - Math.max(minAge, threshold));
return (a + b) / (maxAge - minAge);
};
// death
if (!currentPlant.immortal) {
const deathP = AgeThresholdP(tileBoosts[0] * dragonBoost, 100 - age);
AddOutcome({ plantId: -1, isMature: false, p: deathP * runningP });
runningP -= deathP * runningP;
}
// contamination
if (!currentPlant.noContam) {
const contamChances = [];
for (const key in plantContam) {
let inclusionP = plantContam[key];
if (plants[key].weed) inclusionP *= soilWeedMult;
contamChances.push([key, inclusionP]);
}
let totalContamP = 0;
for (const [key1, inclusionP1] of contamChances) {
if (plants[key1].id === plantId || inclusionP1 === 0) continue;
let hasNeighborP = 0;
for (const i of cardinals) {
let isNeighborP = 0;
for (const o of neighResults[i]) {
if (o.plantId === key1 && o.isMature) isNeighborP += o.p;
}
hasNeighborP += isNeighborP * (1 - hasNeighborP);
}
if (hasNeighborP < epsilon) continue;
let q = [1];
for (const [key2, inclusionP2] of contamChances) {
if (key1 !== key2) {
const newQ = Array(q.length + 1).fill(0);
for (let k = 0; k < q.length; k++) {
newQ[k] += q[k] * (1 - inclusionP2);
newQ[k + 1] += q[k] * inclusionP2;
}
q = newQ;
}
}
const E = q.reduce((acc, probXk, k) => acc + probXk / (1 + k), 0);
const contamP = inclusionP1 * E * hasNeighborP * runningP;
AddOutcome({ plantId: plants[key1].id, isMature: false, p: contamP });
totalContamP += contamP;
}
runningP -= totalContamP;
}
// survival (remaining probability)
const maturityP = AgeThresholdP(tileBoosts[0] * dragonBoost, currentPlant.mature - age);
AddOutcome({ plantId, isMature: true, p: maturityP * runningP });
AddOutcome({ plantId, isMature: false, p: (1 - maturityP) * runningP });
} else {
// tile is empty
let noNeighborsChance = 1;
neighResults.forEach((neighbor) => {
let emptyChance = 0;
const emptyOutcome = neighbor.find((outcome) => outcome.plantId === -1);
if (emptyOutcome) emptyChance = emptyOutcome.p;
noNeighborsChance *= emptyChance;
});
// weeds
const weedChance = 0.002 * soilWeedMult * tileBoosts[1];
AddOutcome({ plantId: 13, isMature: false, p: weedChance * noNeighborsChance });
AddOutcome({ plantId: -1, isMature: false, p: (1 - weedChance) * noNeighborsChance });
runningP -= noNeighborsChance;
// mutation
if (noNeighborsChance < 1) {
let totalMutationP = 0;
const CombineNeighbors = function (i = 0, current = [], comboP = 1, results = []) {
if (i >= neighResults.length) {
results.push({ tiles: current.slice(), comboP });
return results;
}
for (const state of neighResults[i])
CombineNeighbors(i + 1, [...current, state], comboP * state.p, results);
return results;
};
const loopsBase = (soilsById[soil].key === 'woodchips' ? 3 : 1) * dragonBoost;
for (const combo of CombineNeighbors()) {
// possible combinations of neighboring tiles
const neighs = {};
const neighsM = {};
for (const tile of combo.tiles) {
if (tile.plantId === -1) continue;
const { key } = plantsById[tile.plantId];
neighs[key] = (neighs[key] || 0) + 1;
if (tile.isMature) neighsM[key] = (neighsM[key] || 0) + 1;
}
const muts = getMuts(neighs, neighsM);
let perLoopMutationP = 0; // probability that any mutation occurs on a single loop with this combo
const mutationChances = [];
for (const [key, mutValue] of muts) {
let inclusionP = mutValue;
if (plants[key].weed) inclusionP *= soilWeedMult;
if (plants[key].weed || plants[key].fungus) inclusionP *= tileBoosts[1];
if (inclusionP > 0) mutationChances.push([key, inclusionP]);
}
const perLoopMutations = [];
for (const [key1, inclusionP1] of mutationChances) {
let q = [1];
for (const [key2, inclusionP2] of mutationChances) {
if (key1 !== key2) {
const newQ = Array(q.length + 1).fill(0);
for (let k = 0; k < q.length; k++) {
newQ[k] += q[k] * (1 - inclusionP2);
newQ[k + 1] += q[k] * inclusionP2;
}
q = newQ;
}
}
const E = q.reduce((acc, probXk, k) => acc + probXk / (1 + k), 0);
const mutationP = inclusionP1 * E;
perLoopMutationP += mutationP;
perLoopMutations.push([key1, mutationP * combo.comboP * runningP]);
}
if (perLoopMutationP === 0) continue;
let loopsBoost = 1;
if (loopsBase > 1) {
if (Number.isInteger(loopsBase)) {
loopsBoost = (1 - (1 - perLoopMutationP) ** loopsBase) / perLoopMutationP;
} else {
const loopsFloor = Math.floor(loopsBase);
const loopsFrac = loopsBase % 1;
const boostN = (1 - (1 - perLoopMutationP) ** loopsFloor) / perLoopMutationP;
const boostNp1 = (1 - (1 - perLoopMutationP) ** (loopsFloor + 1)) / perLoopMutationP;
loopsBoost = (1 - loopsFrac) * boostN + loopsFrac * boostNp1;
}
}
for (const [key, mutationP] of perLoopMutations) {
AddOutcome({ plantId: plants[key].id, maturityP: 0, p: mutationP * loopsBoost });
totalMutationP += mutationP * loopsBoost;
}
}
runningP -= totalMutationP;
}
// nothing (remaining probability)
AddOutcome({ plantId: -1, isMature: false, p: runningP });
}
const total = futureStates.reduce((sum, o) => sum + o.p, 0);
if (Math.abs(total - 1) > 1e-9) {
futureStates.forEach((o) => {
o.p /= total;
});
}
return futureStates;
}

View File

@@ -1,42 +1,154 @@
/* eslint-disable guard-for-in */
/* eslint-disable no-restricted-syntax */
import Beautify from '../../BeautifyAndFormatting/Beautify.js'; import Beautify from '../../BeautifyAndFormatting/Beautify.js';
import { TooltipName } from '../../VariablesAndData.js'; import { TooltipName } from '../../VariablesAndData.js';
import * as Create from '../CreateTooltip.js'; import * as Create from '../CreateTooltip.js';
import {
CacheFarmLevel,
CacheGardenSoil,
CachePlotChances,
CacheSupremeIntellect,
} from '../../../Cache/VariablesAndData.js';
import CalculateAllPlotChances from '../../HelperFunctions/CalculateAllPlotChances.js';
/** /**
* This function adds extra info to the Garden plots tooltips * This function adds extra info to the garden plot tooltips
* It adds to the additional information to l('CMTooltipArea') * It adds to the additional information to l('CMTooltipArea')
*/ */
export default function GardenPlots() { export default function GardenPlots() {
const { minigame } = Game.Objects.Farm; const { minigame } = Game.Objects.Farm;
if ( if (Game.mods.cookieMonsterFramework.saveData.cookieMonsterMod.settings.TooltipPlots) {
Game.mods.cookieMonsterFramework.saveData.cookieMonsterMod.settings.TooltipPlots && const tooltipBorder = l('CMTooltipBorder');
minigame.plot[TooltipName[1]][TooltipName[0]][0] !== 0
) { if (minigame.plot[TooltipName[1]][TooltipName[0]][0] !== 0) {
const mature = const rewardTooltip = document.createElement('div');
minigame.plot[TooltipName[1]][TooltipName[0]][1] > rewardTooltip.appendChild(Create.TooltipCreateHeader('Reward (Current / Maximum)'));
minigame.plantsById[minigame.plot[TooltipName[1]][TooltipName[0]][0] - 1].mature; const mature =
const plantName = minigame.plot[TooltipName[1]][TooltipName[0]][1] >=
minigame.plantsById[minigame.plot[TooltipName[1]][TooltipName[0]][0] - 1].name; minigame.plantsById[minigame.plot[TooltipName[1]][TooltipName[0]][0] - 1].mature;
l('CMTooltipBorder').appendChild(Create.TooltipCreateHeader('Reward (Current / Maximum)')); const plantName =
const reward = document.createElement('div'); minigame.plantsById[minigame.plot[TooltipName[1]][TooltipName[0]][0] - 1].name;
reward.id = 'CMTooltipPlantReward'; const reward = document.createElement('div');
l('CMTooltipBorder').appendChild(reward); reward.id = 'CMTooltipPlantReward';
if (plantName === 'Chocoroot' || plantName === 'White chocoroot') { rewardTooltip.appendChild(reward);
l('CMTooltipPlantReward').textContent = `${ if (plantName === 'Chocoroot' || plantName === 'White chocoroot') {
mature ? Beautify(Math.min(Game.cookies * 0.03, Game.cookiesPs * 60 * 3)) : '0' reward.textContent = `${
} / ${Beautify(Game.cookiesPs * 60 * 3)}`; mature ? Beautify(Math.min(Game.cookies * 0.03, Game.cookiesPs * 60 * 3)) : '0'
} else if (plantName === 'Bakeberry') { } / ${Beautify(Game.cookiesPs * 60 * 3)}`;
l('CMTooltipPlantReward').textContent = `${ } else if (plantName === 'Bakeberry') {
mature ? Beautify(Math.min(Game.cookies * 0.03, Game.cookiesPs * 60 * 30)) : '0' reward.textContent = `${
} / ${Beautify(Game.cookiesPs * 60 * 30)}`; mature ? Beautify(Math.min(Game.cookies * 0.03, Game.cookiesPs * 60 * 30)) : '0'
} else if (plantName === 'Queenbeet') { } / ${Beautify(Game.cookiesPs * 60 * 30)}`;
l('CMTooltipPlantReward').textContent = `${ } else if (plantName === 'Queenbeet') {
mature ? Beautify(Math.min(Game.cookies * 0.04, Game.cookiesPs * 60 * 60)) : '0' reward.textContent = `${
} / ${Beautify(Game.cookiesPs * 60 * 60)}`; mature ? Beautify(Math.min(Game.cookies * 0.04, Game.cookiesPs * 60 * 60)) : '0'
} else if (plantName === 'Duketater') { } / ${Beautify(Game.cookiesPs * 60 * 60)}`;
l('CMTooltipPlantReward').textContent = `${ } else if (plantName === 'Duketater') {
mature ? Beautify(Math.min(Game.cookies * 0.08, Game.cookiesPs * 60 * 120)) : '0' reward.textContent = `${
} / ${Beautify(Game.cookiesPs * 60 * 120)}`; mature ? Beautify(Math.min(Game.cookies * 0.08, Game.cookiesPs * 60 * 120)) : '0'
} else l('CMTooltipArea').style.display = 'none'; } / ${Beautify(Game.cookiesPs * 60 * 120)}`;
} else rewardTooltip.style.display = 'none';
if (rewardTooltip.style.display !== 'none') tooltipBorder.appendChild(rewardTooltip);
}
if (
minigame.parent.level !== CacheFarmLevel ||
minigame.soil !== CacheGardenSoil ||
Game.auraMult('Supreme Intellect') !== CacheSupremeIntellect
) {
CacheFarmLevel = minigame.parent.level;
CacheGardenSoil = minigame.soil;
CacheSupremeIntellect = Game.auraMult('Supreme Intellect');
CalculateAllPlotChances(minigame, CacheSupremeIntellect);
}
const plotChances = CachePlotChances[TooltipName[1]][TooltipName[0]];
const plotTooltip = document.createElement('div');
if (l('CMTooltipPlantReward')) plotTooltip.style.marginTop = '5px';
plotTooltip.appendChild(Create.TooltipCreateHeader('After Next Tick:'));
const showIcon = [];
for (const id in minigame.plantsById) {
showIcon[id] = minigame.plantsById[id].unlocked !== 0;
for (let y = 0; y < 6 && !showIcon[id]; y++) {
for (let x = 0; x < 6; x++) {
// eslint-disable-next-line eqeqeq
if (minigame.plot[y][x][0] - 1 == id) {
showIcon[id] = true;
break;
}
}
}
}
const tooltipOutcomes = document.createElement('div');
const ConvertToPercentage = function (x) {
if (x <= 0) return '0%';
if (x >= 1) return '100%';
const decimals =
Game.mods.cookieMonsterFramework.saveData.cookieMonsterMod.settings.ScaleDecimals + 1;
const delta = 10 ** -decimals;
const xH = x * 100;
if (xH < delta) return `<${Beautify(delta)}%`;
if (xH > 100 - delta) return `>${Beautify(100 - delta)}%`;
return `${Beautify(xH)}%`;
};
for (const outcome of plotChances) {
const outcomeInfo = document.createElement('div');
outcomeInfo.style.height = '48px';
outcomeInfo.style.display = 'flex';
outcomeInfo.style.alignItems = 'center';
const outcomeIcon = document.createElement('img');
outcomeIcon.style.float = 'left';
outcomeIcon.style.objectFit = 'none';
if (outcome.plantId === -1) {
outcomeIcon.style.width = '40px';
outcomeIcon.style.height = '40px';
outcomeIcon.style.margin = '4px';
outcomeIcon.src = `${Game.resPath}img/gardenPlots.png`;
outcomeIcon.style.objectPosition = `${0 * -40}px ${0 * -40}px`;
// add brown colour
outcomeIcon.style.background = 'saddlebrown';
outcomeIcon.style.maskImage = `url(${Game.resPath}img/gardenPlots.png)`;
} else {
outcomeIcon.style.width = '48px';
outcomeIcon.style.height = '48px';
outcomeIcon.style.margin = '0px';
if (!showIcon[outcome.plantId]) {
outcomeIcon.src = `${Game.resPath}img/icons.png?v=${Game.version}`;
outcomeIcon.style.objectPosition = `${0 * -48}px ${7 * -48}px`; // question mark
} else {
outcomeIcon.src = `${Game.resPath}img/gardenPlants.png?v=${Game.version}`;
outcomeIcon.style.objectPosition = `${4 * -48}px ${minigame.plantsById[outcome.plantId].icon * -48}px`;
}
}
outcomeInfo.appendChild(outcomeIcon);
const outcomeInfoText = document.createElement('div');
outcomeInfoText.style.marginLeft = '5px';
const outcomeProbability = document.createElement('div');
outcomeProbability.textContent = ConvertToPercentage(outcome.p);
outcomeInfoText.appendChild(outcomeProbability);
if (outcome.plantId !== -1) {
const outcomeMaturityChance = document.createElement('small');
outcomeMaturityChance.innerHTML = `<small>${ConvertToPercentage(outcome.maturityP)} chance of being mature</small>`;
outcomeInfoText.appendChild(outcomeMaturityChance);
}
outcomeInfo.appendChild(outcomeInfoText);
tooltipOutcomes.appendChild(outcomeInfo);
}
plotTooltip.appendChild(tooltipOutcomes);
tooltipBorder.appendChild(plotTooltip);
} else l('CMTooltipArea').style.display = 'none'; } else l('CMTooltipArea').style.display = 'none';
} }

View File

@@ -1,5 +1,6 @@
/** Functions related to replacing tooltips */ /** Functions related to replacing tooltips */
import CalculateAllPlotChances from '../../Disp/HelperFunctions/CalculateAllPlotChances.js';
import { CreateTooltip } from '../../Disp/Tooltips/Tooltip.js'; import { CreateTooltip } from '../../Disp/Tooltips/Tooltip.js';
import { LoadMinigames, TooltipBuildBackup, TooltipLumpBackup } from '../VariablesAndData.js'; // eslint-disable-line no-unused-vars import { LoadMinigames, TooltipBuildBackup, TooltipLumpBackup } from '../VariablesAndData.js'; // eslint-disable-line no-unused-vars
import ReplaceNativeGrimoire from './NativeGrimoire.js'; import ReplaceNativeGrimoire from './NativeGrimoire.js';
@@ -37,7 +38,7 @@ function ReplaceTooltipLump() {
} }
/** /**
* This function replaces the original .onmouseover functions of all garden plants * Replaces functions for the garden minigame
*/ */
function ReplaceTooltipGarden() { function ReplaceTooltipGarden() {
if (Game.Objects.Farm.minigameLoaded) { if (Game.Objects.Farm.minigameLoaded) {
@@ -55,6 +56,13 @@ function ReplaceTooltipGarden() {
Game.tooltip.wobble(); Game.tooltip.wobble();
}; };
}); });
// overwrite the harvesting function to allow CachePlotChances to be updated
const OldBuildPlot = Game.Objects.Farm.minigame.buildPlot;
Game.Objects.Farm.minigame.buildPlot = function () {
OldBuildPlot(arguments); // eslint-disable-line prefer-rest-params
CalculateAllPlotChances(Game.Objects.Farm.minigame, Game.auraMult('Supreme Intellect'));
};
} }
} }

View File

@@ -76,6 +76,8 @@ export default function CalculateGains() {
if (SimHas('Dragon scale')) mult *= 1.03; if (SimHas('Dragon scale')) mult *= 1.03;
if (SimHas('Wrinkler ambergris')) mult *= 1.06;
// Check effect of chosen Gods // Check effect of chosen Gods
let buildMult = 1; let buildMult = 1;
if (SimHasGod) { if (SimHasGod) {